@tailor-platform/sdk 1.35.2 → 1.36.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.
Files changed (40) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/application-BB5TqXWY.mjs +4 -0
  3. package/dist/{application-BnJRroGX.mjs → application-BwboBFcU.mjs} +102 -17
  4. package/dist/application-BwboBFcU.mjs.map +1 -0
  5. package/dist/cli/index.mjs +241 -6
  6. package/dist/cli/index.mjs.map +1 -1
  7. package/dist/cli/lib.d.mts +190 -6
  8. package/dist/cli/lib.mjs +3 -3
  9. package/dist/{client-BmQP4kKS.mjs → client-B6icVEv4.mjs} +1 -1
  10. package/dist/{client-CA2NM_4R.mjs → client-CN15WgW2.mjs} +25 -8
  11. package/dist/client-CN15WgW2.mjs.map +1 -0
  12. package/dist/configure/index.d.mts +5 -4
  13. package/dist/configure/index.mjs +38 -9
  14. package/dist/configure/index.mjs.map +1 -1
  15. package/dist/{crash-report-Bd2T8BhU.mjs → crash-report-CB1UtT3O.mjs} +1 -1
  16. package/dist/{crash-report-CPkI2-cp.mjs → crash-report-CdxPj_SW.mjs} +2 -2
  17. package/dist/{crash-report-CPkI2-cp.mjs.map → crash-report-CdxPj_SW.mjs.map} +1 -1
  18. package/dist/env-_ce3IYbl.d.mts +30 -0
  19. package/dist/{index-DTJkkO-t.d.mts → index-C7vIBAg8.d.mts} +2 -2
  20. package/dist/{index--9iVDOXn.d.mts → index-CYaunQeL.d.mts} +76 -5
  21. package/dist/{index-qVqjEYnr.d.mts → index-CxSLivW7.d.mts} +2 -2
  22. package/dist/{index-D4pBPp65.d.mts → index-DDCyefuU.d.mts} +2 -2
  23. package/dist/{index-niQ9Qblw.d.mts → index-DZN1QFLM.d.mts} +2 -2
  24. package/dist/plugin/builtin/enum-constants/index.d.mts +1 -1
  25. package/dist/plugin/builtin/file-utils/index.d.mts +1 -1
  26. package/dist/plugin/builtin/kysely-type/index.d.mts +1 -1
  27. package/dist/plugin/builtin/seed/index.d.mts +1 -1
  28. package/dist/plugin/index.d.mts +2 -1
  29. package/dist/{plugin-D8hKE6rZ.d.mts → plugin-CiPUxkyN.d.mts} +4 -28
  30. package/dist/{runtime-D4O-RfcH.mjs → runtime-C7RRDaB3.mjs} +230 -22
  31. package/dist/runtime-C7RRDaB3.mjs.map +1 -0
  32. package/dist/utils/test/index.d.mts +2 -2
  33. package/dist/{workflow.generated-DMt8PNVd.d.mts → workflow.generated-8BeGQsVU.d.mts} +212 -4
  34. package/docs/services/idp.md +50 -0
  35. package/docs/services/secret.md +25 -0
  36. package/package.json +4 -3
  37. package/dist/application-BnJRroGX.mjs.map +0 -1
  38. package/dist/application-mGasp_EX.mjs +0 -4
  39. package/dist/client-CA2NM_4R.mjs.map +0 -1
  40. package/dist/runtime-D4O-RfcH.mjs.map +0 -1
@@ -1,6 +1,6 @@
1
1
  /// <reference types="@tailor-platform/function-types" />
2
- import { U as TailorDBType, rt as TailorField } from "../../plugin-D8hKE6rZ.mjs";
3
- import { et as WORKFLOW_TEST_ENV_KEY, n as output } from "../../index--9iVDOXn.mjs";
2
+ import { U as TailorDBType, rt as TailorField } from "../../plugin-CiPUxkyN.mjs";
3
+ import { n as output, rt as WORKFLOW_TEST_ENV_KEY } from "../../index-CYaunQeL.mjs";
4
4
  import { StandardSchemaV1 } from "@standard-schema/spec";
5
5
 
6
6
  //#region src/utils/test/mock.d.ts
@@ -1,5 +1,5 @@
1
1
  /// <reference types="@tailor-platform/function-types" />
2
- import { Pt as BuiltinIdP, S as TailorDBServiceInput, T as AuthConfig } from "./plugin-D8hKE6rZ.mjs";
2
+ import { Nt as BuiltinIdP, S as TailorDBServiceInput, T as AuthConfig } from "./plugin-CiPUxkyN.mjs";
3
3
 
4
4
  //#region src/types/idp.generated.d.ts
5
5
  /**
@@ -59,6 +59,193 @@ type IdPInput = {
59
59
  emailConfig?: {
60
60
  fromName?: string | undefined;
61
61
  passwordResetSubject?: string | undefined;
62
+ } | undefined; /** Per-operation permission policies for IdP users */
63
+ permission?: {
64
+ create: readonly (readonly (string | boolean | readonly string[] | readonly boolean[] | {
65
+ user: string;
66
+ } | {
67
+ idpUser: "name" | "id" | "disabled";
68
+ } | {
69
+ oldIdpUser: "name" | "id" | "disabled";
70
+ } | {
71
+ newIdpUser: "name" | "id" | "disabled";
72
+ })[] | readonly (boolean | readonly (string | boolean | readonly string[] | readonly boolean[] | {
73
+ user: string;
74
+ } | {
75
+ idpUser: "name" | "id" | "disabled";
76
+ } | {
77
+ oldIdpUser: "name" | "id" | "disabled";
78
+ } | {
79
+ newIdpUser: "name" | "id" | "disabled";
80
+ })[])[] | {
81
+ conditions: readonly (string | boolean | readonly string[] | readonly boolean[] | {
82
+ user: string;
83
+ } | {
84
+ idpUser: "name" | "id" | "disabled";
85
+ } | {
86
+ oldIdpUser: "name" | "id" | "disabled";
87
+ } | {
88
+ newIdpUser: "name" | "id" | "disabled";
89
+ })[] | readonly (readonly (string | boolean | readonly string[] | readonly boolean[] | {
90
+ user: string;
91
+ } | {
92
+ idpUser: "name" | "id" | "disabled";
93
+ } | {
94
+ oldIdpUser: "name" | "id" | "disabled";
95
+ } | {
96
+ newIdpUser: "name" | "id" | "disabled";
97
+ })[])[];
98
+ description?: string | undefined;
99
+ permit?: boolean | undefined;
100
+ })[];
101
+ read: readonly (readonly (string | boolean | readonly string[] | readonly boolean[] | {
102
+ user: string;
103
+ } | {
104
+ idpUser: "name" | "id" | "disabled";
105
+ } | {
106
+ oldIdpUser: "name" | "id" | "disabled";
107
+ } | {
108
+ newIdpUser: "name" | "id" | "disabled";
109
+ })[] | readonly (boolean | readonly (string | boolean | readonly string[] | readonly boolean[] | {
110
+ user: string;
111
+ } | {
112
+ idpUser: "name" | "id" | "disabled";
113
+ } | {
114
+ oldIdpUser: "name" | "id" | "disabled";
115
+ } | {
116
+ newIdpUser: "name" | "id" | "disabled";
117
+ })[])[] | {
118
+ conditions: readonly (string | boolean | readonly string[] | readonly boolean[] | {
119
+ user: string;
120
+ } | {
121
+ idpUser: "name" | "id" | "disabled";
122
+ } | {
123
+ oldIdpUser: "name" | "id" | "disabled";
124
+ } | {
125
+ newIdpUser: "name" | "id" | "disabled";
126
+ })[] | readonly (readonly (string | boolean | readonly string[] | readonly boolean[] | {
127
+ user: string;
128
+ } | {
129
+ idpUser: "name" | "id" | "disabled";
130
+ } | {
131
+ oldIdpUser: "name" | "id" | "disabled";
132
+ } | {
133
+ newIdpUser: "name" | "id" | "disabled";
134
+ })[])[];
135
+ description?: string | undefined;
136
+ permit?: boolean | undefined;
137
+ })[];
138
+ update: readonly (readonly (string | boolean | readonly string[] | readonly boolean[] | {
139
+ user: string;
140
+ } | {
141
+ idpUser: "name" | "id" | "disabled";
142
+ } | {
143
+ oldIdpUser: "name" | "id" | "disabled";
144
+ } | {
145
+ newIdpUser: "name" | "id" | "disabled";
146
+ })[] | readonly (boolean | readonly (string | boolean | readonly string[] | readonly boolean[] | {
147
+ user: string;
148
+ } | {
149
+ idpUser: "name" | "id" | "disabled";
150
+ } | {
151
+ oldIdpUser: "name" | "id" | "disabled";
152
+ } | {
153
+ newIdpUser: "name" | "id" | "disabled";
154
+ })[])[] | {
155
+ conditions: readonly (string | boolean | readonly string[] | readonly boolean[] | {
156
+ user: string;
157
+ } | {
158
+ idpUser: "name" | "id" | "disabled";
159
+ } | {
160
+ oldIdpUser: "name" | "id" | "disabled";
161
+ } | {
162
+ newIdpUser: "name" | "id" | "disabled";
163
+ })[] | readonly (readonly (string | boolean | readonly string[] | readonly boolean[] | {
164
+ user: string;
165
+ } | {
166
+ idpUser: "name" | "id" | "disabled";
167
+ } | {
168
+ oldIdpUser: "name" | "id" | "disabled";
169
+ } | {
170
+ newIdpUser: "name" | "id" | "disabled";
171
+ })[])[];
172
+ description?: string | undefined;
173
+ permit?: boolean | undefined;
174
+ })[];
175
+ delete: readonly (readonly (string | boolean | readonly string[] | readonly boolean[] | {
176
+ user: string;
177
+ } | {
178
+ idpUser: "name" | "id" | "disabled";
179
+ } | {
180
+ oldIdpUser: "name" | "id" | "disabled";
181
+ } | {
182
+ newIdpUser: "name" | "id" | "disabled";
183
+ })[] | readonly (boolean | readonly (string | boolean | readonly string[] | readonly boolean[] | {
184
+ user: string;
185
+ } | {
186
+ idpUser: "name" | "id" | "disabled";
187
+ } | {
188
+ oldIdpUser: "name" | "id" | "disabled";
189
+ } | {
190
+ newIdpUser: "name" | "id" | "disabled";
191
+ })[])[] | {
192
+ conditions: readonly (string | boolean | readonly string[] | readonly boolean[] | {
193
+ user: string;
194
+ } | {
195
+ idpUser: "name" | "id" | "disabled";
196
+ } | {
197
+ oldIdpUser: "name" | "id" | "disabled";
198
+ } | {
199
+ newIdpUser: "name" | "id" | "disabled";
200
+ })[] | readonly (readonly (string | boolean | readonly string[] | readonly boolean[] | {
201
+ user: string;
202
+ } | {
203
+ idpUser: "name" | "id" | "disabled";
204
+ } | {
205
+ oldIdpUser: "name" | "id" | "disabled";
206
+ } | {
207
+ newIdpUser: "name" | "id" | "disabled";
208
+ })[])[];
209
+ description?: string | undefined;
210
+ permit?: boolean | undefined;
211
+ })[];
212
+ sendPasswordResetEmail: readonly (readonly (string | boolean | readonly string[] | readonly boolean[] | {
213
+ user: string;
214
+ } | {
215
+ idpUser: "name" | "id" | "disabled";
216
+ } | {
217
+ oldIdpUser: "name" | "id" | "disabled";
218
+ } | {
219
+ newIdpUser: "name" | "id" | "disabled";
220
+ })[] | readonly (boolean | readonly (string | boolean | readonly string[] | readonly boolean[] | {
221
+ user: string;
222
+ } | {
223
+ idpUser: "name" | "id" | "disabled";
224
+ } | {
225
+ oldIdpUser: "name" | "id" | "disabled";
226
+ } | {
227
+ newIdpUser: "name" | "id" | "disabled";
228
+ })[])[] | {
229
+ conditions: readonly (string | boolean | readonly string[] | readonly boolean[] | {
230
+ user: string;
231
+ } | {
232
+ idpUser: "name" | "id" | "disabled";
233
+ } | {
234
+ oldIdpUser: "name" | "id" | "disabled";
235
+ } | {
236
+ newIdpUser: "name" | "id" | "disabled";
237
+ })[] | readonly (readonly (string | boolean | readonly string[] | readonly boolean[] | {
238
+ user: string;
239
+ } | {
240
+ idpUser: "name" | "id" | "disabled";
241
+ } | {
242
+ oldIdpUser: "name" | "id" | "disabled";
243
+ } | {
244
+ newIdpUser: "name" | "id" | "disabled";
245
+ })[])[];
246
+ description?: string | undefined;
247
+ permit?: boolean | undefined;
248
+ })[];
62
249
  } | undefined;
63
250
  };
64
251
  //#endregion
@@ -77,6 +264,7 @@ type IdPExternalConfig = {
77
264
  };
78
265
  type IdPOwnConfig = Omit<DefinedIdp<string, IdPInput, string>, "provider">;
79
266
  type IdPConfig = IdPOwnConfig | IdPExternalConfig;
267
+ type IdPUserField = "id" | "name" | "disabled";
80
268
  //#endregion
81
269
  //#region src/configure/services/secrets/index.d.ts
82
270
  declare const secretsDefinitionBrand: unique symbol;
@@ -84,8 +272,15 @@ type SecretsDefinitionBrand = {
84
272
  readonly [secretsDefinitionBrand]: true;
85
273
  };
86
274
  type SecretsVaultInput = Record<string, string>;
275
+ type SecretsVaultInputNullish = Record<string, string | undefined | null>;
87
276
  type SecretsInput = Record<string, SecretsVaultInput>;
88
- type DefinedSecrets<T extends SecretsInput> = {
277
+ type SecretsInputNullish = Record<string, SecretsVaultInputNullish>;
278
+ type SecretsOptions = {
279
+ readonly ignoreNullishValues: boolean;
280
+ };
281
+ type DefinedSecrets<T extends SecretsInputNullish> = {
282
+ readonly vaults: T;
283
+ readonly options: SecretsOptions;
89
284
  get<V extends Extract<keyof T, string>, S extends Extract<keyof T[V], string>>(vault: V, secret: S): Promise<string | undefined>;
90
285
  getAll<V extends Extract<keyof T, string>, S extends Extract<keyof T[V], string>>(vault: V, secrets: readonly S[]): Promise<(string | undefined)[]>;
91
286
  } & SecretsDefinitionBrand;
@@ -98,6 +293,19 @@ type SecretsConfig = Omit<ReturnType<typeof defineSecretManager>, "get" | "getAl
98
293
  * @returns Defined secrets with typed runtime access methods
99
294
  */
100
295
  declare function defineSecretManager<const T extends SecretsInput>(config: T): DefinedSecrets<T>;
296
+ /**
297
+ * Define secrets configuration for the Tailor SDK with ignoreNullishValues option.
298
+ * When `ignoreNullishValues` is true, secrets with nullish values are skipped during deploy
299
+ * instead of causing an error. This is useful for CI environments where not all
300
+ * secret values are available.
301
+ * @param config - Secrets configuration mapping vault names to their secrets
302
+ * @param options - Options for secret management behavior
303
+ * @param options.ignoreNullishValues - When true, secrets with nullish values are skipped during deploy
304
+ * @returns Defined secrets with typed runtime access methods
305
+ */
306
+ declare function defineSecretManager<const T extends SecretsInputNullish>(config: T, options: {
307
+ ignoreNullishValues: true;
308
+ }): DefinedSecrets<T>;
101
309
  //#endregion
102
310
  //#region src/types/staticwebsite.generated.d.ts
103
311
  type StaticWebsite = {
@@ -202,5 +410,5 @@ type RetryPolicy = {
202
410
  backoffMultiplier: number;
203
411
  };
204
412
  //#endregion
205
- export { IdPEmailConfig as _, ResolverExternalConfig as a, IdPInput as b, WorkflowServiceConfig as c, defineStaticWebSite as d, SecretsConfig as f, IdpDefinitionBrand as g, IdPExternalConfig as h, ExecutorServiceInput as i, WorkflowServiceInput as l, IdPConfig as m, AppConfig as n, ResolverServiceConfig as o, defineSecretManager as p, ExecutorServiceConfig as r, ResolverServiceInput as s, RetryPolicy as t, StaticWebsiteConfig as u, IdPGqlOperations as v, IdPGqlOperationsInput as y };
206
- //# sourceMappingURL=workflow.generated-DMt8PNVd.d.mts.map
413
+ export { IdpDefinitionBrand as _, ResolverExternalConfig as a, IdPGqlOperationsInput as b, WorkflowServiceConfig as c, defineStaticWebSite as d, SecretsConfig as f, IdPUserField as g, IdPExternalConfig as h, ExecutorServiceInput as i, WorkflowServiceInput as l, IdPConfig as m, AppConfig as n, ResolverServiceConfig as o, defineSecretManager as p, ExecutorServiceConfig as r, ResolverServiceInput as s, RetryPolicy as t, StaticWebsiteConfig as u, IdPEmailConfig as v, IdPInput as x, IdPGqlOperations as y };
414
+ //# sourceMappingURL=workflow.generated-8BeGQsVU.d.mts.map
@@ -99,6 +99,56 @@ defineIdp("my-idp", {
99
99
 
100
100
  **Validation:** Each field must be 200 characters or less and must not contain newline characters.
101
101
 
102
+ ### permission
103
+
104
+ Per-operation permission policies for IdP user management. Controls who can create, read, update, delete users, and send password reset emails.
105
+
106
+ ```typescript
107
+ defineIdp("my-idp", {
108
+ authorization: "loggedIn",
109
+ clients: ["my-client"],
110
+ permission: {
111
+ create: [{ conditions: [[{ user: "role" }, "=", "ADMIN"]], permit: true }],
112
+ read: [{ conditions: [[{ user: "_loggedIn" }, "=", true]], permit: true }],
113
+ update: [
114
+ { conditions: [[{ newIdpUser: "name" }, "!=", { oldIdpUser: "name" }]], permit: true },
115
+ ],
116
+ delete: [{ conditions: [[{ user: "role" }, "=", "ADMIN"]], permit: true }],
117
+ sendPasswordResetEmail: [{ conditions: [], permit: true }],
118
+ },
119
+ });
120
+ ```
121
+
122
+ **Operations:**
123
+
124
+ - `create` - Controls who can create IdP users
125
+ - `read` - Controls who can read IdP users
126
+ - `update` - Controls who can update IdP users
127
+ - `delete` - Controls who can delete IdP users
128
+ - `sendPasswordResetEmail` - Controls who can send password reset emails
129
+
130
+ **Operands:**
131
+
132
+ - `{ user: "field" }` - Authenticated user's attribute
133
+ - `{ idpUser: "field" }` - IdP user field (for create/read/delete). Allowed values: `"id"`, `"name"`, `"disabled"`
134
+ - `{ oldIdpUser: "field" }` - Previous IdP user field value (for update only). Allowed values: `"id"`, `"name"`, `"disabled"`
135
+ - `{ newIdpUser: "field" }` - New IdP user field value (for update only). Allowed values: `"id"`, `"name"`, `"disabled"`
136
+ - Literal values: `string`, `boolean`, `string[]`, `boolean[]`
137
+
138
+ **Operators:** `"="`, `"!="`, `"in"`, `"not in"`
139
+
140
+ **Helper:** `unsafeAllowAllIdPPermission` grants full access without conditions. Intended only for development and testing.
141
+
142
+ ```typescript
143
+ import { unsafeAllowAllIdPPermission } from "@tailor-platform/sdk";
144
+
145
+ defineIdp("my-idp", {
146
+ authorization: "loggedIn",
147
+ clients: ["my-client"],
148
+ permission: unsafeAllowAllIdPPermission,
149
+ });
150
+ ```
151
+
102
152
  ## Using idp.provider()
103
153
 
104
154
  The `idp.provider()` method creates a type-safe reference to the IdP for use in Auth configuration. The client name is validated at compile time against the clients defined in the IdP.
@@ -64,6 +64,31 @@ export default defineConfig({
64
64
 
65
65
  The exported `secrets` object provides type-safe `get()` and `getAll()` methods for runtime access from resolvers, executors, and workflows.
66
66
 
67
+ ### Skipping Secrets with Missing Values
68
+
69
+ In CI environments, you may not have all secret values available (e.g., secrets are already set on the platform and you don't want to duplicate them in CI environment variables). Use the `ignoreNullishValues` option to skip secrets whose values are `undefined` or `null`:
70
+
71
+ ```typescript
72
+ export const secrets = defineSecretManager(
73
+ {
74
+ "api-keys": {
75
+ "stripe-secret-key": process.env.STRIPE_SECRET_KEY,
76
+ "sendgrid-api-key": process.env.SENDGRID_API_KEY,
77
+ },
78
+ },
79
+ { ignoreNullishValues: true },
80
+ );
81
+ ```
82
+
83
+ When `ignoreNullishValues: true`:
84
+
85
+ - Secrets with a string value are created or updated as normal
86
+ - Secrets with `undefined` or `null` values are **skipped** — they are not created, updated, or deleted
87
+ - Skipped secrets are shown in the deploy output for visibility
88
+ - Secrets removed from the config entirely are still deleted (orphan cleanup)
89
+
90
+ This allows you to set secret values once (e.g., via local `tailor-sdk apply` or the CLI) and then deploy from CI without needing the actual values in CI environment variables.
91
+
67
92
  ## Using Secrets
68
93
 
69
94
  ### Runtime Access with `get()` / `getAll()`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tailor-platform/sdk",
3
- "version": "1.35.2",
3
+ "version": "1.36.0",
4
4
  "description": "Tailor Platform SDK - The SDK to work with Tailor Platform",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -83,6 +83,7 @@
83
83
  "@connectrpc/connect-node": "2.1.1",
84
84
  "@inquirer/core": "11.1.8",
85
85
  "@inquirer/prompts": "8.4.0",
86
+ "@jridgewell/trace-mapping": "0.3.31",
86
87
  "@liam-hq/cli": "0.7.24",
87
88
  "@napi-rs/keyring": "1.2.0",
88
89
  "@opentelemetry/api": "1.9.1",
@@ -138,9 +139,9 @@
138
139
  "@vitest/coverage-v8": "4.1.2",
139
140
  "eslint": "10.2.0",
140
141
  "eslint-plugin-jsdoc": "62.9.0",
141
- "eslint-plugin-oxlint": "1.58.0",
142
+ "eslint-plugin-oxlint": "1.59.0",
142
143
  "oxfmt": "0.44.0",
143
- "oxlint": "1.58.0",
144
+ "oxlint": "1.59.0",
144
145
  "oxlint-tsgolint": "0.20.0",
145
146
  "sonda": "0.11.1",
146
147
  "tsdown": "0.21.7",