@zitadel/cli 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -0
- package/dist/index.mjs +1450 -1047
- package/dist/index.mjs.map +1 -1
- package/dist/lib/oclif/help.mjs +3 -2
- package/dist/lib/oclif/help.mjs.map +1 -1
- package/dist/skills/zitadel/SKILL.md +111 -0
- package/dist/skills/zitadel-cli/SKILL.md +635 -0
- package/dist/skills/zitadel-cli/references/driving-login-ui.md +124 -0
- package/dist/skills/zitadel-components/SKILL.md +152 -0
- package/dist/skills/zitadel-sdk-angular/SKILL.md +149 -0
- package/dist/skills/zitadel-sdk-next/SKILL.md +174 -0
- package/dist/skills/zitadel-sdk-nuxt/SKILL.md +149 -0
- package/dist/skills/zitadel-sdk-qwik/SKILL.md +136 -0
- package/dist/skills/zitadel-sdk-qwik-router/SKILL.md +126 -0
- package/dist/skills/zitadel-sdk-react/SKILL.md +149 -0
- package/dist/skills/zitadel-sdk-solid/SKILL.md +144 -0
- package/dist/skills/zitadel-sdk-solid-start/SKILL.md +149 -0
- package/dist/skills/zitadel-sdk-svelte/SKILL.md +137 -0
- package/dist/skills/zitadel-sdk-sveltekit/SKILL.md +147 -0
- package/dist/skills/zitadel-sdk-tanstack-start/SKILL.md +150 -0
- package/dist/skills/zitadel-sdk-vue/SKILL.md +147 -0
- package/dist/{skills-hint-N1H5-ny1.mjs → skills-hint-C8oe8cCo.mjs} +1446 -231
- package/dist/skills-hint-C8oe8cCo.mjs.map +1 -0
- package/oclif.manifest.json +102 -3
- package/package.json +8 -5
- package/skills/zitadel-cli/SKILL.md +62 -9
- package/dist/skills-hint-N1H5-ny1.mjs.map +0 -1
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: zitadel-sdk-tanstack-start
|
|
3
|
+
description: >-
|
|
4
|
+
Integrate Zitadel authentication into an existing or custom TanStack Start app
|
|
5
|
+
with @zitadel/sdk-tanstack-start. Use when the user wants login, logout,
|
|
6
|
+
session handling, or protected routes in a TanStack Start (React) app and is
|
|
7
|
+
wiring the SDK by hand rather than letting the CLI scaffold a fresh project —
|
|
8
|
+
registering the request middleware in `src/start.ts`, guarding a route with a
|
|
9
|
+
server function, or rendering the `ZitadelLogin` / `ZitadelSession` widgets.
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# @zitadel/sdk-tanstack-start
|
|
13
|
+
|
|
14
|
+
TanStack Start request middleware and helpers that add Zitadel (Nextgen) auth to
|
|
15
|
+
a TanStack Start app. The middleware proxies auth traffic same-origin under
|
|
16
|
+
`/__nextgen`, verifies the session JWT via JWKS on the server, places the result
|
|
17
|
+
on the request context as `nextgenAuth`, and redirects unauthenticated requests
|
|
18
|
+
on protected routes. Unlike the other meta-framework SDKs it also ships the
|
|
19
|
+
widgets (a `/react` entry), so no other Zitadel package is needed.
|
|
20
|
+
|
|
21
|
+
## When to use
|
|
22
|
+
|
|
23
|
+
The `zitadel` CLI (`zitadel setup --framework tanstack-start`) scaffolds
|
|
24
|
+
`src/start.ts`, login/register/profile routes, and `.env.local` into a fresh or
|
|
25
|
+
detected TanStack Start project — prefer it for greenfield work. Reach for
|
|
26
|
+
**this skill** when you are adding auth to an **existing or custom** TanStack
|
|
27
|
+
Start app by hand, or adjusting a scaffolded wiring.
|
|
28
|
+
|
|
29
|
+
## Install
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pnpm add @zitadel/sdk-tanstack-start@latest
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Peer deps: `@tanstack/react-start >=1.168.10`, `react >=18`, `react-dom >=18`.
|
|
36
|
+
|
|
37
|
+
## Integrate
|
|
38
|
+
|
|
39
|
+
**1. Request middleware.** Register it in `src/start.ts`, the file TanStack Start
|
|
40
|
+
auto-loads, via `requestMiddleware`. Having this file turns off the automatic
|
|
41
|
+
CSRF protection for server functions, so list `createCsrfMiddleware` before auth:
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import { createCsrfMiddleware, createMiddleware, createStart } from '@tanstack/react-start';
|
|
45
|
+
import { createNextgenRequestMiddleware } from '@zitadel/sdk-tanstack-start/server';
|
|
46
|
+
|
|
47
|
+
const csrfMiddleware = createCsrfMiddleware({
|
|
48
|
+
filter: (ctx) => ctx.handlerType === 'serverFn',
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const authMiddleware = createMiddleware({ type: 'request' }).server(
|
|
52
|
+
createNextgenRequestMiddleware({
|
|
53
|
+
url: process.env.ZITADEL_URL,
|
|
54
|
+
projectSecret: process.env.ZITADEL_PROJECT_SECRET,
|
|
55
|
+
protectedRoutes: ['/admin', '/dashboard*'], // trailing * matches sub-paths
|
|
56
|
+
loginPath: '/login',
|
|
57
|
+
}),
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
export const startInstance = createStart(() => ({
|
|
61
|
+
requestMiddleware: [csrfMiddleware, authMiddleware],
|
|
62
|
+
}));
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Sessions count only in the app's own project: `projectId`, else
|
|
66
|
+
`ZITADEL_PROJECT_ID`, else `VITE_ZITADEL_PROJECT_ID`. With none set, nobody is
|
|
67
|
+
signed in.
|
|
68
|
+
|
|
69
|
+
The same proxy/verify/protect decision is exported as the framework-agnostic
|
|
70
|
+
`handleNextgenRequest(request, options)` for a custom server entry.
|
|
71
|
+
|
|
72
|
+
**2. Read auth and guard routes through a server function.** Server functions
|
|
73
|
+
receive the middleware's context; a route's `beforeLoad` does not, and on
|
|
74
|
+
client-side navigation it runs in the browser. Call a server function from
|
|
75
|
+
`beforeLoad`:
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
import { createServerFn } from '@tanstack/react-start';
|
|
79
|
+
import { createFileRoute, redirect } from '@tanstack/react-router';
|
|
80
|
+
import { getAuth } from '@zitadel/sdk-tanstack-start/server';
|
|
81
|
+
|
|
82
|
+
// A server function's return value is serialised to the browser, so return
|
|
83
|
+
// only client-safe fields: `getAuth` also carries the raw session token.
|
|
84
|
+
const fetchAuth = createServerFn().handler(({ context }) => {
|
|
85
|
+
const auth = getAuth(context);
|
|
86
|
+
return auth.isAuthenticated
|
|
87
|
+
? { isAuthenticated: true as const, userId: auth.session.userId }
|
|
88
|
+
: { isAuthenticated: false as const };
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
export const Route = createFileRoute('/admin')({
|
|
92
|
+
beforeLoad: async () => {
|
|
93
|
+
const auth = await fetchAuth();
|
|
94
|
+
if (!auth.isAuthenticated) throw redirect({ to: '/login' });
|
|
95
|
+
return { userId: auth.userId };
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**3. Render the widgets** from the `/react` entry, with `configureZitadel` from
|
|
101
|
+
`/client`:
|
|
102
|
+
|
|
103
|
+
```tsx
|
|
104
|
+
import { ZitadelLogin } from '@zitadel/sdk-tanstack-start/react';
|
|
105
|
+
import { configureZitadel } from '@zitadel/sdk-tanstack-start/client';
|
|
106
|
+
|
|
107
|
+
const project = configureZitadel({
|
|
108
|
+
projectId: import.meta.env.VITE_ZITADEL_PROJECT_ID,
|
|
109
|
+
proxyPath: '/__nextgen',
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
export function LoginPage() {
|
|
113
|
+
return <ZitadelLogin project={project} purpose="login" postSignInUrl="/admin" />;
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
`<ZitadelSession project={project} postSignOutUrl="/login" />` renders the
|
|
118
|
+
signed-in card with sign-out, and `<ZitadelLogout>` a sign-out control on its own.
|
|
119
|
+
|
|
120
|
+
## Widget props and events
|
|
121
|
+
|
|
122
|
+
This SDK is not server-only: its `/react` entry wraps the widgets from `@zitadel/sdk-react`, so no other package is needed. Read the `@zitadel/sdk-react` skill for the widget props and events.
|
|
123
|
+
|
|
124
|
+
## Read these, don't guess
|
|
125
|
+
|
|
126
|
+
The package README at `node_modules/@zitadel/sdk-tanstack-start/README.md` and
|
|
127
|
+
the bundled `.d.ts` types (`dist/server.d.ts`, `dist/client.d.ts`,
|
|
128
|
+
`dist/react.d.ts`) are authoritative and versioned with the installed package —
|
|
129
|
+
read them before wiring anything, and let them override anything remembered.
|
|
130
|
+
This skill teaches the pattern, not a full catalog of options, widget props, or
|
|
131
|
+
the shared JWT-verification pipeline (that lives in `@zitadel/sdk-core`). Check
|
|
132
|
+
exact option names, props, and defaults against the installed version rather
|
|
133
|
+
than assuming.
|
|
134
|
+
|
|
135
|
+
## Gotchas
|
|
136
|
+
|
|
137
|
+
- **Import widgets from `/react`, not `/client`.** `/client` only configures the
|
|
138
|
+
SDK and exports no components.
|
|
139
|
+
- **The widgets render nothing on the server and during hydration.** They mount
|
|
140
|
+
right after, with every prop in place; do not expect them in the SSR markup.
|
|
141
|
+
- **Keep `createCsrfMiddleware` ahead of auth.** `src/start.ts` opts the app out
|
|
142
|
+
of TanStack Start's automatic CSRF protection.
|
|
143
|
+
- **`beforeLoad` has no `nextgenAuth`.** Read it with `getAuth(context)` inside a
|
|
144
|
+
server function, not from the route context.
|
|
145
|
+
- **Never return `getAuth(context)` itself from a server function.** Its session
|
|
146
|
+
carries the raw token, and a server function's result reaches browser scripts.
|
|
147
|
+
Return only `userId` and other client-safe fields.
|
|
148
|
+
- **`protectedRoutes` only guards full document requests.** Client-side `<Link>`
|
|
149
|
+
navigation needs the `beforeLoad` server-function guard; without it only the
|
|
150
|
+
`ZitadelSession` card sends a signed-out visitor away.
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: zitadel-sdk-vue
|
|
3
|
+
description: >-
|
|
4
|
+
Integrate Zitadel authentication into a Vue 3 single-page app with
|
|
5
|
+
@zitadel/sdk-vue. Use when the user wants to add Zitadel login, logout, or a
|
|
6
|
+
signed-in session card to an existing or custom Vue/Vite SPA — wiring the
|
|
7
|
+
configureZitadel handle, the ZitadelLogin / ZitadelLogout / ZitadelSession
|
|
8
|
+
components, the same-origin backend proxy, and post-sign-in / post-sign-out
|
|
9
|
+
redirects.
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# @zitadel/sdk-vue
|
|
13
|
+
|
|
14
|
+
`@zitadel/sdk-vue` provides Vue 3 components wrapping the Zitadel auth UI web
|
|
15
|
+
components (`ZitadelLogin`, `ZitadelLogout`, `ZitadelSession`) for client-side
|
|
16
|
+
SPAs (Vite, etc.). You configure one project handle with `configureZitadel(...)`
|
|
17
|
+
and hand it to the components; they talk to the backend over a same-origin
|
|
18
|
+
proxy path.
|
|
19
|
+
|
|
20
|
+
## When to use
|
|
21
|
+
|
|
22
|
+
Reach for this skill when integrating Zitadel into an **existing or custom** Vue
|
|
23
|
+
app, where you are adding the components by hand.
|
|
24
|
+
|
|
25
|
+
For a **fresh** scaffold, prefer the CLI instead — it wires the proxy, env, and
|
|
26
|
+
components for you:
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
npx @zitadel/cli@latest setup --framework vue --non-interactive --json
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Use this skill when `setup` is not appropriate (an app with its own structure,
|
|
33
|
+
a partial integration, or customizing what the CLI produced).
|
|
34
|
+
|
|
35
|
+
## Install
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
npm install @zitadel/sdk-vue@latest
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Peer dependencies: `vue >=3.2`. Requires TypeScript ≥ 5.0 (the published types use `export type *`).
|
|
42
|
+
|
|
43
|
+
## Integrate
|
|
44
|
+
|
|
45
|
+
Configure once with `configureZitadel(...)`, then pass the returned handle as
|
|
46
|
+
`:project` to each component. The components register the underlying web
|
|
47
|
+
components on import — no Vue plugin or `app.use(...)` is needed.
|
|
48
|
+
|
|
49
|
+
```vue
|
|
50
|
+
<script setup lang="ts">
|
|
51
|
+
import { ZitadelLogin, configureZitadel } from '@zitadel/sdk-vue';
|
|
52
|
+
|
|
53
|
+
const project = configureZitadel({
|
|
54
|
+
projectId: import.meta.env.VITE_ZITADEL_PROJECT_ID,
|
|
55
|
+
proxyPath: '/__nextgen',
|
|
56
|
+
});
|
|
57
|
+
</script>
|
|
58
|
+
|
|
59
|
+
<template>
|
|
60
|
+
<ZitadelLogin :project="project" purpose="login" postSignInUrl="/" />
|
|
61
|
+
</template>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Logout and the signed-in session card take the same `:project` handle:
|
|
65
|
+
|
|
66
|
+
```vue
|
|
67
|
+
<ZitadelLogout :project="project" postSignOutUrl="/login" />
|
|
68
|
+
<ZitadelSession :project="project" />
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
- `purpose` on `ZitadelLogin` is `"login"` by default (also accepts the other
|
|
72
|
+
flow purposes, e.g. registration).
|
|
73
|
+
- `postSignInUrl` / `postSignOutUrl` are where the browser lands after the flow.
|
|
74
|
+
- The widgets call `${proxyPath}/…` **same-origin** (default `/__nextgen`), so
|
|
75
|
+
your host must proxy that path to the Zitadel backend. For local development
|
|
76
|
+
you can instead point `proxyPath` straight at the backend cross-origin, e.g.
|
|
77
|
+
`proxyPath: 'http://localhost:8080'` (the `zitadel start` local runtime port).
|
|
78
|
+
|
|
79
|
+
## Widget props and events
|
|
80
|
+
|
|
81
|
+
`ZitadelLogin`, `ZitadelLogout` and `ZitadelSession` take the props below, spelled the same in every SPA SDK. An unset prop keeps the widget's own default.
|
|
82
|
+
|
|
83
|
+
| Prop | Type | Default | Widgets | Description |
|
|
84
|
+
| --- | --- | --- | --- | --- |
|
|
85
|
+
| `project` | `ZitadelProject` | unset | Login, Logout, Session | The handle from `configureZitadel(...)`. Wins over `projectId` and `proxyPath`. |
|
|
86
|
+
| `projectId` | `string` | unset | Login, Logout, Session | Project id, read when no `project` handle is passed. |
|
|
87
|
+
| `proxyPath` | `string` | `"/__nextgen"` | Login, Logout, Session | Same-origin path the widget calls. |
|
|
88
|
+
| `purpose` | `CreateFlowBodyPurpose` | `"login"` | Login | Flow purpose. |
|
|
89
|
+
| `flowName` | `string` | unset | Login | Runs the flow definition with this `name`; unset runs the project's default flow for the purpose. |
|
|
90
|
+
| `postSignInUrl` | `string` | unset | Login | Where to navigate after a completed sign-in. When the page's `next` query parameter names a path on the same origin, as the server SDKs' middleware sets it for a signed-out visit to a protected route, the widget returns there instead. |
|
|
91
|
+
| `forcePostSignInUrl` | `boolean` | `false` | Login | Navigates to `postSignInUrl` even when the page's `next` query parameter names a path, for a page that uses `next` for something of its own. |
|
|
92
|
+
| `postSignOutUrl` | `string` | unset | Logout, Session | Where to navigate after sign-out. |
|
|
93
|
+
| `resumeFlowId` | `string` or `null` | unset | Login | An existing flow's id to resume instead of starting a new flow; unset, `null` or `""` falls back to the `flow` query parameter, and an id that no longer resolves starts a new flow. |
|
|
94
|
+
| `variant` | `"widget"` or `"page"` | `"widget"` | Login, Session | `widget` is content-sized and paints no page chrome; `page` claims the viewport, paints the surface background and loads the brand font, and on Login focuses the first field. |
|
|
95
|
+
| `theme` | `"light"`, `"dark"` or `"auto"` | unset | Login, Logout, Session | Colour mode. Unset follows the tenant's branding theme on Login, then the variant default (`dark` for `page`, `auto` for `widget`); Logout defaults to `auto`. `auto` follows `prefers-color-scheme`. |
|
|
96
|
+
| `suppressHeader` | `boolean` | `false` | Login, Session | Visually hides the widget's own heading block while keeping it in the accessibility tree, for pages that already carry the heading. |
|
|
97
|
+
| `suppressPasswordToggle` | `boolean` | `false` | Login | Hides the show/hide button on password fields. |
|
|
98
|
+
| `heading` | `string` | `"Signed in as"` | Session | Heading text override. |
|
|
99
|
+
| `logoutLabel` | `string` | `"Sign out"` | Session | Logout action label override. |
|
|
100
|
+
| `locales` | `Record<string, Partial<Record<string, string>>>` | unset | Login | Copy overrides merged over the builtin dictionaries, keyed by primary language subtag, for example `{ en: { "identifier.title": "Welcome back" } }`. |
|
|
101
|
+
| `lang` | `string` | browser language | Login | BCP-47 language override. |
|
|
102
|
+
|
|
103
|
+
Each widget event reaches the callback in the last column, which receives the event's `detail` payload.
|
|
104
|
+
|
|
105
|
+
| Widget event | Fires when | Detail | Widgets | Callback |
|
|
106
|
+
| --- | --- | --- | --- | --- |
|
|
107
|
+
| `zitadel-flow-step` | Login shows a step, the first one included. | `{ step }` | Login | `@flowStep` |
|
|
108
|
+
| `zitadel-flow-input` | The visitor edits a field. | `{ name, value }` | Login | `@flowInput` |
|
|
109
|
+
| `zitadel-flow-complete` | The flow reaches a terminal step. | `{ behavior, redirect_uri?, handoff_token?, handoff_token_expires_at? }` | Login | `@flowComplete` |
|
|
110
|
+
| `zitadel-flow-redirect` | The widget hands the browser to an identity provider; nobody is signed in yet. | `{ redirect_url, step }` | Login | `@flowRedirect` |
|
|
111
|
+
| `zitadel-flow-error` | The flow reports an error. | `{ message }` | Login | `@flowError` |
|
|
112
|
+
| `zitadel-signout` | The user signs out. | `{ display, identifier }` | Logout, Session | `@signout` |
|
|
113
|
+
|
|
114
|
+
```vue
|
|
115
|
+
<ZitadelLogin :project="project" theme="light" @flowComplete="track" />
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
The `zitadel-flow-complete`, `zitadel-flow-redirect` and `zitadel-signout` details carry a `waitUntil(promise)`; call it from your handler to make the widget wait for your async work before it navigates.
|
|
119
|
+
|
|
120
|
+
## Read these, don't guess
|
|
121
|
+
|
|
122
|
+
The SDK and this skill version independently — discover the real surface before
|
|
123
|
+
writing code, and treat it as authoritative over anything here:
|
|
124
|
+
|
|
125
|
+
- `node_modules/@zitadel/sdk-vue/README.md` — the installed README.
|
|
126
|
+
- `node_modules/@zitadel/sdk-vue/dist/index.d.ts` — the TypeScript types: the
|
|
127
|
+
exact exports and every component prop. The public exports are
|
|
128
|
+
`ZitadelLogin`, `ZitadelLogout`, `ZitadelSession`, `configureZitadel`,
|
|
129
|
+
`getApi`, `getZitadelConfig`, the `ZitadelConfig` / `ZitadelProject` types,
|
|
130
|
+
and `businessLocales`.
|
|
131
|
+
|
|
132
|
+
Check the installed version's props rather than assuming; emitted events and
|
|
133
|
+
optional props (`locales`, `lang`, `theme`, `variant`, `suppressHeader`, …)
|
|
134
|
+
evolve.
|
|
135
|
+
|
|
136
|
+
## Gotchas
|
|
137
|
+
|
|
138
|
+
- **Server rendering.** If your app renders on the server, mount the widget on the client only, after hydration (the `ZitadelLogin` wrapper sets `projectId` and `proxyPath` as element properties, so adding them to the wrapper does not put them in server markup), or use a raw `<zitadel-login>` element with `project-id` and `proxy-path` as attributes, because a widget that starts before its configuration arrives shows an error instead of the flow.
|
|
139
|
+
- **Production SPA deployment is not yet supported.** The same-origin proxy path
|
|
140
|
+
must come from your hosting platform, and the CLI cannot scaffold those host
|
|
141
|
+
configs yet (see ADR 036 and zitadel/nextgen#560). The CLI dev proxy covers
|
|
142
|
+
local development only.
|
|
143
|
+
- **Same-origin by default.** Unless you override `proxyPath`, the widgets
|
|
144
|
+
expect `/__nextgen` to be proxied to the backend on the same origin — a bare
|
|
145
|
+
SPA with no proxy will fail its auth calls.
|
|
146
|
+
- **TypeScript ≥ 5.0 is required**; older compilers choke on the `export type *`
|
|
147
|
+
re-exports in the published type definitions.
|