fabienne
fabienne8mo ago

Proto and Client Package for Typescript - Beta Feature

We have released two new packages from our typescript repository. The client package is a TypeScript and JavaScript client library for interacting with all available Zitadel APIs. It allows developers to easily integrate their applications for authentication, authorization, and user management in Node.js and browser environments. The proto package provides Zitadel’s type definitions to use with the client package and interact with Zitadel’s gRPC APIs in any TypeScript or JavaScript application. Testing Period: till 31. March 2025 Testing Objectives: - Did you encounter problems or bugs? - General feedback on feature enhancements - Do you miss any features in the package? How to test: You can find the installation and usage instructions in the following links: - Zitadel Client - Zitadel Proto Test the packages and add improvement or bug reports directly to the github repository or let us know your general feedback below!
npm
@zitadel/client
This package exports services and utilities to interact with ZITADEL. Latest version: 1.0.2, last published: 16 days ago. Start using @zitadel/client in your project by running npm i @zitadel/client. There are no other projects in the npm registry using @zitadel/client.
npm
@zitadel/proto
This package provides the Protocol Buffers (proto) definitions used by ZITADEL projects. It includes the proto files and generated code for interacting with ZITADEL's gRPC APIs.. Latest version: 1.0.2, last published: 16 days ago. Start using @zitadel/proto in your project by running npm i @zitadel/proto. There is 1 other project in the npm re...
GitHub
Issues · zitadel/typescript
Typescript packages and application to showcase the ZITADEL resource API - Issues · zitadel/typescript
36 Replies
Unknown User
Unknown User8mo ago
Message Not Public
Sign In & Join Server To View
fabienne
fabienneOP8mo ago
@peintnermax Mark you here for the feedback. 😄
Unknown User
Unknown User8mo ago
Message Not Public
Sign In & Join Server To View
cris
cris7mo ago
am I wrong or with this new client you can't create projects nor add new machine users? nvm I found it under v1 as a feedback it seems that using in node is quite not straightforward (e.g. drop the imports and you are ready to go) currently I'm getting compilation errors if I try to import it using module: "nodenext" and if I'm switching to a dynamic import a still get this error:
Error [ERR_REQUIRE_ESM]: require() of ES Module <PROJECT_PATH>/node_modules/@zitadel/proto/zitadel/admin_pb.js from <PROJECT_PATH>/node_modules/@zitadel/client/dist/v1.cjs not supported.
Instead, change the require of admin_pb.js in <PROJECT_PATH>/node_modules/@zitadel/client/dist/v1.cjs to a dynamic import() which is available in all CommonJS modules.
Error [ERR_REQUIRE_ESM]: require() of ES Module <PROJECT_PATH>/node_modules/@zitadel/proto/zitadel/admin_pb.js from <PROJECT_PATH>/node_modules/@zitadel/client/dist/v1.cjs not supported.
Instead, change the require of admin_pb.js in <PROJECT_PATH>/node_modules/@zitadel/client/dist/v1.cjs to a dynamic import() which is available in all CommonJS modules.
Unknown User
Unknown User7mo ago
Message Not Public
Sign In & Join Server To View
cris
cris7mo ago
I'm on 1.0.6 I've played a bit with the settings and now I am on a new error with jest it might be a jest configuration problem but when using it without the new client everything worked... so it might be something about ESM support @peintnermax so I think I was able to pinpoint the problem. Basically even if @zitadel/client is built to work with CJS @zitadel/proto doesn't, so if you are in enviroment that supports only CJS (like jest global hooks) the imports break. you can try requiring the library by a normal NodeJS application (no "module" option added).
const { createServerTransport, newSystemToken } = require('@zitadel/client/node');
const {
createAdminServiceClient,
createManagementServiceClient,
} = require('@zitadel/client/v1');


newSystemToken({}).then((token) => {
const adminService = createAdminServiceClient(createServerTransport('https://api.zitadel.ch', token));
const managementService = createManagementServiceClient(createServerTransport('https://api.zitadel.ch', token));
// use the adminService and managementService
});
const { createServerTransport, newSystemToken } = require('@zitadel/client/node');
const {
createAdminServiceClient,
createManagementServiceClient,
} = require('@zitadel/client/v1');


newSystemToken({}).then((token) => {
const adminService = createAdminServiceClient(createServerTransport('https://api.zitadel.ch', token));
const managementService = createManagementServiceClient(createServerTransport('https://api.zitadel.ch', token));
// use the adminService and managementService
});
are you planning to support also CJS ? ah forgot this is the error that you should get by running node index.js
[path-to-project]/node_modules/@zitadel/client/dist/v1.cjs:6
var _admin_pbjs = require('@zitadel/proto/zitadel/admin_pb.js');
^

Error [ERR_REQUIRE_ESM]: require() of ES Module [path-to-project]/node_modules/@zitadel/proto/zitadel/admin_pb.js from [path-to-project]/node_modules/@zitadel/client/dist/v1.cjs not supported.
Instead, change the require of admin_pb.js in [path-to-project]/node_modules/@zitadel/client/dist/v1.cjs to a dynamic import() which is available in all CommonJS modules.
at Object.<anonymous> ([path-to-project]/node_modules/@zitadel/client/dist/v1.cjs:6:19) {
code: 'ERR_REQUIRE_ESM'
}
[path-to-project]/node_modules/@zitadel/client/dist/v1.cjs:6
var _admin_pbjs = require('@zitadel/proto/zitadel/admin_pb.js');
^

Error [ERR_REQUIRE_ESM]: require() of ES Module [path-to-project]/node_modules/@zitadel/proto/zitadel/admin_pb.js from [path-to-project]/node_modules/@zitadel/client/dist/v1.cjs not supported.
Instead, change the require of admin_pb.js in [path-to-project]/node_modules/@zitadel/client/dist/v1.cjs to a dynamic import() which is available in all CommonJS modules.
at Object.<anonymous> ([path-to-project]/node_modules/@zitadel/client/dist/v1.cjs:6:19) {
code: 'ERR_REQUIRE_ESM'
}
hope it helps. btw dynamically import them (await import()) and enabling nodeResolution: node16 worked with jest. Not ideal but at least I can move on . (please let me know if this channel is not meant for this kind of support) So I was able to finally get back on track and upgrade both zitadel and client. As a general feeback: the onboarding process for existing nodejs +jest + typescript project is quite a pain (ofc is not enterly your fault since the ESM + CJS landscape is already a mess). I would happier if in the future I would not need special module resoltions and other workarounds to make the library work. Another thing that I had to add is:
// FORCEFULLY ignore ts errors since we just need the type and therefore no actual require will happen at runtime.
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-expect-error
import type { createManagementServiceClient } from '@zitadel/client/v1';

//export client type
export type ManagementServiceClient = ReturnType<
typeof createManagementServiceClient
>;
// FORCEFULLY ignore ts errors since we just need the type and therefore no actual require will happen at runtime.
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-expect-error
import type { createManagementServiceClient } from '@zitadel/client/v1';

//export client type
export type ManagementServiceClient = ReturnType<
typeof createManagementServiceClient
>;
So another thing that could be improved is to export ServiceClient types so that they can be easly used. (unless they are already exported and I didn't see it).
Unknown User
Unknown User7mo ago
Message Not Public
Sign In & Join Server To View
cris
cris7mo ago
I did, in the end I used this two options:
"module": "nodenext",
"moduleResolution": "node16",
"module": "nodenext",
"moduleResolution": "node16",
but you have to use dynamic imports (which might be something you don't want to do ) and some work around as the above.
Unknown User
Unknown User7mo ago
Message Not Public
Sign In & Join Server To View
Yordis Prieto
Yordis Prieto7mo ago
Definitely drop support by now, especially for the latest NodeJS (if I am not mistaken they allow mixing them). I would also remove the chunking and things like that from tsup
cris
cris7mo ago
in my expirience the problem with jest was exactly mixing things up since jest is basically trying to do dirty tricks with nodejs module loading (it injects global variables and other stuff), it might be something confined in that environment however, for us is very important to use ts client libraries in that place because we do e2e testing of our api there. (we create fake users, add permissions etc.)
Unknown User
Unknown User7mo ago
Message Not Public
Sign In & Join Server To View
Yordis Prieto
Yordis Prieto7mo ago
What is exactly broken? Where the module resolution is used precisely?
cris
cris7mo ago
I'll try to get back to you with a minimal project setup, but basically it should break in any Jest project
Unknown User
Unknown User7mo ago
Message Not Public
Sign In & Join Server To View
Yordis Prieto
Yordis Prieto7mo ago
Do you have the example repo? Ideally it will be based on ESM and the module resolution is not node but bundler depending of the setup
tafaust
tafaust7mo ago
I do it the same way in my nestjs backend but the approach is a bit subpar because it lacks intellisense I did already ask here: https://github.com/zitadel/typescript/issues/288#issuecomment-2707824038 but are there any plans to export @zitadel/proto types with CJS support? I can support with a PR @peintnermax. Is that welcome/accepted? @Yordis Prieto I can see why you'd suggest to drop CJS support but it will be unavailable for NestJS users (https://github.com/nestjs/nest/issues/13319#issuecomment-2022145229 for I don't know how long) and also make working with the @zitadel/client as SDK bit of a PITA. I wish I had the capacity to migrate all of our backends to https://deepkit.io/ because they have ESM support... but it is just not feasible for me atm. Why not go dual? @cris did you end up writing mocks like such
jest.mock('@zitadel/client/node', () => ({
newSystemToken: jest.fn().mockResolvedValue('mock-token'),
createServerTransport: jest
.fn()
.mockReturnValue({ transport: 'mock-transport' }),
}));
jest.mock('@zitadel/client/node', () => ({
newSystemToken: jest.fn().mockResolvedValue('mock-token'),
createServerTransport: jest
.fn()
.mockReturnValue({ transport: 'mock-transport' }),
}));
for all the exports of the @zitadel/client ? If the Zitadel team decides to support CommonJS, I am more than happy to provide a timely PR
cris
cris7mo ago
+1 to keep CJS support. As far as I know, you would just need to apply the same compile configuration of @zitadel/client to @zitadel/proto (as the client has already the .cjs file generated) no I didn't need to mock anything, cause I'm using the client for e2e testing and we are running a real test instance of zitadel I just created them:
// Zitadel client is still a work in progress and it struggles
// in jest cjs environment. We are just importing the type here
// but still TSC complains about not zitadel client incompatibilities.
// We are safe because we are not actually using the js from that module.
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-expect-error
import type { createManagementServiceClient } from '@zitadel/client/v1';
import type {
createOIDCServiceClient, // eslint-disable-next-line @typescript-eslint/ban-ts-comment
createSessionServiceClient, //@ts-expect-error
} from '@zitadel/client/v2';

export type ManagementServiceClient = ReturnType<
typeof createManagementServiceClient
>;
export type OIDCServiceClient = ReturnType<typeof createOIDCServiceClient>;
export type SessionServiceClient = ReturnType<
typeof createSessionServiceClient
>;

//... later inside an async function
const { createServerTransport } = await import('@zitadel/client/node');
const { createManagementServiceClient } = await import('@zitadel/client/v1');
const { createOIDCServiceClient, createSessionServiceClient } = await import(
'@zitadel/client/v2'
);

const session = createSessionServiceClient(transport);
const oidc = createOIDCServiceClient(transport);
const management = createManagementServiceClient(transport);
// Zitadel client is still a work in progress and it struggles
// in jest cjs environment. We are just importing the type here
// but still TSC complains about not zitadel client incompatibilities.
// We are safe because we are not actually using the js from that module.
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-expect-error
import type { createManagementServiceClient } from '@zitadel/client/v1';
import type {
createOIDCServiceClient, // eslint-disable-next-line @typescript-eslint/ban-ts-comment
createSessionServiceClient, //@ts-expect-error
} from '@zitadel/client/v2';

export type ManagementServiceClient = ReturnType<
typeof createManagementServiceClient
>;
export type OIDCServiceClient = ReturnType<typeof createOIDCServiceClient>;
export type SessionServiceClient = ReturnType<
typeof createSessionServiceClient
>;

//... later inside an async function
const { createServerTransport } = await import('@zitadel/client/node');
const { createManagementServiceClient } = await import('@zitadel/client/v1');
const { createOIDCServiceClient, createSessionServiceClient } = await import(
'@zitadel/client/v2'
);

const session = createSessionServiceClient(transport);
const oidc = createOIDCServiceClient(transport);
const management = createManagementServiceClient(transport);
and about the top comment, I don't really understand why tsc complains even if I'm just importing a type (even the tsc doc confirm that such kind of imports are removed from the compiled js).
Unknown User
Unknown User6mo ago
Message Not Public
Sign In & Join Server To View
tafaust
tafaust6mo ago
Thanks for the feedback @peintnermax. I created https://github.com/zitadel/typescript/issues/395 to keep track of it
GitHub
Add CommonJS support for @zitadel/proto · Issue #395 · zitadel/type...
Preflight Checklist I could not find a solution in the existing issues, docs, nor discussions I have joined the ZITADEL chat Describe your problem I have a NestJs backend and want to use @zitadel/c...
Yordis Prieto
Yordis Prieto6mo ago
:facepalm: what a mess, incredible to see Nest locking the thread :SadgeCry:
tafaust
tafaust6mo ago
Unfortunately yes, my next venture will be based off of deepkit https://github.com/zitadel/typescript/pull/398 if somebody wants to support with a review. constructive feedback is greatly appreciated especially for the tests, those are AI generated ... 😅
tafaust
tafaust6mo ago
incorporated changes request by @peintnermax. review of the changes are very welcome. especially your thoughts on https://github.com/zitadel/typescript/pull/398#issuecomment-2739388624
GitHub
feat(zitadel-proto): add CJS and ESM support; export in Zitadel api...
…tructure; add build configuration Definition of Ready I am happy with the code Short description of the feature/issue is added in the pr description PR is linked to the corresponding user stor...
tafaust
tafaust6mo ago
the sooner we are able to get the PR through the door, the faster we have CJS support ready 🙂 Is there any way we can get this merged this week? We need it urgently in our startup and I'm close to just implement proto in our monorepo and drop the PR for CJS support
cris
cris6mo ago
I tried in my nest-js project but still got issues... shoul I change the imports? Can't I use these one:
import { createManagementServiceClient } from '@zitadel/client/v1';
import {
createOIDCServiceClient,
createSessionServiceClient,
} from '@zitadel/client/v2';
import { createManagementServiceClient } from '@zitadel/client/v1';
import {
createOIDCServiceClient,
createSessionServiceClient,
} from '@zitadel/client/v2';
@tafaust
tafaust
tafaust6mo ago
wdym @cris ? the zitadel proto cjs support PR is still open and pending
cris
cris6mo ago
I cloned and linked it as dependency in my project
tafaust
tafaust6mo ago
I am working on CJS support for @zitadel/proto. AFAIU there already is CJS support for @zitadel/client
tafaust
tafaust5mo ago
@peintnermax any update? the PR is open Closed the PR. This is taking too long. I will implement the SDK with CJS support as lib in my nx monorepo now. Sorry folks.
Unknown User
Unknown User5mo ago
Message Not Public
Sign In & Join Server To View
tafaust
tafaust5mo ago
no worries @peintnermax, this missing "feature" was just a roadblock for so long that I ended up writing our own zitadel sdk for nestjs in my private nx monorepo I won't be using the official zitadel sdk in my nestjs wrapper I guess because I have another nx lib that generates the CommonJS compatible sdk from gRPC just-in-time and allows for greater flexibility in our case when there is an export missing
cris
cris5mo ago
yup I knew but since client depends on proto I got a bunch of troubles as shown here: https://discord.com/channels/927474939156643850/1332345712268283904/1339534984498909184
Yordis Prieto
Yordis Prieto5mo ago
One of the best things about protobuf is that people can codegen the clients without requiring SDK packages. By design, it is encouraging to codegen your version from the spec. It could be an anti-pattern to depend on packages, since you will depend of their publishing lifecycle and the defauled configuration of the protoc may not be what you want. Keep that in mind!
cris
cris3mo ago
finally I had time to look into this. Check this out: https://github.com/zitadel/typescript/pull/489 Let me know what you think, I tested in our E2E test suite and worked without additional configuration.
GitHub
Improve CJS support by relu91 · Pull Request #489 · zitadel/type...
This PR resolves a subtle runtime error in zitadel-client when used in CommonJS (CJS) environments, particularly in VM-based setups like Jest. Even after #398, the client was still inadvertently im...

Did you find this page helpful?