@tailor-platform/sdk 2.25.0 → 2.27.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 (116) hide show
  1. package/CHANGELOG.md +106 -0
  2. package/dist/application-DFeuELRo.mjs +200 -0
  3. package/dist/application-DFeuELRo.mjs.map +1 -0
  4. package/dist/application-nT_4a5HO.mjs +1 -0
  5. package/dist/cli/commands/deploy/deploy.d.mts +2 -0
  6. package/dist/cli/commands/deploy/tailordb/migration-validation.d.mts +2 -1
  7. package/dist/cli/commands/tailordb/migrate/bundler.d.mts +7 -6
  8. package/dist/cli/commands/tailordb/migrate/diff-calculator.d.mts +12 -0
  9. package/dist/cli/commands/tailordb/migrate/remote-state.d.mts +1 -0
  10. package/dist/cli/lib.d.mts +2 -2
  11. package/dist/cli/lib.mjs +1 -1
  12. package/dist/cli/lib.mjs.map +1 -1
  13. package/dist/cli/main.mjs +43 -43
  14. package/dist/cli/main.mjs.map +1 -1
  15. package/dist/cli/shared/workspace-name.d.mts +2 -0
  16. package/dist/completion/zsh-worker.zsh +4 -2
  17. package/dist/configure/config/types.d.mts +11 -0
  18. package/dist/configure/index.d.mts +6 -6
  19. package/dist/configure/index.mjs +1 -1
  20. package/dist/configure/index.mjs.map +1 -1
  21. package/dist/configure/services/auth/types.d.mts +6 -1
  22. package/dist/configure/services/executor/trigger/event.d.mts +1 -1
  23. package/dist/configure/services/executor/trigger/webhook.d.mts +1 -1
  24. package/dist/configure/services/idp/permission.d.mts +2 -2
  25. package/dist/configure/services/resolver/resolver.d.mts +1 -1
  26. package/dist/configure/services/tailordb/schema.d.mts +1 -1
  27. package/dist/configure/services/tailordb/types.d.mts +1 -1
  28. package/dist/configure/services/workflow/job.d.mts +1 -1
  29. package/dist/configure/types/field.types.d.mts +48 -11
  30. package/dist/configure/types/type.d.mts +1 -1
  31. package/dist/date-CgP7gMG_.mjs +2 -0
  32. package/dist/date-CgP7gMG_.mjs.map +1 -0
  33. package/dist/{secretmanager-5olfnI1b.mjs → date-representation-Cr7W7Pn2.mjs} +2 -2
  34. package/dist/date-representation-Cr7W7Pn2.mjs.map +1 -0
  35. package/dist/{field-parse-DhnFs9WG.mjs → field-parse-C41e3UAF.mjs} +2 -2
  36. package/dist/{field-parse-DhnFs9WG.mjs.map → field-parse-C41e3UAF.mjs.map} +1 -1
  37. package/dist/idp-G_ojPBB5.mjs.map +1 -1
  38. package/dist/kysely/index.d.mts +47 -15
  39. package/dist/kysely/index.mjs +1 -1
  40. package/dist/kysely/index.mjs.map +1 -1
  41. package/dist/kysely-type-RDX59E1j.mjs +48 -0
  42. package/dist/kysely-type-RDX59E1j.mjs.map +1 -0
  43. package/dist/{manager-8-JOvuLl.mjs → manager-Bk-7vkwd.mjs} +2 -2
  44. package/dist/{manager-8-JOvuLl.mjs.map → manager-Bk-7vkwd.mjs.map} +1 -1
  45. package/dist/migration-steps-C6F3zNdQ.mjs +3 -0
  46. package/dist/migration-steps-C6F3zNdQ.mjs.map +1 -0
  47. package/dist/plugin/builtin/kysely-type/index.d.mts +11 -0
  48. package/dist/plugin/builtin/kysely-type/index.mjs +1 -1
  49. package/dist/plugin/index.mjs +1 -1
  50. package/dist/register-ts-hook-D6KXrGrB.mjs +1009 -0
  51. package/dist/register-ts-hook-D6KXrGrB.mjs.map +1 -0
  52. package/dist/runtime/idp.d.mts +6 -0
  53. package/dist/runtime/index.d.mts +8 -0
  54. package/dist/runtime/index.mjs +1 -1
  55. package/dist/runtime/types.d.mts +5 -0
  56. package/dist/{schema-CRtAmDcl.mjs → schema-B6hJQWp6.mjs} +2 -2
  57. package/dist/{schema-CRtAmDcl.mjs.map → schema-B6hJQWp6.mjs.map} +1 -1
  58. package/dist/seed/index.d.mts +3 -1
  59. package/dist/seed/index.mjs +7 -9
  60. package/dist/seed/index.mjs.map +1 -1
  61. package/dist/service-Cc7OY0Oh.mjs +7 -0
  62. package/dist/service-Cc7OY0Oh.mjs.map +1 -0
  63. package/dist/service-sH2MZ4_W.mjs +1 -0
  64. package/dist/service_pb-Dw2ilc1O.mjs +2 -0
  65. package/dist/{service_pb-ZClWtj1X.mjs.map → service_pb-Dw2ilc1O.mjs.map} +1 -1
  66. package/dist/service_pb-GDOqfwb6.mjs +1 -0
  67. package/dist/types/field.generated.d.mts +2 -2
  68. package/dist/utils/test/index.mjs +1 -1
  69. package/dist/vitest/date-representation.d.mts +23 -0
  70. package/dist/vitest/index.d.mts +5 -2
  71. package/dist/vitest/index.mjs +1 -1
  72. package/dist/vitest/index.mjs.map +1 -1
  73. package/dist/vitest/migration-steps.d.mts +45 -0
  74. package/dist/vitest/mocks/file.d.mts +1 -1
  75. package/dist/vitest/mocks/idp.d.mts +1 -0
  76. package/dist/vitest/mocks/tailordb-pglite.d.mts +1 -0
  77. package/dist/vitest/pglite-kysely.d.mts +14 -1
  78. package/dist/vitest/pglite-temporal.d.mts +9 -0
  79. package/dist/vitest/setup.d.mts +3 -1
  80. package/dist/vitest/setup.mjs +1 -1
  81. package/dist/vitest/setup.mjs.map +1 -1
  82. package/dist/{workspace_resource_pb-CxR_6fyN.mjs → workspace_resource_pb-ChWejcj0.mjs} +2 -2
  83. package/dist/workspace_resource_pb-ChWejcj0.mjs.map +1 -0
  84. package/docs/cli/application.md +24 -16
  85. package/docs/cli/function.md +2 -0
  86. package/docs/cli/workspace.md +1 -1
  87. package/docs/configuration.md +19 -6
  88. package/docs/github-actions.md +124 -58
  89. package/docs/plugin/custom.md +2 -1
  90. package/docs/services/auth.md +20 -0
  91. package/docs/services/executor.md +2 -2
  92. package/docs/services/idp.md +6 -1
  93. package/docs/services/resolver.md +4 -2
  94. package/docs/services/staticwebsite.md +5 -5
  95. package/docs/services/tailordb-migration.md +159 -35
  96. package/docs/services/tailordb.md +2 -2
  97. package/docs/testing.md +5 -1
  98. package/package.json +12 -12
  99. package/dist/application-ChqHuhZW.mjs +0 -1
  100. package/dist/application-DS0XKBtK.mjs +0 -200
  101. package/dist/application-DS0XKBtK.mjs.map +0 -1
  102. package/dist/date-Dri6Yas-.mjs +0 -2
  103. package/dist/date-Dri6Yas-.mjs.map +0 -1
  104. package/dist/kysely-type-C-iyFFH7.mjs +0 -43
  105. package/dist/kysely-type-C-iyFFH7.mjs.map +0 -1
  106. package/dist/register-ts-hook-DPAW0Z4M.mjs +0 -924
  107. package/dist/register-ts-hook-DPAW0Z4M.mjs.map +0 -1
  108. package/dist/secretmanager-5olfnI1b.mjs.map +0 -1
  109. package/dist/service-Bx-7Lz06.mjs +0 -1
  110. package/dist/service-CL1Bp4It.mjs +0 -7
  111. package/dist/service-CL1Bp4It.mjs.map +0 -1
  112. package/dist/service_pb-ZClWtj1X.mjs +0 -2
  113. package/dist/service_pb-dB3RrGeh.mjs +0 -1
  114. package/dist/tailordb-ddl-DqInYupv.mjs +0 -7
  115. package/dist/tailordb-ddl-DqInYupv.mjs.map +0 -1
  116. package/dist/workspace_resource_pb-CxR_6fyN.mjs.map +0 -1
@@ -1,6 +1,6 @@
1
+ import { NullableToOptional, output } from "../../../types/helpers.mjs";
1
2
  import { DefinedFieldMetadata, FieldMetadata, TailorField, TailorFieldType } from "../../types/field.types.mjs";
2
3
  import { TailorEnv } from "../../../runtime/types.mjs";
3
- import { NullableToOptional, output } from "../../../types/helpers.mjs";
4
4
  import { TailorDBInstance } from "../tailordb/types.mjs";
5
5
  import { AuthConnectionConfig } from "../../../types/auth-connection.generated.mjs";
6
6
  import { IdProvider, OAuth2Client, OAuth2ClientInput, SCIMAttribute, SCIMConfig, TenantProvider } from "../../../types/auth.generated.mjs";
@@ -124,6 +124,11 @@ export type FederatedIdentity = {
124
124
  export type BeforeLoginClaims = JsonObject & {
125
125
  /** Present only for federated (Google/Microsoft) logins; `undefined` for password logins. */
126
126
  federated_identity?: FederatedIdentity;
127
+ /**
128
+ * When the user's Built-in IdP password was last set, in seconds since the
129
+ * Unix epoch. `undefined` when the user has no password.
130
+ */
131
+ password_updated_at?: number;
127
132
  };
128
133
  export type BeforeLoginHookArgs = {
129
134
  claims: BeforeLoginClaims;
@@ -1,5 +1,5 @@
1
- import { TailorEnv, TailorPrincipal } from "../../../../runtime/types.mjs";
2
1
  import { SerializeDates, output } from "../../../../types/helpers.mjs";
2
+ import { TailorEnv, TailorPrincipal } from "../../../../runtime/types.mjs";
3
3
  import { AuthAccessTokenTrigger as AuthAccessTokenTrigger$1, IdpUserTrigger as IdpUserTrigger$1, ResolverExecutedTrigger as ResolverExecutedTrigger$1, TailorDBTrigger as TailorDBTrigger$1, WorkflowExecutionTrigger as WorkflowExecutionTrigger$1, WorkflowJobExecutionTrigger as WorkflowJobExecutionTrigger$1 } from "../../../../types/executor.generated.mjs";
4
4
  import { TailorDBType } from "../../tailordb/schema.mjs";
5
5
  import { IdpName } from "../../../types/idp-name.mjs";
@@ -1,5 +1,5 @@
1
- import { TailorEnv } from "../../../../runtime/types.mjs";
2
1
  import { JsonValue } from "../../../../types/helpers.mjs";
2
+ import { TailorEnv } from "../../../../runtime/types.mjs";
3
3
  import { IncomingWebhookTrigger as IncomingWebhookTrigger$1 } from "../../../../types/executor.generated.mjs";
4
4
  //#region src/configure/services/executor/trigger/webhook.d.ts
5
5
  export interface IncomingWebhookArgs<T extends IncomingWebhookRequest> {
@@ -37,10 +37,10 @@ type IdPActionPermission<User extends object = InferredAttributes, Update extend
37
37
  * @example
38
38
  * const permission: IdPPermission = {
39
39
  * create: [{ conditions: [[{ user: "role" }, "=", "ADMIN"]], permit: true }],
40
- * read: [{ conditions: [[{ user: "_loggedIn" }, "=", true]], permit: true }],
40
+ * read: [{ conditions: [[{ user: "role" }, "=", "ADMIN"]], permit: true }],
41
41
  * update: [{ conditions: [[{ newIdpUser: "name" }, "=", { user: "id" }]], permit: true }],
42
42
  * delete: [{ conditions: [[{ user: "role" }, "=", "ADMIN"]], permit: true }],
43
- * sendPasswordResetEmail: [{ conditions: [], permit: true }],
43
+ * sendPasswordResetEmail: [{ conditions: [[{ user: "role" }, "=", "ADMIN"]], permit: true }],
44
44
  * unenrollMfa: [{ conditions: [[{ user: "role" }, "=", "ADMIN"]], permit: true }],
45
45
  * };
46
46
  */
@@ -1,5 +1,5 @@
1
- import { TailorEnv, TailorPrincipal } from "../../../runtime/types.mjs";
2
1
  import { InferFieldsOutput, output } from "../../../types/helpers.mjs";
2
+ import { TailorEnv, TailorPrincipal } from "../../../runtime/types.mjs";
3
3
  import { MachineUserName } from "../auth/types.mjs";
4
4
  import { ResolverInput } from "../../../types/resolver.generated.mjs";
5
5
  import { ResolverPermission } from "./permission.mjs";
@@ -1,6 +1,6 @@
1
+ import { InferFieldsOutput, IsUnion, TypeLevelError, UnionToIntersection, output } from "../../../types/helpers.mjs";
1
2
  import { FieldOptions, FieldOutput, FieldValidateInput, TailorFieldType, TailorToTs } from "../../types/field.types.mjs";
2
3
  import { InferredAttributes } from "../../../runtime/types.mjs";
3
- import { InferFieldsOutput, IsUnion, TypeLevelError, UnionToIntersection, output } from "../../../types/helpers.mjs";
4
4
  import { DBFieldMetadata, DefinedDBFieldMetadata, ExcludeDefaultedDBFields, ExcludeHookedDBFields, ExcludeNestedDBFields, Hook, IndexDef, RelationType, SerialConfig, TailorDBField as TailorDBField$1, TailorDBType as TailorDBType$1, TypeFeatures, TypeHook, TypeValidateFn, UpdateHookFn } from "./types.mjs";
5
5
  import { AllowedValues, AllowedValuesOutput } from "../../types/field.mjs";
6
6
  import { FieldParseArgs } from "../../../runtime/field-parse.mjs";
@@ -1,6 +1,6 @@
1
+ import { DeepReadonly, InferFieldsOutput, Prettify, output } from "../../../types/helpers.mjs";
1
2
  import { DefinedFieldMetadata, FieldMetadata, TailorField, TailorFieldType } from "../../types/field.types.mjs";
2
3
  import { InferredAttributes, TailorPrincipal } from "../../../runtime/types.mjs";
3
- import { DeepReadonly, InferFieldsOutput, Prettify, output } from "../../../types/helpers.mjs";
4
4
  import { DBFieldMetadata as DBFieldMetadata$1, GqlOperationsInput, RawPermissions, TailorDBServiceConfigInput } from "../../../types/tailordb.generated.mjs";
5
5
  //#region src/configure/services/tailordb/types.d.ts
6
6
  export type SerialConfig<T extends "string" | "integer" = "string" | "integer"> = Prettify<{
@@ -1,5 +1,5 @@
1
- import { TailorEnv, TailorPrincipal } from "../../../runtime/types.mjs";
2
1
  import { JsonCompatible, TypeLevelError } from "../../../types/helpers.mjs";
2
+ import { TailorEnv, TailorPrincipal } from "../../../runtime/types.mjs";
3
3
  import { ExecJobFunctionOptions } from "../../../runtime/workflow.mjs";
4
4
  //#region src/configure/services/workflow/job.d.ts
5
5
  /**
@@ -1,3 +1,4 @@
1
+ import { IsUnion, TypeLevelError } from "../../types/helpers.mjs";
1
2
  import { Temporal } from "temporal-spec";
2
3
  //#region src/configure/types/field.types.d.ts
3
4
  export interface EnumValue {
@@ -20,7 +21,8 @@ export type TailorToTs = {
20
21
  nested: Record<string, unknown>;
21
22
  } & Record<TailorFieldType, unknown>;
22
23
  export interface FieldMetadata {
23
- as?: "string" | "date" | "temporal";
24
+ /** Date value representation. `"default"` follows the configured `defaultDateRepresentation`. */
25
+ as?: "string" | "date" | "temporal" | "default";
24
26
  description?: string;
25
27
  required?: boolean;
26
28
  array?: boolean;
@@ -39,31 +41,66 @@ export type FieldOptions = {
39
41
  optional?: boolean;
40
42
  array?: boolean;
41
43
  };
44
+ /**
45
+ * Registry of each application's `defaultDateRepresentation`. `tailor generate`
46
+ * writes one entry per application into `tailor.d.ts`, keyed by the app name:
47
+ * `declare module "@tailor-platform/sdk" { interface DateRepresentationRegistry { shop: "temporal" } }`.
48
+ * An app without the setting is recorded as `"unset"`. Application names are
49
+ * unique within a workspace, so two entries never share a key.
50
+ */
51
+ export interface DateRepresentationRegistry {}
52
+ /** Representation the SDK applies when no app configures one. */
53
+ type BuiltinDateDefault = undefined;
54
+ export type DateDefaultConflictMessage = "defaultDateRepresentation differs between the tailor.config.ts files included in this TypeScript program; use the same value in each, or give each application its own tsconfig.json";
55
+ type DateDefaultOfValue<Value> = Value extends "temporal" | "date" ? Value : Value extends "unset" ? undefined : never;
56
+ type NormalizeDateDefault<Value, Builtin> = Value extends undefined ? Builtin : Value;
57
+ /**
58
+ * Resolve the default date representation declared by a registry: the single
59
+ * value every included app agrees on, or a type-level error when they differ.
60
+ */
61
+ export type DateDefaultOf<Registry, Builtin = BuiltinDateDefault> = [DateDefaultOfValue<Registry[keyof Registry]>] extends [never] ? Builtin : IsUnion<NormalizeDateDefault<DateDefaultOfValue<Registry[keyof Registry]>, Builtin>> extends true ? TypeLevelError<DateDefaultConflictMessage> : NormalizeDateDefault<DateDefaultOfValue<Registry[keyof Registry]>, Builtin>;
62
+ type DefaultDateRepresentation = DateDefaultOf<DateRepresentationRegistry>;
63
+ /** Explicit `as` values a date field accepts. */
64
+ export type DateRepresentationOption = "string" | "date" | "temporal";
65
+ type ResolveDateRepresentation<As, Default> = As extends DateRepresentationOption ? As : Default;
42
66
  /** Options for a date field. */
43
67
  export type DateFieldOptions = FieldOptions & {
44
68
  /**
45
69
  * Use a Date at midnight UTC, or a Temporal.PlainDate, instead of a
46
- * YYYY-MM-DD string. Defaults to string.
70
+ * YYYY-MM-DD string. Defaults to `defaultDateRepresentation`, or string.
47
71
  */
48
- as?: "string" | "date" | "temporal";
72
+ as?: DateRepresentationOption;
49
73
  };
50
- export type DateFieldValue<As> = As extends "date" ? Date : As extends "temporal" ? Temporal.PlainDate : string;
74
+ type DateValueOf<R> = R extends "date" ? Date : R extends "temporal" ? Temporal.PlainDate : R extends TypeLevelError<string> ? R : string;
75
+ /** Value type of a date field under an explicit `Default` representation. */
76
+ export type DateFieldValueFor<As, Default> = DateValueOf<ResolveDateRepresentation<As, Default>>;
77
+ export type DateFieldValue<As> = DateFieldValueFor<As, DefaultDateRepresentation>;
51
78
  /** Options for a datetime field. */
52
79
  export type DateTimeFieldOptions = FieldOptions & {
53
- /** Choose string, Date, or Temporal.Instant values. Defaults to string input and string | Date output. */
54
- as?: "string" | "date" | "temporal";
80
+ /**
81
+ * Choose string, Date, or Temporal.Instant values. Defaults to
82
+ * `defaultDateRepresentation`, or string input and string | Date output.
83
+ */
84
+ as?: DateRepresentationOption;
55
85
  };
56
- export type DateTimeFieldValue<As> = As extends "date" ? Date : As extends "temporal" ? Temporal.Instant : As extends "string" ? string : string | Date;
86
+ type DateTimeValueOf<R> = R extends "date" ? Date : R extends "temporal" ? Temporal.Instant : R extends "string" ? string : R extends TypeLevelError<string> ? R : string | Date;
87
+ /** Value type of a datetime field under an explicit `Default` representation. */
88
+ export type DateTimeFieldValueFor<As, Default> = DateTimeValueOf<ResolveDateRepresentation<As, Default>>;
89
+ export type DateTimeFieldValue<As> = DateTimeFieldValueFor<As, DefaultDateRepresentation>;
57
90
  /** Options for a time field. */
58
91
  export type TimeFieldOptions = FieldOptions & {
59
92
  /**
60
93
  * Choose HH:mm strings, Date values on 1970-01-01 UTC, or Temporal.PlainTime values.
61
- * Defaults to string. Date output uses UTC hours/minutes and ignores the date.
62
- * Seconds and fractional seconds are truncated in both representations.
94
+ * Defaults to `defaultDateRepresentation`, or string. Date output uses UTC
95
+ * hours/minutes and ignores the date. Seconds and fractional seconds are
96
+ * truncated in both representations.
63
97
  */
64
- as?: "string" | "date" | "temporal";
98
+ as?: DateRepresentationOption;
65
99
  };
66
- export type TimeFieldValue<As> = As extends "date" ? Date : As extends "temporal" ? Temporal.PlainTime : string;
100
+ type TimeValueOf<R> = R extends "date" ? Date : R extends "temporal" ? Temporal.PlainTime : R extends TypeLevelError<string> ? R : string;
101
+ /** Value type of a time field under an explicit `Default` representation. */
102
+ export type TimeFieldValueFor<As, Default> = TimeValueOf<ResolveDateRepresentation<As, Default>>;
103
+ export type TimeFieldValue<As> = TimeFieldValueFor<As, DefaultDateRepresentation>;
67
104
  export type FieldOutput<T, O extends FieldOptions> = OptionalFieldOutput<ArrayFieldOutput<T, O>, O>;
68
105
  type OptionalFieldOutput<T, O extends FieldOptions> = O["optional"] extends true ? T | null : T;
69
106
  type ArrayFieldOutput<T, O extends FieldOptions> = [O] extends [{
@@ -1,5 +1,5 @@
1
- import { DefinedFieldMetadata, FieldMetadata, FieldValidateInput, TailorField as TailorField$1, TailorFieldType } from "./field.types.mjs";
2
1
  import { TypeLevelError } from "../../types/helpers.mjs";
2
+ import { DefinedFieldMetadata, FieldMetadata, FieldValidateInput, TailorField as TailorField$1, TailorFieldType } from "./field.types.mjs";
3
3
  import "./field.mjs";
4
4
  import { FieldParseArgs } from "../../runtime/field-parse.mjs";
5
5
  import { StandardSchemaV1 } from "@standard-schema/spec";
@@ -0,0 +1,2 @@
1
+ function getTemporal(){let e=globalThis.Temporal;if(!e)throw ReferenceError(`Temporal is unavailable. Use the Tailor Platform runtime or the SDK tailor-runtime Vitest environment.`);return e}const e={get PlainDate(){return getTemporal().PlainDate},get PlainTime(){return getTemporal().PlainTime},get PlainDateTime(){return getTemporal().PlainDateTime},get PlainYearMonth(){return getTemporal().PlainYearMonth},get PlainMonthDay(){return getTemporal().PlainMonthDay},get ZonedDateTime(){return getTemporal().ZonedDateTime},get Duration(){return getTemporal().Duration},get Instant(){return getTemporal().Instant},get Now(){return getTemporal().Now}};function formatDate(e){return formatDateTime(e).slice(0,10)}function formatDateTime(e){let t=e.getUTCFullYear();if(!Number.isFinite(t)||t<0||t>9999){let n=Number.isNaN(e.getTime())?`an invalid Date`:`year ${t}`;throw RangeError(`Expected a Date with a 4-digit year (0000-9999), but received ${n}`)}return e.toISOString()}function formatHoursMinutes(e,t){return`${String(e).padStart(2,`0`)}:${String(t).padStart(2,`0`)}`}function formatTime(e){if(!Number.isFinite(e.getTime()))throw RangeError(`Expected a valid Date, but received an invalid Date`);return formatHoursMinutes(e.getUTCHours(),e.getUTCMinutes())}function formatTemporal(e){let t=getTemporal();if(e instanceof t.PlainTime)return formatHoursMinutes(e.hour,e.minute);let n=e.toString({calendarName:`never`});if(!/^\d{4}-/.test(n)){let r=e instanceof t.Instant;throw RangeError(`Expected a Temporal.${r?`Instant`:`PlainDate`} with a 4-digit ${r?`UTC `:``}year (0000-9999), but received ${n}`)}return n}function serialize(e,t,n){if(e.metadata.array){if(!Array.isArray(t))return t;let r=t.map((t,r)=>serializeValue(e,t,`${n}[${r}]`));return r.every((e,n)=>e===t[n])?t:r}return serializeValue(e,t,n)}function describePathTarget(e){return e||`the top-level value`}function truncateForDescription(e){return e.length>100?`${e.slice(0,100)}...`:e}function describeReceivedValue(e){if(Array.isArray(e)){let t=e.slice(0,100),n=[...new Set(Array.from(t,e=>typeof e))];return n.length>0?`an array of ${n.join(`/`)}`:`an empty array`}if(typeof e==`string`)return`a string (${JSON.stringify(truncateForDescription(e))})`;let t=typeof e;return t===`object`?`an object`:t===`function`?`a function`:`a ${t} (${truncateForDescription(String(e))})`}function bundledDateDefault(){let e=globalThis.process?.env.__TAILOR_PLATFORM_BUNDLE_DATE_DEFAULT;return e===`temporal`||e===`date`?e:`legacy`}function dateRepresentationOf(e,t,n=bundledDateDefault()){if(e!==`date`&&e!==`datetime`&&e!==`time`)return;let r=t==="default"?n:t;return r===`date`||r===`temporal`?r:void 0}function isDateRepresentationField(e,t,n){let r=dateRepresentationOf(e.type,e.metadata.as,n);return r!==void 0&&(t===void 0||r===t)}function throwInvalidDate(e,t){let n=e instanceof Error?e.message:String(e);throw RangeError(`Invalid date at ${describePathTarget(t)}: ${n}`,{cause:e})}function serializeAsDate(e,t,n){if(!(t instanceof Date))throw TypeError(`Expected a Date instance at ${describePathTarget(n)}, but received ${describeReceivedValue(t)}`);try{return e===`datetime`?formatDateTime(t):e===`time`?formatTime(t):formatDate(t)}catch(e){return throwInvalidDate(e,n)}}function serializeAsTemporal(e,t,n){let r=getTemporal(),i=e===`date`?r.PlainDate:e===`datetime`?r.Instant:r.PlainTime;if(!(t instanceof i))throw TypeError(`Expected a Temporal.${i.name} instance at ${describePathTarget(n)}, but received ${describeReceivedValue(t)}`);try{return formatTemporal(t)}catch(e){return throwInvalidDate(e,n)}}const t={date:globalThis.process?.env.__TAILOR_PLATFORM_BUNDLE_WITHOUT_DATE?void 0:serializeAsDate,temporal:globalThis.process?.env.__TAILOR_PLATFORM_BUNDLE_WITHOUT_TEMPORAL?void 0:serializeAsTemporal};function serializeValue(e,n,r){if(n==null)return n;let{type:i}=e,a=dateRepresentationOf(i,e.metadata.as);if(a){let e=t[a];if(!e)throw Error(`Serializing fields declared with as: "${a}" is not included in this bundle.`);return e(i,n,r)}if(i!==`nested`||typeof n!=`object`||Array.isArray(n))return n;let o=n,s=o;for(let[t,n]of Object.entries(e.fields)){let e=serialize(n,o[t],r?`${r}.${t}`:t);e!==o[t]&&(s===o&&(s={...o}),Object.defineProperty(s,t,{value:e,enumerable:!0,configurable:!0,writable:!0}))}return s}function hasDateRepresentationFields(e,t,n){return isDateRepresentationField(e,t,n)||Object.values(e.fields).some(e=>hasDateRepresentationFields(e,t,n))}function serializeDateFields(e,t){return serialize(e,t,``)}export{e as a,serializeDateFields as i,formatDate as n,getTemporal as o,hasDateRepresentationFields as r,dateRepresentationOf as t};
2
+ //# sourceMappingURL=date-CgP7gMG_.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date-CgP7gMG_.mjs","names":["temporal","Temporal","date","year","received","hour","minute","value","iso","isInstant","field","converted","item","path","index","text","sample","elementTypes","type","gate","resolved","as","defaultRepresentation","representation","reason","error","expected","dateSerializers","serializeAs","record","result","key","child"],"sources":["../src/runtime/temporal.ts","../src/runtime/date.ts"],"sourcesContent":["import type { Temporal as TemporalTypes } from \"temporal-spec\";\n\n/**\n * Get the host Temporal implementation when a value is needed.\n * @returns Host Temporal implementation\n * @internal\n */\nexport function getTemporal(): typeof TemporalTypes {\n const temporal = (globalThis as unknown as { Temporal?: typeof TemporalTypes }).Temporal;\n if (!temporal) {\n throw new ReferenceError(\n \"Temporal is unavailable. Use the Tailor Platform runtime or the SDK tailor-runtime Vitest environment.\",\n );\n }\n return temporal;\n}\n\n/**\n * Typed access to the runtime's Temporal API, without installing a polyfill.\n * Constructors are resolved on access so configuration files can load in Node.js.\n * @example\n * import { Temporal } from \"@tailor-platform/sdk/runtime\";\n * const tomorrow: Temporal.PlainDate = Temporal.Now.plainDateISO().add({ days: 1 });\n */\nexport const Temporal: typeof TemporalTypes = {\n get PlainDate() {\n return getTemporal().PlainDate;\n },\n get PlainTime() {\n return getTemporal().PlainTime;\n },\n get PlainDateTime() {\n return getTemporal().PlainDateTime;\n },\n get PlainYearMonth() {\n return getTemporal().PlainYearMonth;\n },\n get PlainMonthDay() {\n return getTemporal().PlainMonthDay;\n },\n get ZonedDateTime() {\n return getTemporal().ZonedDateTime;\n },\n get Duration() {\n return getTemporal().Duration;\n },\n get Instant() {\n return getTemporal().Instant;\n },\n get Now() {\n return getTemporal().Now;\n },\n};\n\n/** Temporal instance types supplied by the SDK, independent of TypeScript's lib settings. */\n// Type-only merging supports Temporal.PlainDate annotations on the value import.\n// oxlint-disable-next-line typescript/no-namespace\nexport declare namespace Temporal {\n /** The runtime Temporal.PlainDate instance. */\n type PlainDate = TemporalTypes.PlainDate;\n /** The runtime Temporal.PlainTime instance. */\n type PlainTime = TemporalTypes.PlainTime;\n /** The runtime Temporal.PlainDateTime instance. */\n type PlainDateTime = TemporalTypes.PlainDateTime;\n /** The runtime Temporal.PlainYearMonth instance. */\n type PlainYearMonth = TemporalTypes.PlainYearMonth;\n /** The runtime Temporal.PlainMonthDay instance. */\n type PlainMonthDay = TemporalTypes.PlainMonthDay;\n /** The runtime Temporal.ZonedDateTime instance. */\n type ZonedDateTime = TemporalTypes.ZonedDateTime;\n /** The runtime Temporal.Duration instance. */\n type Duration = TemporalTypes.Duration;\n /** The runtime Temporal.Instant instance. */\n type Instant = TemporalTypes.Instant;\n}\n","import { getTemporal } from \"./temporal\";\nimport type { FieldMetadata, TailorFieldType } from \"#/configure/types/field.types\";\nimport type { EffectiveDateDefault } from \"./types\";\nimport type { Temporal } from \"temporal-spec\";\n\n/**\n * Format a Date using its UTC calendar date.\n * @param date - Date to format\n * @returns Date string in YYYY-MM-DD format\n */\nexport function formatDate(date: Date): string {\n return formatDateTime(date).slice(0, 10);\n}\n\nfunction formatDateTime(date: Date): string {\n const year = date.getUTCFullYear();\n if (!Number.isFinite(year) || year < 0 || year > 9999) {\n const received = Number.isNaN(date.getTime()) ? \"an invalid Date\" : `year ${year}`;\n throw new RangeError(\n `Expected a Date with a 4-digit year (0000-9999), but received ${received}`,\n );\n }\n return date.toISOString();\n}\n\nfunction formatHoursMinutes(hour: number, minute: number): string {\n return `${String(hour).padStart(2, \"0\")}:${String(minute).padStart(2, \"0\")}`;\n}\n\nfunction formatTime(date: Date): string {\n if (!Number.isFinite(date.getTime())) {\n throw new RangeError(\"Expected a valid Date, but received an invalid Date\");\n }\n return formatHoursMinutes(date.getUTCHours(), date.getUTCMinutes());\n}\n\nfunction formatTemporal(value: Temporal.PlainDate | Temporal.Instant | Temporal.PlainTime): string {\n const Temporal = getTemporal();\n if (value instanceof Temporal.PlainTime) return formatHoursMinutes(value.hour, value.minute);\n const iso = value.toString({ calendarName: \"never\" });\n if (!/^\\d{4}-/.test(iso)) {\n const isInstant = value instanceof Temporal.Instant;\n throw new RangeError(\n `Expected a Temporal.${isInstant ? \"Instant\" : \"PlainDate\"} with a 4-digit ${isInstant ? \"UTC \" : \"\"}year (0000-9999), but received ${iso}`,\n );\n }\n return iso;\n}\n\ntype DateField = {\n readonly type: TailorFieldType;\n readonly metadata: FieldMetadata;\n readonly fields: Record<string, DateField>;\n};\n\ntype DateRepresentationField = {\n readonly type: TailorFieldType;\n readonly metadata: Pick<FieldMetadata, \"as\">;\n readonly fields: Record<string, DateRepresentationField>;\n};\n\nfunction serialize(field: DateField, value: unknown, path: string): unknown {\n if (field.metadata.array) {\n if (!Array.isArray(value)) return value;\n const converted = value.map((item, index) => serializeValue(field, item, `${path}[${index}]`));\n return converted.every((item, index) => item === value[index]) ? value : converted;\n }\n return serializeValue(field, value, path);\n}\n\nfunction describePathTarget(path: string): string {\n return path || \"the top-level value\";\n}\n\nconst MAX_DESCRIBED_VALUE_LENGTH = 100;\nconst MAX_DESCRIBED_ARRAY_SAMPLE = 100;\n\nfunction truncateForDescription(text: string): string {\n return text.length > MAX_DESCRIBED_VALUE_LENGTH\n ? `${text.slice(0, MAX_DESCRIBED_VALUE_LENGTH)}...`\n : text;\n}\n\nfunction describeReceivedValue(value: unknown): string {\n if (Array.isArray(value)) {\n const sample = value.slice(0, MAX_DESCRIBED_ARRAY_SAMPLE);\n const elementTypes = [...new Set(Array.from(sample, (item) => typeof item))];\n return elementTypes.length > 0 ? `an array of ${elementTypes.join(\"/\")}` : \"an empty array\";\n }\n if (typeof value === \"string\")\n return `a string (${JSON.stringify(truncateForDescription(value))})`;\n const type = typeof value;\n if (type === \"object\") return \"an object\";\n if (type === \"function\") return \"a function\";\n return `a ${type} (${truncateForDescription(String(value))})`;\n}\n\ntype DateRepresentation = \"date\" | \"temporal\";\n\ntype MaybeProcessGlobal = { process?: { env: Record<string, string | undefined> } };\n\n// Read per call rather than at module load: the Vitest setup file sets the gate\n// after the runtime modules are evaluated. Bundles fold it to a literal.\nfunction bundledDateDefault(): EffectiveDateDefault {\n const gate = (globalThis as MaybeProcessGlobal).process?.env\n .__TAILOR_PLATFORM_BUNDLE_DATE_DEFAULT;\n return gate === \"temporal\" || gate === \"date\" ? gate : \"legacy\";\n}\n\n/**\n * Get the Date or Temporal representation a field converts its values to.\n * @param type - Field type\n * @param as - The field's `as` option\n * @param defaultRepresentation - Representation for fields whose `as` is `\"default\"`; read from the bundle when omitted\n * @returns The representation, or undefined when values stay strings\n * @internal\n */\nexport function dateRepresentationOf(\n type: TailorFieldType,\n as: FieldMetadata[\"as\"],\n defaultRepresentation: EffectiveDateDefault = bundledDateDefault(),\n): DateRepresentation | undefined {\n if (type !== \"date\" && type !== \"datetime\" && type !== \"time\") return undefined;\n const resolved = as === \"default\" ? defaultRepresentation : as;\n return resolved === \"date\" || resolved === \"temporal\" ? resolved : undefined;\n}\n\nfunction isDateRepresentationField(\n field: DateRepresentationField,\n representation?: DateRepresentation,\n defaultRepresentation?: EffectiveDateDefault,\n): boolean {\n const as = dateRepresentationOf(field.type, field.metadata.as, defaultRepresentation);\n return as !== undefined && (representation === undefined || as === representation);\n}\n\ntype DateSerializer = (type: TailorFieldType, value: unknown, path: string) => string;\n\nfunction throwInvalidDate(error: unknown, path: string): never {\n const reason = error instanceof Error ? error.message : String(error);\n throw new RangeError(`Invalid date at ${describePathTarget(path)}: ${reason}`, {\n cause: error,\n });\n}\n\nfunction serializeAsDate(type: TailorFieldType, value: unknown, path: string): string {\n if (!(value instanceof Date)) {\n throw new TypeError(\n `Expected a Date instance at ${describePathTarget(path)}, but received ${describeReceivedValue(value)}`,\n );\n }\n try {\n if (type === \"datetime\") return formatDateTime(value);\n if (type === \"time\") return formatTime(value);\n return formatDate(value);\n } catch (error) {\n return throwInvalidDate(error, path);\n }\n}\n\nfunction serializeAsTemporal(type: TailorFieldType, value: unknown, path: string): string {\n const Temporal = getTemporal();\n const expected =\n type === \"date\"\n ? Temporal.PlainDate\n : type === \"datetime\"\n ? Temporal.Instant\n : Temporal.PlainTime;\n if (!(value instanceof expected)) {\n throw new TypeError(\n `Expected a Temporal.${expected.name} instance at ${describePathTarget(path)}, but received ${describeReceivedValue(value)}`,\n );\n }\n try {\n return formatTemporal(value);\n } catch (error) {\n return throwInvalidDate(error, path);\n }\n}\n\nconst dateSerializers: Record<DateRepresentation, DateSerializer | undefined> = {\n date: (globalThis as MaybeProcessGlobal).process?.env.__TAILOR_PLATFORM_BUNDLE_WITHOUT_DATE\n ? undefined\n : serializeAsDate,\n temporal: (globalThis as MaybeProcessGlobal).process?.env\n .__TAILOR_PLATFORM_BUNDLE_WITHOUT_TEMPORAL\n ? undefined\n : serializeAsTemporal,\n};\n\nfunction serializeValue(field: DateField, value: unknown, path: string): unknown {\n if (value === null || value === undefined) return value;\n const { type } = field;\n const as = dateRepresentationOf(type, field.metadata.as);\n if (as) {\n const serializeAs = dateSerializers[as];\n if (!serializeAs) {\n throw new Error(\n `Serializing fields declared with as: \"${as}\" is not included in this bundle.`,\n );\n }\n return serializeAs(type, value, path);\n }\n if (type !== \"nested\" || typeof value !== \"object\" || Array.isArray(value)) return value;\n const record = value as Record<string, unknown>;\n let result = record;\n for (const [key, child] of Object.entries(field.fields)) {\n const converted = serialize(child, record[key], path ? `${path}.${key}` : key);\n if (converted !== record[key]) {\n if (result === record) result = { ...record };\n Object.defineProperty(result, key, {\n value: converted,\n enumerable: true,\n configurable: true,\n writable: true,\n });\n }\n }\n return result;\n}\n\n/**\n * Check whether a field or any of its nested fields uses a Date or Temporal representation.\n * @param field - Field to inspect\n * @param representation - Only match fields using this representation\n * @param defaultRepresentation - Representation for fields whose `as` is `\"default\"`; read from the bundle when omitted\n * @returns Whether serializeDateFields would convert any value of the field\n * @internal\n */\nexport function hasDateRepresentationFields(\n field: DateRepresentationField,\n representation?: DateRepresentation,\n defaultRepresentation?: EffectiveDateDefault,\n): boolean {\n return (\n isDateRepresentationField(field, representation, defaultRepresentation) ||\n Object.values(field.fields).some((child) =>\n hasDateRepresentationFields(child, representation, defaultRepresentation),\n )\n );\n}\n\n/**\n * Convert fields using Date or Temporal representations to date, datetime, or time strings.\n * @param field - Field defining the value's shape\n * @param value - Value to serialize\n * @returns Value with Date and Temporal fields converted to strings\n * @internal\n */\nexport function serializeDateFields(field: DateField, value: unknown): unknown {\n return serialize(field, value, \"\");\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{t as e}from"./assert-WeXvmG4j.mjs";import{vi as t}from"vitest";function withDispose(e,t){return Object.defineProperty(e,Symbol.dispose,{value:t,enumerable:!1,writable:!0,configurable:!0}),e}function tailorRoot(){let e=globalThis;return e.tailor||={context:{getInvoker:()=>null}},e.tailor}function tailordbRoot(){let e=globalThis;return e.tailordb||={},e.tailordb}const n=Symbol(`tailorSecretStore`);function mockSecretmanager(r={}){let i=tailorRoot(),a=i.secretmanager,o={store:structuredClone(a?.[n]?.store??{})};for(let[e,t]of Object.entries(r.secrets??{}))o.store[e]={...o.store[e],...t};async function defaultGetSecret(e,t){return o.store[e]?.[t]}async function defaultGetSecrets(t,n){let r=o.store[t]??{},i={};for(let t of n)t in r&&(i[t]=e(r[t],`vault entry missing for: ${t}`));return i}let s=t.fn(defaultGetSecret),c=t.fn(defaultGetSecrets);return i.secretmanager={getSecret:s,getSecrets:c,[n]:o},withDispose({getSecret:s,getSecrets:c,setSecrets(e){o.store=e},setSecret(e,t,n){o.store={...o.store,[e]:{...o.store[e],[t]:n}}},mergeSecrets(e,t){o.store={...o.store,[e]:{...o.store[e],...t}}},get calls(){return[...s.mock.calls.map((e,t)=>({order:s.mock.invocationCallOrder[t]??0,call:{method:`getSecret`,vault:e[0],name:e[1]}})),...c.mock.calls.map((e,t)=>({order:c.mock.invocationCallOrder[t]??0,call:{method:`getSecrets`,vault:e[0],names:e[1]}}))].toSorted((e,t)=>e.order-t.order).map(e=>e.call)},clear(){s.mockClear(),c.mockClear()},reset(){o.store={},s.mockReset(),s.mockImplementation(defaultGetSecret),c.mockReset(),c.mockImplementation(defaultGetSecrets)}},()=>{i.secretmanager=a})}export{withDispose as i,tailorRoot as n,tailordbRoot as r,mockSecretmanager as t};
2
- //# sourceMappingURL=secretmanager-5olfnI1b.mjs.map
1
+ import{t as e}from"./assert-WeXvmG4j.mjs";import{vi as t}from"vitest";function withDispose(e,t){return Object.defineProperty(e,Symbol.dispose,{value:t,enumerable:!1,writable:!0,configurable:!0}),e}function tailorRoot(){let e=globalThis;return e.tailor||={context:{getInvoker:()=>null}},e.tailor}function tailordbRoot(){let e=globalThis;return e.tailordb||={},e.tailordb}const n=Symbol(`tailorSecretStore`);function mockSecretmanager(r={}){let i=tailorRoot(),a=i.secretmanager,o={store:structuredClone(a?.[n]?.store??{})};for(let[e,t]of Object.entries(r.secrets??{}))o.store[e]={...o.store[e],...t};async function defaultGetSecret(e,t){return o.store[e]?.[t]}async function defaultGetSecrets(t,n){let r=o.store[t]??{},i={};for(let t of n)t in r&&(i[t]=e(r[t],`vault entry missing for: ${t}`));return i}let s=t.fn(defaultGetSecret),c=t.fn(defaultGetSecrets);return i.secretmanager={getSecret:s,getSecrets:c,[n]:o},withDispose({getSecret:s,getSecrets:c,setSecrets(e){o.store=e},setSecret(e,t,n){o.store={...o.store,[e]:{...o.store[e],[t]:n}}},mergeSecrets(e,t){o.store={...o.store,[e]:{...o.store[e],...t}}},get calls(){return[...s.mock.calls.map((e,t)=>({order:s.mock.invocationCallOrder[t]??0,call:{method:`getSecret`,vault:e[0],name:e[1]}})),...c.mock.calls.map((e,t)=>({order:c.mock.invocationCallOrder[t]??0,call:{method:`getSecrets`,vault:e[0],names:e[1]}}))].toSorted((e,t)=>e.order-t.order).map(e=>e.call)},clear(){s.mockClear(),c.mockClear()},reset(){o.store={},s.mockReset(),s.mockImplementation(defaultGetSecret),c.mockReset(),c.mockImplementation(defaultGetSecrets)}},()=>{i.secretmanager=a})}const r=`__TAILOR_PLATFORM_BUNDLE_DATE_DEFAULT`;function applyDateDefault(e){let t=process.env[r];return e===`legacy`?delete process.env[r]:process.env[r]=e,()=>{t===void 0?delete process.env[r]:process.env[r]=t}}function applyDateRepresentation(e){return applyDateDefault(e===`string`?`legacy`:e)}export{tailordbRoot as a,tailorRoot as i,applyDateRepresentation as n,withDispose as o,mockSecretmanager as r,applyDateDefault as t};
2
+ //# sourceMappingURL=date-representation-Cr7W7Pn2.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date-representation-Cr7W7Pn2.mjs","names":["assertDefined","facade","dispose","g","SECRET_STORE","root","prev","holder","vault","secrets","options","name","vaultData","result","names","getSecret","vi","getSecrets","value","i","args","a","b","DATE_DEFAULT_GATE","previous","dateDefault","representation"],"sources":["../src/vitest/mocks/shared.ts","../src/vitest/mocks/secretmanager.ts","../src/vitest/date-representation.ts"],"sourcesContent":["// ---------------------------------------------------------------------------\n// Shared helpers\n// ---------------------------------------------------------------------------\n\n// Attach a non-enumerable `Symbol.dispose` to a facade so it works with `using`.\nexport function withDispose<T extends object>(facade: T, dispose: () => void): T & Disposable {\n Object.defineProperty(facade, Symbol.dispose, {\n value: dispose,\n enumerable: false,\n writable: true,\n configurable: true,\n });\n return facade as T & Disposable;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function tailorRoot(): Record<string, any> {\n const g = globalThis as Record<string, unknown>;\n if (!g.tailor) {\n // Ensure the container (and the always-present context stub) exists even if\n // the base globals were not installed (e.g. a unit test that only acquires\n // a single mock without the tailor-runtime environment).\n g.tailor = { context: { getInvoker: () => null } };\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return g.tailor as Record<string, any>;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function tailordbRoot(): Record<string, any> {\n const g = globalThis as Record<string, unknown>;\n if (!g.tailordb) {\n g.tailordb = {};\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return g.tailordb as Record<string, any>;\n}\n","import { vi } from \"vitest\";\nimport { assertDefined } from \"#/utils/assert\";\nimport { tailorRoot, withDispose } from \"./shared\";\n\ninterface SecretCall {\n method: \"getSecret\" | \"getSecrets\";\n vault: string;\n name?: string;\n names?: readonly string[];\n}\n\n/** Initial fixtures for a Secret Manager mock. */\nexport interface MockSecretmanagerOptions {\n /** Secrets to merge over fixtures inherited from the currently installed mock. */\n secrets?: Record<string, Record<string, string>>;\n}\n\n// ---------------------------------------------------------------------------\n// SecretManager Mock\n// ---------------------------------------------------------------------------\n\n// Hidden accessor key used to inherit the previous scope's secret store on\n// acquisition (so secrets seeded once outside tests — e.g. from tailor.config.ts\n// via setup.ts — remain visible) while still isolating per-test overrides.\nconst SECRET_STORE = Symbol(\"tailorSecretStore\");\n\n/**\n * Acquire a disposable mock for `tailor.secretmanager`. The secret store is\n * inherited (cloned) from the currently-installed mock on acquisition and\n * restored on dispose, so secrets seeded outside the test survive across\n * `using` scopes while per-test `setSecrets()` overrides stay isolated.\n * @param options - Initial Secret Manager fixtures\n * @returns Disposable SecretManager mock control object\n * @example\n * ```typescript\n * import { mockSecretmanager } from \"@tailor-platform/sdk/vitest\";\n *\n * test(\"reads secrets from vault\", async () => {\n * using sm = mockSecretmanager({ secrets: { \"my-vault\": { API_KEY: \"sk-123\" } } });\n * sm.setSecret(\"my-vault\", \"API_KEY\", \"replacement\");\n * // …\n * });\n * ```\n */\nexport function mockSecretmanager(options: MockSecretmanagerOptions = {}) {\n const root = tailorRoot();\n const prev = root.secretmanager;\n\n const holder: { store: Record<string, Record<string, string>> } = {\n // prior mock state may be absent\n // oxlint-disable-next-line typescript/no-unnecessary-condition\n store: structuredClone((prev?.[SECRET_STORE]?.store as typeof holder.store) ?? {}),\n };\n for (const [vault, secrets] of Object.entries(options.secrets ?? {})) {\n holder.store[vault] = { ...holder.store[vault], ...secrets };\n }\n\n async function defaultGetSecret(vault: string, name: string): Promise<string | undefined> {\n return holder.store[vault]?.[name];\n }\n\n async function defaultGetSecrets<const T extends readonly string[]>(\n vault: string,\n names: T,\n ): Promise<Partial<Record<T[number], string>>> {\n const vaultData = holder.store[vault] ?? {};\n const result: Record<string, string> = {};\n for (const name of names) {\n if (name in vaultData) {\n result[name] = assertDefined(vaultData[name], `vault entry missing for: ${name}`);\n }\n }\n return result as Partial<Record<T[number], string>>;\n }\n\n const getSecret = vi.fn(defaultGetSecret);\n const getSecrets = vi.fn(defaultGetSecrets);\n\n root.secretmanager = { getSecret, getSecrets, [SECRET_STORE]: holder };\n\n const facade = {\n /** The `getSecret` `vi.fn`. */\n getSecret,\n /** The `getSecrets` `vi.fn`. */\n getSecrets,\n\n setSecrets(secrets: Record<string, Record<string, string>>): void {\n holder.store = secrets;\n },\n\n setSecret(vault: string, name: string, value: string): void {\n holder.store = {\n ...holder.store,\n [vault]: { ...holder.store[vault], [name]: value },\n };\n },\n\n mergeSecrets(vault: string, secrets: Record<string, string>): void {\n holder.store = {\n ...holder.store,\n [vault]: { ...holder.store[vault], ...secrets },\n };\n },\n\n get calls(): SecretCall[] {\n // Merge both methods' calls back into chronological order via vi.fn's\n // global invocationCallOrder, so a test mixing getSecret/getSecrets sees\n // them in the order they actually ran (not all getSecret, then all getSecrets).\n const entries: { order: number; call: SecretCall }[] = [\n ...getSecret.mock.calls.map((args, i) => ({\n order: getSecret.mock.invocationCallOrder[i] ?? 0,\n call: { method: \"getSecret\" as const, vault: args[0], name: args[1] },\n })),\n ...getSecrets.mock.calls.map((args, i) => ({\n order: getSecrets.mock.invocationCallOrder[i] ?? 0,\n call: {\n method: \"getSecrets\" as const,\n vault: args[0],\n names: args[1],\n },\n })),\n ];\n return entries.toSorted((a, b) => a.order - b.order).map((e) => e.call);\n },\n\n clear(): void {\n getSecret.mockClear();\n getSecrets.mockClear();\n },\n\n reset(): void {\n holder.store = {};\n getSecret.mockReset();\n getSecret.mockImplementation(defaultGetSecret);\n getSecrets.mockReset();\n getSecrets.mockImplementation(defaultGetSecrets);\n },\n };\n\n return withDispose(facade, () => {\n root.secretmanager = prev;\n });\n}\n","import type { DateRepresentationOption } from \"#/configure/types/field.types\";\nimport type { EffectiveDateDefault } from \"#/runtime/types\";\n\nconst DATE_DEFAULT_GATE = \"__TAILOR_PLATFORM_BUNDLE_DATE_DEFAULT\";\n\n/**\n * Expose the date default to `t` date fields in this worker, the way the\n * define plugin folds it into deployed bundles.\n * @param dateDefault - The representation `t` date fields without `as` follow\n * @returns A function that restores the previous value\n */\nexport function applyDateDefault(dateDefault: EffectiveDateDefault): () => void {\n const previous = process.env[DATE_DEFAULT_GATE];\n if (dateDefault === \"legacy\") {\n delete process.env[DATE_DEFAULT_GATE];\n } else {\n process.env[DATE_DEFAULT_GATE] = dateDefault;\n }\n return () => {\n if (previous === undefined) delete process.env[DATE_DEFAULT_GATE];\n else process.env[DATE_DEFAULT_GATE] = previous;\n };\n}\n\n/**\n * Give `t.date()`, `t.datetime()`, and `t.time()` fields that omit `as` the\n * given representation for the rest of this test worker, as if the code under\n * test were bundled under that `defaultDateRepresentation`; `\"string\"` is the\n * representation of a project that leaves the setting unset. Generated\n * migration tests call it with the representation recorded in the migration's\n * `diff.json`, so a later change to `tailor.config.ts` does not alter what the\n * test exercises.\n * @param representation - The representation to apply, as `as` names it\n * @returns A function that restores the previous representation\n */\nexport function applyDateRepresentation(representation: DateRepresentationOption): () => void {\n return applyDateDefault(representation === \"string\" ? \"legacy\" : representation);\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{n as e,o as t,t as n}from"./date-Dri6Yas-.mjs";const r={uuid:/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,date:/^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})$/,time:/^(?<hour>[01]\d|2[0-3]):(?<minute>[0-5]\d)$/,datetime:/^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})[Tt](?<hour>[01]\d|2[0-3]):(?<minute>[0-5]\d):(?<second>[0-5]\d|60)(\.(?<fraction>\d+))?(?<offset>[Zz]|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/,decimal:/^-?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/};function isNestedObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)&&!(e instanceof Date)}function validateBaseValue(e){let{field:t,value:n,pathArray:i,issues:a}=e,o=i.length>0?i:void 0,s=a.length;switch(t.type){case`string`:typeof n!=`string`&&a.push({message:`Expected a string: received ${String(n)}`,path:o});break;case`integer`:(typeof n!=`number`||!Number.isInteger(n))&&a.push({message:`Expected an integer: received ${String(n)}`,path:o});break;case`float`:(typeof n!=`number`||!Number.isFinite(n))&&a.push({message:`Expected a number: received ${String(n)}`,path:o});break;case`boolean`:typeof n!=`boolean`&&a.push({message:`Expected a boolean: received ${String(n)}`,path:o});break;case`uuid`:(typeof n!=`string`||!r.uuid.test(n))&&a.push({message:`Expected a valid UUID: received ${String(n)}`,path:o});break;case`date`:(typeof n!=`string`||!r.date.test(n))&&a.push({message:`Expected to match "yyyy-MM-dd" format: received ${String(n)}`,path:o});break;case`datetime`:(typeof n!=`string`||!r.datetime.test(n))&&a.push({message:`Expected to match ISO format: received ${String(n)}`,path:o});break;case`time`:(typeof n!=`string`||!r.time.test(n))&&a.push({message:`Expected to match "HH:mm" format: received ${String(n)}`,path:o});break;case`decimal`:(typeof n!=`string`||!r.decimal.test(n))&&a.push({message:`Expected a decimal string: received ${String(n)}`,path:o});break;case`enum`:if(t._metadata.allowedValues){let e=t._metadata.allowedValues.map(e=>e.value);(typeof n!=`string`||!e.includes(n))&&a.push({message:`Must be one of [${e.join(`, `)}]: received ${String(n)}`,path:o})}break;case`nested`:{if(!isNestedObject(n))return a.push({message:`Expected an object: received ${String(n)}`,path:o}),!1;let r=!0;for(let[a,o]of Object.entries(t.fields)){let t=n[a];validateBaseField({...e,field:o,value:t,pathArray:i.concat(a)})||(r=!1)}return r}}return a.length===s}function validateCustomValue(e,t){let{value:n,pathArray:r,issues:i}=e,a=r.length>0?r:void 0;for(let e of t){let t=e({value:n});typeof t==`string`&&i.push({message:t,path:a})}}function validateBaseField(e){let{field:t,value:n,pathArray:r,issues:i}=e,a=r.length>0?r:void 0,o=n==null;if(t._metadata.required&&o)return i.push({message:`Required field is missing`,path:a}),!1;if(!t._metadata.required&&o)return!0;let s=!0;if(t._metadata.array){if(!Array.isArray(n))return i.push({message:`Expected an array`,path:a}),!1;for(let t=0;t<n.length;t++)validateBaseValue({...e,value:n[t],pathArray:r.concat(`[${t}]`)})||(s=!1)}else s=validateBaseValue(e);return s}function validateCustomField(e){let{field:t,value:n,pathArray:r}=e;if(n==null)return;if(t.type===`nested`){let i=t._metadata.array?n:[n];for(let n=0;n<i.length;n++){let a=i[n],o=t._metadata.array?r.concat(`[${n}]`):r;for(let[n,r]of Object.entries(t.fields))validateCustomField({...e,field:r,value:a[n],pathArray:o.concat(n)})}}let i=t._metadata.validate;i?.length&&validateCustomValue(e,i)}function parseInternal(e,t=a){let{value:n}=e,r=[],i={...e,issues:r};return validateBaseField(i)&&(n=deserializeDates(i,t),r.length===0&&validateCustomField({...i,value:n})),r.length>0?{issues:r}:{value:n??null}}function rejectLeapSecond(e,t){if(e===`datetime`&&t.slice(17,19)===`60`)throw RangeError(`Leap seconds are not supported`)}function parseAsDate(t,n){rejectLeapSecond(t,n);let r=new Date(t===`date`?`${n}T00:00:00.000Z`:t===`time`?`1970-01-01T${n}:00.000Z`:n);if(!Number.isFinite(r.getTime()))throw RangeError(`Invalid Date`);if(t!==`time`){let t=n.slice(0,10);if(e(/* @__PURE__ */ new Date(`${t}T00:00:00.000Z`))!==t)throw RangeError(`Invalid calendar date`)}return r}function parseAsTemporal(e,n){rejectLeapSecond(e,n);let r=t();return e===`date`?r.PlainDate.from(n):e===`datetime`?r.Instant.from(n):r.PlainTime.from(n)}const i={date:parseAsDate,temporal:parseAsTemporal},a={date:globalThis.process?.env.__TAILOR_PLATFORM_BUNDLE_WITHOUT_DATE?void 0:parseAsDate,temporal:globalThis.process?.env.__TAILOR_PLATFORM_BUNDLE_WITHOUT_TEMPORAL?void 0:parseAsTemporal};function deserializeDates(e,t){let{field:r,value:i,issues:a,pathArray:o}=e;if(i==null)return i;let convert=(i,o)=>{let{type:s}=r,c=n(s,r._metadata.as);if(c){let e=t[c];if(!e)throw Error(`Parsing fields declared with as: "${c}" is not included in this bundle. Parse them with parseDateFields, exported by "@tailor-platform/sdk/runtime".`);try{return e(s,String(i))}catch(e){if(!(e instanceof RangeError))throw e;return a.push({message:`Expected a valid ${s===`date`?`calendar date`:s}: received ${i}`,path:o.length>0?o:void 0}),i}}if(r.type!==`nested`)return i;let l=i,u=l;for(let[n,i]of Object.entries(r.fields)){let r=deserializeDates({...e,field:i,value:l[n],pathArray:o.concat(n)},t);r!==l[n]&&(u===l&&(u={...l}),Object.defineProperty(u,n,{value:r,enumerable:!0,configurable:!0,writable:!0}))}return u};if(!r._metadata.array)return convert(i,o);let s=i,c=s.map((e,t)=>convert(e,o.concat(`[${t}]`)));return c.every((e,t)=>e===s[t])?i:c}function parseInputFields(e){let{fields:t,...n}=e;return parseInternal({...n,field:{type:`nested`,fields:t,_metadata:{required:!0}},pathArray:[]})}function parseDateFields(e,t){return parseInternal({...t,field:e,pathArray:[]},i)}export{parseInternal as i,parseDateFields as n,parseInputFields as r,isNestedObject as t};
2
- //# sourceMappingURL=field-parse-DhnFs9WG.mjs.map
1
+ import{n as e,o as t,t as n}from"./date-CgP7gMG_.mjs";const r={uuid:/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,date:/^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})$/,time:/^(?<hour>[01]\d|2[0-3]):(?<minute>[0-5]\d)$/,datetime:/^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})[Tt](?<hour>[01]\d|2[0-3]):(?<minute>[0-5]\d):(?<second>[0-5]\d|60)(\.(?<fraction>\d+))?(?<offset>[Zz]|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/,decimal:/^-?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/};function isNestedObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)&&!(e instanceof Date)}function validateBaseValue(e){let{field:t,value:n,pathArray:i,issues:a}=e,o=i.length>0?i:void 0,s=a.length;switch(t.type){case`string`:typeof n!=`string`&&a.push({message:`Expected a string: received ${String(n)}`,path:o});break;case`integer`:(typeof n!=`number`||!Number.isInteger(n))&&a.push({message:`Expected an integer: received ${String(n)}`,path:o});break;case`float`:(typeof n!=`number`||!Number.isFinite(n))&&a.push({message:`Expected a number: received ${String(n)}`,path:o});break;case`boolean`:typeof n!=`boolean`&&a.push({message:`Expected a boolean: received ${String(n)}`,path:o});break;case`uuid`:(typeof n!=`string`||!r.uuid.test(n))&&a.push({message:`Expected a valid UUID: received ${String(n)}`,path:o});break;case`date`:(typeof n!=`string`||!r.date.test(n))&&a.push({message:`Expected to match "yyyy-MM-dd" format: received ${String(n)}`,path:o});break;case`datetime`:(typeof n!=`string`||!r.datetime.test(n))&&a.push({message:`Expected to match ISO format: received ${String(n)}`,path:o});break;case`time`:(typeof n!=`string`||!r.time.test(n))&&a.push({message:`Expected to match "HH:mm" format: received ${String(n)}`,path:o});break;case`decimal`:(typeof n!=`string`||!r.decimal.test(n))&&a.push({message:`Expected a decimal string: received ${String(n)}`,path:o});break;case`enum`:if(t._metadata.allowedValues){let e=t._metadata.allowedValues.map(e=>e.value);(typeof n!=`string`||!e.includes(n))&&a.push({message:`Must be one of [${e.join(`, `)}]: received ${String(n)}`,path:o})}break;case`nested`:{if(!isNestedObject(n))return a.push({message:`Expected an object: received ${String(n)}`,path:o}),!1;let r=!0;for(let[a,o]of Object.entries(t.fields)){let t=n[a];validateBaseField({...e,field:o,value:t,pathArray:i.concat(a)})||(r=!1)}return r}}return a.length===s}function validateCustomValue(e,t){let{value:n,pathArray:r,issues:i}=e,a=r.length>0?r:void 0;for(let e of t){let t=e({value:n});typeof t==`string`&&i.push({message:t,path:a})}}function validateBaseField(e){let{field:t,value:n,pathArray:r,issues:i}=e,a=r.length>0?r:void 0,o=n==null;if(t._metadata.required&&o)return i.push({message:`Required field is missing`,path:a}),!1;if(!t._metadata.required&&o)return!0;let s=!0;if(t._metadata.array){if(!Array.isArray(n))return i.push({message:`Expected an array`,path:a}),!1;for(let t=0;t<n.length;t++)validateBaseValue({...e,value:n[t],pathArray:r.concat(`[${t}]`)})||(s=!1)}else s=validateBaseValue(e);return s}function validateCustomField(e){let{field:t,value:n,pathArray:r}=e;if(n==null)return;if(t.type===`nested`){let i=t._metadata.array?n:[n];for(let n=0;n<i.length;n++){let a=i[n],o=t._metadata.array?r.concat(`[${n}]`):r;for(let[n,r]of Object.entries(t.fields))validateCustomField({...e,field:r,value:a[n],pathArray:o.concat(n)})}}let i=t._metadata.validate;i?.length&&validateCustomValue(e,i)}function parseInternal(e,t=a){let{value:n}=e,r=[],i={...e,issues:r};return validateBaseField(i)&&(n=deserializeDates(i,t),r.length===0&&validateCustomField({...i,value:n})),r.length>0?{issues:r}:{value:n??null}}function rejectLeapSecond(e,t){if(e===`datetime`&&t.slice(17,19)===`60`)throw RangeError(`Leap seconds are not supported`)}function parseAsDate(t,n){rejectLeapSecond(t,n);let r=new Date(t===`date`?`${n}T00:00:00.000Z`:t===`time`?`1970-01-01T${n}:00.000Z`:n);if(!Number.isFinite(r.getTime()))throw RangeError(`Invalid Date`);if(t!==`time`){let t=n.slice(0,10);if(e(/* @__PURE__ */ new Date(`${t}T00:00:00.000Z`))!==t)throw RangeError(`Invalid calendar date`)}return r}function parseAsTemporal(e,n){rejectLeapSecond(e,n);let r=t();return e===`date`?r.PlainDate.from(n):e===`datetime`?r.Instant.from(n):r.PlainTime.from(n)}const i={date:parseAsDate,temporal:parseAsTemporal},a={date:globalThis.process?.env.__TAILOR_PLATFORM_BUNDLE_WITHOUT_DATE?void 0:parseAsDate,temporal:globalThis.process?.env.__TAILOR_PLATFORM_BUNDLE_WITHOUT_TEMPORAL?void 0:parseAsTemporal};function deserializeDates(e,t){let{field:r,value:i,issues:a,pathArray:o}=e;if(i==null)return i;let convert=(i,o)=>{let{type:s}=r,c=n(s,r._metadata.as);if(c){let e=t[c];if(!e)throw Error(`Parsing fields declared with as: "${c}" is not included in this bundle. Parse them with parseDateFields, exported by "@tailor-platform/sdk/runtime".`);try{return e(s,String(i))}catch(e){if(!(e instanceof RangeError))throw e;return a.push({message:`Expected a valid ${s===`date`?`calendar date`:s}: received ${i}`,path:o.length>0?o:void 0}),i}}if(r.type!==`nested`)return i;let l=i,u=l;for(let[n,i]of Object.entries(r.fields)){let r=deserializeDates({...e,field:i,value:l[n],pathArray:o.concat(n)},t);r!==l[n]&&(u===l&&(u={...l}),Object.defineProperty(u,n,{value:r,enumerable:!0,configurable:!0,writable:!0}))}return u};if(!r._metadata.array)return convert(i,o);let s=i,c=s.map((e,t)=>convert(e,o.concat(`[${t}]`)));return c.every((e,t)=>e===s[t])?i:c}function parseInputFields(e){let{fields:t,...n}=e;return parseInternal({...n,field:{type:`nested`,fields:t,_metadata:{required:!0}},pathArray:[]})}function parseDateFields(e,t){return parseInternal({...t,field:e,pathArray:[]},i)}export{parseInternal as i,parseDateFields as n,parseInputFields as r,isNestedObject as t};
2
+ //# sourceMappingURL=field-parse-C41e3UAF.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"field-parse-DhnFs9WG.mjs","names":["formatDate","getTemporal","dateRepresentationOf","regex","value","args","path","pathArray","initialIssueCount","issues","field","allowedValues","v","nestedBaseValid","fieldName","nestedField","fieldValue","fn","validateFns","result","isNullOrUndefined","baseValid","i","records","record","recordPath","bundledDateParsers","validationArgs","dateParsers","type","text","date","calendarDate","Temporal","allDateParsers","as","parse","item","error","itemPath","key","child","converted","values","index","parseArgs"],"sources":["../src/runtime/field-parse.ts"],"sourcesContent":["import { dateRepresentationOf, formatDate } from \"./date\";\nimport { getTemporal } from \"./temporal\";\nimport type { FieldMetadata, TailorFieldType } from \"#/configure/types/field.types\";\nimport type { TailorPrincipal } from \"#/runtime/types\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\nconst regex = {\n uuid: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,\n date: /^(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})$/,\n time: /^(?<hour>[01]\\d|2[0-3]):(?<minute>[0-5]\\d)$/,\n datetime:\n /^(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})[Tt](?<hour>[01]\\d|2[0-3]):(?<minute>[0-5]\\d):(?<second>[0-5]\\d|60)(\\.(?<fraction>\\d+))?(?<offset>[Zz]|[+-](?:[01]\\d|2[0-3]):[0-5]\\d)$/,\n decimal: /^-?(\\d+\\.?\\d*|\\.\\d+)([eE][+-]?\\d+)?$/,\n} as const;\n\n/**\n * Whether a value is an acceptable shape for a nested field. Runtime input may\n * not match the declared field type, so anything this rejects is reported\n * against the field rather than recursed into.\n * @param value - The value to check\n * @returns `true` when the value is a plain object the parser recurses into\n */\nexport function isNestedObject(value: unknown): value is Record<string, unknown> {\n return (\n typeof value === \"object\" && value !== null && !Array.isArray(value) && !(value instanceof Date)\n );\n}\n\nexport type FieldParseArgs = {\n value: unknown;\n data: unknown;\n invoker: TailorPrincipal | null;\n};\n\nexport type FieldParseInternalArgs = {\n value: unknown;\n data: unknown;\n invoker: TailorPrincipal | null;\n pathArray: string[];\n};\n\nexport type FieldRuntime<T extends TailorFieldType = TailorFieldType> = {\n readonly type: T;\n readonly fields: Record<string, FieldRuntime>;\n _metadata: FieldMetadata;\n};\n\ntype FieldParseRuntimeArgs<T extends TailorFieldType> = FieldParseInternalArgs & {\n field: FieldRuntime<T>;\n};\n\ntype FieldValidationArgs<T extends TailorFieldType> = FieldParseRuntimeArgs<T> & {\n issues: StandardSchemaV1.Issue[];\n};\n\nfunction validateBaseValue<T extends TailorFieldType>(args: FieldValidationArgs<T>): boolean {\n const { field, value, pathArray, issues } = args;\n const path = pathArray.length > 0 ? pathArray : undefined;\n const initialIssueCount = issues.length;\n\n switch (field.type) {\n case \"string\":\n if (typeof value !== \"string\") {\n issues.push({\n message: `Expected a string: received ${String(value)}`,\n path,\n });\n }\n break;\n\n case \"integer\":\n if (typeof value !== \"number\" || !Number.isInteger(value)) {\n issues.push({\n message: `Expected an integer: received ${String(value)}`,\n path,\n });\n }\n break;\n\n case \"float\":\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n issues.push({\n message: `Expected a number: received ${String(value)}`,\n path,\n });\n }\n break;\n\n case \"boolean\":\n if (typeof value !== \"boolean\") {\n issues.push({\n message: `Expected a boolean: received ${String(value)}`,\n path,\n });\n }\n break;\n\n case \"uuid\":\n if (typeof value !== \"string\" || !regex.uuid.test(value)) {\n issues.push({\n message: `Expected a valid UUID: received ${String(value)}`,\n path,\n });\n }\n break;\n case \"date\":\n if (typeof value !== \"string\" || !regex.date.test(value)) {\n issues.push({\n message: `Expected to match \"yyyy-MM-dd\" format: received ${String(value)}`,\n path,\n });\n }\n break;\n case \"datetime\":\n if (typeof value !== \"string\" || !regex.datetime.test(value)) {\n issues.push({\n message: `Expected to match ISO format: received ${String(value)}`,\n path,\n });\n }\n break;\n case \"time\":\n if (typeof value !== \"string\" || !regex.time.test(value)) {\n issues.push({\n message: `Expected to match \"HH:mm\" format: received ${String(value)}`,\n path,\n });\n }\n break;\n case \"decimal\":\n if (typeof value !== \"string\" || !regex.decimal.test(value)) {\n issues.push({\n message: `Expected a decimal string: received ${String(value)}`,\n path,\n });\n }\n break;\n\n case \"enum\":\n if (field._metadata.allowedValues) {\n const allowedValues = field._metadata.allowedValues.map((v) => v.value);\n if (typeof value !== \"string\" || !allowedValues.includes(value)) {\n issues.push({\n message: `Must be one of [${allowedValues.join(\", \")}]: received ${String(value)}`,\n path,\n });\n }\n }\n break;\n\n case \"nested\": {\n if (!isNestedObject(value)) {\n issues.push({\n message: `Expected an object: received ${String(value)}`,\n path,\n });\n return false;\n }\n\n let nestedBaseValid = true;\n for (const [fieldName, nestedField] of Object.entries(field.fields)) {\n const fieldValue = value[fieldName];\n if (\n !validateBaseField({\n ...args,\n field: nestedField,\n value: fieldValue,\n pathArray: pathArray.concat(fieldName),\n })\n ) {\n nestedBaseValid = false;\n }\n }\n return nestedBaseValid;\n }\n }\n\n return issues.length === initialIssueCount;\n}\n\nfunction validateCustomValue<T extends TailorFieldType>(\n args: FieldValidationArgs<T>,\n validateFns: NonNullable<FieldMetadata[\"validate\"]>,\n): void {\n const { value, pathArray, issues } = args;\n const path = pathArray.length > 0 ? pathArray : undefined;\n\n for (const fn of validateFns) {\n const result = fn({ value });\n if (typeof result === \"string\") {\n issues.push({\n message: result,\n path,\n });\n }\n }\n}\n\nfunction validateBaseField<T extends TailorFieldType>(args: FieldValidationArgs<T>): boolean {\n const { field, value, pathArray, issues } = args;\n const path = pathArray.length > 0 ? pathArray : undefined;\n\n const isNullOrUndefined = value === null || value === undefined;\n if (field._metadata.required && isNullOrUndefined) {\n issues.push({\n message: \"Required field is missing\",\n path,\n });\n return false;\n }\n\n if (!field._metadata.required && isNullOrUndefined) {\n return true;\n }\n\n let baseValid = true;\n if (field._metadata.array) {\n if (!Array.isArray(value)) {\n issues.push({\n message: \"Expected an array\",\n path,\n });\n return false;\n }\n\n for (let i = 0; i < value.length; i++) {\n if (\n !validateBaseValue({\n ...args,\n value: value[i],\n pathArray: pathArray.concat(`[${i}]`),\n })\n ) {\n baseValid = false;\n }\n }\n } else {\n baseValid = validateBaseValue(args);\n }\n\n return baseValid;\n}\n\nfunction validateCustomField<T extends TailorFieldType>(args: FieldValidationArgs<T>): void {\n const { field, value, pathArray } = args;\n if (value === null || value === undefined) {\n return;\n }\n\n if (field.type === \"nested\") {\n const records = field._metadata.array\n ? (value as Record<string, unknown>[])\n : [value as Record<string, unknown>];\n\n for (let i = 0; i < records.length; i++) {\n const record = records[i] as Record<string, unknown>;\n const recordPath = field._metadata.array ? pathArray.concat(`[${i}]`) : pathArray;\n for (const [fieldName, nestedField] of Object.entries(field.fields)) {\n validateCustomField({\n ...args,\n field: nestedField,\n value: record[fieldName],\n pathArray: recordPath.concat(fieldName),\n });\n }\n }\n }\n\n const validateFns = field._metadata.validate;\n if (validateFns?.length) {\n validateCustomValue(args, validateFns);\n }\n}\n\nexport function parseInternal<T extends TailorFieldType, Output>(\n args: FieldParseRuntimeArgs<T>,\n dateParsers: DateParsers = bundledDateParsers,\n): StandardSchemaV1.Result<Output> {\n let { value } = args;\n const issues: StandardSchemaV1.Issue[] = [];\n const validationArgs = { ...args, issues };\n const baseValid = validateBaseField(validationArgs);\n if (baseValid) {\n value = deserializeDates(validationArgs, dateParsers);\n if (issues.length === 0) {\n validateCustomField({ ...validationArgs, value });\n }\n }\n if (issues.length > 0) {\n return { issues };\n }\n\n return { value: (value ?? null) as Output };\n}\n\ntype DateParser = (type: TailorFieldType, text: string) => unknown;\n\ntype DateParsers = {\n readonly date: DateParser | undefined;\n readonly temporal: DateParser | undefined;\n};\n\nfunction rejectLeapSecond(type: TailorFieldType, text: string): void {\n if (type === \"datetime\" && text.slice(17, 19) === \"60\") {\n throw new RangeError(\"Leap seconds are not supported\");\n }\n}\n\nfunction parseAsDate(type: TailorFieldType, text: string): Date {\n rejectLeapSecond(type, text);\n const date = new Date(\n type === \"date\"\n ? `${text}T00:00:00.000Z`\n : type === \"time\"\n ? `1970-01-01T${text}:00.000Z`\n : text,\n );\n if (!Number.isFinite(date.getTime())) throw new RangeError(\"Invalid Date\");\n if (type !== \"time\") {\n const calendarDate = text.slice(0, 10);\n if (formatDate(new Date(`${calendarDate}T00:00:00.000Z`)) !== calendarDate) {\n throw new RangeError(\"Invalid calendar date\");\n }\n }\n return date;\n}\n\nfunction parseAsTemporal(type: TailorFieldType, text: string): unknown {\n rejectLeapSecond(type, text);\n const Temporal = getTemporal();\n if (type === \"date\") return Temporal.PlainDate.from(text);\n if (type === \"datetime\") return Temporal.Instant.from(text);\n return Temporal.PlainTime.from(text);\n}\n\nconst allDateParsers: DateParsers = { date: parseAsDate, temporal: parseAsTemporal };\n\ntype MaybeProcessGlobal = { process?: { env: Record<string, string | undefined> } };\n\nconst bundledDateParsers: DateParsers = {\n date: (globalThis as MaybeProcessGlobal).process?.env.__TAILOR_PLATFORM_BUNDLE_WITHOUT_DATE\n ? undefined\n : parseAsDate,\n temporal: (globalThis as MaybeProcessGlobal).process?.env\n .__TAILOR_PLATFORM_BUNDLE_WITHOUT_TEMPORAL\n ? undefined\n : parseAsTemporal,\n};\n\nfunction deserializeDates(\n args: FieldValidationArgs<TailorFieldType>,\n dateParsers: DateParsers,\n): unknown {\n const { field, value, issues, pathArray } = args;\n if (value === null || value === undefined) return value;\n const convert = (item: unknown, itemPath: string[]): unknown => {\n const { type } = field;\n const as = dateRepresentationOf(type, field._metadata.as);\n if (as) {\n const parse = dateParsers[as];\n if (!parse) {\n throw new Error(\n `Parsing fields declared with as: \"${as}\" is not included in this bundle. Parse them with parseDateFields, exported by \"@tailor-platform/sdk/runtime\".`,\n );\n }\n try {\n return parse(type, String(item));\n } catch (error) {\n if (!(error instanceof RangeError)) throw error;\n issues.push({\n message: `Expected a valid ${type === \"date\" ? \"calendar date\" : type}: received ${item}`,\n path: itemPath.length > 0 ? itemPath : undefined,\n });\n return item;\n }\n }\n if (field.type !== \"nested\") return item;\n const record = item as Record<string, unknown>;\n let result = record;\n for (const [key, child] of Object.entries(field.fields)) {\n const converted = deserializeDates(\n {\n ...args,\n field: child,\n value: record[key],\n pathArray: itemPath.concat(key),\n },\n dateParsers,\n );\n if (converted !== record[key]) {\n if (result === record) result = { ...record };\n Object.defineProperty(result, key, {\n value: converted,\n enumerable: true,\n configurable: true,\n writable: true,\n });\n }\n }\n return result;\n };\n if (!field._metadata.array) return convert(value, pathArray);\n const values = value as unknown[];\n const converted = values.map((item, index) => convert(item, pathArray.concat(`[${index}]`)));\n return converted.every((item, index) => item === values[index]) ? value : converted;\n}\n\ntype ParseInputFieldsArgs = FieldParseArgs & {\n fields: Record<string, FieldRuntime>;\n};\n\n/**\n * Validate a value against a record of input fields, treating the record as a\n * single required object — the same code path deployed functions run via\n * `t.object(fields).parse(...)`, so local validation matches platform behavior.\n * @param args - Input field definitions plus the value, context data, and user\n * @returns Validation result\n */\nexport function parseInputFields(args: ParseInputFieldsArgs): StandardSchemaV1.Result<unknown> {\n const { fields, ...parseArgs } = args;\n return parseInternal({\n ...parseArgs,\n field: { type: \"nested\", fields, _metadata: { required: true } },\n pathArray: [],\n });\n}\n\ntype ParsableField<Output> = FieldRuntime & {\n parse(args: FieldParseArgs): StandardSchemaV1.Result<Output>;\n};\n\n/**\n * Parse a value like `field.parse`, converting fields declared with `as: \"date\"` or\n * `as: \"temporal\"` even in bundles that leave that conversion out of `field.parse`.\n * @param field - Field defining the value's shape\n * @param args - Value to parse, with the context data and invoker passed to validators\n * @returns Validation result with Date and Temporal fields converted\n */\nexport function parseDateFields<Output>(\n field: ParsableField<Output>,\n args: FieldParseArgs,\n): StandardSchemaV1.Result<Output> {\n return parseInternal({ ...args, field, pathArray: [] }, allDateParsers);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"field-parse-C41e3UAF.mjs","names":["formatDate","getTemporal","dateRepresentationOf","regex","value","args","path","pathArray","initialIssueCount","issues","field","allowedValues","v","nestedBaseValid","fieldName","nestedField","fieldValue","fn","validateFns","result","isNullOrUndefined","baseValid","i","records","record","recordPath","bundledDateParsers","validationArgs","dateParsers","type","text","date","calendarDate","Temporal","allDateParsers","as","parse","item","error","itemPath","key","child","converted","values","index","parseArgs"],"sources":["../src/runtime/field-parse.ts"],"sourcesContent":["import { dateRepresentationOf, formatDate } from \"./date\";\nimport { getTemporal } from \"./temporal\";\nimport type { FieldMetadata, TailorFieldType } from \"#/configure/types/field.types\";\nimport type { TailorPrincipal } from \"#/runtime/types\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\nconst regex = {\n uuid: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,\n date: /^(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})$/,\n time: /^(?<hour>[01]\\d|2[0-3]):(?<minute>[0-5]\\d)$/,\n datetime:\n /^(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})[Tt](?<hour>[01]\\d|2[0-3]):(?<minute>[0-5]\\d):(?<second>[0-5]\\d|60)(\\.(?<fraction>\\d+))?(?<offset>[Zz]|[+-](?:[01]\\d|2[0-3]):[0-5]\\d)$/,\n decimal: /^-?(\\d+\\.?\\d*|\\.\\d+)([eE][+-]?\\d+)?$/,\n} as const;\n\n/**\n * Whether a value is an acceptable shape for a nested field. Runtime input may\n * not match the declared field type, so anything this rejects is reported\n * against the field rather than recursed into.\n * @param value - The value to check\n * @returns `true` when the value is a plain object the parser recurses into\n */\nexport function isNestedObject(value: unknown): value is Record<string, unknown> {\n return (\n typeof value === \"object\" && value !== null && !Array.isArray(value) && !(value instanceof Date)\n );\n}\n\nexport type FieldParseArgs = {\n value: unknown;\n data: unknown;\n invoker: TailorPrincipal | null;\n};\n\nexport type FieldParseInternalArgs = {\n value: unknown;\n data: unknown;\n invoker: TailorPrincipal | null;\n pathArray: string[];\n};\n\nexport type FieldRuntime<T extends TailorFieldType = TailorFieldType> = {\n readonly type: T;\n readonly fields: Record<string, FieldRuntime>;\n _metadata: FieldMetadata;\n};\n\ntype FieldParseRuntimeArgs<T extends TailorFieldType> = FieldParseInternalArgs & {\n field: FieldRuntime<T>;\n};\n\ntype FieldValidationArgs<T extends TailorFieldType> = FieldParseRuntimeArgs<T> & {\n issues: StandardSchemaV1.Issue[];\n};\n\nfunction validateBaseValue<T extends TailorFieldType>(args: FieldValidationArgs<T>): boolean {\n const { field, value, pathArray, issues } = args;\n const path = pathArray.length > 0 ? pathArray : undefined;\n const initialIssueCount = issues.length;\n\n switch (field.type) {\n case \"string\":\n if (typeof value !== \"string\") {\n issues.push({\n message: `Expected a string: received ${String(value)}`,\n path,\n });\n }\n break;\n\n case \"integer\":\n if (typeof value !== \"number\" || !Number.isInteger(value)) {\n issues.push({\n message: `Expected an integer: received ${String(value)}`,\n path,\n });\n }\n break;\n\n case \"float\":\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n issues.push({\n message: `Expected a number: received ${String(value)}`,\n path,\n });\n }\n break;\n\n case \"boolean\":\n if (typeof value !== \"boolean\") {\n issues.push({\n message: `Expected a boolean: received ${String(value)}`,\n path,\n });\n }\n break;\n\n case \"uuid\":\n if (typeof value !== \"string\" || !regex.uuid.test(value)) {\n issues.push({\n message: `Expected a valid UUID: received ${String(value)}`,\n path,\n });\n }\n break;\n case \"date\":\n if (typeof value !== \"string\" || !regex.date.test(value)) {\n issues.push({\n message: `Expected to match \"yyyy-MM-dd\" format: received ${String(value)}`,\n path,\n });\n }\n break;\n case \"datetime\":\n if (typeof value !== \"string\" || !regex.datetime.test(value)) {\n issues.push({\n message: `Expected to match ISO format: received ${String(value)}`,\n path,\n });\n }\n break;\n case \"time\":\n if (typeof value !== \"string\" || !regex.time.test(value)) {\n issues.push({\n message: `Expected to match \"HH:mm\" format: received ${String(value)}`,\n path,\n });\n }\n break;\n case \"decimal\":\n if (typeof value !== \"string\" || !regex.decimal.test(value)) {\n issues.push({\n message: `Expected a decimal string: received ${String(value)}`,\n path,\n });\n }\n break;\n\n case \"enum\":\n if (field._metadata.allowedValues) {\n const allowedValues = field._metadata.allowedValues.map((v) => v.value);\n if (typeof value !== \"string\" || !allowedValues.includes(value)) {\n issues.push({\n message: `Must be one of [${allowedValues.join(\", \")}]: received ${String(value)}`,\n path,\n });\n }\n }\n break;\n\n case \"nested\": {\n if (!isNestedObject(value)) {\n issues.push({\n message: `Expected an object: received ${String(value)}`,\n path,\n });\n return false;\n }\n\n let nestedBaseValid = true;\n for (const [fieldName, nestedField] of Object.entries(field.fields)) {\n const fieldValue = value[fieldName];\n if (\n !validateBaseField({\n ...args,\n field: nestedField,\n value: fieldValue,\n pathArray: pathArray.concat(fieldName),\n })\n ) {\n nestedBaseValid = false;\n }\n }\n return nestedBaseValid;\n }\n }\n\n return issues.length === initialIssueCount;\n}\n\nfunction validateCustomValue<T extends TailorFieldType>(\n args: FieldValidationArgs<T>,\n validateFns: NonNullable<FieldMetadata[\"validate\"]>,\n): void {\n const { value, pathArray, issues } = args;\n const path = pathArray.length > 0 ? pathArray : undefined;\n\n for (const fn of validateFns) {\n const result = fn({ value });\n if (typeof result === \"string\") {\n issues.push({\n message: result,\n path,\n });\n }\n }\n}\n\nfunction validateBaseField<T extends TailorFieldType>(args: FieldValidationArgs<T>): boolean {\n const { field, value, pathArray, issues } = args;\n const path = pathArray.length > 0 ? pathArray : undefined;\n\n const isNullOrUndefined = value === null || value === undefined;\n if (field._metadata.required && isNullOrUndefined) {\n issues.push({\n message: \"Required field is missing\",\n path,\n });\n return false;\n }\n\n if (!field._metadata.required && isNullOrUndefined) {\n return true;\n }\n\n let baseValid = true;\n if (field._metadata.array) {\n if (!Array.isArray(value)) {\n issues.push({\n message: \"Expected an array\",\n path,\n });\n return false;\n }\n\n for (let i = 0; i < value.length; i++) {\n if (\n !validateBaseValue({\n ...args,\n value: value[i],\n pathArray: pathArray.concat(`[${i}]`),\n })\n ) {\n baseValid = false;\n }\n }\n } else {\n baseValid = validateBaseValue(args);\n }\n\n return baseValid;\n}\n\nfunction validateCustomField<T extends TailorFieldType>(args: FieldValidationArgs<T>): void {\n const { field, value, pathArray } = args;\n if (value === null || value === undefined) {\n return;\n }\n\n if (field.type === \"nested\") {\n const records = field._metadata.array\n ? (value as Record<string, unknown>[])\n : [value as Record<string, unknown>];\n\n for (let i = 0; i < records.length; i++) {\n const record = records[i] as Record<string, unknown>;\n const recordPath = field._metadata.array ? pathArray.concat(`[${i}]`) : pathArray;\n for (const [fieldName, nestedField] of Object.entries(field.fields)) {\n validateCustomField({\n ...args,\n field: nestedField,\n value: record[fieldName],\n pathArray: recordPath.concat(fieldName),\n });\n }\n }\n }\n\n const validateFns = field._metadata.validate;\n if (validateFns?.length) {\n validateCustomValue(args, validateFns);\n }\n}\n\nexport function parseInternal<T extends TailorFieldType, Output>(\n args: FieldParseRuntimeArgs<T>,\n dateParsers: DateParsers = bundledDateParsers,\n): StandardSchemaV1.Result<Output> {\n let { value } = args;\n const issues: StandardSchemaV1.Issue[] = [];\n const validationArgs = { ...args, issues };\n const baseValid = validateBaseField(validationArgs);\n if (baseValid) {\n value = deserializeDates(validationArgs, dateParsers);\n if (issues.length === 0) {\n validateCustomField({ ...validationArgs, value });\n }\n }\n if (issues.length > 0) {\n return { issues };\n }\n\n return { value: (value ?? null) as Output };\n}\n\ntype DateParser = (type: TailorFieldType, text: string) => unknown;\n\ntype DateParsers = {\n readonly date: DateParser | undefined;\n readonly temporal: DateParser | undefined;\n};\n\nfunction rejectLeapSecond(type: TailorFieldType, text: string): void {\n if (type === \"datetime\" && text.slice(17, 19) === \"60\") {\n throw new RangeError(\"Leap seconds are not supported\");\n }\n}\n\nfunction parseAsDate(type: TailorFieldType, text: string): Date {\n rejectLeapSecond(type, text);\n const date = new Date(\n type === \"date\"\n ? `${text}T00:00:00.000Z`\n : type === \"time\"\n ? `1970-01-01T${text}:00.000Z`\n : text,\n );\n if (!Number.isFinite(date.getTime())) throw new RangeError(\"Invalid Date\");\n if (type !== \"time\") {\n const calendarDate = text.slice(0, 10);\n if (formatDate(new Date(`${calendarDate}T00:00:00.000Z`)) !== calendarDate) {\n throw new RangeError(\"Invalid calendar date\");\n }\n }\n return date;\n}\n\nfunction parseAsTemporal(type: TailorFieldType, text: string): unknown {\n rejectLeapSecond(type, text);\n const Temporal = getTemporal();\n if (type === \"date\") return Temporal.PlainDate.from(text);\n if (type === \"datetime\") return Temporal.Instant.from(text);\n return Temporal.PlainTime.from(text);\n}\n\nconst allDateParsers: DateParsers = { date: parseAsDate, temporal: parseAsTemporal };\n\ntype MaybeProcessGlobal = { process?: { env: Record<string, string | undefined> } };\n\nconst bundledDateParsers: DateParsers = {\n date: (globalThis as MaybeProcessGlobal).process?.env.__TAILOR_PLATFORM_BUNDLE_WITHOUT_DATE\n ? undefined\n : parseAsDate,\n temporal: (globalThis as MaybeProcessGlobal).process?.env\n .__TAILOR_PLATFORM_BUNDLE_WITHOUT_TEMPORAL\n ? undefined\n : parseAsTemporal,\n};\n\nfunction deserializeDates(\n args: FieldValidationArgs<TailorFieldType>,\n dateParsers: DateParsers,\n): unknown {\n const { field, value, issues, pathArray } = args;\n if (value === null || value === undefined) return value;\n const convert = (item: unknown, itemPath: string[]): unknown => {\n const { type } = field;\n const as = dateRepresentationOf(type, field._metadata.as);\n if (as) {\n const parse = dateParsers[as];\n if (!parse) {\n throw new Error(\n `Parsing fields declared with as: \"${as}\" is not included in this bundle. Parse them with parseDateFields, exported by \"@tailor-platform/sdk/runtime\".`,\n );\n }\n try {\n return parse(type, String(item));\n } catch (error) {\n if (!(error instanceof RangeError)) throw error;\n issues.push({\n message: `Expected a valid ${type === \"date\" ? \"calendar date\" : type}: received ${item}`,\n path: itemPath.length > 0 ? itemPath : undefined,\n });\n return item;\n }\n }\n if (field.type !== \"nested\") return item;\n const record = item as Record<string, unknown>;\n let result = record;\n for (const [key, child] of Object.entries(field.fields)) {\n const converted = deserializeDates(\n {\n ...args,\n field: child,\n value: record[key],\n pathArray: itemPath.concat(key),\n },\n dateParsers,\n );\n if (converted !== record[key]) {\n if (result === record) result = { ...record };\n Object.defineProperty(result, key, {\n value: converted,\n enumerable: true,\n configurable: true,\n writable: true,\n });\n }\n }\n return result;\n };\n if (!field._metadata.array) return convert(value, pathArray);\n const values = value as unknown[];\n const converted = values.map((item, index) => convert(item, pathArray.concat(`[${index}]`)));\n return converted.every((item, index) => item === values[index]) ? value : converted;\n}\n\ntype ParseInputFieldsArgs = FieldParseArgs & {\n fields: Record<string, FieldRuntime>;\n};\n\n/**\n * Validate a value against a record of input fields, treating the record as a\n * single required object — the same code path deployed functions run via\n * `t.object(fields).parse(...)`, so local validation matches platform behavior.\n * @param args - Input field definitions plus the value, context data, and user\n * @returns Validation result\n */\nexport function parseInputFields(args: ParseInputFieldsArgs): StandardSchemaV1.Result<unknown> {\n const { fields, ...parseArgs } = args;\n return parseInternal({\n ...parseArgs,\n field: { type: \"nested\", fields, _metadata: { required: true } },\n pathArray: [],\n });\n}\n\ntype ParsableField<Output> = FieldRuntime & {\n parse(args: FieldParseArgs): StandardSchemaV1.Result<Output>;\n};\n\n/**\n * Parse a value like `field.parse`, converting fields declared with `as: \"date\"` or\n * `as: \"temporal\"` even in bundles that leave that conversion out of `field.parse`.\n * @param field - Field defining the value's shape\n * @param args - Value to parse, with the context data and invoker passed to validators\n * @returns Validation result with Date and Temporal fields converted\n */\nexport function parseDateFields<Output>(\n field: ParsableField<Output>,\n args: FieldParseArgs,\n): StandardSchemaV1.Result<Output> {\n return parseInternal({ ...args, field, pathArray: [] }, allDateParsers);\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"idp-G_ojPBB5.mjs","names":["idp","#impl","config","options","userId","name","input"],"sources":["../src/runtime/idp.ts"],"sourcesContent":["/**\n * IDP (Identity Provider) utilities.\n *\n * Thin typed wrapper around the platform-provided `tailor.idp` runtime API.\n * At runtime this delegates to `globalThis.tailor.idp`. Use `mockIdp` from\n * `@tailor-platform/sdk/vitest` to mock these calls in unit tests.\n * @example\n * import { idp } from \"@tailor-platform/sdk/runtime\";\n *\n * const client = new idp.Client({ namespace: \"my-namespace\" });\n * const { users } = await client.users({ first: 10 });\n */\n\n/** Configuration object for `idp.Client`. */\nexport interface ClientConfig {\n namespace: string;\n}\n\n/** User record returned by IDP operations. */\nexport interface User {\n id: string;\n name: string;\n disabled: boolean;\n createdAt?: string;\n /**\n * True when the user has at least one enrolled MFA second factor. False when\n * the namespace has MFA disabled or the user has not enrolled a factor.\n */\n mfaEnrolled: boolean;\n /**\n * Enrolled MFA second factor IDs. Pass an entry into\n * `idp.Client.unenrollMfa()` to remove that factor.\n */\n mfaFactorIds: string[];\n}\n\n/** Filter options for `idp.Client.users()`. */\nexport interface UserQuery {\n /** Filter by user IDs */\n ids?: string[];\n /** Filter by user names */\n names?: string[];\n}\n\n/** Pagination/filter options for `idp.Client.users()`. */\nexport interface ListUsersOptions {\n /** Maximum number of users to return */\n first?: number;\n /** Page token for pagination */\n after?: string;\n /** Query filter for users */\n query?: UserQuery;\n}\n\n/** Response shape for `idp.Client.users()`. */\nexport interface ListUsersResponse {\n users: User[];\n nextPageToken: string | null;\n totalCount: number;\n}\n\n/** Input for `idp.Client.createUser()`. */\nexport interface CreateUserInput {\n /** The user's name (typically email) */\n name: string;\n /** The user's password. If omitted, the user is created without a password (cannot log in with any password). */\n password?: string;\n /** Whether the user is disabled */\n disabled?: boolean;\n}\n\n/** Input for `idp.Client.updateUser()`. */\nexport interface UpdateUserInput {\n /** The user's ID */\n id: string;\n /** New name for the user */\n name?: string;\n /** New password for the user. Cannot be used with clearPassword. */\n password?: string;\n /** If true, remove the user's password. Cannot be used with password. */\n clearPassword?: boolean;\n /** New disabled status for the user */\n disabled?: boolean;\n}\n\n/** Input for `idp.Client.sendPasswordResetEmail()`. */\nexport interface SendPasswordResetEmailInput {\n /** The ID of the user */\n userId: string;\n /** The URI to redirect to after password reset */\n redirectUri: string;\n /** The sender display name. Defaults to 'Tailor Platform IdP'. */\n fromName?: string;\n /** The email subject line. Defaults to the localized default subject. */\n subject?: string;\n}\n\n/** Input for `idp.Client.unenrollMfa()`. */\nexport interface UnenrollMfaInput {\n /** The ID of the user whose factor will be unenrolled. */\n userId: string;\n /**\n * The ID of the factor to unenroll. Factor IDs are exposed on the user\n * record (see {@link User.mfaFactorIds}).\n */\n mfaFactorId: string;\n}\n\n/** Instance methods exposed by `tailor.idp.Client`. */\nexport interface IdpClientInstance {\n users(options?: ListUsersOptions): Promise<ListUsersResponse>;\n user(userId: string): Promise<User>;\n userByName(name: string): Promise<User>;\n createUser(input: CreateUserInput): Promise<User>;\n updateUser(input: UpdateUserInput): Promise<User>;\n deleteUser(userId: string): Promise<boolean>;\n sendPasswordResetEmail(input: SendPasswordResetEmailInput): Promise<boolean>;\n unenrollMfa(input: UnenrollMfaInput): Promise<boolean>;\n}\n\n/**\n * Constructor shape for `tailor.idp.Client`.\n * @internal\n */\nexport interface IdpClientConstructor {\n new (config: ClientConfig): IdpClientInstance;\n}\n\n/**\n * Platform API surface for `tailor.idp`. Describes the shape the platform\n * runtime injects on `globalThis.tailor.idp`.\n * @internal\n */\nexport interface TailorIdpAPI {\n Client: IdpClientConstructor;\n}\n\n/**\n * IDP Client for user management operations.\n *\n * Wraps the platform-provided `tailor.idp.Client` and exposes the same surface.\n */\nclass Client {\n #impl: IdpClientInstance;\n\n constructor(config: ClientConfig) {\n this.#impl = new (globalThis as unknown as { tailor: { idp: TailorIdpAPI } }).tailor.idp.Client(\n config,\n );\n }\n\n /**\n * List users in the namespace with optional filtering and pagination.\n * @param options - Pagination and filter options\n * @returns Page of users with `nextPageToken` and `totalCount`\n */\n users(options?: ListUsersOptions): Promise<ListUsersResponse> {\n return this.#impl.users(options);\n }\n\n /**\n * Get a user by ID.\n * @param userId - IDP user ID\n * @returns The matching user\n */\n user(userId: string): Promise<User> {\n return this.#impl.user(userId);\n }\n\n /**\n * Get a user by name.\n * @param name - IDP user name\n * @returns The matching user\n */\n userByName(name: string): Promise<User> {\n return this.#impl.userByName(name);\n }\n\n /**\n * Create a new user.\n * @param input - User attributes\n * @returns The newly created user\n */\n createUser(input: CreateUserInput): Promise<User> {\n return this.#impl.createUser(input);\n }\n\n /**\n * Update an existing user.\n * @param input - User ID plus attributes to update\n * @returns The updated user\n */\n updateUser(input: UpdateUserInput): Promise<User> {\n return this.#impl.updateUser(input);\n }\n\n /**\n * Delete a user by ID.\n * @param userId - IDP user ID\n * @returns `true` when the user was deleted\n */\n deleteUser(userId: string): Promise<boolean> {\n return this.#impl.deleteUser(userId);\n }\n\n /**\n * Send a password reset email to a user.\n * @param input - Target user ID and redirect URI\n * @returns `true` when the email was queued\n */\n sendPasswordResetEmail(input: SendPasswordResetEmailInput): Promise<boolean> {\n return this.#impl.sendPasswordResetEmail(input);\n }\n\n /**\n * Unenroll an MFA factor from a user.\n * @param input - Target user ID and factor ID (see {@link User.mfaFactorIds})\n * @returns `true` when the factor was removed\n */\n unenrollMfa(input: UnenrollMfaInput): Promise<boolean> {\n return this.#impl.unenrollMfa(input);\n }\n}\n\n// Keep the object typed to the public API so the private wrapper class does not leak into d.ts.\n/** Runtime API for `tailor.idp`. */\nexport const idp: TailorIdpAPI = { Client };\n"],"mappings":"AAkOA,MAAaA,EAAoB,CAAE,YApFtB,CACX,GAEA,YAAY,EAAsB,CAChC,KAAKC,GAAQ,IAAK,WAA4D,OAAO,IAAI,OACvFC,CACF,CACF,CAOA,MAAM,EAAwD,CAC5D,OAAO,KAAKD,GAAM,MAAME,CAAO,CACjC,CAOA,KAAK,EAA+B,CAClC,OAAO,KAAKF,GAAM,KAAKG,CAAM,CAC/B,CAOA,WAAW,EAA6B,CACtC,OAAO,KAAKH,GAAM,WAAWI,CAAI,CACnC,CAOA,WAAW,EAAuC,CAChD,OAAO,KAAKJ,GAAM,WAAWK,CAAK,CACpC,CAOA,WAAW,EAAuC,CAChD,OAAO,KAAKL,GAAM,WAAWK,CAAK,CACpC,CAOA,WAAW,EAAkC,CAC3C,OAAO,KAAKL,GAAM,WAAWG,CAAM,CACrC,CAOA,uBAAuB,EAAsD,CAC3E,OAAO,KAAKH,GAAM,uBAAuBK,CAAK,CAChD,CAOA,YAAY,EAA2C,CACrD,OAAO,KAAKL,GAAM,YAAYK,CAAK,CACrC,CACF,CAI0C"}
1
+ {"version":3,"file":"idp-G_ojPBB5.mjs","names":["idp","#impl","config","options","userId","name","input"],"sources":["../src/runtime/idp.ts"],"sourcesContent":["/**\n * IDP (Identity Provider) utilities.\n *\n * Thin typed wrapper around the platform-provided `tailor.idp` runtime API.\n * At runtime this delegates to `globalThis.tailor.idp`. Use `mockIdp` from\n * `@tailor-platform/sdk/vitest` to mock these calls in unit tests.\n * @example\n * import { idp } from \"@tailor-platform/sdk/runtime\";\n *\n * const client = new idp.Client({ namespace: \"my-namespace\" });\n * const { users } = await client.users({ first: 10 });\n */\n\n/** Configuration object for `idp.Client`. */\nexport interface ClientConfig {\n namespace: string;\n}\n\n/** User record returned by IDP operations. */\nexport interface User {\n id: string;\n name: string;\n disabled: boolean;\n createdAt?: string;\n /**\n * True when the user has at least one enrolled MFA second factor. False when\n * the namespace has MFA disabled or the user has not enrolled a factor.\n */\n mfaEnrolled: boolean;\n /**\n * Enrolled MFA second factor IDs. Pass an entry into\n * `idp.Client.unenrollMfa()` to remove that factor.\n */\n mfaFactorIds: string[];\n /**\n * When the user's password was last set, as an ISO 8601 UTC string\n * (e.g. `2026-10-05T01:02:03.456Z`). `null` when the user has no password,\n * including after `idp.Client.updateUser()` with `clearPassword: true`.\n */\n passwordUpdatedAt: string | null;\n}\n\n/** Filter options for `idp.Client.users()`. */\nexport interface UserQuery {\n /** Filter by user IDs */\n ids?: string[];\n /** Filter by user names */\n names?: string[];\n}\n\n/** Pagination/filter options for `idp.Client.users()`. */\nexport interface ListUsersOptions {\n /** Maximum number of users to return */\n first?: number;\n /** Page token for pagination */\n after?: string;\n /** Query filter for users */\n query?: UserQuery;\n}\n\n/** Response shape for `idp.Client.users()`. */\nexport interface ListUsersResponse {\n users: User[];\n nextPageToken: string | null;\n totalCount: number;\n}\n\n/** Input for `idp.Client.createUser()`. */\nexport interface CreateUserInput {\n /** The user's name (typically email) */\n name: string;\n /** The user's password. If omitted, the user is created without a password (cannot log in with any password). */\n password?: string;\n /** Whether the user is disabled */\n disabled?: boolean;\n}\n\n/** Input for `idp.Client.updateUser()`. */\nexport interface UpdateUserInput {\n /** The user's ID */\n id: string;\n /** New name for the user */\n name?: string;\n /** New password for the user. Cannot be used with clearPassword. */\n password?: string;\n /** If true, remove the user's password. Cannot be used with password. */\n clearPassword?: boolean;\n /** New disabled status for the user */\n disabled?: boolean;\n}\n\n/** Input for `idp.Client.sendPasswordResetEmail()`. */\nexport interface SendPasswordResetEmailInput {\n /** The ID of the user */\n userId: string;\n /** The URI to redirect to after password reset */\n redirectUri: string;\n /** The sender display name. Defaults to 'Tailor Platform IdP'. */\n fromName?: string;\n /** The email subject line. Defaults to the localized default subject. */\n subject?: string;\n}\n\n/** Input for `idp.Client.unenrollMfa()`. */\nexport interface UnenrollMfaInput {\n /** The ID of the user whose factor will be unenrolled. */\n userId: string;\n /**\n * The ID of the factor to unenroll. Factor IDs are exposed on the user\n * record (see {@link User.mfaFactorIds}).\n */\n mfaFactorId: string;\n}\n\n/** Instance methods exposed by `tailor.idp.Client`. */\nexport interface IdpClientInstance {\n users(options?: ListUsersOptions): Promise<ListUsersResponse>;\n user(userId: string): Promise<User>;\n userByName(name: string): Promise<User>;\n createUser(input: CreateUserInput): Promise<User>;\n updateUser(input: UpdateUserInput): Promise<User>;\n deleteUser(userId: string): Promise<boolean>;\n sendPasswordResetEmail(input: SendPasswordResetEmailInput): Promise<boolean>;\n unenrollMfa(input: UnenrollMfaInput): Promise<boolean>;\n}\n\n/**\n * Constructor shape for `tailor.idp.Client`.\n * @internal\n */\nexport interface IdpClientConstructor {\n new (config: ClientConfig): IdpClientInstance;\n}\n\n/**\n * Platform API surface for `tailor.idp`. Describes the shape the platform\n * runtime injects on `globalThis.tailor.idp`.\n * @internal\n */\nexport interface TailorIdpAPI {\n Client: IdpClientConstructor;\n}\n\n/**\n * IDP Client for user management operations.\n *\n * Wraps the platform-provided `tailor.idp.Client` and exposes the same surface.\n */\nclass Client {\n #impl: IdpClientInstance;\n\n constructor(config: ClientConfig) {\n this.#impl = new (globalThis as unknown as { tailor: { idp: TailorIdpAPI } }).tailor.idp.Client(\n config,\n );\n }\n\n /**\n * List users in the namespace with optional filtering and pagination.\n * @param options - Pagination and filter options\n * @returns Page of users with `nextPageToken` and `totalCount`\n */\n users(options?: ListUsersOptions): Promise<ListUsersResponse> {\n return this.#impl.users(options);\n }\n\n /**\n * Get a user by ID.\n * @param userId - IDP user ID\n * @returns The matching user\n */\n user(userId: string): Promise<User> {\n return this.#impl.user(userId);\n }\n\n /**\n * Get a user by name.\n * @param name - IDP user name\n * @returns The matching user\n */\n userByName(name: string): Promise<User> {\n return this.#impl.userByName(name);\n }\n\n /**\n * Create a new user.\n * @param input - User attributes\n * @returns The newly created user\n */\n createUser(input: CreateUserInput): Promise<User> {\n return this.#impl.createUser(input);\n }\n\n /**\n * Update an existing user.\n * @param input - User ID plus attributes to update\n * @returns The updated user\n */\n updateUser(input: UpdateUserInput): Promise<User> {\n return this.#impl.updateUser(input);\n }\n\n /**\n * Delete a user by ID.\n * @param userId - IDP user ID\n * @returns `true` when the user was deleted\n */\n deleteUser(userId: string): Promise<boolean> {\n return this.#impl.deleteUser(userId);\n }\n\n /**\n * Send a password reset email to a user.\n * @param input - Target user ID and redirect URI\n * @returns `true` when the email was queued\n */\n sendPasswordResetEmail(input: SendPasswordResetEmailInput): Promise<boolean> {\n return this.#impl.sendPasswordResetEmail(input);\n }\n\n /**\n * Unenroll an MFA factor from a user.\n * @param input - Target user ID and factor ID (see {@link User.mfaFactorIds})\n * @returns `true` when the factor was removed\n */\n unenrollMfa(input: UnenrollMfaInput): Promise<boolean> {\n return this.#impl.unenrollMfa(input);\n }\n}\n\n// Keep the object typed to the public API so the private wrapper class does not leak into d.ts.\n/** Runtime API for `tailor.idp`. */\nexport const idp: TailorIdpAPI = { Client };\n"],"mappings":"AAwOA,MAAaA,EAAoB,CAAE,YApFtB,CACX,GAEA,YAAY,EAAsB,CAChC,KAAKC,GAAQ,IAAK,WAA4D,OAAO,IAAI,OACvFC,CACF,CACF,CAOA,MAAM,EAAwD,CAC5D,OAAO,KAAKD,GAAM,MAAME,CAAO,CACjC,CAOA,KAAK,EAA+B,CAClC,OAAO,KAAKF,GAAM,KAAKG,CAAM,CAC/B,CAOA,WAAW,EAA6B,CACtC,OAAO,KAAKH,GAAM,WAAWI,CAAI,CACnC,CAOA,WAAW,EAAuC,CAChD,OAAO,KAAKJ,GAAM,WAAWK,CAAK,CACpC,CAOA,WAAW,EAAuC,CAChD,OAAO,KAAKL,GAAM,WAAWK,CAAK,CACpC,CAOA,WAAW,EAAkC,CAC3C,OAAO,KAAKL,GAAM,WAAWG,CAAM,CACrC,CAOA,uBAAuB,EAAsD,CAC3E,OAAO,KAAKH,GAAM,uBAAuBK,CAAK,CAChD,CAOA,YAAY,EAA2C,CACrD,OAAO,KAAKL,GAAM,YAAYK,CAAK,CACrC,CACF,CAI0C"}
@@ -1,9 +1,16 @@
1
1
  import { TypeLevelError, output } from "../types/helpers.mjs";
2
2
  import { IsAutoFilledDBField, IsReadOnlyDBField, TailorAnyDBField, TailorAnyDBType } from "../configure/services/tailordb/types.mjs";
3
+ import { Temporal, Temporal as Temporal$1 } from "temporal-spec";
3
4
  import { ColumnType, ColumnType as ColumnType$1, Insertable, Insertable as Insertable$1, Kysely, Kysely as Kysely$1, KyselyConfig, KyselyConfig as KyselyConfig$1, Selectable, Selectable as Selectable$1, Transaction, Transaction as Transaction$1, Updateable, Updateable as Updateable$1, sql } from "kysely";
4
5
  import { TailordbDialect } from "@tailor-platform/function-kysely-tailordb";
5
6
  //#region src/kysely/index.d.ts
6
7
  export type Timestamp = ColumnType$1<Date, Date | string, Date | string>;
8
+ /** Column type for a `date` field read back as `Temporal.PlainDate` (`createGetDB`'s `temporal` option). */
9
+ export type TemporalDate = ColumnType$1<Temporal$1.PlainDate, Temporal$1.PlainDate | string, Temporal$1.PlainDate | string>;
10
+ /** Column type for a `datetime` field read back as `Temporal.Instant` (`createGetDB`'s `temporal` option). */
11
+ export type TemporalInstant = ColumnType$1<Temporal$1.Instant, Temporal$1.Instant | string, Temporal$1.Instant | string>;
12
+ /** Column type for a `time` field read back as `Temporal.PlainTime` (`createGetDB`'s `temporal` option). */
13
+ export type TemporalTime = ColumnType$1<Temporal$1.PlainTime, Temporal$1.PlainTime | string, Temporal$1.PlainTime | string>;
7
14
  type ResolveSelect<T> = T extends ColumnType$1<infer S, unknown, unknown> ? S : T;
8
15
  type ResolveInsert<T> = T extends ColumnType$1<unknown, infer I, unknown> ? I : T;
9
16
  type ResolveUpdate<T> = T extends ColumnType$1<unknown, unknown, infer U> ? U : T;
@@ -15,11 +22,23 @@ export type Serial<T = string | number> = ColumnType$1<T, SerialColumnMustBeOmit
15
22
  type FlattenColumns<T> = { [K in keyof T]: T[K]; } & {};
16
23
  export type TailordbKysely<DB> = Kysely$1<DB>;
17
24
  export type NamespaceDB<NS, N extends keyof NS = keyof NS> = TailordbKysely<NS[N]>;
25
+ /** Options for {@link createGetDB}. */
26
+ export type CreateGetDBOptions = {
27
+ /**
28
+ * When `true`, date/datetime fields come back as `Temporal.PlainDate`/
29
+ * `Temporal.Instant`, and top-level time fields come back as `Temporal.PlainTime`,
30
+ * instead of `Date`/`string`. Nested time fields remain strings. Match the `temporal`
31
+ * option `kyselyTypePlugin` was configured with so the generated table types agree
32
+ * with this runtime behavior. Defaults to `false`.
33
+ */
34
+ temporal?: boolean;
35
+ };
18
36
  /**
19
37
  * Create a namespace-aware getDB function for generated code.
38
+ * @param options - Settings applied to every Kysely instance the returned `getDB` creates
20
39
  * @returns A getDB function that creates Kysely instances for specific namespaces
21
40
  */
22
- export declare function createGetDB<NS>(): <const N extends keyof NS & string>(namespace: N, config?: Omit<KyselyConfig$1, "dialect">) => TailordbKysely<NS[N]>;
41
+ export declare function createGetDB<NS>(options?: CreateGetDBOptions): <const N extends keyof NS & string>(namespace: N, config?: Omit<KyselyConfig$1, "dialect">) => TailordbKysely<NS[N]>;
23
42
  export type NamespaceTransaction<NS, K extends keyof NS | TailordbKysely<NS[keyof NS]> = keyof NS> = K extends TailordbKysely<infer DB> ? Transaction$1<DB> : K extends keyof NS ? Transaction$1<NS[K]> : never;
24
43
  export type NamespaceTableName<NS> = { [N in keyof NS]: keyof NS[N]; }[keyof NS];
25
44
  export type NamespaceTable<NS, T extends NamespaceTableName<NS>> = { [N in keyof NS]: T extends keyof NS[N] ? NS[N][T] : never; }[keyof NS];
@@ -34,21 +53,24 @@ type IsArrayDBField<F> = F extends TailorAnyDBField ? F["_defined"]["array"] ext
34
53
  type Unwrapped<F> = Exclude<output<F>, null>;
35
54
  type ElementOutput<F> = IsArrayDBField<F> extends true ? Unwrapped<F> extends readonly (infer E)[] ? E : Unwrapped<F> : Unwrapped<F>;
36
55
  type NestedFieldsOf<F> = F extends TailorAnyDBField ? F["fields"] : never;
37
- type NestedProps<Fields> = { -readonly [K in keyof Fields as null extends output<Fields[K]> ? never : K]: DBColumn<Fields[K]>; } & { -readonly [K in keyof Fields as null extends output<Fields[K]> ? K : never]?: DBColumn<Fields[K]>; };
38
- type NestedNeedsColumnType<Fields> = true extends { [K in keyof Fields]: DBFieldType<Fields[K]> extends "date" | "datetime" ? true : null extends output<Fields[K]> ? true : DBFieldType<Fields[K]> extends "nested" ? NestedNeedsColumnType<NestedFieldsOf<Fields[K]>> : Fields[K] extends TailorAnyDBField ? IsAutoFilledDBField<Fields[K]> : false; }[keyof Fields] ? true : false;
39
- type NestedColumn<F> = NestedNeedsColumnType<NestedFieldsOf<F>> extends true ? ObjectColumnType<FlattenColumns<NestedProps<NestedFieldsOf<F>>>> : FlattenColumns<NestedProps<NestedFieldsOf<F>>>;
40
- type ElementColumn<F> = DBFieldType<F> extends "date" | "datetime" ? Timestamp : DBFieldType<F> extends "nested" ? NestedColumn<F> : ElementOutput<F>;
41
- type ArrayedColumn<F> = IsArrayDBField<F> extends true ? ElementColumn<F> extends ColumnType$1<unknown, unknown, unknown> ? ArrayColumnType<ElementColumn<F>> : ElementColumn<F>[] : ElementColumn<F>;
42
- type NullableColumn<F> = null extends output<F> ? ArrayedColumn<F> | null : ArrayedColumn<F>;
43
- type DBColumn<F> = F extends TailorAnyDBField ? IsReadOnlyDBField<F> extends true ? Serial<NullableColumn<F>> : IsAutoFilledDBField<F> extends true ? Generated<NullableColumn<F>> : NullableColumn<F> : never;
44
- type TailorDBColumns<T extends TailorDBColumnsSource> = { [K in keyof DBFieldsOf<T>]: K extends "id" ? Generated<output<DBFieldsOf<T>[K]>> : DBColumn<DBFieldsOf<T>[K]>; };
56
+ type NestedProps<Fields, IsTemporal extends boolean> = { -readonly [K in keyof Fields as null extends output<Fields[K]> ? never : K]: DBColumn<Fields[K], IsTemporal, true>; } & { -readonly [K in keyof Fields as null extends output<Fields[K]> ? K : never]?: DBColumn<Fields[K], IsTemporal, true>; };
57
+ type NestedNeedsColumnType<Fields, IsTemporal extends boolean> = true extends { [K in keyof Fields]: DBFieldType<Fields[K]> extends "nested" ? NestedNeedsColumnType<NestedFieldsOf<Fields[K]>, IsTemporal> : ElementColumn<Fields[K], IsTemporal, true> extends ColumnType$1<unknown, unknown, unknown> ? true : null extends output<Fields[K]> ? true : Fields[K] extends TailorAnyDBField ? IsAutoFilledDBField<Fields[K]> : false; }[keyof Fields] ? true : false;
58
+ type NestedColumn<F, IsTemporal extends boolean> = NestedNeedsColumnType<NestedFieldsOf<F>, IsTemporal> extends true ? ObjectColumnType<FlattenColumns<NestedProps<NestedFieldsOf<F>, IsTemporal>>> : FlattenColumns<NestedProps<NestedFieldsOf<F>, IsTemporal>>;
59
+ type DateColumn<Type extends "date" | "datetime" | "time", IsTemporal extends boolean, IsNested extends boolean> = IsTemporal extends true ? Type extends "date" ? TemporalDate : Type extends "datetime" ? TemporalInstant : IsNested extends true ? string : TemporalTime : Type extends "date" | "datetime" ? Timestamp : string;
60
+ type ElementColumn<F, IsTemporal extends boolean, IsNested extends boolean> = DBFieldType<F> extends "nested" ? NestedColumn<F, IsTemporal> : DBFieldType<F> extends "date" | "datetime" | "time" ? DateColumn<DBFieldType<F>, IsTemporal, IsNested> : ElementOutput<F>;
61
+ type ArrayedColumn<F, IsTemporal extends boolean, IsNested extends boolean> = IsArrayDBField<F> extends true ? ElementColumn<F, IsTemporal, IsNested> extends ColumnType$1<unknown, unknown, unknown> ? ArrayColumnType<ElementColumn<F, IsTemporal, IsNested>> : ElementColumn<F, IsTemporal, IsNested>[] : ElementColumn<F, IsTemporal, IsNested>;
62
+ type NullableColumn<F, IsTemporal extends boolean, IsNested extends boolean> = null extends output<F> ? ArrayedColumn<F, IsTemporal, IsNested> | null : ArrayedColumn<F, IsTemporal, IsNested>;
63
+ type DBColumn<F, IsTemporal extends boolean, IsNested extends boolean = false> = F extends TailorAnyDBField ? IsReadOnlyDBField<F> extends true ? Serial<NullableColumn<F, IsTemporal, IsNested>> : IsAutoFilledDBField<F> extends true ? Generated<NullableColumn<F, IsTemporal, IsNested>> : NullableColumn<F, IsTemporal, IsNested> : never;
64
+ type TailorDBColumns<T extends TailorDBColumnsSource, IsTemporal extends boolean> = { [K in keyof DBFieldsOf<T>]: K extends "id" ? Generated<output<DBFieldsOf<T>[K]>> : DBColumn<DBFieldsOf<T>[K], IsTemporal>; };
45
65
  /**
46
66
  * Create input derived from a TailorDB table (`typeof myTable`) or a field collection.
47
67
  *
48
68
  * Each field resolves to the column type `kyselyTypePlugin` writes for it, so this and
49
69
  * the generated table types agree: `.serial()` fields are never caller-supplied,
50
70
  * `.default()` / `.hooks({ create })` fields may be omitted, optional fields stay
51
- * optional, `id` is platform-generated, and a date or datetime reads back as `Date`.
71
+ * optional, `id` is platform-generated, and date/datetime/time fields read back as
72
+ * `Date`/`string`, or as their `Temporal` counterparts when `IsTemporal` is `true`.
73
+ * Nested time fields remain strings in either mode.
52
74
  *
53
75
  * Pass a field collection when the fields are a type parameter — a shared module that
54
76
  * lets each project extend a table with its own fields cannot name a generated table
@@ -60,15 +82,25 @@ type TailorDBColumns<T extends TailorDBColumnsSource> = { [K in keyof DBFieldsOf
60
82
  * it: while `F` is still an unresolved type parameter the mapping stays deferred, so
61
83
  * assigning to it inside the function body reports the unevaluated conditional rather
62
84
  * than a readable shape.
85
+ * @param IsTemporal - Pass `true` to accept `Temporal.PlainDate`/`Temporal.Instant` for
86
+ * date/datetime fields and `Temporal.PlainTime` for top-level time fields (alongside a
87
+ * plain string), matching a `getDB` created with `createGetDB({ temporal: true })`.
88
+ * Nested time fields remain strings. Defaults to `false`.
63
89
  * @example
64
90
  * function createInput<const F extends Record<string, TailorAnyDBField>>(fields: F) {
65
91
  * return (input: TailorDBInsertable<F>) => { ... };
66
92
  * }
67
93
  */
68
- export type TailorDBInsertable<T extends TailorDBColumnsSource> = FlattenColumns<Insertable$1<TailorDBColumns<T>>>;
69
- /** Read shape of a TailorDB table or field collection. See {@link TailorDBInsertable}. */
70
- export type TailorDBSelectable<T extends TailorDBColumnsSource> = FlattenColumns<Selectable$1<TailorDBColumns<T>>>;
94
+ export type TailorDBInsertable<T extends TailorDBColumnsSource, IsTemporal extends boolean = false> = FlattenColumns<Insertable$1<TailorDBColumns<T, IsTemporal>>>;
95
+ /**
96
+ * Read shape of a TailorDB table or field collection. See {@link TailorDBInsertable}.
97
+ * @param IsTemporal - Pass `true` to read date/datetime fields as `Temporal.PlainDate`/
98
+ * `Temporal.Instant` and top-level time fields as `Temporal.PlainTime`, matching a
99
+ * `getDB` created with `createGetDB({ temporal: true })`. Nested time fields remain
100
+ * strings. Defaults to `false` (`Date` for date/datetime, `string` for time).
101
+ */
102
+ export type TailorDBSelectable<T extends TailorDBColumnsSource, IsTemporal extends boolean = false> = FlattenColumns<Selectable$1<TailorDBColumns<T, IsTemporal>>>;
71
103
  /** Update input for a TailorDB table or field collection. See {@link TailorDBInsertable}. */
72
- export type TailorDBUpdateable<T extends TailorDBColumnsSource> = FlattenColumns<Updateable$1<TailorDBColumns<T>>>;
104
+ export type TailorDBUpdateable<T extends TailorDBColumnsSource, IsTemporal extends boolean = false> = FlattenColumns<Updateable$1<TailorDBColumns<T, IsTemporal>>>;
73
105
  //#endregion
74
- export { type ColumnType, type Insertable, Kysely, type KyselyConfig, type Selectable, TailordbDialect, type Transaction, type Updateable, sql };
106
+ export { type ColumnType, type Insertable, Kysely, type KyselyConfig, type Selectable, TailordbDialect, type Temporal, type Transaction, type Updateable, sql };