@zitadel/config 0.0.0 → 0.1.0-alpha.15
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/defaults/README-flows.md +52 -0
- package/defaults/README-schemas.md +135 -0
- package/defaults/default-human-user.json +46 -0
- package/defaults/default-login.json +131 -0
- package/dist/defaults-B2iIPSSl.mjs +201 -0
- package/dist/defaults-B2iIPSSl.mjs.map +1 -0
- package/dist/defaults-DzfOT2_7.d.mts +30 -0
- package/dist/defaults-DzfOT2_7.d.mts.map +1 -0
- package/dist/defaults.d.mts +2 -0
- package/dist/defaults.mjs +2 -0
- package/dist/index.d.mts +4 -0
- package/dist/index.mjs +4 -0
- package/dist/normalize.d.mts +40 -0
- package/dist/normalize.d.mts.map +1 -0
- package/dist/normalize.mjs +82 -0
- package/dist/normalize.mjs.map +1 -0
- package/dist/schemas.d.mts +7 -0
- package/dist/schemas.d.mts.map +1 -0
- package/dist/schemas.mjs +9 -0
- package/dist/schemas.mjs.map +1 -0
- package/package.json +58 -4
- package/README.md +0 -3
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# `.zitadel/flows/`
|
|
2
|
+
|
|
3
|
+
Flow definitions. Each JSON file describes an end-to-end journey —
|
|
4
|
+
which fields the user sees at each step, which credentials are checked,
|
|
5
|
+
and how one step transitions to the next. The Zitadel flow engine runs
|
|
6
|
+
these on the platform; the widget renders whatever the engine emits.
|
|
7
|
+
|
|
8
|
+
Flows and schemas work together: the user schema in
|
|
9
|
+
`.zitadel/schemas/` defines **what** data exists, the flow defines
|
|
10
|
+
**when and where** users are asked to provide it. If you add a property
|
|
11
|
+
to the schema, users won't see a new field until a flow step lists it.
|
|
12
|
+
|
|
13
|
+
## What's in a flow file
|
|
14
|
+
|
|
15
|
+
- `purposes` — entry step for each purpose (`login`, `register`, …). A
|
|
16
|
+
single flow can serve multiple purposes.
|
|
17
|
+
- `steps[]` — the ordered list of screens. Each step's `fields[]`
|
|
18
|
+
references properties of the pinned schema (or reserved tokens like
|
|
19
|
+
`x-auth-methods#password`), and `transitions` wires it to the next
|
|
20
|
+
step.
|
|
21
|
+
- `user_schema` — pins the flow to one specific user-schema revision.
|
|
22
|
+
- `audience` (optional) — scopes the flow to specific apps or teams.
|
|
23
|
+
|
|
24
|
+
## Making changes
|
|
25
|
+
|
|
26
|
+
The common workflow:
|
|
27
|
+
|
|
28
|
+
1. Edit the flow (and, if it needs new data, the schema in
|
|
29
|
+
`.zitadel/schemas/` first).
|
|
30
|
+
2. Run `zitadel plan` to preview the change.
|
|
31
|
+
3. Run `zitadel apply` to publish it.
|
|
32
|
+
|
|
33
|
+
Typical edits:
|
|
34
|
+
|
|
35
|
+
- **Change which fields a step collects** — edit `steps[].fields[]`.
|
|
36
|
+
Values must be properties of the pinned schema (or reserved credential
|
|
37
|
+
tokens).
|
|
38
|
+
- **Add or remove a step** — extend `steps[]`.
|
|
39
|
+
- **Rewire transitions** — edit `steps[].transitions` to point at a
|
|
40
|
+
different next step, or use `action: switch` / `pivot` to jump to
|
|
41
|
+
another flow.
|
|
42
|
+
- **Add another flow** — drop a new JSON file with its own `purposes`
|
|
43
|
+
and `audience` (e.g. a per-team login).
|
|
44
|
+
|
|
45
|
+
## Schema revisions
|
|
46
|
+
|
|
47
|
+
Editing a schema publishes a new immutable revision. When you `apply` a
|
|
48
|
+
schema edit, the CLI rewrites `user_schema` in the flow files pinned to
|
|
49
|
+
the old revision and updates the flows in the same run — the plan
|
|
50
|
+
announces the re-pin beforehand, and the rewrite shows up in your git
|
|
51
|
+
diff. Remember to update `steps[].fields[]` yourself when the edit
|
|
52
|
+
added or removed properties the flow should collect.
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# `.zitadel/schemas/`
|
|
2
|
+
|
|
3
|
+
This folder contains your project's user schemas.
|
|
4
|
+
|
|
5
|
+
A user schema defines **what information is stored about a user** and
|
|
6
|
+
**how that type of user can authenticate**.
|
|
7
|
+
|
|
8
|
+
You can have as many schemas as you need. For example:
|
|
9
|
+
|
|
10
|
+
- `customer.json`
|
|
11
|
+
- `employee.json`
|
|
12
|
+
- `admin.json`
|
|
13
|
+
|
|
14
|
+
Here's a simplified example:
|
|
15
|
+
|
|
16
|
+
``` json
|
|
17
|
+
{
|
|
18
|
+
"objectType": "customer",
|
|
19
|
+
"properties": {
|
|
20
|
+
"firstName": {
|
|
21
|
+
"type": "string"
|
|
22
|
+
},
|
|
23
|
+
"company": {
|
|
24
|
+
"type": "string"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"required": [
|
|
28
|
+
"firstName"
|
|
29
|
+
],
|
|
30
|
+
"x-auth-methods": {
|
|
31
|
+
"password": { "enabled": true, "position": 1 },
|
|
32
|
+
"passkey": { "enabled": true, "position": 2 }
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Each schema is made up of four main sections:
|
|
38
|
+
|
|
39
|
+
## `objectType`
|
|
40
|
+
|
|
41
|
+
Identifies this type of user.
|
|
42
|
+
|
|
43
|
+
Once you've applied a schema for the first time, don't rename it.
|
|
44
|
+
Zitadel uses it to recognise future revisions of the same user type.
|
|
45
|
+
|
|
46
|
+
## `properties`
|
|
47
|
+
|
|
48
|
+
Defines the information stored for users of this type.
|
|
49
|
+
|
|
50
|
+
For example:
|
|
51
|
+
|
|
52
|
+
- First name
|
|
53
|
+
- Last name
|
|
54
|
+
- Company
|
|
55
|
+
- Phone number
|
|
56
|
+
- Custom attributes
|
|
57
|
+
|
|
58
|
+
Every property becomes available to the rest of the identity system,
|
|
59
|
+
including login and registration flows.
|
|
60
|
+
|
|
61
|
+
## `required`
|
|
62
|
+
|
|
63
|
+
Lists which properties every user must provide.
|
|
64
|
+
|
|
65
|
+
Properties that aren't listed here are optional.
|
|
66
|
+
|
|
67
|
+
## `x-auth-methods`
|
|
68
|
+
|
|
69
|
+
Controls how users of this type can authenticate.
|
|
70
|
+
|
|
71
|
+
For example:
|
|
72
|
+
|
|
73
|
+
- Password
|
|
74
|
+
- Passkeys
|
|
75
|
+
- Social login
|
|
76
|
+
|
|
77
|
+
------------------------------------------------------------------------
|
|
78
|
+
|
|
79
|
+
# Making changes
|
|
80
|
+
|
|
81
|
+
The most common workflow looks like this:
|
|
82
|
+
|
|
83
|
+
1. Update your schema.
|
|
84
|
+
2. If you've added, removed or renamed fields, update the corresponding
|
|
85
|
+
login flow in `.zitadel/flows/`.
|
|
86
|
+
3. Run `zitadel plan` to preview the changes.
|
|
87
|
+
4. Run `zitadel apply` to publish them.
|
|
88
|
+
|
|
89
|
+
## Why do I need to update the login flow?
|
|
90
|
+
|
|
91
|
+
The schema defines **what data exists**.
|
|
92
|
+
|
|
93
|
+
The login flow defines **when and where users are asked to provide that
|
|
94
|
+
data**.
|
|
95
|
+
|
|
96
|
+
For example, if you add a `company` property to your schema, users won't
|
|
97
|
+
see a new field on the registration form until you also update the
|
|
98
|
+
registration flow.
|
|
99
|
+
|
|
100
|
+
Likewise, if you remove or rename a property, you'll usually need to
|
|
101
|
+
update any login flows that reference it.
|
|
102
|
+
|
|
103
|
+
------------------------------------------------------------------------
|
|
104
|
+
|
|
105
|
+
# Common changes
|
|
106
|
+
|
|
107
|
+
## Add a new field
|
|
108
|
+
|
|
109
|
+
Add it under `properties`.
|
|
110
|
+
|
|
111
|
+
If every user must provide it, also add it to `required`.
|
|
112
|
+
|
|
113
|
+
Finally, update the login flow if users should be able to enter it.
|
|
114
|
+
|
|
115
|
+
## Make a field optional
|
|
116
|
+
|
|
117
|
+
Remove it from `required`.
|
|
118
|
+
|
|
119
|
+
## Enable passkeys
|
|
120
|
+
|
|
121
|
+
Set `"passkey": { "enabled": true }` in `x-auth-methods`.
|
|
122
|
+
|
|
123
|
+
## Create another user type
|
|
124
|
+
|
|
125
|
+
Create another JSON file in this directory.
|
|
126
|
+
|
|
127
|
+
------------------------------------------------------------------------
|
|
128
|
+
|
|
129
|
+
## Next step
|
|
130
|
+
|
|
131
|
+
Once you've updated your schema, continue with:
|
|
132
|
+
|
|
133
|
+
.zitadel/flows/
|
|
134
|
+
|
|
135
|
+
to update your login and registration flows.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "DefaultHumanUserSchema",
|
|
3
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
4
|
+
"metaSchema": "${SERVER_URL}/user-schema.json",
|
|
5
|
+
"$id": "${USER_SCHEMA_URL}",
|
|
6
|
+
"objectType": "human-user",
|
|
7
|
+
"kind": "user-schema",
|
|
8
|
+
"type": "object",
|
|
9
|
+
"description": "The default editable schema for human users.",
|
|
10
|
+
"x-auth-methods": {
|
|
11
|
+
"password": {
|
|
12
|
+
"enabled": true,
|
|
13
|
+
"position": 1
|
|
14
|
+
},
|
|
15
|
+
"passkey": {
|
|
16
|
+
"enabled": true,
|
|
17
|
+
"position": 2
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"required": [
|
|
21
|
+
"email"
|
|
22
|
+
],
|
|
23
|
+
"properties": {
|
|
24
|
+
"email": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"format": "email",
|
|
27
|
+
"x-unique": "project",
|
|
28
|
+
"description": "The user's email address."
|
|
29
|
+
},
|
|
30
|
+
"givenName": {
|
|
31
|
+
"type": "string",
|
|
32
|
+
"maxLength": 50,
|
|
33
|
+
"description": "The user's given (first) name."
|
|
34
|
+
},
|
|
35
|
+
"familyName": {
|
|
36
|
+
"type": "string",
|
|
37
|
+
"maxLength": 50,
|
|
38
|
+
"description": "The user's family (last) name."
|
|
39
|
+
},
|
|
40
|
+
"dateOfBirth": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"format": "date",
|
|
43
|
+
"description": "The user's date of birth (ISO 8601, YYYY-MM-DD)."
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "default-login",
|
|
3
|
+
"status": "active",
|
|
4
|
+
"user_schema": "${USER_SCHEMA_URL}",
|
|
5
|
+
"purposes": {
|
|
6
|
+
"login": "identifier",
|
|
7
|
+
"register": "register"
|
|
8
|
+
},
|
|
9
|
+
"steps": [
|
|
10
|
+
{
|
|
11
|
+
"name": "identifier",
|
|
12
|
+
"fields": [
|
|
13
|
+
"email"
|
|
14
|
+
],
|
|
15
|
+
"actions": [
|
|
16
|
+
{
|
|
17
|
+
"name": "submit",
|
|
18
|
+
"kind": "submit",
|
|
19
|
+
"primary": true,
|
|
20
|
+
"text_key": "identifier.action.continue"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "passkey",
|
|
24
|
+
"kind": "passkey",
|
|
25
|
+
"primary": false,
|
|
26
|
+
"text_key": "identifier.action.passkey"
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
"transitions": {
|
|
30
|
+
"submit": {
|
|
31
|
+
"target": "password"
|
|
32
|
+
},
|
|
33
|
+
"passkey": {
|
|
34
|
+
"target": "done"
|
|
35
|
+
},
|
|
36
|
+
"user_not_found": {
|
|
37
|
+
"target": "register"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"name": "password",
|
|
43
|
+
"fields": [
|
|
44
|
+
"x-auth-methods#password"
|
|
45
|
+
],
|
|
46
|
+
"actions": [
|
|
47
|
+
{
|
|
48
|
+
"name": "submit",
|
|
49
|
+
"kind": "submit",
|
|
50
|
+
"primary": true,
|
|
51
|
+
"text_key": "password.action.signin"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"name": "passkey",
|
|
55
|
+
"kind": "passkey",
|
|
56
|
+
"primary": false,
|
|
57
|
+
"text_key": "password.action.passkey"
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
"transitions": {
|
|
61
|
+
"submit": {
|
|
62
|
+
"target": "done"
|
|
63
|
+
},
|
|
64
|
+
"passkey": {
|
|
65
|
+
"target": "done"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"name": "register",
|
|
71
|
+
"fields": [
|
|
72
|
+
"email",
|
|
73
|
+
"givenName",
|
|
74
|
+
"familyName",
|
|
75
|
+
"dateOfBirth"
|
|
76
|
+
],
|
|
77
|
+
"actions": [
|
|
78
|
+
{
|
|
79
|
+
"name": "submit",
|
|
80
|
+
"kind": "submit",
|
|
81
|
+
"primary": true,
|
|
82
|
+
"text_key": "register.action.password"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"name": "passkey_register",
|
|
86
|
+
"kind": "passkey_register",
|
|
87
|
+
"primary": false,
|
|
88
|
+
"text_key": "register.action.passkey"
|
|
89
|
+
}
|
|
90
|
+
],
|
|
91
|
+
"transitions": {
|
|
92
|
+
"submit": {
|
|
93
|
+
"target": "register-password"
|
|
94
|
+
},
|
|
95
|
+
"passkey_register": {
|
|
96
|
+
"target": "done"
|
|
97
|
+
},
|
|
98
|
+
"user_already_exists": {
|
|
99
|
+
"target": "password"
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"name": "register-password",
|
|
105
|
+
"fields": [
|
|
106
|
+
"x-auth-methods#password"
|
|
107
|
+
],
|
|
108
|
+
"actions": [
|
|
109
|
+
{
|
|
110
|
+
"name": "submit",
|
|
111
|
+
"kind": "submit",
|
|
112
|
+
"primary": true,
|
|
113
|
+
"text_key": "register-password.action.submit"
|
|
114
|
+
}
|
|
115
|
+
],
|
|
116
|
+
"on_success": "create_user",
|
|
117
|
+
"transitions": {
|
|
118
|
+
"submit": {
|
|
119
|
+
"target": "done"
|
|
120
|
+
},
|
|
121
|
+
"user_already_exists": {
|
|
122
|
+
"target": "password"
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"name": "done",
|
|
128
|
+
"complete": "show"
|
|
129
|
+
}
|
|
130
|
+
]
|
|
131
|
+
}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
//#region defaults/default-human-user.json
|
|
4
|
+
var default_human_user_default = {
|
|
5
|
+
title: "DefaultHumanUserSchema",
|
|
6
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
7
|
+
metaSchema: "${SERVER_URL}/user-schema.json",
|
|
8
|
+
$id: "${USER_SCHEMA_URL}",
|
|
9
|
+
objectType: "human-user",
|
|
10
|
+
kind: "user-schema",
|
|
11
|
+
type: "object",
|
|
12
|
+
description: "The default editable schema for human users.",
|
|
13
|
+
"x-auth-methods": {
|
|
14
|
+
"password": {
|
|
15
|
+
"enabled": true,
|
|
16
|
+
"position": 1
|
|
17
|
+
},
|
|
18
|
+
"passkey": {
|
|
19
|
+
"enabled": true,
|
|
20
|
+
"position": 2
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
required: ["email"],
|
|
24
|
+
properties: {
|
|
25
|
+
"email": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"format": "email",
|
|
28
|
+
"x-unique": "project",
|
|
29
|
+
"description": "The user's email address."
|
|
30
|
+
},
|
|
31
|
+
"givenName": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"maxLength": 50,
|
|
34
|
+
"description": "The user's given (first) name."
|
|
35
|
+
},
|
|
36
|
+
"familyName": {
|
|
37
|
+
"type": "string",
|
|
38
|
+
"maxLength": 50,
|
|
39
|
+
"description": "The user's family (last) name."
|
|
40
|
+
},
|
|
41
|
+
"dateOfBirth": {
|
|
42
|
+
"type": "string",
|
|
43
|
+
"format": "date",
|
|
44
|
+
"description": "The user's date of birth (ISO 8601, YYYY-MM-DD)."
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
//#endregion
|
|
49
|
+
//#region defaults/default-login.json
|
|
50
|
+
var default_login_default = {
|
|
51
|
+
name: "default-login",
|
|
52
|
+
status: "active",
|
|
53
|
+
user_schema: "${USER_SCHEMA_URL}",
|
|
54
|
+
purposes: {
|
|
55
|
+
"login": "identifier",
|
|
56
|
+
"register": "register"
|
|
57
|
+
},
|
|
58
|
+
steps: [
|
|
59
|
+
{
|
|
60
|
+
"name": "identifier",
|
|
61
|
+
"fields": ["email"],
|
|
62
|
+
"actions": [{
|
|
63
|
+
"name": "submit",
|
|
64
|
+
"kind": "submit",
|
|
65
|
+
"primary": true,
|
|
66
|
+
"text_key": "identifier.action.continue"
|
|
67
|
+
}, {
|
|
68
|
+
"name": "passkey",
|
|
69
|
+
"kind": "passkey",
|
|
70
|
+
"primary": false,
|
|
71
|
+
"text_key": "identifier.action.passkey"
|
|
72
|
+
}],
|
|
73
|
+
"transitions": {
|
|
74
|
+
"submit": { "target": "password" },
|
|
75
|
+
"passkey": { "target": "done" },
|
|
76
|
+
"user_not_found": { "target": "register" }
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"name": "password",
|
|
81
|
+
"fields": ["x-auth-methods#password"],
|
|
82
|
+
"actions": [{
|
|
83
|
+
"name": "submit",
|
|
84
|
+
"kind": "submit",
|
|
85
|
+
"primary": true,
|
|
86
|
+
"text_key": "password.action.signin"
|
|
87
|
+
}, {
|
|
88
|
+
"name": "passkey",
|
|
89
|
+
"kind": "passkey",
|
|
90
|
+
"primary": false,
|
|
91
|
+
"text_key": "password.action.passkey"
|
|
92
|
+
}],
|
|
93
|
+
"transitions": {
|
|
94
|
+
"submit": { "target": "done" },
|
|
95
|
+
"passkey": { "target": "done" }
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"name": "register",
|
|
100
|
+
"fields": [
|
|
101
|
+
"email",
|
|
102
|
+
"givenName",
|
|
103
|
+
"familyName",
|
|
104
|
+
"dateOfBirth"
|
|
105
|
+
],
|
|
106
|
+
"actions": [{
|
|
107
|
+
"name": "submit",
|
|
108
|
+
"kind": "submit",
|
|
109
|
+
"primary": true,
|
|
110
|
+
"text_key": "register.action.password"
|
|
111
|
+
}, {
|
|
112
|
+
"name": "passkey_register",
|
|
113
|
+
"kind": "passkey_register",
|
|
114
|
+
"primary": false,
|
|
115
|
+
"text_key": "register.action.passkey"
|
|
116
|
+
}],
|
|
117
|
+
"transitions": {
|
|
118
|
+
"submit": { "target": "register-password" },
|
|
119
|
+
"passkey_register": { "target": "done" },
|
|
120
|
+
"user_already_exists": { "target": "password" }
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"name": "register-password",
|
|
125
|
+
"fields": ["x-auth-methods#password"],
|
|
126
|
+
"actions": [{
|
|
127
|
+
"name": "submit",
|
|
128
|
+
"kind": "submit",
|
|
129
|
+
"primary": true,
|
|
130
|
+
"text_key": "register-password.action.submit"
|
|
131
|
+
}],
|
|
132
|
+
"on_success": "create_user",
|
|
133
|
+
"transitions": {
|
|
134
|
+
"submit": { "target": "done" },
|
|
135
|
+
"user_already_exists": { "target": "password" }
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
"name": "done",
|
|
140
|
+
"complete": "show"
|
|
141
|
+
}
|
|
142
|
+
]
|
|
143
|
+
};
|
|
144
|
+
//#endregion
|
|
145
|
+
//#region src/readmes.ts
|
|
146
|
+
/**
|
|
147
|
+
* README content the CLI copies to `.zitadel/schemas/README.md` during setup.
|
|
148
|
+
* Source of truth is `packages/config/defaults/README-schemas.md`; the Go
|
|
149
|
+
* server-side embed reads the same file (see `defaults.go`).
|
|
150
|
+
*/
|
|
151
|
+
function schemasReadmeContent() {
|
|
152
|
+
return readFileSync(readmeUrl("README-schemas.md"), "utf8");
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* README content the CLI copies to `.zitadel/flows/README.md` during setup.
|
|
156
|
+
* Source of truth is `packages/config/defaults/README-flows.md`.
|
|
157
|
+
*/
|
|
158
|
+
function flowsReadmeContent() {
|
|
159
|
+
return readFileSync(readmeUrl("README-flows.md"), "utf8");
|
|
160
|
+
}
|
|
161
|
+
function readmeUrl(filename) {
|
|
162
|
+
return fileURLToPath(new URL(`../defaults/${filename}`, import.meta.url));
|
|
163
|
+
}
|
|
164
|
+
//#endregion
|
|
165
|
+
//#region src/defaults.ts
|
|
166
|
+
const DEFAULT_BUILTIN_SCHEMA_BASE = "https://nextgen.com/api/schemas";
|
|
167
|
+
const DEFAULT_FLOW_SCHEMA_URI = "https://nextgen.com/flow-definition.json";
|
|
168
|
+
const DEFAULT_SCHEMA_CONFIG_PATH = ".zitadel/schemas/default-human-user.json";
|
|
169
|
+
const DEFAULT_FLOW_CONFIG_PATH = ".zitadel/flows/default-login.json";
|
|
170
|
+
function defaultHumanUserSchemaUrl(builtinSchemaBase = DEFAULT_BUILTIN_SCHEMA_BASE) {
|
|
171
|
+
return `${trimTrailingSlash(builtinSchemaBase)}/default-human-user.json`;
|
|
172
|
+
}
|
|
173
|
+
function getDefaultHumanUserSchema(options = {}) {
|
|
174
|
+
const builtinSchemaBase = trimTrailingSlash(options.builtinSchemaBase ?? "https://nextgen.com/api/schemas");
|
|
175
|
+
return renderTemplate(default_human_user_default, {
|
|
176
|
+
SERVER_URL: builtinSchemaBase,
|
|
177
|
+
USER_SCHEMA_URL: options.userSchemaUrl ?? defaultHumanUserSchemaUrl(builtinSchemaBase)
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
function getDefaultLoginFlow(options = {}) {
|
|
181
|
+
const builtinSchemaBase = trimTrailingSlash(options.builtinSchemaBase ?? "https://nextgen.com/api/schemas");
|
|
182
|
+
return renderTemplate(default_login_default, {
|
|
183
|
+
SERVER_URL: builtinSchemaBase,
|
|
184
|
+
USER_SCHEMA_URL: options.userSchemaUrl ?? defaultHumanUserSchemaUrl(builtinSchemaBase)
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
function renderTemplate(value, replacements) {
|
|
188
|
+
if (Array.isArray(value)) return value.map((item) => renderTemplate(item, replacements));
|
|
189
|
+
if (value !== null && typeof value === "object") return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, renderTemplate(item, replacements)]));
|
|
190
|
+
if (typeof value === "string") return value.replaceAll(/\$\{([A-Z_]+)\}/g, (match, name) => {
|
|
191
|
+
return replacements[name] ?? match;
|
|
192
|
+
});
|
|
193
|
+
return value;
|
|
194
|
+
}
|
|
195
|
+
function trimTrailingSlash(value) {
|
|
196
|
+
return value.replace(/\/+$/u, "");
|
|
197
|
+
}
|
|
198
|
+
//#endregion
|
|
199
|
+
export { defaultHumanUserSchemaUrl as a, flowsReadmeContent as c, DEFAULT_SCHEMA_CONFIG_PATH as i, schemasReadmeContent as l, DEFAULT_FLOW_CONFIG_PATH as n, getDefaultHumanUserSchema as o, DEFAULT_FLOW_SCHEMA_URI as r, getDefaultLoginFlow as s, DEFAULT_BUILTIN_SCHEMA_BASE as t };
|
|
200
|
+
|
|
201
|
+
//# sourceMappingURL=defaults-B2iIPSSl.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults-B2iIPSSl.mjs","names":["defaultHumanUserSchemaTemplate","defaultLoginFlowTemplate"],"sources":["../defaults/default-human-user.json","../defaults/default-login.json","../src/readmes.ts","../src/defaults.ts"],"sourcesContent":["","","import { readFileSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\n\n/**\n * README content the CLI copies to `.zitadel/schemas/README.md` during setup.\n * Source of truth is `packages/config/defaults/README-schemas.md`; the Go\n * server-side embed reads the same file (see `defaults.go`).\n */\nexport function schemasReadmeContent(): string {\n return readFileSync(readmeUrl(\"README-schemas.md\"), \"utf8\");\n}\n\n/**\n * README content the CLI copies to `.zitadel/flows/README.md` during setup.\n * Source of truth is `packages/config/defaults/README-flows.md`.\n */\nexport function flowsReadmeContent(): string {\n return readFileSync(readmeUrl(\"README-flows.md\"), \"utf8\");\n}\n\nfunction readmeUrl(filename: string): string {\n return fileURLToPath(new URL(`../defaults/${filename}`, import.meta.url));\n}\n","import type {\n CreateFlowDefinitionBodyFlowDefinition,\n CreateSchemaBody,\n} from \"@zitadel/api/generated/model\";\n\nimport defaultHumanUserSchemaTemplate from \"../defaults/default-human-user.json\" with {\n type: \"json\",\n};\nimport defaultLoginFlowTemplate from \"../defaults/default-login.json\" with {\n type: \"json\",\n};\n\nexport { flowsReadmeContent, schemasReadmeContent } from \"./readmes.js\";\n\nexport const DEFAULT_BUILTIN_SCHEMA_BASE = \"https://nextgen.com/api/schemas\";\nexport const DEFAULT_FLOW_SCHEMA_URI = \"https://nextgen.com/flow-definition.json\";\nexport const DEFAULT_SCHEMA_CONFIG_PATH = \".zitadel/schemas/default-human-user.json\";\nexport const DEFAULT_FLOW_CONFIG_PATH = \".zitadel/flows/default-login.json\";\n\nexport type DefaultConfigRenderOptions = {\n builtinSchemaBase?: string;\n userSchemaUrl?: string;\n};\n\nexport function defaultHumanUserSchemaUrl(\n builtinSchemaBase = DEFAULT_BUILTIN_SCHEMA_BASE,\n): string {\n return `${trimTrailingSlash(builtinSchemaBase)}/default-human-user.json`;\n}\n\nexport function getDefaultHumanUserSchema(\n options: DefaultConfigRenderOptions = {},\n): CreateSchemaBody {\n const builtinSchemaBase = trimTrailingSlash(\n options.builtinSchemaBase ?? DEFAULT_BUILTIN_SCHEMA_BASE,\n );\n return renderTemplate(defaultHumanUserSchemaTemplate, {\n SERVER_URL: builtinSchemaBase,\n USER_SCHEMA_URL: options.userSchemaUrl ?? defaultHumanUserSchemaUrl(builtinSchemaBase),\n }) as CreateSchemaBody;\n}\n\nexport function getDefaultLoginFlow(\n options: DefaultConfigRenderOptions = {},\n): CreateFlowDefinitionBodyFlowDefinition {\n const builtinSchemaBase = trimTrailingSlash(\n options.builtinSchemaBase ?? DEFAULT_BUILTIN_SCHEMA_BASE,\n );\n return renderTemplate(defaultLoginFlowTemplate, {\n SERVER_URL: builtinSchemaBase,\n USER_SCHEMA_URL: options.userSchemaUrl ?? defaultHumanUserSchemaUrl(builtinSchemaBase),\n }) as CreateFlowDefinitionBodyFlowDefinition;\n}\n\nfunction renderTemplate(value: unknown, replacements: Record<string, string>): unknown {\n if (Array.isArray(value)) {\n return value.map((item) => renderTemplate(item, replacements));\n }\n if (value !== null && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value).map(([key, item]) => [key, renderTemplate(item, replacements)]),\n );\n }\n if (typeof value === \"string\") {\n return value.replaceAll(/\\$\\{([A-Z_]+)\\}/g, (match, name: string) => {\n return replacements[name] ?? match;\n });\n }\n return value;\n}\n\nfunction trimTrailingSlash(value: string): string {\n return value.replace(/\\/+$/u, \"\");\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AEQA,SAAgB,uBAA+B;AAC7C,QAAO,aAAa,UAAU,oBAAoB,EAAE,OAAO;;;;;;AAO7D,SAAgB,qBAA6B;AAC3C,QAAO,aAAa,UAAU,kBAAkB,EAAE,OAAO;;AAG3D,SAAS,UAAU,UAA0B;AAC3C,QAAO,cAAc,IAAI,IAAI,eAAe,YAAY,OAAO,KAAK,IAAI,CAAC;;;;ACP3E,MAAa,8BAA8B;AAC3C,MAAa,0BAA0B;AACvC,MAAa,6BAA6B;AAC1C,MAAa,2BAA2B;AAOxC,SAAgB,0BACd,oBAAoB,6BACZ;AACR,QAAO,GAAG,kBAAkB,kBAAkB,CAAC;;AAGjD,SAAgB,0BACd,UAAsC,EAAE,EACtB;CAClB,MAAM,oBAAoB,kBACxB,QAAQ,qBAAA,kCACT;AACD,QAAO,eAAeA,4BAAgC;EACpD,YAAY;EACZ,iBAAiB,QAAQ,iBAAiB,0BAA0B,kBAAkB;EACvF,CAAC;;AAGJ,SAAgB,oBACd,UAAsC,EAAE,EACA;CACxC,MAAM,oBAAoB,kBACxB,QAAQ,qBAAA,kCACT;AACD,QAAO,eAAeC,uBAA0B;EAC9C,YAAY;EACZ,iBAAiB,QAAQ,iBAAiB,0BAA0B,kBAAkB;EACvF,CAAC;;AAGJ,SAAS,eAAe,OAAgB,cAA+C;AACrF,KAAI,MAAM,QAAQ,MAAM,CACtB,QAAO,MAAM,KAAK,SAAS,eAAe,MAAM,aAAa,CAAC;AAEhE,KAAI,UAAU,QAAQ,OAAO,UAAU,SACrC,QAAO,OAAO,YACZ,OAAO,QAAQ,MAAM,CAAC,KAAK,CAAC,KAAK,UAAU,CAAC,KAAK,eAAe,MAAM,aAAa,CAAC,CAAC,CACtF;AAEH,KAAI,OAAO,UAAU,SACnB,QAAO,MAAM,WAAW,qBAAqB,OAAO,SAAiB;AACnE,SAAO,aAAa,SAAS;GAC7B;AAEJ,QAAO;;AAGT,SAAS,kBAAkB,OAAuB;AAChD,QAAO,MAAM,QAAQ,SAAS,GAAG"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { CreateFlowDefinitionBodyFlowDefinition, CreateSchemaBody } from "@zitadel/api/generated/model";
|
|
2
|
+
|
|
3
|
+
//#region src/readmes.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* README content the CLI copies to `.zitadel/schemas/README.md` during setup.
|
|
6
|
+
* Source of truth is `packages/config/defaults/README-schemas.md`; the Go
|
|
7
|
+
* server-side embed reads the same file (see `defaults.go`).
|
|
8
|
+
*/
|
|
9
|
+
declare function schemasReadmeContent(): string;
|
|
10
|
+
/**
|
|
11
|
+
* README content the CLI copies to `.zitadel/flows/README.md` during setup.
|
|
12
|
+
* Source of truth is `packages/config/defaults/README-flows.md`.
|
|
13
|
+
*/
|
|
14
|
+
declare function flowsReadmeContent(): string;
|
|
15
|
+
//#endregion
|
|
16
|
+
//#region src/defaults.d.ts
|
|
17
|
+
declare const DEFAULT_BUILTIN_SCHEMA_BASE = "https://nextgen.com/api/schemas";
|
|
18
|
+
declare const DEFAULT_FLOW_SCHEMA_URI = "https://nextgen.com/flow-definition.json";
|
|
19
|
+
declare const DEFAULT_SCHEMA_CONFIG_PATH = ".zitadel/schemas/default-human-user.json";
|
|
20
|
+
declare const DEFAULT_FLOW_CONFIG_PATH = ".zitadel/flows/default-login.json";
|
|
21
|
+
type DefaultConfigRenderOptions = {
|
|
22
|
+
builtinSchemaBase?: string;
|
|
23
|
+
userSchemaUrl?: string;
|
|
24
|
+
};
|
|
25
|
+
declare function defaultHumanUserSchemaUrl(builtinSchemaBase?: string): string;
|
|
26
|
+
declare function getDefaultHumanUserSchema(options?: DefaultConfigRenderOptions): CreateSchemaBody;
|
|
27
|
+
declare function getDefaultLoginFlow(options?: DefaultConfigRenderOptions): CreateFlowDefinitionBodyFlowDefinition;
|
|
28
|
+
//#endregion
|
|
29
|
+
export { DefaultConfigRenderOptions as a, getDefaultLoginFlow as c, DEFAULT_SCHEMA_CONFIG_PATH as i, flowsReadmeContent as l, DEFAULT_FLOW_CONFIG_PATH as n, defaultHumanUserSchemaUrl as o, DEFAULT_FLOW_SCHEMA_URI as r, getDefaultHumanUserSchema as s, DEFAULT_BUILTIN_SCHEMA_BASE as t, schemasReadmeContent as u };
|
|
30
|
+
//# sourceMappingURL=defaults-DzfOT2_7.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults-DzfOT2_7.d.mts","names":[],"sources":["../src/readmes.ts","../src/defaults.ts"],"mappings":";;;;;;AAQA;;iBAAgB,oBAAA,CAAA;;;AAQhB;;iBAAgB,kBAAA,CAAA;;;cCFH,2BAAA;AAAA,cACA,uBAAA;AAAA,cACA,0BAAA;AAAA,cACA,wBAAA;AAAA,KAED,0BAAA;EACV,iBAAA;EACA,aAAA;AAAA;AAAA,iBAGc,yBAAA,CACd,iBAAA;AAAA,iBAKc,yBAAA,CACd,OAAA,GAAS,0BAAA,GACR,gBAAA;AAAA,iBAUa,mBAAA,CACd,OAAA,GAAS,0BAAA,GACR,sCAAA"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as DefaultConfigRenderOptions, c as getDefaultLoginFlow, i as DEFAULT_SCHEMA_CONFIG_PATH, l as flowsReadmeContent, n as DEFAULT_FLOW_CONFIG_PATH, o as defaultHumanUserSchemaUrl, r as DEFAULT_FLOW_SCHEMA_URI, s as getDefaultHumanUserSchema, t as DEFAULT_BUILTIN_SCHEMA_BASE, u as schemasReadmeContent } from "./defaults-DzfOT2_7.mjs";
|
|
2
|
+
export { DEFAULT_BUILTIN_SCHEMA_BASE, DEFAULT_FLOW_CONFIG_PATH, DEFAULT_FLOW_SCHEMA_URI, DEFAULT_SCHEMA_CONFIG_PATH, DefaultConfigRenderOptions, defaultHumanUserSchemaUrl, flowsReadmeContent, getDefaultHumanUserSchema, getDefaultLoginFlow, schemasReadmeContent };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as defaultHumanUserSchemaUrl, c as flowsReadmeContent, i as DEFAULT_SCHEMA_CONFIG_PATH, l as schemasReadmeContent, n as DEFAULT_FLOW_CONFIG_PATH, o as getDefaultHumanUserSchema, r as DEFAULT_FLOW_SCHEMA_URI, s as getDefaultLoginFlow, t as DEFAULT_BUILTIN_SCHEMA_BASE } from "./defaults-B2iIPSSl.mjs";
|
|
2
|
+
export { DEFAULT_BUILTIN_SCHEMA_BASE, DEFAULT_FLOW_CONFIG_PATH, DEFAULT_FLOW_SCHEMA_URI, DEFAULT_SCHEMA_CONFIG_PATH, defaultHumanUserSchemaUrl, flowsReadmeContent, getDefaultHumanUserSchema, getDefaultLoginFlow, schemasReadmeContent };
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { a as DefaultConfigRenderOptions, c as getDefaultLoginFlow, i as DEFAULT_SCHEMA_CONFIG_PATH, l as flowsReadmeContent, n as DEFAULT_FLOW_CONFIG_PATH, o as defaultHumanUserSchemaUrl, r as DEFAULT_FLOW_SCHEMA_URI, s as getDefaultHumanUserSchema, t as DEFAULT_BUILTIN_SCHEMA_BASE, u as schemasReadmeContent } from "./defaults-DzfOT2_7.mjs";
|
|
2
|
+
import { USER_PROPERTY_DEFAULTS, normalizeFlowBody, normalizeSchemaBody } from "./normalize.mjs";
|
|
3
|
+
import { createFlowDefinitionRequestSchema, flowConfigSchema, schemaConfigSchema } from "./schemas.mjs";
|
|
4
|
+
export { DEFAULT_BUILTIN_SCHEMA_BASE, DEFAULT_FLOW_CONFIG_PATH, DEFAULT_FLOW_SCHEMA_URI, DEFAULT_SCHEMA_CONFIG_PATH, DefaultConfigRenderOptions, USER_PROPERTY_DEFAULTS, createFlowDefinitionRequestSchema, defaultHumanUserSchemaUrl, flowConfigSchema, flowsReadmeContent, getDefaultHumanUserSchema, getDefaultLoginFlow, normalizeFlowBody, normalizeSchemaBody, schemaConfigSchema, schemasReadmeContent };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { a as defaultHumanUserSchemaUrl, c as flowsReadmeContent, i as DEFAULT_SCHEMA_CONFIG_PATH, l as schemasReadmeContent, n as DEFAULT_FLOW_CONFIG_PATH, o as getDefaultHumanUserSchema, r as DEFAULT_FLOW_SCHEMA_URI, s as getDefaultLoginFlow, t as DEFAULT_BUILTIN_SCHEMA_BASE } from "./defaults-B2iIPSSl.mjs";
|
|
2
|
+
import { USER_PROPERTY_DEFAULTS, normalizeFlowBody, normalizeSchemaBody } from "./normalize.mjs";
|
|
3
|
+
import { createFlowDefinitionRequestSchema, flowConfigSchema, schemaConfigSchema } from "./schemas.mjs";
|
|
4
|
+
export { DEFAULT_BUILTIN_SCHEMA_BASE, DEFAULT_FLOW_CONFIG_PATH, DEFAULT_FLOW_SCHEMA_URI, DEFAULT_SCHEMA_CONFIG_PATH, USER_PROPERTY_DEFAULTS, createFlowDefinitionRequestSchema, defaultHumanUserSchemaUrl, flowConfigSchema, flowsReadmeContent, getDefaultHumanUserSchema, getDefaultLoginFlow, normalizeFlowBody, normalizeSchemaBody, schemaConfigSchema, schemasReadmeContent };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
//#region src/normalize.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Canonical-form normalizers for the two repo-config resource kinds.
|
|
4
|
+
*
|
|
5
|
+
* The sync engine compares `.zitadel/**` files against server responses;
|
|
6
|
+
* the server echoes fields the author never wrote (an empty `audience`
|
|
7
|
+
* on flows) and the meta-schema declares defaults an author may or may
|
|
8
|
+
* not spell out (`x-editable` et al on schema properties). Normalizing
|
|
9
|
+
* both sides before hashing or diffing keeps a one-field edit rendering
|
|
10
|
+
* as a one-field diff.
|
|
11
|
+
*
|
|
12
|
+
* Normalized bodies are for COMPARISON. Never upload them, and never
|
|
13
|
+
* write a normalized schema body to a file: the server stores schema
|
|
14
|
+
* bytes verbatim without materializing meta-schema defaults, so a
|
|
15
|
+
* stripped `"x-editable": true` would vanish from the next published
|
|
16
|
+
* revision. (Flow write-back may reuse {@link normalizeFlowBody} —
|
|
17
|
+
* everything it strips is pure transport noise.)
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Property-level defaults declared by the user-property meta-schema
|
|
21
|
+
* (`api/openapi/endpoints/schemas/user-property.json`). A property that
|
|
22
|
+
* spells one of these out is semantically identical to one that omits it.
|
|
23
|
+
*/
|
|
24
|
+
declare const USER_PROPERTY_DEFAULTS: Readonly<Record<string, boolean>>;
|
|
25
|
+
/**
|
|
26
|
+
* Return a deep copy of a bare flow-definition body with server-echoed
|
|
27
|
+
* noise removed: an empty `audience` and any detail-envelope keys.
|
|
28
|
+
*/
|
|
29
|
+
declare function normalizeFlowBody(body: object): object;
|
|
30
|
+
/**
|
|
31
|
+
* Return a deep copy of a user-schema body with meta-schema property
|
|
32
|
+
* defaults stripped: a property carrying `"x-editable": true` (or the
|
|
33
|
+
* other {@link USER_PROPERTY_DEFAULTS}) normalizes to one omitting it.
|
|
34
|
+
* Only exact default values are removed; `$id` and every other field
|
|
35
|
+
* pass through untouched.
|
|
36
|
+
*/
|
|
37
|
+
declare function normalizeSchemaBody(body: object): object;
|
|
38
|
+
//#endregion
|
|
39
|
+
export { USER_PROPERTY_DEFAULTS, normalizeFlowBody, normalizeSchemaBody };
|
|
40
|
+
//# sourceMappingURL=normalize.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.d.mts","names":[],"sources":["../src/normalize.ts"],"mappings":";;AAuBA;;;;;AAqCA;;;;;AAkBA;;;;;;;;;;;cAvDa,sBAAA,EAAwB,QAAA,CAAS,MAAA;;;;;iBAqC9B,iBAAA,CAAkB,IAAA;;;;;;;;iBAkBlB,mBAAA,CAAoB,IAAA"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
//#region src/normalize.ts
|
|
2
|
+
/**
|
|
3
|
+
* Canonical-form normalizers for the two repo-config resource kinds.
|
|
4
|
+
*
|
|
5
|
+
* The sync engine compares `.zitadel/**` files against server responses;
|
|
6
|
+
* the server echoes fields the author never wrote (an empty `audience`
|
|
7
|
+
* on flows) and the meta-schema declares defaults an author may or may
|
|
8
|
+
* not spell out (`x-editable` et al on schema properties). Normalizing
|
|
9
|
+
* both sides before hashing or diffing keeps a one-field edit rendering
|
|
10
|
+
* as a one-field diff.
|
|
11
|
+
*
|
|
12
|
+
* Normalized bodies are for COMPARISON. Never upload them, and never
|
|
13
|
+
* write a normalized schema body to a file: the server stores schema
|
|
14
|
+
* bytes verbatim without materializing meta-schema defaults, so a
|
|
15
|
+
* stripped `"x-editable": true` would vanish from the next published
|
|
16
|
+
* revision. (Flow write-back may reuse {@link normalizeFlowBody} —
|
|
17
|
+
* everything it strips is pure transport noise.)
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Property-level defaults declared by the user-property meta-schema
|
|
21
|
+
* (`api/openapi/endpoints/schemas/user-property.json`). A property that
|
|
22
|
+
* spells one of these out is semantically identical to one that omits it.
|
|
23
|
+
*/
|
|
24
|
+
const USER_PROPERTY_DEFAULTS = {
|
|
25
|
+
"x-editable": true,
|
|
26
|
+
"x-sensitive": false,
|
|
27
|
+
"x-mfa": false
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Keys of the flow-definition detail envelope. `fetch` in the flow syncer
|
|
31
|
+
* already unwraps the envelope; stripping them here as well makes the
|
|
32
|
+
* normalizer safe on raw detail responses.
|
|
33
|
+
*/
|
|
34
|
+
const FLOW_ENVELOPE_KEYS = [
|
|
35
|
+
"id",
|
|
36
|
+
"project_id",
|
|
37
|
+
"schema_uri",
|
|
38
|
+
"created_at",
|
|
39
|
+
"updated_at"
|
|
40
|
+
];
|
|
41
|
+
function isPlainObject(value) {
|
|
42
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* An `audience` counts as empty when it scopes nothing: no keys, or only
|
|
46
|
+
* `team_ids`/`app_ids` that are null or empty arrays. Unknown keys keep
|
|
47
|
+
* the audience — better a noisy diff than a silently dropped scope.
|
|
48
|
+
*/
|
|
49
|
+
function isEmptyAudience(value) {
|
|
50
|
+
if (!isPlainObject(value)) return false;
|
|
51
|
+
return Object.entries(value).every(([key, entry]) => (key === "team_ids" || key === "app_ids") && (entry === null || entry === void 0 || Array.isArray(entry) && entry.length === 0));
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Return a deep copy of a bare flow-definition body with server-echoed
|
|
55
|
+
* noise removed: an empty `audience` and any detail-envelope keys.
|
|
56
|
+
*/
|
|
57
|
+
function normalizeFlowBody(body) {
|
|
58
|
+
const result = structuredClone(body);
|
|
59
|
+
for (const key of FLOW_ENVELOPE_KEYS) delete result[key];
|
|
60
|
+
if ("audience" in result && isEmptyAudience(result.audience)) delete result.audience;
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Return a deep copy of a user-schema body with meta-schema property
|
|
65
|
+
* defaults stripped: a property carrying `"x-editable": true` (or the
|
|
66
|
+
* other {@link USER_PROPERTY_DEFAULTS}) normalizes to one omitting it.
|
|
67
|
+
* Only exact default values are removed; `$id` and every other field
|
|
68
|
+
* pass through untouched.
|
|
69
|
+
*/
|
|
70
|
+
function normalizeSchemaBody(body) {
|
|
71
|
+
const result = structuredClone(body);
|
|
72
|
+
if (!isPlainObject(result.properties)) return result;
|
|
73
|
+
for (const property of Object.values(result.properties)) {
|
|
74
|
+
if (!isPlainObject(property)) continue;
|
|
75
|
+
for (const [key, defaultValue] of Object.entries(USER_PROPERTY_DEFAULTS)) if (property[key] === defaultValue) delete property[key];
|
|
76
|
+
}
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
//#endregion
|
|
80
|
+
export { USER_PROPERTY_DEFAULTS, normalizeFlowBody, normalizeSchemaBody };
|
|
81
|
+
|
|
82
|
+
//# sourceMappingURL=normalize.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.mjs","names":[],"sources":["../src/normalize.ts"],"sourcesContent":["/**\n * Canonical-form normalizers for the two repo-config resource kinds.\n *\n * The sync engine compares `.zitadel/**` files against server responses;\n * the server echoes fields the author never wrote (an empty `audience`\n * on flows) and the meta-schema declares defaults an author may or may\n * not spell out (`x-editable` et al on schema properties). Normalizing\n * both sides before hashing or diffing keeps a one-field edit rendering\n * as a one-field diff.\n *\n * Normalized bodies are for COMPARISON. Never upload them, and never\n * write a normalized schema body to a file: the server stores schema\n * bytes verbatim without materializing meta-schema defaults, so a\n * stripped `\"x-editable\": true` would vanish from the next published\n * revision. (Flow write-back may reuse {@link normalizeFlowBody} —\n * everything it strips is pure transport noise.)\n */\n\n/**\n * Property-level defaults declared by the user-property meta-schema\n * (`api/openapi/endpoints/schemas/user-property.json`). A property that\n * spells one of these out is semantically identical to one that omits it.\n */\nexport const USER_PROPERTY_DEFAULTS: Readonly<Record<string, boolean>> = {\n \"x-editable\": true,\n \"x-sensitive\": false,\n \"x-mfa\": false,\n};\n\n/**\n * Keys of the flow-definition detail envelope. `fetch` in the flow syncer\n * already unwraps the envelope; stripping them here as well makes the\n * normalizer safe on raw detail responses.\n */\nconst FLOW_ENVELOPE_KEYS = [\"id\", \"project_id\", \"schema_uri\", \"created_at\", \"updated_at\"];\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * An `audience` counts as empty when it scopes nothing: no keys, or only\n * `team_ids`/`app_ids` that are null or empty arrays. Unknown keys keep\n * the audience — better a noisy diff than a silently dropped scope.\n */\nfunction isEmptyAudience(value: unknown): boolean {\n if (!isPlainObject(value)) {\n return false;\n }\n return Object.entries(value).every(\n ([key, entry]) =>\n (key === \"team_ids\" || key === \"app_ids\") &&\n (entry === null || entry === undefined || (Array.isArray(entry) && entry.length === 0)),\n );\n}\n\n/**\n * Return a deep copy of a bare flow-definition body with server-echoed\n * noise removed: an empty `audience` and any detail-envelope keys.\n */\nexport function normalizeFlowBody(body: object): object {\n const result = structuredClone(body) as Record<string, unknown>;\n for (const key of FLOW_ENVELOPE_KEYS) {\n delete result[key];\n }\n if (\"audience\" in result && isEmptyAudience(result.audience)) {\n delete result.audience;\n }\n return result;\n}\n\n/**\n * Return a deep copy of a user-schema body with meta-schema property\n * defaults stripped: a property carrying `\"x-editable\": true` (or the\n * other {@link USER_PROPERTY_DEFAULTS}) normalizes to one omitting it.\n * Only exact default values are removed; `$id` and every other field\n * pass through untouched.\n */\nexport function normalizeSchemaBody(body: object): object {\n const result = structuredClone(body) as Record<string, unknown>;\n if (!isPlainObject(result.properties)) {\n return result;\n }\n for (const property of Object.values(result.properties)) {\n if (!isPlainObject(property)) {\n continue;\n }\n for (const [key, defaultValue] of Object.entries(USER_PROPERTY_DEFAULTS)) {\n if (property[key] === defaultValue) {\n delete property[key];\n }\n }\n }\n return result;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAuBA,MAAa,yBAA4D;CACvE,cAAc;CACd,eAAe;CACf,SAAS;CACV;;;;;;AAOD,MAAM,qBAAqB;CAAC;CAAM;CAAc;CAAc;CAAc;CAAa;AAEzF,SAAS,cAAc,OAAkD;AACvE,QAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM;;;;;;;AAQ7E,SAAS,gBAAgB,OAAyB;AAChD,KAAI,CAAC,cAAc,MAAM,CACvB,QAAO;AAET,QAAO,OAAO,QAAQ,MAAM,CAAC,OAC1B,CAAC,KAAK,YACJ,QAAQ,cAAc,QAAQ,eAC9B,UAAU,QAAQ,UAAU,KAAA,KAAc,MAAM,QAAQ,MAAM,IAAI,MAAM,WAAW,GACvF;;;;;;AAOH,SAAgB,kBAAkB,MAAsB;CACtD,MAAM,SAAS,gBAAgB,KAAK;AACpC,MAAK,MAAM,OAAO,mBAChB,QAAO,OAAO;AAEhB,KAAI,cAAc,UAAU,gBAAgB,OAAO,SAAS,CAC1D,QAAO,OAAO;AAEhB,QAAO;;;;;;;;;AAUT,SAAgB,oBAAoB,MAAsB;CACxD,MAAM,SAAS,gBAAgB,KAAK;AACpC,KAAI,CAAC,cAAc,OAAO,WAAW,CACnC,QAAO;AAET,MAAK,MAAM,YAAY,OAAO,OAAO,OAAO,WAAW,EAAE;AACvD,MAAI,CAAC,cAAc,SAAS,CAC1B;AAEF,OAAK,MAAM,CAAC,KAAK,iBAAiB,OAAO,QAAQ,uBAAuB,CACtE,KAAI,SAAS,SAAS,aACpB,QAAO,SAAS;;AAItB,QAAO"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
//#region src/schemas.d.ts
|
|
2
|
+
declare const schemaConfigSchema: any;
|
|
3
|
+
declare const flowConfigSchema: any;
|
|
4
|
+
declare const createFlowDefinitionRequestSchema: any;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { createFlowDefinitionRequestSchema, flowConfigSchema, schemaConfigSchema };
|
|
7
|
+
//# sourceMappingURL=schemas.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.d.mts","names":[],"sources":["../src/schemas.ts"],"mappings":";cAKa,kBAAA;AAAA,cACA,gBAAA;AAAA,cACA,iCAAA"}
|
package/dist/schemas.mjs
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { CreateFlowDefinitionBody, CreateSchemaBody } from "@zitadel/api/generated/endpoints/zitadelNextGen.zod";
|
|
2
|
+
//#region src/schemas.ts
|
|
3
|
+
const schemaConfigSchema = CreateSchemaBody;
|
|
4
|
+
const flowConfigSchema = CreateFlowDefinitionBody.shape.flow_definition;
|
|
5
|
+
const createFlowDefinitionRequestSchema = CreateFlowDefinitionBody;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { createFlowDefinitionRequestSchema, flowConfigSchema, schemaConfigSchema };
|
|
8
|
+
|
|
9
|
+
//# sourceMappingURL=schemas.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.mjs","names":[],"sources":["../src/schemas.ts"],"sourcesContent":["import {\n CreateFlowDefinitionBody,\n CreateSchemaBody,\n} from \"@zitadel/api/generated/endpoints/zitadelNextGen.zod\";\n\nexport const schemaConfigSchema = CreateSchemaBody;\nexport const flowConfigSchema = CreateFlowDefinitionBody.shape.flow_definition;\nexport const createFlowDefinitionRequestSchema = CreateFlowDefinitionBody;\n"],"mappings":";;AAKA,MAAa,qBAAqB;AAClC,MAAa,mBAAmB,yBAAyB,MAAM;AAC/D,MAAa,oCAAoC"}
|
package/package.json
CHANGED
|
@@ -1,10 +1,64 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zitadel/config",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.0-alpha.15",
|
|
4
|
+
"description": "Versioned Zitadel local config schemas and defaults",
|
|
5
|
+
"homepage": "https://github.com/zitadel/nextgen/tree/main/packages/config#readme",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/zitadel/nextgen/issues"
|
|
8
|
+
},
|
|
5
9
|
"license": "MIT",
|
|
6
|
-
"
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/zitadel/nextgen.git",
|
|
13
|
+
"directory": "packages/config"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"defaults/*.json",
|
|
18
|
+
"defaults/*.md",
|
|
19
|
+
"LICENSE"
|
|
20
|
+
],
|
|
21
|
+
"type": "module",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"@zitadel/source": "./src/index.ts",
|
|
25
|
+
"types": "./dist/index.d.mts",
|
|
26
|
+
"import": "./dist/index.mjs"
|
|
27
|
+
},
|
|
28
|
+
"./defaults": {
|
|
29
|
+
"@zitadel/source": "./src/defaults.ts",
|
|
30
|
+
"types": "./dist/defaults.d.mts",
|
|
31
|
+
"import": "./dist/defaults.mjs"
|
|
32
|
+
},
|
|
33
|
+
"./schemas": {
|
|
34
|
+
"@zitadel/source": "./src/schemas.ts",
|
|
35
|
+
"types": "./dist/schemas.d.mts",
|
|
36
|
+
"import": "./dist/schemas.mjs"
|
|
37
|
+
},
|
|
38
|
+
"./normalize": {
|
|
39
|
+
"@zitadel/source": "./src/normalize.ts",
|
|
40
|
+
"types": "./dist/normalize.d.mts",
|
|
41
|
+
"import": "./dist/normalize.mjs"
|
|
42
|
+
},
|
|
43
|
+
"./defaults/default-human-user.json": "./defaults/default-human-user.json",
|
|
44
|
+
"./defaults/default-login.json": "./defaults/default-login.json",
|
|
45
|
+
"./package.json": "./package.json"
|
|
46
|
+
},
|
|
7
47
|
"publishConfig": {
|
|
8
48
|
"access": "public"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@zitadel/api": "0.1.0-alpha.15"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"tsdown": "^0.21.10",
|
|
55
|
+
"tslib": "^2.8.1",
|
|
56
|
+
"vitest": "^4.1.7"
|
|
57
|
+
},
|
|
58
|
+
"scripts": {
|
|
59
|
+
"build": "tsdown",
|
|
60
|
+
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
61
|
+
"test": "vitest run --passWithNoTests",
|
|
62
|
+
"lint": "oxlint ."
|
|
9
63
|
}
|
|
10
|
-
}
|
|
64
|
+
}
|
package/README.md
DELETED