@tailor-platform/sdk 2.21.0 → 2.23.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 (119) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/agent-skills/tailor/SKILL.md +3 -1
  3. package/dist/aigateway-DsWDjzk4.mjs.map +1 -1
  4. package/dist/application-BtZ8hmx9.mjs +1 -0
  5. package/dist/{application-D4913edS.mjs → application-m2G91kKI.mjs} +29 -29
  6. package/dist/application-m2G91kKI.mjs.map +1 -0
  7. package/dist/assert-WeXvmG4j.mjs.map +1 -1
  8. package/dist/authconnection-CynFBIv8.mjs.map +1 -1
  9. package/dist/brand-C8nMKhJC.mjs.map +1 -1
  10. package/dist/cli/commands/deploy/app-id-lock.d.mts +31 -0
  11. package/dist/cli/lib.d.mts +2 -2
  12. package/dist/cli/lib.mjs +1 -1
  13. package/dist/cli/lib.mjs.map +1 -1
  14. package/dist/cli/main.mjs +41 -41
  15. package/dist/cli/main.mjs.map +1 -1
  16. package/dist/cli/shared/client.d.mts +17 -2
  17. package/dist/cli/shared/logger.d.mts +9 -0
  18. package/dist/cli/shared/tailordb-namespaces.d.mts +1 -1
  19. package/dist/completion/zsh-worker.zsh +13 -7
  20. package/dist/configure/config/index.d.mts +2 -0
  21. package/dist/configure/index.mjs.map +1 -1
  22. package/dist/context-D0QjfxzD.mjs.map +1 -1
  23. package/dist/crashreport-CBaRJl5h.mjs +1 -0
  24. package/dist/{crashreport-BAz-ph5O.mjs → crashreport-DFpRn-LS.mjs} +4 -4
  25. package/dist/crashreport-DFpRn-LS.mjs.map +1 -0
  26. package/dist/date-Dri6Yas-.mjs.map +1 -1
  27. package/dist/errors-CpvSChyL.mjs +7 -0
  28. package/dist/errors-CpvSChyL.mjs.map +1 -0
  29. package/dist/es-builtins-SfvXRVoG.mjs.map +1 -1
  30. package/dist/field-parse-DhnFs9WG.mjs.map +1 -1
  31. package/dist/file-DKBOj5q4.mjs.map +1 -1
  32. package/dist/globals-BCmGX05J.mjs.map +1 -1
  33. package/dist/guards-yDXyKC9F.mjs +2 -0
  34. package/dist/guards-yDXyKC9F.mjs.map +1 -0
  35. package/dist/iconv-DlFMt2gW.mjs.map +1 -1
  36. package/dist/idp-G_ojPBB5.mjs.map +1 -1
  37. package/dist/interceptor-DQg3cR_9.mjs.map +1 -1
  38. package/dist/kysely/index.mjs.map +1 -1
  39. package/dist/kysely-type-C-iyFFH7.mjs.map +1 -1
  40. package/dist/logger-DP2BjQ93.mjs.map +1 -1
  41. package/dist/logger-Db-YRTwK.mjs +9 -0
  42. package/dist/logger-Db-YRTwK.mjs.map +1 -0
  43. package/dist/{manager-C0dE7pd0.mjs → manager-8-JOvuLl.mjs} +2 -2
  44. package/dist/manager-8-JOvuLl.mjs.map +1 -0
  45. package/dist/multiline-EyzjEwn9.mjs.map +1 -1
  46. package/dist/node-builtins-DYfhPBnz.mjs.map +1 -1
  47. package/dist/package-json-C690ceex.mjs.map +1 -1
  48. package/dist/platform-serialize-DkiTdHOt.mjs.map +1 -1
  49. package/dist/plugin/builtin/enum-constants/index.mjs.map +1 -1
  50. package/dist/plugin/builtin/file-utils/index.mjs.map +1 -1
  51. package/dist/plugin/index.mjs +1 -1
  52. package/dist/plugin/index.mjs.map +1 -1
  53. package/dist/register-ts-hook-ztnEFW6n.mjs +922 -0
  54. package/dist/register-ts-hook-ztnEFW6n.mjs.map +1 -0
  55. package/dist/registry-BijIDRVA.mjs.map +1 -1
  56. package/dist/repl-editor-DGJBfIt1.mjs.map +1 -1
  57. package/dist/schema-CRtAmDcl.mjs.map +1 -1
  58. package/dist/secret-file-C9wp_FCX.mjs.map +1 -1
  59. package/dist/secretmanager-5olfnI1b.mjs.map +1 -1
  60. package/dist/secretmanager-vHQoXdQz.mjs.map +1 -1
  61. package/dist/seed/index.mjs +7 -6
  62. package/dist/seed/index.mjs.map +1 -1
  63. package/dist/seed-C3P_T_Eh.mjs.map +1 -1
  64. package/dist/service-Bx-7Lz06.mjs +1 -0
  65. package/dist/{service-BrGSi2IQ.mjs → service-CL1Bp4It.mjs} +3 -3
  66. package/dist/service-CL1Bp4It.mjs.map +1 -0
  67. package/dist/{service-8xznUrPU.mjs → service-DFmt9UJP.mjs} +2 -2
  68. package/dist/service-DFmt9UJP.mjs.map +1 -0
  69. package/dist/service_pb-ZClWtj1X.mjs +2 -0
  70. package/dist/service_pb-ZClWtj1X.mjs.map +1 -0
  71. package/dist/service_pb-dB3RrGeh.mjs +1 -0
  72. package/dist/tailor-proto/src/tailor/v1/function_pb.d.mts +83 -1
  73. package/dist/tailor-proto/src/tailor/v1/function_resource_pb.d.mts +7 -1
  74. package/dist/tailor-proto/src/tailor/v1/service_pb.d.mts +79 -7
  75. package/dist/tailor-proto/src/tailor/v1/workflow_pb.d.mts +40 -1
  76. package/dist/tailor-proto/src/tailor/v1/workflow_resource_pb.d.mts +119 -2
  77. package/dist/tailor-proto/src/tailor/v1/workspace_pb.d.mts +7 -0
  78. package/dist/tailordb-ddl-DqInYupv.mjs.map +1 -1
  79. package/dist/telemetry-Bklv9kQY.mjs.map +1 -1
  80. package/dist/type-source--ZNcV8RJ.mjs.map +1 -1
  81. package/dist/user-agent-vdHYF3QL.mjs.map +1 -1
  82. package/dist/utils/test/index.mjs.map +1 -1
  83. package/dist/vitest/environment.mjs.map +1 -1
  84. package/dist/vitest/index.mjs.map +1 -1
  85. package/dist/vitest/mocks/file.d.mts +1 -1
  86. package/dist/vitest/setup.mjs.map +1 -1
  87. package/dist/wait-point-invoker-eiP-IIux.mjs.map +1 -1
  88. package/dist/wait-point-registry-B-ESkTZX.mjs.map +1 -1
  89. package/dist/workflow-Cs9ISw6j.mjs.map +1 -1
  90. package/dist/{workspace_resource_pb-D2njwgsE.mjs → workspace_resource_pb-CxR_6fyN.mjs} +2 -2
  91. package/dist/workspace_resource_pb-CxR_6fyN.mjs.map +1 -0
  92. package/docs/cli/application.md +23 -5
  93. package/docs/cli/function.md +2 -2
  94. package/docs/cli-reference.md +22 -12
  95. package/docs/configuration.md +1 -1
  96. package/docs/github-actions.md +90 -24
  97. package/docs/migration/v2.md +70 -5
  98. package/docs/plugin/index.md +1 -1
  99. package/package.json +10 -10
  100. package/dist/application-D4913edS.mjs.map +0 -1
  101. package/dist/application-DBHaxmJE.mjs +0 -1
  102. package/dist/crashreport-BAz-ph5O.mjs.map +0 -1
  103. package/dist/crashreport-BfOkOFgc.mjs +0 -1
  104. package/dist/errors-sNtg2Mv3.mjs +0 -7
  105. package/dist/errors-sNtg2Mv3.mjs.map +0 -1
  106. package/dist/guards-DsX7dJCP.mjs +0 -2
  107. package/dist/guards-DsX7dJCP.mjs.map +0 -1
  108. package/dist/logger-Cp5U2IDI.mjs +0 -9
  109. package/dist/logger-Cp5U2IDI.mjs.map +0 -1
  110. package/dist/manager-C0dE7pd0.mjs.map +0 -1
  111. package/dist/register-ts-hook-YtsAGTMD.mjs +0 -921
  112. package/dist/register-ts-hook-YtsAGTMD.mjs.map +0 -1
  113. package/dist/service-8xznUrPU.mjs.map +0 -1
  114. package/dist/service-BrGSi2IQ.mjs.map +0 -1
  115. package/dist/service-DWMm-4Vm.mjs +0 -1
  116. package/dist/service_pb-DNskuJQC.mjs +0 -1
  117. package/dist/service_pb-y2GYIgfs.mjs +0 -2
  118. package/dist/service_pb-y2GYIgfs.mjs.map +0 -1
  119. package/dist/workspace_resource_pb-D2njwgsE.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"idp-G_ojPBB5.mjs","names":[],"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,MAAa,EAAoB,CAAE,YApFtB,CACX,GAEA,YAAY,EAAsB,CAChC,KAAK,GAAQ,IAAK,WAA4D,OAAO,IAAI,OACvF,CACF,CACF,CAOA,MAAM,EAAwD,CAC5D,OAAO,KAAK,GAAM,MAAM,CAAO,CACjC,CAOA,KAAK,EAA+B,CAClC,OAAO,KAAK,GAAM,KAAK,CAAM,CAC/B,CAOA,WAAW,EAA6B,CACtC,OAAO,KAAK,GAAM,WAAW,CAAI,CACnC,CAOA,WAAW,EAAuC,CAChD,OAAO,KAAK,GAAM,WAAW,CAAK,CACpC,CAOA,WAAW,EAAuC,CAChD,OAAO,KAAK,GAAM,WAAW,CAAK,CACpC,CAOA,WAAW,EAAkC,CAC3C,OAAO,KAAK,GAAM,WAAW,CAAM,CACrC,CAOA,uBAAuB,EAAsD,CAC3E,OAAO,KAAK,GAAM,uBAAuB,CAAK,CAChD,CAOA,YAAY,EAA2C,CACrD,OAAO,KAAK,GAAM,YAAY,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\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 +1 @@
1
- {"version":3,"file":"interceptor-DQg3cR_9.mjs","names":[],"sources":["../src/cli/telemetry/interceptor.ts"],"sourcesContent":["import { trace, SpanStatusCode } from \"@opentelemetry/api\";\nimport type { Interceptor } from \"@connectrpc/connect\";\n\n/**\n * Create a Connect-RPC interceptor that records OTLP spans for each RPC call.\n * When no TracerProvider is registered, the OTel API automatically provides\n * noop spans with zero overhead.\n * @returns Tracing interceptor\n */\nexport function createTracingInterceptor(): Interceptor {\n return (next) => async (req) => {\n const tracer = trace.getTracer(\"tailor\");\n\n return tracer.startActiveSpan(`rpc.${req.method.name}`, async (span) => {\n span.setAttribute(\"rpc.method\", req.method.name);\n span.setAttribute(\"rpc.service\", \"OperatorService\");\n span.setAttribute(\"rpc.system\", \"connect-rpc\");\n\n try {\n const response = await next(req);\n span.setStatus({ code: SpanStatusCode.OK });\n return response;\n } catch (error) {\n span.setStatus({ code: SpanStatusCode.ERROR });\n if (error instanceof Error) {\n span.recordException(error);\n }\n throw error;\n } finally {\n span.end();\n }\n });\n };\n}\n"],"mappings":"+DASA,SAAgB,0BAAwC,CACtD,MAAQ,IAAS,KAAO,IACP,EAAM,UAAU,QAEnB,CAAC,CAAC,gBAAgB,OAAO,EAAI,OAAO,OAAQ,KAAO,IAAS,CACtE,EAAK,aAAa,aAAc,EAAI,OAAO,IAAI,EAC/C,EAAK,aAAa,cAAe,iBAAiB,EAClD,EAAK,aAAa,aAAc,aAAa,EAE7C,GAAI,CACF,IAAM,EAAW,MAAM,EAAK,CAAG,EAE/B,OADA,EAAK,UAAU,CAAE,KAAM,EAAe,EAAG,CAAC,EACnC,CACT,OAAS,EAAO,CAKd,MAJA,EAAK,UAAU,CAAE,KAAM,EAAe,KAAM,CAAC,EACzC,aAAiB,OACnB,EAAK,gBAAgB,CAAK,EAEtB,CACR,QAAU,CACR,EAAK,IAAI,CACX,CACF,CAAC,CAEL"}
1
+ {"version":3,"file":"interceptor-DQg3cR_9.mjs","names":["trace","req","span","response","next","SpanStatusCode","error"],"sources":["../src/cli/telemetry/interceptor.ts"],"sourcesContent":["import { trace, SpanStatusCode } from \"@opentelemetry/api\";\nimport type { Interceptor } from \"@connectrpc/connect\";\n\n/**\n * Create a Connect-RPC interceptor that records OTLP spans for each RPC call.\n * When no TracerProvider is registered, the OTel API automatically provides\n * noop spans with zero overhead.\n * @returns Tracing interceptor\n */\nexport function createTracingInterceptor(): Interceptor {\n return (next) => async (req) => {\n const tracer = trace.getTracer(\"tailor\");\n\n return tracer.startActiveSpan(`rpc.${req.method.name}`, async (span) => {\n span.setAttribute(\"rpc.method\", req.method.name);\n span.setAttribute(\"rpc.service\", \"OperatorService\");\n span.setAttribute(\"rpc.system\", \"connect-rpc\");\n\n try {\n const response = await next(req);\n span.setStatus({ code: SpanStatusCode.OK });\n return response;\n } catch (error) {\n span.setStatus({ code: SpanStatusCode.ERROR });\n if (error instanceof Error) {\n span.recordException(error);\n }\n throw error;\n } finally {\n span.end();\n }\n });\n };\n}\n"],"mappings":"+DASA,SAAgB,0BAAwC,CACtD,MAAQ,IAAS,KAAO,IACPA,EAAM,UAAU,QAEnB,CAAC,CAAC,gBAAgB,OAAOC,EAAI,OAAO,OAAQ,KAAO,IAAS,CACtEC,EAAK,aAAa,aAAcD,EAAI,OAAO,IAAI,EAC/CC,EAAK,aAAa,cAAe,iBAAiB,EAClDA,EAAK,aAAa,aAAc,aAAa,EAE7C,GAAI,CACF,IAAMC,EAAW,MAAMC,EAAKH,CAAG,EAE/B,OADAC,EAAK,UAAU,CAAE,KAAMG,EAAe,EAAG,CAAC,EACnCF,CACT,OAASG,EAAO,CAKd,MAJAJ,EAAK,UAAU,CAAE,KAAMG,EAAe,KAAM,CAAC,EACzCC,aAAiB,OACnBJ,EAAK,gBAAgBI,CAAK,EAEtBA,CACR,QAAU,CACRJ,EAAK,IAAI,CACX,CACF,CAAC,CAEL"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["Kysely","TailordbDialect"],"sources":["../../src/kysely/index.ts"],"sourcesContent":["/**\n * Kysely integration module for generated TailorDB code.\n *\n * Re-exports kysely and function-kysely-tailordb types through a single import path\n * to avoid phantom dependency issues with pnpm, and provides the namespace-aware\n * utility types and factory functions the code generator emits against.\n *\n * It also holds the `TailorDB*` input types, which hand-written code uses to derive\n * create/read/update shapes straight from a table or field collection. They live here\n * rather than in the main entry point because they are built out of kysely's column\n * types, which the main entry point does not otherwise depend on.\n */\n\nimport { TailordbDialect } from \"@tailor-platform/function-kysely-tailordb\";\nimport {\n type ColumnType,\n Kysely,\n type Insertable,\n type KyselyConfig,\n type Selectable,\n type Transaction as KyselyTransaction,\n type Updateable,\n} from \"kysely\";\nimport type {\n IsAutoFilledDBField,\n IsReadOnlyDBField,\n TailorAnyDBField,\n TailorAnyDBType,\n} from \"#/configure/services/tailordb/types\";\nimport type { output, TypeLevelError } from \"#/types/helpers\";\n\nexport {\n type ColumnType,\n Kysely,\n type KyselyConfig,\n type Transaction,\n type Insertable,\n type Selectable,\n sql,\n type Updateable,\n} from \"kysely\";\n\nexport { TailordbDialect } from \"@tailor-platform/function-kysely-tailordb\";\n\nexport type Timestamp = ColumnType<Date, Date | string, Date | string>;\ntype ResolveSelect<T> = T extends ColumnType<infer S, unknown, unknown> ? S : T;\ntype ResolveInsert<T> = T extends ColumnType<unknown, infer I, unknown> ? I : T;\ntype ResolveUpdate<T> = T extends ColumnType<unknown, unknown, infer U> ? U : T;\nexport type ObjectColumnType<T> = ColumnType<\n { [K in keyof T]-?: Exclude<ResolveSelect<T[K]>, undefined> },\n { [K in keyof T]: ResolveInsert<T[K]> },\n { [K in keyof T]: ResolveUpdate<T[K]> }\n>;\nexport type ArrayColumnType<T> = ColumnType<\n ResolveSelect<T>[],\n ResolveInsert<T>[],\n ResolveUpdate<T>[]\n>;\nexport type Generated<T> =\n T extends ColumnType<infer S, infer I, infer U>\n ? ColumnType<S, I | undefined, U>\n : ColumnType<T, T | undefined, T>;\n// The insert/update types carry the reason so that supplying a value fails with it,\n// instead of the bare \"does not exist\" an absent key produces. The named alias is\n// what survives in nested positions (values()/set()), where tsc elides the marker's\n// type argument and only the name reaches the user.\n// `| undefined` is what makes the column omittable; Kysely drops undefined columns\n// from the statement, so passing it explicitly is the same as leaving it out.\ntype SerialColumnMustBeOmitted = TypeLevelError<\"assigned by .serial(); remove it from the input\">;\nexport type Serial<T = string | number> = ColumnType<\n T,\n SerialColumnMustBeOmitted | undefined,\n SerialColumnMustBeOmitted | undefined\n>;\n\n// Kysely composes its input types out of intersections. Flattening them keeps the\n// shape readable in assignability errors and editor tooltips.\ntype FlattenColumns<T> = { [K in keyof T]: T[K] } & {};\n\nexport type TailordbKysely<DB> = Kysely<DB>;\nexport type NamespaceDB<NS, N extends keyof NS = keyof NS> = TailordbKysely<NS[N]>;\n\n/**\n * Create a namespace-aware getDB function for generated code.\n * @returns A getDB function that creates Kysely instances for specific namespaces\n */\nexport function createGetDB<NS>() {\n return function getDB<const N extends keyof NS & string>(\n namespace: N,\n config?: Omit<KyselyConfig, \"dialect\">,\n ): TailordbKysely<NS[N]> {\n const client = new tailordb.Client({ namespace });\n return new Kysely<NS[N]>({\n dialect: new TailordbDialect(client),\n ...config,\n });\n };\n}\n\nexport type NamespaceTransaction<NS, K extends keyof NS | TailordbKysely<NS[keyof NS]> = keyof NS> =\n K extends TailordbKysely<infer DB>\n ? KyselyTransaction<DB>\n : K extends keyof NS\n ? KyselyTransaction<NS[K]>\n : never;\n\nexport type NamespaceTableName<NS> = {\n [N in keyof NS]: keyof NS[N];\n}[keyof NS];\n\nexport type NamespaceTable<NS, T extends NamespaceTableName<NS>> = {\n [N in keyof NS]: T extends keyof NS[N] ? NS[N][T] : never;\n}[keyof NS];\n\nexport type NamespaceInsertable<NS, T extends NamespaceTableName<NS>> = FlattenColumns<\n Insertable<NamespaceTable<NS, T>>\n>;\nexport type NamespaceSelectable<NS, T extends NamespaceTableName<NS>> = FlattenColumns<\n Selectable<NamespaceTable<NS, T>>\n>;\nexport type NamespaceUpdateable<NS, T extends NamespaceTableName<NS>> = FlattenColumns<\n Updateable<NamespaceTable<NS, T>>\n>;\n\n/** What the derived input types accept: a table (`typeof myTable`) or a field collection. */\ntype TailorDBColumnsSource = TailorAnyDBType | Record<string, TailorAnyDBField>;\n\ntype DBFieldsOf<T> = T extends TailorAnyDBType ? T[\"fields\"] : T;\n\n// The column mapping below mirrors the one `kyselyTypePlugin` applies when it writes a\n// table interface (`plugin/builtin/kysely-type/type-processor.ts`), so both surfaces\n// resolve a field to the same column type — including inside nested objects, where the\n// function runtime also hands back a Date for a date/datetime.\n// `example/tests/kysely-parity.ts` pins the two against each other on real generator output.\ntype DBFieldType<F> = F extends TailorAnyDBField ? F[\"_defined\"][\"type\"] : never;\ntype IsArrayDBField<F> = F extends TailorAnyDBField\n ? F[\"_defined\"][\"array\"] extends true\n ? true\n : false\n : false;\n\ntype Unwrapped<F> = Exclude<output<F>, null>;\ntype ElementOutput<F> =\n IsArrayDBField<F> extends true\n ? Unwrapped<F> extends readonly (infer E)[]\n ? E\n : Unwrapped<F>\n : Unwrapped<F>;\n\ntype NestedFieldsOf<F> = F extends TailorAnyDBField ? F[\"fields\"] : never;\n\n// Nested props carry the same column mapping as top-level ones, so a datetime inside an\n// object also resolves to Timestamp. The optional marker matches what the output type\n// gives them, which is what the generator emits too.\n// `-readonly` because a field collection is inferred with `const`, and the generated\n// table interfaces declare their nested props mutable.\ntype NestedProps<Fields> = {\n -readonly [K in keyof Fields as null extends output<Fields[K]> ? never : K]: DBColumn<Fields[K]>;\n} & {\n -readonly [K in keyof Fields as null extends output<Fields[K]> ? K : never]?: DBColumn<Fields[K]>;\n};\n\n// The generator reaches for ObjectColumnType only when the object holds something whose\n// select and insert types differ: a timestamp, an optional prop, or a filled-in one.\ntype NestedNeedsColumnType<Fields> = true extends {\n [K in keyof Fields]: DBFieldType<Fields[K]> extends \"date\" | \"datetime\"\n ? true\n : null extends output<Fields[K]>\n ? true\n : DBFieldType<Fields[K]> extends \"nested\"\n ? NestedNeedsColumnType<NestedFieldsOf<Fields[K]>>\n : Fields[K] extends TailorAnyDBField\n ? IsAutoFilledDBField<Fields[K]>\n : false;\n}[keyof Fields]\n ? true\n : false;\n\ntype NestedColumn<F> =\n NestedNeedsColumnType<NestedFieldsOf<F>> extends true\n ? ObjectColumnType<FlattenColumns<NestedProps<NestedFieldsOf<F>>>>\n : FlattenColumns<NestedProps<NestedFieldsOf<F>>>;\n\ntype ElementColumn<F> =\n DBFieldType<F> extends \"date\" | \"datetime\"\n ? Timestamp\n : DBFieldType<F> extends \"nested\"\n ? NestedColumn<F>\n : ElementOutput<F>;\n\n// A ColumnType cannot sit inside an array — Kysely only unwraps it at the top level of a\n// table property — so an array of them keeps the ColumnType outermost.\ntype ArrayedColumn<F> =\n IsArrayDBField<F> extends true\n ? ElementColumn<F> extends ColumnType<unknown, unknown, unknown>\n ? ArrayColumnType<ElementColumn<F>>\n : ElementColumn<F>[]\n : ElementColumn<F>;\n\ntype NullableColumn<F> = null extends output<F> ? ArrayedColumn<F> | null : ArrayedColumn<F>;\n\ntype DBColumn<F> = F extends TailorAnyDBField\n ? IsReadOnlyDBField<F> extends true\n ? Serial<NullableColumn<F>>\n : IsAutoFilledDBField<F> extends true\n ? Generated<NullableColumn<F>>\n : NullableColumn<F>\n : never;\n\n// The column map the three derived types are built from. Not exported: it is how the\n// mapping is expressed, not something callers need to name.\ntype TailorDBColumns<T extends TailorDBColumnsSource> = {\n [K in keyof DBFieldsOf<T>]: K extends \"id\"\n ? Generated<output<DBFieldsOf<T>[K]>>\n : DBColumn<DBFieldsOf<T>[K]>;\n};\n\n/**\n * Create input derived from a TailorDB table (`typeof myTable`) or a field collection.\n *\n * Each field resolves to the column type `kyselyTypePlugin` writes for it, so this and\n * the generated table types agree: `.serial()` fields are never caller-supplied,\n * `.default()` / `.hooks({ create })` fields may be omitted, optional fields stay\n * optional, `id` is platform-generated, and a date or datetime reads back as `Date`.\n *\n * Pass a field collection when the fields are a type parameter — a shared module that\n * lets each project extend a table with its own fields cannot name a generated table\n * type. Declare it as `<const F extends Record<string, TailorAnyDBField>>` so the field\n * types are inferred; a bare `Record<string, TailorAnyDBField>` erases them and nothing\n * is checked.\n *\n * Hand the result to callers rather than consuming it inside the generic that declares\n * it: while `F` is still an unresolved type parameter the mapping stays deferred, so\n * assigning to it inside the function body reports the unevaluated conditional rather\n * than a readable shape.\n * @example\n * function createInput<const F extends Record<string, TailorAnyDBField>>(fields: F) {\n * return (input: TailorDBInsertable<F>) => { ... };\n * }\n */\nexport type TailorDBInsertable<T extends TailorDBColumnsSource> = FlattenColumns<\n Insertable<TailorDBColumns<T>>\n>;\n\n/** Read shape of a TailorDB table or field collection. See {@link TailorDBInsertable}. */\nexport type TailorDBSelectable<T extends TailorDBColumnsSource> = FlattenColumns<\n Selectable<TailorDBColumns<T>>\n>;\n\n/** Update input for a TailorDB table or field collection. See {@link TailorDBInsertable}. */\nexport type TailorDBUpdateable<T extends TailorDBColumnsSource> = FlattenColumns<\n Updateable<TailorDBColumns<T>>\n>;\n"],"mappings":"sJAsFA,SAAgB,aAAkB,CAChC,OAAO,SACL,EACA,EACuB,CACvB,IAAM,EAAS,IAAI,SAAS,OAAO,CAAE,WAAU,CAAC,EAChD,OAAO,IAAIA,EAAc,CACvB,QAAS,IAAIC,EAAgB,CAAM,EACnC,GAAG,CACL,CAAC,CACH,CACF"}
1
+ {"version":3,"file":"index.mjs","names":["Kysely","TailordbDialect","TailordbDialect$1","Kysely$1","client","config","Kysely","TailordbDialect","sql"],"sources":["../../src/kysely/index.ts"],"sourcesContent":["/**\n * Kysely integration module for generated TailorDB code.\n *\n * Re-exports kysely and function-kysely-tailordb types through a single import path\n * to avoid phantom dependency issues with pnpm, and provides the namespace-aware\n * utility types and factory functions the code generator emits against.\n *\n * It also holds the `TailorDB*` input types, which hand-written code uses to derive\n * create/read/update shapes straight from a table or field collection. They live here\n * rather than in the main entry point because they are built out of kysely's column\n * types, which the main entry point does not otherwise depend on.\n */\n\nimport { TailordbDialect } from \"@tailor-platform/function-kysely-tailordb\";\nimport {\n type ColumnType,\n Kysely,\n type Insertable,\n type KyselyConfig,\n type Selectable,\n type Transaction as KyselyTransaction,\n type Updateable,\n} from \"kysely\";\nimport type {\n IsAutoFilledDBField,\n IsReadOnlyDBField,\n TailorAnyDBField,\n TailorAnyDBType,\n} from \"#/configure/services/tailordb/types\";\nimport type { output, TypeLevelError } from \"#/types/helpers\";\n\nexport {\n type ColumnType,\n Kysely,\n type KyselyConfig,\n type Transaction,\n type Insertable,\n type Selectable,\n sql,\n type Updateable,\n} from \"kysely\";\n\nexport { TailordbDialect } from \"@tailor-platform/function-kysely-tailordb\";\n\nexport type Timestamp = ColumnType<Date, Date | string, Date | string>;\ntype ResolveSelect<T> = T extends ColumnType<infer S, unknown, unknown> ? S : T;\ntype ResolveInsert<T> = T extends ColumnType<unknown, infer I, unknown> ? I : T;\ntype ResolveUpdate<T> = T extends ColumnType<unknown, unknown, infer U> ? U : T;\nexport type ObjectColumnType<T> = ColumnType<\n { [K in keyof T]-?: Exclude<ResolveSelect<T[K]>, undefined> },\n { [K in keyof T]: ResolveInsert<T[K]> },\n { [K in keyof T]: ResolveUpdate<T[K]> }\n>;\nexport type ArrayColumnType<T> = ColumnType<\n ResolveSelect<T>[],\n ResolveInsert<T>[],\n ResolveUpdate<T>[]\n>;\nexport type Generated<T> =\n T extends ColumnType<infer S, infer I, infer U>\n ? ColumnType<S, I | undefined, U>\n : ColumnType<T, T | undefined, T>;\n// The insert/update types carry the reason so that supplying a value fails with it,\n// instead of the bare \"does not exist\" an absent key produces. The named alias is\n// what survives in nested positions (values()/set()), where tsc elides the marker's\n// type argument and only the name reaches the user.\n// `| undefined` is what makes the column omittable; Kysely drops undefined columns\n// from the statement, so passing it explicitly is the same as leaving it out.\ntype SerialColumnMustBeOmitted = TypeLevelError<\"assigned by .serial(); remove it from the input\">;\nexport type Serial<T = string | number> = ColumnType<\n T,\n SerialColumnMustBeOmitted | undefined,\n SerialColumnMustBeOmitted | undefined\n>;\n\n// Kysely composes its input types out of intersections. Flattening them keeps the\n// shape readable in assignability errors and editor tooltips.\ntype FlattenColumns<T> = { [K in keyof T]: T[K] } & {};\n\nexport type TailordbKysely<DB> = Kysely<DB>;\nexport type NamespaceDB<NS, N extends keyof NS = keyof NS> = TailordbKysely<NS[N]>;\n\n/**\n * Create a namespace-aware getDB function for generated code.\n * @returns A getDB function that creates Kysely instances for specific namespaces\n */\nexport function createGetDB<NS>() {\n return function getDB<const N extends keyof NS & string>(\n namespace: N,\n config?: Omit<KyselyConfig, \"dialect\">,\n ): TailordbKysely<NS[N]> {\n const client = new tailordb.Client({ namespace });\n return new Kysely<NS[N]>({\n dialect: new TailordbDialect(client),\n ...config,\n });\n };\n}\n\nexport type NamespaceTransaction<NS, K extends keyof NS | TailordbKysely<NS[keyof NS]> = keyof NS> =\n K extends TailordbKysely<infer DB>\n ? KyselyTransaction<DB>\n : K extends keyof NS\n ? KyselyTransaction<NS[K]>\n : never;\n\nexport type NamespaceTableName<NS> = {\n [N in keyof NS]: keyof NS[N];\n}[keyof NS];\n\nexport type NamespaceTable<NS, T extends NamespaceTableName<NS>> = {\n [N in keyof NS]: T extends keyof NS[N] ? NS[N][T] : never;\n}[keyof NS];\n\nexport type NamespaceInsertable<NS, T extends NamespaceTableName<NS>> = FlattenColumns<\n Insertable<NamespaceTable<NS, T>>\n>;\nexport type NamespaceSelectable<NS, T extends NamespaceTableName<NS>> = FlattenColumns<\n Selectable<NamespaceTable<NS, T>>\n>;\nexport type NamespaceUpdateable<NS, T extends NamespaceTableName<NS>> = FlattenColumns<\n Updateable<NamespaceTable<NS, T>>\n>;\n\n/** What the derived input types accept: a table (`typeof myTable`) or a field collection. */\ntype TailorDBColumnsSource = TailorAnyDBType | Record<string, TailorAnyDBField>;\n\ntype DBFieldsOf<T> = T extends TailorAnyDBType ? T[\"fields\"] : T;\n\n// The column mapping below mirrors the one `kyselyTypePlugin` applies when it writes a\n// table interface (`plugin/builtin/kysely-type/type-processor.ts`), so both surfaces\n// resolve a field to the same column type — including inside nested objects, where the\n// function runtime also hands back a Date for a date/datetime.\n// `example/tests/kysely-parity.ts` pins the two against each other on real generator output.\ntype DBFieldType<F> = F extends TailorAnyDBField ? F[\"_defined\"][\"type\"] : never;\ntype IsArrayDBField<F> = F extends TailorAnyDBField\n ? F[\"_defined\"][\"array\"] extends true\n ? true\n : false\n : false;\n\ntype Unwrapped<F> = Exclude<output<F>, null>;\ntype ElementOutput<F> =\n IsArrayDBField<F> extends true\n ? Unwrapped<F> extends readonly (infer E)[]\n ? E\n : Unwrapped<F>\n : Unwrapped<F>;\n\ntype NestedFieldsOf<F> = F extends TailorAnyDBField ? F[\"fields\"] : never;\n\n// Nested props carry the same column mapping as top-level ones, so a datetime inside an\n// object also resolves to Timestamp. The optional marker matches what the output type\n// gives them, which is what the generator emits too.\n// `-readonly` because a field collection is inferred with `const`, and the generated\n// table interfaces declare their nested props mutable.\ntype NestedProps<Fields> = {\n -readonly [K in keyof Fields as null extends output<Fields[K]> ? never : K]: DBColumn<Fields[K]>;\n} & {\n -readonly [K in keyof Fields as null extends output<Fields[K]> ? K : never]?: DBColumn<Fields[K]>;\n};\n\n// The generator reaches for ObjectColumnType only when the object holds something whose\n// select and insert types differ: a timestamp, an optional prop, or a filled-in one.\ntype NestedNeedsColumnType<Fields> = true extends {\n [K in keyof Fields]: DBFieldType<Fields[K]> extends \"date\" | \"datetime\"\n ? true\n : null extends output<Fields[K]>\n ? true\n : DBFieldType<Fields[K]> extends \"nested\"\n ? NestedNeedsColumnType<NestedFieldsOf<Fields[K]>>\n : Fields[K] extends TailorAnyDBField\n ? IsAutoFilledDBField<Fields[K]>\n : false;\n}[keyof Fields]\n ? true\n : false;\n\ntype NestedColumn<F> =\n NestedNeedsColumnType<NestedFieldsOf<F>> extends true\n ? ObjectColumnType<FlattenColumns<NestedProps<NestedFieldsOf<F>>>>\n : FlattenColumns<NestedProps<NestedFieldsOf<F>>>;\n\ntype ElementColumn<F> =\n DBFieldType<F> extends \"date\" | \"datetime\"\n ? Timestamp\n : DBFieldType<F> extends \"nested\"\n ? NestedColumn<F>\n : ElementOutput<F>;\n\n// A ColumnType cannot sit inside an array — Kysely only unwraps it at the top level of a\n// table property — so an array of them keeps the ColumnType outermost.\ntype ArrayedColumn<F> =\n IsArrayDBField<F> extends true\n ? ElementColumn<F> extends ColumnType<unknown, unknown, unknown>\n ? ArrayColumnType<ElementColumn<F>>\n : ElementColumn<F>[]\n : ElementColumn<F>;\n\ntype NullableColumn<F> = null extends output<F> ? ArrayedColumn<F> | null : ArrayedColumn<F>;\n\ntype DBColumn<F> = F extends TailorAnyDBField\n ? IsReadOnlyDBField<F> extends true\n ? Serial<NullableColumn<F>>\n : IsAutoFilledDBField<F> extends true\n ? Generated<NullableColumn<F>>\n : NullableColumn<F>\n : never;\n\n// The column map the three derived types are built from. Not exported: it is how the\n// mapping is expressed, not something callers need to name.\ntype TailorDBColumns<T extends TailorDBColumnsSource> = {\n [K in keyof DBFieldsOf<T>]: K extends \"id\"\n ? Generated<output<DBFieldsOf<T>[K]>>\n : DBColumn<DBFieldsOf<T>[K]>;\n};\n\n/**\n * Create input derived from a TailorDB table (`typeof myTable`) or a field collection.\n *\n * Each field resolves to the column type `kyselyTypePlugin` writes for it, so this and\n * the generated table types agree: `.serial()` fields are never caller-supplied,\n * `.default()` / `.hooks({ create })` fields may be omitted, optional fields stay\n * optional, `id` is platform-generated, and a date or datetime reads back as `Date`.\n *\n * Pass a field collection when the fields are a type parameter — a shared module that\n * lets each project extend a table with its own fields cannot name a generated table\n * type. Declare it as `<const F extends Record<string, TailorAnyDBField>>` so the field\n * types are inferred; a bare `Record<string, TailorAnyDBField>` erases them and nothing\n * is checked.\n *\n * Hand the result to callers rather than consuming it inside the generic that declares\n * it: while `F` is still an unresolved type parameter the mapping stays deferred, so\n * assigning to it inside the function body reports the unevaluated conditional rather\n * than a readable shape.\n * @example\n * function createInput<const F extends Record<string, TailorAnyDBField>>(fields: F) {\n * return (input: TailorDBInsertable<F>) => { ... };\n * }\n */\nexport type TailorDBInsertable<T extends TailorDBColumnsSource> = FlattenColumns<\n Insertable<TailorDBColumns<T>>\n>;\n\n/** Read shape of a TailorDB table or field collection. See {@link TailorDBInsertable}. */\nexport type TailorDBSelectable<T extends TailorDBColumnsSource> = FlattenColumns<\n Selectable<TailorDBColumns<T>>\n>;\n\n/** Update input for a TailorDB table or field collection. See {@link TailorDBInsertable}. */\nexport type TailorDBUpdateable<T extends TailorDBColumnsSource> = FlattenColumns<\n Updateable<TailorDBColumns<T>>\n>;\n"],"mappings":"sJAsFA,SAAgB,aAAkB,CAChC,OAAO,SACL,EACA,EACuB,CACvB,IAAMI,EAAS,IAAI,SAAS,OAAO,CAAE,WAAU,CAAC,EAChD,OAAO,IAAIJ,EAAc,CACvB,QAAS,IAAIC,EAAgBG,CAAM,EACnC,GAAGC,CACL,CAAC,CACH,CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"kysely-type-C-iyFFH7.mjs","names":[],"sources":["../src/plugin/builtin/kysely-type/type-processor.ts","../src/plugin/builtin/kysely-type/pglite-schema.ts","../src/plugin/builtin/kysely-type/index.ts"],"sourcesContent":["import { COLUMN_TYPE_ALIASES, mapFieldTypeToColumnType } from \"#/utils/field-column-type\";\nimport multiline from \"#/utils/multiline\";\nimport {\n type KyselyFieldConfig,\n type KyselyNamespaceMetadata,\n type KyselyTypeMetadata,\n type UsedUtilityTypes,\n} from \"./types\";\nimport type { TailorDBType } from \"#/parser/service/tailordb/types\";\n\ntype FieldTypeResult = {\n type: string;\n usedUtilityTypes: UsedUtilityTypes;\n};\n\nfunction emptyUsedUtilityTypes(): UsedUtilityTypes {\n return { Timestamp: false, Serial: false, ObjectColumnType: false, ArrayColumnType: false };\n}\n\nfunction mergeUsedUtilityTypes(a: UsedUtilityTypes, b: UsedUtilityTypes): UsedUtilityTypes {\n return {\n Timestamp: a.Timestamp || b.Timestamp,\n Serial: a.Serial || b.Serial,\n ObjectColumnType: a.ObjectColumnType || b.ObjectColumnType,\n ArrayColumnType: a.ArrayColumnType || b.ArrayColumnType,\n };\n}\n\n/**\n * Get the enum type definition.\n * @param fieldConfig - The field configuration\n * @returns The enum type as a string union\n */\nfunction getEnumType(fieldConfig: KyselyFieldConfig): string {\n const allowedValues = fieldConfig.allowedValues;\n\n if (allowedValues && Array.isArray(allowedValues)) {\n return allowedValues\n .map((v: string | { value: string }) => {\n const value = typeof v === \"string\" ? v : v.value;\n return `\"${value}\"`;\n })\n .join(\" | \");\n }\n return \"string\";\n}\n\n/**\n * Get the nested object type definition.\n * @param fieldConfig - The field configuration\n * @returns The nested type with used utility types\n */\nfunction getNestedType(fieldConfig: KyselyFieldConfig): FieldTypeResult {\n const fields = fieldConfig.fields;\n if (!fields || typeof fields !== \"object\") {\n return {\n type: \"string\",\n usedUtilityTypes: emptyUsedUtilityTypes(),\n };\n }\n\n const fieldResults = Object.entries(fields).map(([fieldName, config]) => {\n const result = generateFieldType(config);\n const optional = config.required !== true ? \"?\" : \"\";\n return {\n fieldType: `${fieldName}${optional}: ${result.type}`,\n usedUtilityTypes: result.usedUtilityTypes,\n };\n });\n\n const aggregatedUtilityTypes = fieldResults.reduce(\n (acc, result) => mergeUsedUtilityTypes(acc, result.usedUtilityTypes),\n emptyUsedUtilityTypes(),\n );\n\n const fieldTypes = fieldResults.map((r) => r.fieldType);\n const obj = `{\\n ${fieldTypes.join(\";\\n \")}${fieldTypes.length > 0 ? \";\" : \"\"}\\n}`;\n\n const hasOptionalFields = Object.values(fields).some((config) => config.required !== true);\n const hasGeneratedFields = Object.values(fields).some(\n (config) =>\n config.hooks?.create || config.default !== undefined || config.optionalOnCreate === true,\n );\n if (aggregatedUtilityTypes.Timestamp || hasOptionalFields || hasGeneratedFields) {\n return {\n type: `ObjectColumnType<${obj}>`,\n usedUtilityTypes: { ...aggregatedUtilityTypes, ObjectColumnType: true },\n };\n }\n return { type: obj, usedUtilityTypes: aggregatedUtilityTypes };\n}\n\n/**\n * Get the base Kysely type for a field (without array/null modifiers).\n * @param fieldConfig - The field configuration\n * @returns The base type with used utility types\n */\nfunction getBaseType(fieldConfig: KyselyFieldConfig): FieldTypeResult {\n const fieldType = fieldConfig.type;\n const usedUtilityTypes = emptyUsedUtilityTypes();\n\n if (fieldType === \"enum\") {\n return { type: getEnumType(fieldConfig), usedUtilityTypes };\n }\n if (fieldType === \"nested\") {\n return getNestedType(fieldConfig);\n }\n\n const type = mapFieldTypeToColumnType(fieldType);\n usedUtilityTypes.Timestamp = type === \"Timestamp\";\n\n return { type, usedUtilityTypes };\n}\n\n/**\n * Generate the complete field type including array and null modifiers.\n * @param fieldConfig - The field configuration\n * @returns The complete field type with used utility types\n */\nfunction generateFieldType(fieldConfig: KyselyFieldConfig): FieldTypeResult {\n const baseTypeResult = getBaseType(fieldConfig);\n const usedUtilityTypes = { ...baseTypeResult.usedUtilityTypes };\n\n const isArray = fieldConfig.array === true;\n const isNullable = fieldConfig.required !== true;\n\n // A ColumnType-shaped alias and ObjectColumnType cannot be wrapped with [] for\n // arrays, because Kysely only resolves ColumnType at the top-level table\n // property. Use ArrayColumnType to keep the ColumnType at the top level.\n const isColumnTypeBase = COLUMN_TYPE_ALIASES.has(baseTypeResult.type);\n\n let finalType = baseTypeResult.type;\n if (isArray) {\n if (isColumnTypeBase || finalType.startsWith(\"ObjectColumnType<\")) {\n finalType = `ArrayColumnType<${baseTypeResult.type}>`;\n usedUtilityTypes.ArrayColumnType = true;\n } else {\n const needsParens = fieldConfig.type === \"enum\";\n finalType = needsParens ? `(${baseTypeResult.type})[]` : `${baseTypeResult.type}[]`;\n }\n }\n if (isNullable) {\n finalType = `${finalType} | null`;\n }\n\n if (fieldConfig.serial) {\n usedUtilityTypes.Serial = true;\n finalType = `Serial<${finalType}>`;\n }\n if (\n fieldConfig.hooks?.create ||\n fieldConfig.default !== undefined ||\n fieldConfig.optionalOnCreate === true\n ) {\n finalType = `Generated<${finalType}>`;\n }\n\n return { type: finalType, usedUtilityTypes };\n}\n\n/**\n * Generate the table interface.\n * @param name - Table name\n * @param fields - Field configurations keyed by field name\n * @returns The type definition and used utility types\n */\nfunction generateTableInterface(\n name: string,\n fields: Record<string, KyselyFieldConfig>,\n): {\n typeDef: string;\n usedUtilityTypes: UsedUtilityTypes;\n} {\n const fieldEntries = Object.entries(fields).filter(([fieldName]) => fieldName !== \"id\");\n\n const fieldResults = fieldEntries.map(([fieldName, fieldConfig]) => ({\n fieldName,\n ...generateFieldType(fieldConfig),\n }));\n\n const fieldLines = [\n \"id: Generated<string>;\",\n ...fieldResults.map((result) => `${result.fieldName}: ${result.type};`),\n ];\n\n const aggregatedUtilityTypes = fieldResults.reduce(\n (acc, result) => mergeUsedUtilityTypes(acc, result.usedUtilityTypes),\n emptyUsedUtilityTypes(),\n );\n\n const typeDef = multiline /* ts */ `\n ${name}: {\n ${fieldLines.join(\"\\n\")}\n }\n `;\n\n return { typeDef, usedUtilityTypes: aggregatedUtilityTypes };\n}\n\n/**\n * Generate KyselyTypeMetadata from field configurations.\n * @param name - Table name\n * @param fields - Field configurations keyed by field name\n * @returns Generated Kysely type metadata\n */\nexport function processKyselyFields(\n name: string,\n fields: Record<string, KyselyFieldConfig>,\n): KyselyTypeMetadata {\n const result = generateTableInterface(name, fields);\n\n return {\n name,\n typeDef: result.typeDef,\n usedUtilityTypes: result.usedUtilityTypes,\n };\n}\n\n/**\n * Convert a TailorDBType into KyselyTypeMetadata.\n * @param type - Parsed TailorDB table\n * @returns Generated Kysely type metadata\n */\nexport async function processKyselyType(type: TailorDBType): Promise<KyselyTypeMetadata> {\n return processKyselyFields(\n type.name,\n Object.fromEntries(\n Object.entries(type.fields).map(([fieldName, parsedField]) => [\n fieldName,\n parsedField.config,\n ]),\n ),\n );\n}\n\n/**\n * Generate unified types file from multiple namespaces.\n * @param namespaceData - Namespace metadata\n * @returns Generated types file contents\n */\nexport function generateUnifiedKyselyTypes(namespaceData: KyselyNamespaceMetadata[]): string {\n if (namespaceData.length === 0) {\n return \"\";\n }\n\n // Aggregate used utility types from all namespaces\n const globalUsedUtilityTypes = namespaceData\n .flatMap((ns) => ns.types)\n .reduce(\n (acc, type) => mergeUsedUtilityTypes(acc, type.usedUtilityTypes),\n emptyUsedUtilityTypes(),\n );\n\n const utilityTypeImports: string[] = [\"type Generated\"];\n if (globalUsedUtilityTypes.Timestamp) {\n utilityTypeImports.push(\"type Timestamp\");\n }\n if (globalUsedUtilityTypes.ObjectColumnType) {\n utilityTypeImports.push(\"type ObjectColumnType\");\n }\n if (globalUsedUtilityTypes.ArrayColumnType) {\n utilityTypeImports.push(\"type ArrayColumnType\");\n }\n if (globalUsedUtilityTypes.Serial) {\n utilityTypeImports.push(\"type Serial\");\n }\n\n const importsSection = multiline /* ts */ `\n import {\n createGetDB,\n ${utilityTypeImports.join(\",\\n\")},\n type NamespaceDB,\n type NamespaceInsertable,\n type NamespaceSelectable,\n type NamespaceTable,\n type NamespaceTableName,\n type NamespaceTransaction,\n type NamespaceUpdateable,\n } from \"@tailor-platform/sdk/kysely\";\n `;\n\n // Generate Namespace interface with multiple namespaces\n const namespaceInterfaces = namespaceData\n .map(({ namespace, types }) => {\n const typeDefsWithIndent = types\n .map((type) => {\n return type.typeDef\n .split(\"\\n\")\n .map((line) => (line.trim() ? ` ${line}` : \"\"))\n .join(\"\\n\");\n })\n .join(\"\\n\\n\");\n\n return ` \"${namespace}\": {\\n${typeDefsWithIndent}\\n }`;\n })\n .join(\",\\n\");\n\n const namespaceInterface = `export interface Namespace {\\n${namespaceInterfaces}\\n}`;\n\n const getDBFunction = multiline /* ts */ `\n export const getDB = createGetDB<Namespace>();\n\n export type DB<N extends keyof Namespace = keyof Namespace> = NamespaceDB<Namespace, N>;\n `;\n\n const utilityTypeExports = multiline /* ts */ `\n export type Transaction<K extends keyof Namespace | DB = keyof Namespace> =\n NamespaceTransaction<Namespace, K>;\n\n type TableName = NamespaceTableName<Namespace>;\n export type Table<T extends TableName> = NamespaceTable<Namespace, T>;\n\n export type Insertable<T extends TableName> = NamespaceInsertable<Namespace, T>;\n export type Selectable<T extends TableName> = NamespaceSelectable<Namespace, T>;\n export type Updateable<T extends TableName> = NamespaceUpdateable<Namespace, T>;\n `;\n\n return (\n [importsSection, namespaceInterface, getDBFunction, utilityTypeExports].join(\"\\n\\n\") + \"\\n\"\n );\n}\n","import { generatePgliteSchemaModule, type DDLTableConfig } from \"#/utils/tailordb-ddl\";\nimport type { TailorDBType } from \"#/parser/service/tailordb/types\";\n\n/** Tables of one namespace, as the schema module groups them. */\nexport interface PGliteSchemaNamespace {\n namespace: string;\n tables: Record<string, TailorDBType>;\n}\n\n/**\n * Reduce parsed tables to what the DDL generator reads.\n * @param tables - Parsed TailorDB tables keyed by name\n * @returns DDL table configs in the same order\n */\nexport function toDDLTables(tables: Record<string, TailorDBType>): DDLTableConfig[] {\n return Object.values(tables).map((type) => ({\n name: type.name,\n fields: Object.fromEntries(\n Object.entries(type.fields).map(([fieldName, field]) => [fieldName, field.config]),\n ),\n indexes: type.indexes,\n }));\n}\n\n/**\n * Render the module that exports each namespace's `CREATE TABLE` script for\n * `pglite.exec()`.\n * @param namespaces - Namespaces with their parsed tables\n * @returns TypeScript source of the schema module\n */\nexport function generatePGliteSchemaModule(namespaces: readonly PGliteSchemaNamespace[]): string {\n return generatePgliteSchemaModule(\n namespaces.map(({ namespace, tables }) => ({ namespace, tables: toDDLTables(tables) })),\n { generatedBy: \"the kysely-type plugin\" },\n );\n}\n","import { resolve } from \"pathe\";\nimport { generatePGliteSchemaModule } from \"./pglite-schema\";\nimport { processKyselyType, generateUnifiedKyselyTypes } from \"./type-processor\";\nimport type { Plugin, GeneratorResult, TailorDBReadyContext } from \"#/plugin/types\";\nimport type { KyselyTypeMetadata, KyselyNamespaceMetadata } from \"./types\";\n\n/** Unique identifier for the Kysely type generator plugin. */\nexport const KyselyGeneratorID = \"@tailor-platform/kysely-type\";\n\ntype KyselyTypePluginOptions = {\n distPath: string;\n pgliteSchemaPath?: string;\n};\n\n// Register this plugin's config type under its own id, via the package's\n// real public specifier, so callers can resolve it type-safely from a\n// `Plugin[]` array (see plugin/get-plugin-config.ts's resolvePluginConfig)\n// without importing KyselyTypePluginOptions, which stays unexported.\ndeclare module \"@tailor-platform/sdk/plugin\" {\n interface PluginConfigRegistry {\n \"@tailor-platform/kysely-type\": KyselyTypePluginOptions;\n }\n}\n\n/** Conventional output path used when `kyselyTypePlugin` has no `distPath` configured. */\nexport const DEFAULT_KYSELY_TYPES_DIST_PATH = \"./generated/tailordb.ts\";\n\n/**\n * Plugin that generates Kysely type definitions for TailorDB tables.\n * @param options - Plugin options\n * @param options.distPath - Output file path for generated types\n * @param options.pgliteSchemaPath - Output file path for the PGlite `CREATE TABLE` script module; omit to skip it\n * @returns Plugin instance with onTailorDBReady hook\n */\nexport function kyselyTypePlugin(\n options: KyselyTypePluginOptions,\n): Plugin<unknown, KyselyTypePluginOptions> {\n return {\n id: KyselyGeneratorID,\n description: \"Generates Kysely type definitions for TailorDB tables\",\n pluginConfig: options,\n\n async onTailorDBReady(\n ctx: TailorDBReadyContext<KyselyTypePluginOptions>,\n ): Promise<GeneratorResult> {\n const { distPath, pgliteSchemaPath } = ctx.pluginConfig;\n if (pgliteSchemaPath && resolve(distPath) === resolve(pgliteSchemaPath)) {\n throw new Error(\"distPath and pgliteSchemaPath must resolve to different files.\");\n }\n\n const allNamespaceData: KyselyNamespaceMetadata[] = [];\n\n for (const ns of ctx.tailordb) {\n const typeMetadataList: KyselyTypeMetadata[] = [];\n\n for (const type of Object.values(ns.tables)) {\n const metadata = await processKyselyType(type);\n typeMetadataList.push(metadata);\n }\n\n if (typeMetadataList.length === 0) continue;\n\n allNamespaceData.push({\n namespace: ns.namespace,\n types: typeMetadataList,\n });\n }\n\n const files: GeneratorResult[\"files\"] = [];\n if (allNamespaceData.length > 0) {\n const content = generateUnifiedKyselyTypes(allNamespaceData);\n files.push({\n path: ctx.pluginConfig.distPath,\n content,\n });\n if (ctx.pluginConfig.pgliteSchemaPath) {\n files.push({\n path: ctx.pluginConfig.pgliteSchemaPath,\n content: generatePGliteSchemaModule(\n ctx.tailordb.filter((ns) => Object.keys(ns.tables).length > 0),\n ),\n });\n }\n }\n\n return { files };\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"kysely-type-C-iyFFH7.mjs","names":["multiline","COLUMN_TYPE_ALIASES","mapFieldTypeToColumnType","generatePgliteSchemaModule","a","b","allowedValues","fieldConfig","v","fields","fieldResults","fieldName","config","result","aggregatedUtilityTypes","acc","fieldTypes","r","obj","hasOptionalFields","hasGeneratedFields","fieldType","usedUtilityTypes","type","baseTypeResult","isArray","isNullable","isColumnTypeBase","finalType","fieldLines","name","parsedField","namespaceData","globalUsedUtilityTypes","ns","utilityTypeImports","namespace","types","line","tables","field","namespaces","KyselyGeneratorID","DEFAULT_KYSELY_TYPES_DIST_PATH","options","ctx","pgliteSchemaPath","resolve","distPath","allNamespaceData","typeMetadataList","metadata","files","content"],"sources":["../src/plugin/builtin/kysely-type/type-processor.ts","../src/plugin/builtin/kysely-type/pglite-schema.ts","../src/plugin/builtin/kysely-type/index.ts"],"sourcesContent":["import { COLUMN_TYPE_ALIASES, mapFieldTypeToColumnType } from \"#/utils/field-column-type\";\nimport multiline from \"#/utils/multiline\";\nimport {\n type KyselyFieldConfig,\n type KyselyNamespaceMetadata,\n type KyselyTypeMetadata,\n type UsedUtilityTypes,\n} from \"./types\";\nimport type { TailorDBType } from \"#/parser/service/tailordb/types\";\n\ntype FieldTypeResult = {\n type: string;\n usedUtilityTypes: UsedUtilityTypes;\n};\n\nfunction emptyUsedUtilityTypes(): UsedUtilityTypes {\n return { Timestamp: false, Serial: false, ObjectColumnType: false, ArrayColumnType: false };\n}\n\nfunction mergeUsedUtilityTypes(a: UsedUtilityTypes, b: UsedUtilityTypes): UsedUtilityTypes {\n return {\n Timestamp: a.Timestamp || b.Timestamp,\n Serial: a.Serial || b.Serial,\n ObjectColumnType: a.ObjectColumnType || b.ObjectColumnType,\n ArrayColumnType: a.ArrayColumnType || b.ArrayColumnType,\n };\n}\n\n/**\n * Get the enum type definition.\n * @param fieldConfig - The field configuration\n * @returns The enum type as a string union\n */\nfunction getEnumType(fieldConfig: KyselyFieldConfig): string {\n const allowedValues = fieldConfig.allowedValues;\n\n if (allowedValues && Array.isArray(allowedValues)) {\n return allowedValues\n .map((v: string | { value: string }) => {\n const value = typeof v === \"string\" ? v : v.value;\n return `\"${value}\"`;\n })\n .join(\" | \");\n }\n return \"string\";\n}\n\n/**\n * Get the nested object type definition.\n * @param fieldConfig - The field configuration\n * @returns The nested type with used utility types\n */\nfunction getNestedType(fieldConfig: KyselyFieldConfig): FieldTypeResult {\n const fields = fieldConfig.fields;\n if (!fields || typeof fields !== \"object\") {\n return {\n type: \"string\",\n usedUtilityTypes: emptyUsedUtilityTypes(),\n };\n }\n\n const fieldResults = Object.entries(fields).map(([fieldName, config]) => {\n const result = generateFieldType(config);\n const optional = config.required !== true ? \"?\" : \"\";\n return {\n fieldType: `${fieldName}${optional}: ${result.type}`,\n usedUtilityTypes: result.usedUtilityTypes,\n };\n });\n\n const aggregatedUtilityTypes = fieldResults.reduce(\n (acc, result) => mergeUsedUtilityTypes(acc, result.usedUtilityTypes),\n emptyUsedUtilityTypes(),\n );\n\n const fieldTypes = fieldResults.map((r) => r.fieldType);\n const obj = `{\\n ${fieldTypes.join(\";\\n \")}${fieldTypes.length > 0 ? \";\" : \"\"}\\n}`;\n\n const hasOptionalFields = Object.values(fields).some((config) => config.required !== true);\n const hasGeneratedFields = Object.values(fields).some(\n (config) =>\n config.hooks?.create || config.default !== undefined || config.optionalOnCreate === true,\n );\n if (aggregatedUtilityTypes.Timestamp || hasOptionalFields || hasGeneratedFields) {\n return {\n type: `ObjectColumnType<${obj}>`,\n usedUtilityTypes: { ...aggregatedUtilityTypes, ObjectColumnType: true },\n };\n }\n return { type: obj, usedUtilityTypes: aggregatedUtilityTypes };\n}\n\n/**\n * Get the base Kysely type for a field (without array/null modifiers).\n * @param fieldConfig - The field configuration\n * @returns The base type with used utility types\n */\nfunction getBaseType(fieldConfig: KyselyFieldConfig): FieldTypeResult {\n const fieldType = fieldConfig.type;\n const usedUtilityTypes = emptyUsedUtilityTypes();\n\n if (fieldType === \"enum\") {\n return { type: getEnumType(fieldConfig), usedUtilityTypes };\n }\n if (fieldType === \"nested\") {\n return getNestedType(fieldConfig);\n }\n\n const type = mapFieldTypeToColumnType(fieldType);\n usedUtilityTypes.Timestamp = type === \"Timestamp\";\n\n return { type, usedUtilityTypes };\n}\n\n/**\n * Generate the complete field type including array and null modifiers.\n * @param fieldConfig - The field configuration\n * @returns The complete field type with used utility types\n */\nfunction generateFieldType(fieldConfig: KyselyFieldConfig): FieldTypeResult {\n const baseTypeResult = getBaseType(fieldConfig);\n const usedUtilityTypes = { ...baseTypeResult.usedUtilityTypes };\n\n const isArray = fieldConfig.array === true;\n const isNullable = fieldConfig.required !== true;\n\n // A ColumnType-shaped alias and ObjectColumnType cannot be wrapped with [] for\n // arrays, because Kysely only resolves ColumnType at the top-level table\n // property. Use ArrayColumnType to keep the ColumnType at the top level.\n const isColumnTypeBase = COLUMN_TYPE_ALIASES.has(baseTypeResult.type);\n\n let finalType = baseTypeResult.type;\n if (isArray) {\n if (isColumnTypeBase || finalType.startsWith(\"ObjectColumnType<\")) {\n finalType = `ArrayColumnType<${baseTypeResult.type}>`;\n usedUtilityTypes.ArrayColumnType = true;\n } else {\n const needsParens = fieldConfig.type === \"enum\";\n finalType = needsParens ? `(${baseTypeResult.type})[]` : `${baseTypeResult.type}[]`;\n }\n }\n if (isNullable) {\n finalType = `${finalType} | null`;\n }\n\n if (fieldConfig.serial) {\n usedUtilityTypes.Serial = true;\n finalType = `Serial<${finalType}>`;\n }\n if (\n fieldConfig.hooks?.create ||\n fieldConfig.default !== undefined ||\n fieldConfig.optionalOnCreate === true\n ) {\n finalType = `Generated<${finalType}>`;\n }\n\n return { type: finalType, usedUtilityTypes };\n}\n\n/**\n * Generate the table interface.\n * @param name - Table name\n * @param fields - Field configurations keyed by field name\n * @returns The type definition and used utility types\n */\nfunction generateTableInterface(\n name: string,\n fields: Record<string, KyselyFieldConfig>,\n): {\n typeDef: string;\n usedUtilityTypes: UsedUtilityTypes;\n} {\n const fieldEntries = Object.entries(fields).filter(([fieldName]) => fieldName !== \"id\");\n\n const fieldResults = fieldEntries.map(([fieldName, fieldConfig]) => ({\n fieldName,\n ...generateFieldType(fieldConfig),\n }));\n\n const fieldLines = [\n \"id: Generated<string>;\",\n ...fieldResults.map((result) => `${result.fieldName}: ${result.type};`),\n ];\n\n const aggregatedUtilityTypes = fieldResults.reduce(\n (acc, result) => mergeUsedUtilityTypes(acc, result.usedUtilityTypes),\n emptyUsedUtilityTypes(),\n );\n\n const typeDef = multiline /* ts */ `\n ${name}: {\n ${fieldLines.join(\"\\n\")}\n }\n `;\n\n return { typeDef, usedUtilityTypes: aggregatedUtilityTypes };\n}\n\n/**\n * Generate KyselyTypeMetadata from field configurations.\n * @param name - Table name\n * @param fields - Field configurations keyed by field name\n * @returns Generated Kysely type metadata\n */\nexport function processKyselyFields(\n name: string,\n fields: Record<string, KyselyFieldConfig>,\n): KyselyTypeMetadata {\n const result = generateTableInterface(name, fields);\n\n return {\n name,\n typeDef: result.typeDef,\n usedUtilityTypes: result.usedUtilityTypes,\n };\n}\n\n/**\n * Convert a TailorDBType into KyselyTypeMetadata.\n * @param type - Parsed TailorDB table\n * @returns Generated Kysely type metadata\n */\nexport async function processKyselyType(type: TailorDBType): Promise<KyselyTypeMetadata> {\n return processKyselyFields(\n type.name,\n Object.fromEntries(\n Object.entries(type.fields).map(([fieldName, parsedField]) => [\n fieldName,\n parsedField.config,\n ]),\n ),\n );\n}\n\n/**\n * Generate unified types file from multiple namespaces.\n * @param namespaceData - Namespace metadata\n * @returns Generated types file contents\n */\nexport function generateUnifiedKyselyTypes(namespaceData: KyselyNamespaceMetadata[]): string {\n if (namespaceData.length === 0) {\n return \"\";\n }\n\n // Aggregate used utility types from all namespaces\n const globalUsedUtilityTypes = namespaceData\n .flatMap((ns) => ns.types)\n .reduce(\n (acc, type) => mergeUsedUtilityTypes(acc, type.usedUtilityTypes),\n emptyUsedUtilityTypes(),\n );\n\n const utilityTypeImports: string[] = [\"type Generated\"];\n if (globalUsedUtilityTypes.Timestamp) {\n utilityTypeImports.push(\"type Timestamp\");\n }\n if (globalUsedUtilityTypes.ObjectColumnType) {\n utilityTypeImports.push(\"type ObjectColumnType\");\n }\n if (globalUsedUtilityTypes.ArrayColumnType) {\n utilityTypeImports.push(\"type ArrayColumnType\");\n }\n if (globalUsedUtilityTypes.Serial) {\n utilityTypeImports.push(\"type Serial\");\n }\n\n const importsSection = multiline /* ts */ `\n import {\n createGetDB,\n ${utilityTypeImports.join(\",\\n\")},\n type NamespaceDB,\n type NamespaceInsertable,\n type NamespaceSelectable,\n type NamespaceTable,\n type NamespaceTableName,\n type NamespaceTransaction,\n type NamespaceUpdateable,\n } from \"@tailor-platform/sdk/kysely\";\n `;\n\n // Generate Namespace interface with multiple namespaces\n const namespaceInterfaces = namespaceData\n .map(({ namespace, types }) => {\n const typeDefsWithIndent = types\n .map((type) => {\n return type.typeDef\n .split(\"\\n\")\n .map((line) => (line.trim() ? ` ${line}` : \"\"))\n .join(\"\\n\");\n })\n .join(\"\\n\\n\");\n\n return ` \"${namespace}\": {\\n${typeDefsWithIndent}\\n }`;\n })\n .join(\",\\n\");\n\n const namespaceInterface = `export interface Namespace {\\n${namespaceInterfaces}\\n}`;\n\n const getDBFunction = multiline /* ts */ `\n export const getDB = createGetDB<Namespace>();\n\n export type DB<N extends keyof Namespace = keyof Namespace> = NamespaceDB<Namespace, N>;\n `;\n\n const utilityTypeExports = multiline /* ts */ `\n export type Transaction<K extends keyof Namespace | DB = keyof Namespace> =\n NamespaceTransaction<Namespace, K>;\n\n type TableName = NamespaceTableName<Namespace>;\n export type Table<T extends TableName> = NamespaceTable<Namespace, T>;\n\n export type Insertable<T extends TableName> = NamespaceInsertable<Namespace, T>;\n export type Selectable<T extends TableName> = NamespaceSelectable<Namespace, T>;\n export type Updateable<T extends TableName> = NamespaceUpdateable<Namespace, T>;\n `;\n\n return (\n [importsSection, namespaceInterface, getDBFunction, utilityTypeExports].join(\"\\n\\n\") + \"\\n\"\n );\n}\n","import { generatePgliteSchemaModule, type DDLTableConfig } from \"#/utils/tailordb-ddl\";\nimport type { TailorDBType } from \"#/parser/service/tailordb/types\";\n\n/** Tables of one namespace, as the schema module groups them. */\nexport interface PGliteSchemaNamespace {\n namespace: string;\n tables: Record<string, TailorDBType>;\n}\n\n/**\n * Reduce parsed tables to what the DDL generator reads.\n * @param tables - Parsed TailorDB tables keyed by name\n * @returns DDL table configs in the same order\n */\nexport function toDDLTables(tables: Record<string, TailorDBType>): DDLTableConfig[] {\n return Object.values(tables).map((type) => ({\n name: type.name,\n fields: Object.fromEntries(\n Object.entries(type.fields).map(([fieldName, field]) => [fieldName, field.config]),\n ),\n indexes: type.indexes,\n }));\n}\n\n/**\n * Render the module that exports each namespace's `CREATE TABLE` script for\n * `pglite.exec()`.\n * @param namespaces - Namespaces with their parsed tables\n * @returns TypeScript source of the schema module\n */\nexport function generatePGliteSchemaModule(namespaces: readonly PGliteSchemaNamespace[]): string {\n return generatePgliteSchemaModule(\n namespaces.map(({ namespace, tables }) => ({ namespace, tables: toDDLTables(tables) })),\n { generatedBy: \"the kysely-type plugin\" },\n );\n}\n","import { resolve } from \"pathe\";\nimport { generatePGliteSchemaModule } from \"./pglite-schema\";\nimport { processKyselyType, generateUnifiedKyselyTypes } from \"./type-processor\";\nimport type { Plugin, GeneratorResult, TailorDBReadyContext } from \"#/plugin/types\";\nimport type { KyselyTypeMetadata, KyselyNamespaceMetadata } from \"./types\";\n\n/** Unique identifier for the Kysely type generator plugin. */\nexport const KyselyGeneratorID = \"@tailor-platform/kysely-type\";\n\ntype KyselyTypePluginOptions = {\n distPath: string;\n pgliteSchemaPath?: string;\n};\n\n// Register this plugin's config type under its own id, via the package's\n// real public specifier, so callers can resolve it type-safely from a\n// `Plugin[]` array (see plugin/get-plugin-config.ts's resolvePluginConfig)\n// without importing KyselyTypePluginOptions, which stays unexported.\ndeclare module \"@tailor-platform/sdk/plugin\" {\n interface PluginConfigRegistry {\n \"@tailor-platform/kysely-type\": KyselyTypePluginOptions;\n }\n}\n\n/** Conventional output path used when `kyselyTypePlugin` has no `distPath` configured. */\nexport const DEFAULT_KYSELY_TYPES_DIST_PATH = \"./generated/tailordb.ts\";\n\n/**\n * Plugin that generates Kysely type definitions for TailorDB tables.\n * @param options - Plugin options\n * @param options.distPath - Output file path for generated types\n * @param options.pgliteSchemaPath - Output file path for the PGlite `CREATE TABLE` script module; omit to skip it\n * @returns Plugin instance with onTailorDBReady hook\n */\nexport function kyselyTypePlugin(\n options: KyselyTypePluginOptions,\n): Plugin<unknown, KyselyTypePluginOptions> {\n return {\n id: KyselyGeneratorID,\n description: \"Generates Kysely type definitions for TailorDB tables\",\n pluginConfig: options,\n\n async onTailorDBReady(\n ctx: TailorDBReadyContext<KyselyTypePluginOptions>,\n ): Promise<GeneratorResult> {\n const { distPath, pgliteSchemaPath } = ctx.pluginConfig;\n if (pgliteSchemaPath && resolve(distPath) === resolve(pgliteSchemaPath)) {\n throw new Error(\"distPath and pgliteSchemaPath must resolve to different files.\");\n }\n\n const allNamespaceData: KyselyNamespaceMetadata[] = [];\n\n for (const ns of ctx.tailordb) {\n const typeMetadataList: KyselyTypeMetadata[] = [];\n\n for (const type of Object.values(ns.tables)) {\n const metadata = await processKyselyType(type);\n typeMetadataList.push(metadata);\n }\n\n if (typeMetadataList.length === 0) continue;\n\n allNamespaceData.push({\n namespace: ns.namespace,\n types: typeMetadataList,\n });\n }\n\n const files: GeneratorResult[\"files\"] = [];\n if (allNamespaceData.length > 0) {\n const content = generateUnifiedKyselyTypes(allNamespaceData);\n files.push({\n path: ctx.pluginConfig.distPath,\n content,\n });\n if (ctx.pluginConfig.pgliteSchemaPath) {\n files.push({\n path: ctx.pluginConfig.pgliteSchemaPath,\n content: generatePGliteSchemaModule(\n ctx.tailordb.filter((ns) => Object.keys(ns.tables).length > 0),\n ),\n });\n }\n }\n\n return { files };\n },\n };\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"logger-DP2BjQ93.mjs","names":[],"sources":["../src/runtime/logger.ts"],"sourcesContent":["/**\n * Structured logging utilities.\n *\n * Thin typed wrapper around the platform-provided `tailor.logger` runtime API.\n * At runtime this delegates to `globalThis.tailor.logger`. Use `mockLogger`\n * from `@tailor-platform/sdk/vitest` to mock these calls in unit tests.\n *\n * Unlike `console.*`, each call carries a severity and structured attributes.\n * The message is written to standard output, and the full entry with its\n * attributes is exported over OpenTelemetry, where the attributes are queryable.\n * @example\n * import { logger } from \"@tailor-platform/sdk/runtime\";\n *\n * logger.setAttributes({ requestId: \"r-123\" });\n * logger.info(\"order processed\", { orderId: \"o-1\", total: 99.5 });\n */\n\n/**\n * A single log attribute value. Values outside this union (`null`, nested\n * objects, mixed-type arrays) are silently dropped by the platform.\n */\nexport type LogAttributeValue =\n | string\n | number\n | boolean\n | readonly string[]\n | readonly number[]\n | readonly boolean[];\n\n/**\n * Structured attributes attached to a log entry. The platform keeps at most 32\n * entries, drops any entry whose key exceeds 128 bytes, and truncates string\n * values over 4096 bytes and arrays over 64 elements.\n */\nexport type LogAttributes = Record<string, LogAttributeValue>;\n\n/**\n * Platform API surface for `tailor.logger`. Describes the shape the platform\n * runtime injects on `globalThis.tailor.logger`.\n *\n * Each method below is also re-exported as a top-level named export from this\n * module so callers can either `import * as logger from\n * \"@tailor-platform/sdk/runtime/logger\"` or pick individual methods.\n */\nexport interface TailorLoggerAPI {\n /**\n * Emits a `debug`-severity log entry.\n * @param message - The log message\n * @param attributes - Structured attributes to attach to this entry\n */\n debug(message: string, attributes?: LogAttributes): void;\n\n /**\n * Emits an `info`-severity log entry.\n * @param message - The log message\n * @param attributes - Structured attributes to attach to this entry\n */\n info(message: string, attributes?: LogAttributes): void;\n\n /**\n * Emits a `warn`-severity log entry.\n * @param message - The log message\n * @param attributes - Structured attributes to attach to this entry\n */\n warn(message: string, attributes?: LogAttributes): void;\n\n /**\n * Emits an `error`-severity log entry.\n * @param message - The log message\n * @param attributes - Structured attributes to attach to this entry\n */\n error(message: string, attributes?: LogAttributes): void;\n\n /**\n * Merges attributes into every subsequent log entry from the current\n * execution. Later keys overwrite earlier ones; per-call attributes passed to\n * `debug`/`info`/`warn`/`error` take precedence.\n * @param attributes - Attributes to attach to subsequent entries\n */\n setAttributes(attributes: LogAttributes): void;\n}\n\n// Each wrapper below inlines the `(globalThis as GlobalWithLogger).tailor.logger` cast\n// (rather than sharing a helper) so bundle-log-level.ts's manualPureFunctions\n// can statically match the callee and tree-shake calls below the build's logLevel.\ntype GlobalWithLogger = { tailor: { logger: TailorLoggerAPI } };\n\n/**\n * See {@link TailorLoggerAPI.debug}.\n * @param args - Forwarded to {@link TailorLoggerAPI.debug}\n */\nexport const debug: TailorLoggerAPI[\"debug\"] = (...args) => {\n (globalThis as GlobalWithLogger).tailor.logger.debug(...args);\n};\n\n/**\n * See {@link TailorLoggerAPI.info}.\n * @param args - Forwarded to {@link TailorLoggerAPI.info}\n */\nexport const info: TailorLoggerAPI[\"info\"] = (...args) => {\n (globalThis as GlobalWithLogger).tailor.logger.info(...args);\n};\n\n/**\n * See {@link TailorLoggerAPI.warn}.\n * @param args - Forwarded to {@link TailorLoggerAPI.warn}\n */\nexport const warn: TailorLoggerAPI[\"warn\"] = (...args) => {\n (globalThis as GlobalWithLogger).tailor.logger.warn(...args);\n};\n\n/**\n * See {@link TailorLoggerAPI.error}.\n * @param args - Forwarded to {@link TailorLoggerAPI.error}\n */\nexport const error: TailorLoggerAPI[\"error\"] = (...args) => {\n (globalThis as GlobalWithLogger).tailor.logger.error(...args);\n};\n\n/**\n * See {@link TailorLoggerAPI.setAttributes}.\n * @param args - Forwarded to {@link TailorLoggerAPI.setAttributes}\n */\nexport const setAttributes: TailorLoggerAPI[\"setAttributes\"] = (...args) => {\n (globalThis as GlobalWithLogger).tailor.logger.setAttributes(...args);\n};\n\n/** `tailor.logger` API object. See {@link TailorLoggerAPI} for method docs. */\nexport const logger: TailorLoggerAPI = {\n debug,\n info,\n warn,\n error,\n setAttributes,\n};\n"],"mappings":"AA2FA,MAAa,OAAmC,GAAG,IAAS,CAC1D,WAAiC,OAAO,OAAO,MAAM,GAAG,CAAI,CAC9D,EAMa,MAAiC,GAAG,IAAS,CACxD,WAAiC,OAAO,OAAO,KAAK,GAAG,CAAI,CAC7D,EAMa,MAAiC,GAAG,IAAS,CACxD,WAAiC,OAAO,OAAO,KAAK,GAAG,CAAI,CAC7D,EAMa,OAAmC,GAAG,IAAS,CAC1D,WAAiC,OAAO,OAAO,MAAM,GAAG,CAAI,CAC9D,EAMa,eAAmD,GAAG,IAAS,CAC1E,WAAiC,OAAO,OAAO,cAAc,GAAG,CAAI,CACtE,EAGa,EAA0B,CACrC,MACA,KACA,KACA,MACA,aACF"}
1
+ {"version":3,"file":"logger-DP2BjQ93.mjs","names":["args","logger"],"sources":["../src/runtime/logger.ts"],"sourcesContent":["/**\n * Structured logging utilities.\n *\n * Thin typed wrapper around the platform-provided `tailor.logger` runtime API.\n * At runtime this delegates to `globalThis.tailor.logger`. Use `mockLogger`\n * from `@tailor-platform/sdk/vitest` to mock these calls in unit tests.\n *\n * Unlike `console.*`, each call carries a severity and structured attributes.\n * The message is written to standard output, and the full entry with its\n * attributes is exported over OpenTelemetry, where the attributes are queryable.\n * @example\n * import { logger } from \"@tailor-platform/sdk/runtime\";\n *\n * logger.setAttributes({ requestId: \"r-123\" });\n * logger.info(\"order processed\", { orderId: \"o-1\", total: 99.5 });\n */\n\n/**\n * A single log attribute value. Values outside this union (`null`, nested\n * objects, mixed-type arrays) are silently dropped by the platform.\n */\nexport type LogAttributeValue =\n | string\n | number\n | boolean\n | readonly string[]\n | readonly number[]\n | readonly boolean[];\n\n/**\n * Structured attributes attached to a log entry. The platform keeps at most 32\n * entries, drops any entry whose key exceeds 128 bytes, and truncates string\n * values over 4096 bytes and arrays over 64 elements.\n */\nexport type LogAttributes = Record<string, LogAttributeValue>;\n\n/**\n * Platform API surface for `tailor.logger`. Describes the shape the platform\n * runtime injects on `globalThis.tailor.logger`.\n *\n * Each method below is also re-exported as a top-level named export from this\n * module so callers can either `import * as logger from\n * \"@tailor-platform/sdk/runtime/logger\"` or pick individual methods.\n */\nexport interface TailorLoggerAPI {\n /**\n * Emits a `debug`-severity log entry.\n * @param message - The log message\n * @param attributes - Structured attributes to attach to this entry\n */\n debug(message: string, attributes?: LogAttributes): void;\n\n /**\n * Emits an `info`-severity log entry.\n * @param message - The log message\n * @param attributes - Structured attributes to attach to this entry\n */\n info(message: string, attributes?: LogAttributes): void;\n\n /**\n * Emits a `warn`-severity log entry.\n * @param message - The log message\n * @param attributes - Structured attributes to attach to this entry\n */\n warn(message: string, attributes?: LogAttributes): void;\n\n /**\n * Emits an `error`-severity log entry.\n * @param message - The log message\n * @param attributes - Structured attributes to attach to this entry\n */\n error(message: string, attributes?: LogAttributes): void;\n\n /**\n * Merges attributes into every subsequent log entry from the current\n * execution. Later keys overwrite earlier ones; per-call attributes passed to\n * `debug`/`info`/`warn`/`error` take precedence.\n * @param attributes - Attributes to attach to subsequent entries\n */\n setAttributes(attributes: LogAttributes): void;\n}\n\n// Each wrapper below inlines the `(globalThis as GlobalWithLogger).tailor.logger` cast\n// (rather than sharing a helper) so bundle-log-level.ts's manualPureFunctions\n// can statically match the callee and tree-shake calls below the build's logLevel.\ntype GlobalWithLogger = { tailor: { logger: TailorLoggerAPI } };\n\n/**\n * See {@link TailorLoggerAPI.debug}.\n * @param args - Forwarded to {@link TailorLoggerAPI.debug}\n */\nexport const debug: TailorLoggerAPI[\"debug\"] = (...args) => {\n (globalThis as GlobalWithLogger).tailor.logger.debug(...args);\n};\n\n/**\n * See {@link TailorLoggerAPI.info}.\n * @param args - Forwarded to {@link TailorLoggerAPI.info}\n */\nexport const info: TailorLoggerAPI[\"info\"] = (...args) => {\n (globalThis as GlobalWithLogger).tailor.logger.info(...args);\n};\n\n/**\n * See {@link TailorLoggerAPI.warn}.\n * @param args - Forwarded to {@link TailorLoggerAPI.warn}\n */\nexport const warn: TailorLoggerAPI[\"warn\"] = (...args) => {\n (globalThis as GlobalWithLogger).tailor.logger.warn(...args);\n};\n\n/**\n * See {@link TailorLoggerAPI.error}.\n * @param args - Forwarded to {@link TailorLoggerAPI.error}\n */\nexport const error: TailorLoggerAPI[\"error\"] = (...args) => {\n (globalThis as GlobalWithLogger).tailor.logger.error(...args);\n};\n\n/**\n * See {@link TailorLoggerAPI.setAttributes}.\n * @param args - Forwarded to {@link TailorLoggerAPI.setAttributes}\n */\nexport const setAttributes: TailorLoggerAPI[\"setAttributes\"] = (...args) => {\n (globalThis as GlobalWithLogger).tailor.logger.setAttributes(...args);\n};\n\n/** `tailor.logger` API object. See {@link TailorLoggerAPI} for method docs. */\nexport const logger: TailorLoggerAPI = {\n debug,\n info,\n warn,\n error,\n setAttributes,\n};\n"],"mappings":"AA2FA,MAAa,OAAmC,GAAGA,IAAS,CAC1D,WAAiC,OAAO,OAAO,MAAM,GAAGA,CAAI,CAC9D,EAMa,MAAiC,GAAGA,IAAS,CACxD,WAAiC,OAAO,OAAO,KAAK,GAAGA,CAAI,CAC7D,EAMa,MAAiC,GAAGA,IAAS,CACxD,WAAiC,OAAO,OAAO,KAAK,GAAGA,CAAI,CAC7D,EAMa,OAAmC,GAAGA,IAAS,CAC1D,WAAiC,OAAO,OAAO,MAAM,GAAGA,CAAI,CAC9D,EAMa,eAAmD,GAAGA,IAAS,CAC1E,WAAiC,OAAO,OAAO,cAAc,GAAGA,CAAI,CACtE,EAGaC,EAA0B,CACrC,MACA,KACA,KACA,MACA,aACF"}
@@ -0,0 +1,9 @@
1
+ import{formatWithOptions as e,stripVTControlCharacters as t,styleText as n}from"node:util";import{formatDistanceToNowStrict as r}from"date-fns";import{isCI as i}from"std-env";import{eastAsianWidth as a}from"get-east-asian-width";const style=e=>t=>n(e,t,{validateStream:!1}),o={bold:style(`bold`),dim:style(`dim`),italic:style(`italic`),gray:style(`gray`),white:style(`white`),red:style(`red`),green:style(`green`),yellow:style(`yellow`),cyan:style(`cyan`),magenta:style(`magenta`),redBright:style(`redBright`),greenBright:style(`greenBright`),cyanBright:style(`cyanBright`)},supportsColor=e=>{let t=process.env.FORCE_COLOR;return t===void 0?process.env.NODE_DISABLE_COLORS!==void 0||(process.env.NO_COLOR??``)!==``||process.env.TERM===`dumb`?!1:e.isTTY===!0:t!==`0`&&t!==`false`};function renderFor(e,n){return supportsColor(e)?n:t(n)}const s=/\x1b\[[0-9;]*m/g,c=/\r\n?/g,l=new Intl.Segmenter(void 0,{granularity:`grapheme`});function maxOf(e,t=0){return e.reduce((e,t)=>t>e?t:e,t)}function isStrippableControlCharacter(e){let t=e.codePointAt(0)??0;return e===`
2
+ `?!1:t<=31||t===127}function normalizeControlCharacters(e){let t=e.match(s)??[];return e.split(s).map(e=>{let t=[];for(let n of e)n===` `?t.push(` `.repeat(8)):isStrippableControlCharacter(n)||t.push(n);return t.join(``)}).reduce((e,n,r)=>e+n+(t[r]??``),``)}function sanitizeCell(e){return normalizeControlCharacters(String(e??``).replace(c,`
3
+ `))}const u=/^(?:\p{Default_Ignorable_Code_Point}|\p{Control}|\p{Format}|\p{Nonspacing_Mark}|\p{Enclosing_Mark}|\p{Surrogate})+$/v,d=/^\p{RGI_Emoji}$/v;function displayWidth(e){let t=0;for(let{segment:n}of l.segment(e.replace(s,``))){if(u.test(n))continue;if(d.test(n)){t+=2;continue}let e=n.codePointAt(0);t+=e===void 0?0:a(e)}return t}function toCellLines(e){return e.split(`
4
+ `).map(e=>({text:e,width:displayWidth(e)}))}function padCell(e,t){return e.text+` `.repeat(Math.max(0,t-e.width))}function renderBorder(e,t,n,r){return e+r.map(e=>`─`.repeat(e+2)).join(t)+n}function validateConsistentColumnCount(e){let t=e[0]?.length;t!==void 0&&e.forEach((e,n)=>{if(e.length!==t)throw Error(`renderTable: all rows must have the same number of columns (expected ${t}, row ${n} has ${e.length}).`)})}function renderTable(e,t={}){let n=e.map(e=>e.map(sanitizeCell));validateConsistentColumnCount(n);let r=n.length,i=n[0]?.length??0;if(r===0||i===0)return``;let a=n.map(e=>Array.from({length:i},(t,n)=>toCellLines(e[n]??``))),o=Array.from({length:i},(e,t)=>maxOf(a.map(e=>maxOf((e[t]??[]).map(e=>e.width))))),shouldDrawLine=e=>t.singleLine?e===0||e===r:(t.drawHorizontalLine??(()=>!0))(e,r),s=[];return shouldDrawLine(0)&&s.push(renderBorder(`┌`,`┬`,`┐`,o)),a.forEach((e,t)=>{let n=maxOf(e.map(e=>e.length),1);for(let t=0;t<n;t++){let n=e.map((e,n)=>padCell(e[t]??{text:``,width:0},o[n]??0));s.push(`│ ${n.join(` │ `)} │`)}t<r-1&&shouldDrawLine(t+1)&&s.push(renderBorder(`├`,`┼`,`┤`,o))}),shouldDrawLine(r)&&s.push(renderBorder(`└`,`┴`,`┘`,o)),`${s.join(`
5
+ `)}\n`}const f=/* @__PURE__ */ new Set([`true`,`t`,`yes`,`y`,`on`,`1`]),p=/* @__PURE__ */ new Set([`false`,`f`,`no`,`n`,`off`,`0`]);function parseBoolean(e){if(e===void 0)return;let t=e.trim().toLowerCase();if(t!==``){if(f.has(t))return!0;if(p.has(t))return!1}}const m=`TAILOR_JSON_OUTPUT`;function interactiveTerminal(){return!i&&process.stdin.isTTY===!0&&process.stdout.isTTY===!0}var CIPromptError=class extends Error{constructor(e){let t=v===`flag`?` JSON output is enabled by --json; drop it to restore prompts.`:v===`env`?` JSON output is enabled by ${m}; unset it to restore prompts.`:` JSON output is enabled by --json and ${m}; drop the flag and unset the variable to restore prompts.`,n=_&&v!==void 0&&interactiveTerminal()?t:``;super((e??`Interactive prompts are not available in this environment. Provide the required options explicitly.`)+n),this.name=`CIPromptError`}};const h={success:o.green,error:o.red,warning:o.yellow,info:o.cyan,create:o.green,update:o.yellow,delete:o.red,replace:o.magenta,unchanged:o.gray,bold:o.bold,dim:o.gray,highlight:o.cyanBright,successBright:o.greenBright,errorBright:o.redBright,resourceType:o.bold,resourceName:o.cyan,path:o.cyan,value:o.white,placeholder:e=>o.italic(o.gray(e))},g={success:h.success(`✓`),error:h.error(`✖`),warning:h.warning(`⚠`),info:h.info(`i`),create:h.create(`+`),update:h.update(`~`),delete:h.delete(`-`),replace:h.replace(`±`),bullet:h.dim(`•`),arrow:h.dim(`→`)};let _=!1,v,y=!1;const b=/* @__PURE__ */ new Set,x=`<redacted>`;function buildAutomaton(e){let t={children:/* @__PURE__ */ new Map,fail:void 0,outputs:[]};t.fail=t;for(let n of e){let e=t;for(let r=0;r<n.length;r++){let i=n[r],a=e.children.get(i);a||(a={children:/* @__PURE__ */ new Map,fail:t,outputs:[]},e.children.set(i,a)),e=a}e.outputs.push(n)}let n=[...t.children.values()];for(let e=0;e<n.length;e++){let r=n[e];for(let[e,i]of r.children){let a=r.fail;for(;a!==t&&!a.children.has(e);)a=a.fail;i.fail=a.children.get(e)??t,i.outputs=i.outputs.concat(i.fail.outputs),n.push(i)}}return t}let S=null;function getAutomaton(){return S??=buildAutomaton(b),S}function findSecretSpans(e){let t=[],n=getAutomaton(),r=n;for(let i=0;i<e.length;i++){let a=e[i];for(;r!==n&&!r.children.has(a);)r=r.fail;r=r.children.get(a)??n;for(let e of r.outputs)t.push([i+1-e.length,i+1])}return t}function redactSecrets(e){if(b.size===0)return e;let t=[];for(let n=0,r;(r=e.indexOf(x,n))!==-1;)t.push([r,r+10]),n=r+10;let n=findSecretSpans(e).filter(([e,n])=>!t.some(([t,r])=>e>=t&&n<=r));if(n.length===0)return e;n.sort(([e],[t])=>e-t);let r=[];for(let e of n){let t=r.at(-1);t&&e[0]<=t[1]?t[1]=Math.max(t[1],e[1]):r.push(e)}let i=``,a=0;for(let[t,n]of r)i+=e.slice(a,t)+x,a=n;return i+e.slice(a)}const C={info:`ℹ`,success:`✔`,warn:`⚠`,error:`✖`,debug:`⚙`,trace:`→`,log:``},w={info:h.info,success:h.success,warn:h.warning,error:h.error,debug:h.dim,trace:h.dim,log:e=>e};function formatLogLine(e){let{mode:t,indent:n,type:r,message:i,timestamp:a}=e,o=n>0?` `.repeat(n):``,s=w[r]||(e=>e);if(t===`plain`)return`${o}${s(i)}\n`;let c=C[r]||``,l=s(`${c?`${c} `:``}${i}`);return`${o}${a??``}${l}\n`}function writeLog(t,n,r){let i=r?.mode??`default`,a=r?.indent??0,o={breakLength:process.stdout.columns||80},s=formatLogLine({mode:i,indent:a,type:t,message:e(o,n),timestamp:i===`stream`?`${(/* @__PURE__ */ new Date()).toLocaleTimeString()} `:``});process.stderr.write(renderFor(process.stderr,redactSecrets(s)))}const T={get jsonMode(){return _},set jsonMode(e){_=e,e||(v=void 0)},setJsonMode(e,t){_=e,v=e?t:void 0},get verbose(){return y||parseBoolean(process.env.DEBUG)===!0||process.env.RUNNER_DEBUG===`1`},set verbose(e){y=e},info(e,t){writeLog(`info`,e,t)},success(e,t){writeLog(`success`,e,t)},warn(e,t){writeLog(`warn`,e,t)},error(e,t){writeLog(`error`,e,t)},log(e){writeLog(`log`,e,{mode:`plain`})},newline(){process.stderr.write(`
6
+ `)},debug(e){T.verbose&&writeLog(`log`,h.dim(e),{mode:`plain`})},registerSecret(e){if(typeof e!=`string`||[...e].length<4)return;let t=b.size;b.add(e);let n=JSON.stringify(e).slice(1,-1);n!==e&&b.add(n);let r=new URLSearchParams([[`v`,e]]).toString().slice(2);r!==e&&b.add(r),b.size!==t&&(S=null)},out(e,t){if(typeof e==`string`){process.stdout.write(renderFor(process.stdout,e.endsWith(`
7
+ `)?e:e+`
8
+ `));return}if(this.jsonMode){console.log(JSON.stringify(e));return}let n=t?.display,formatValue=(e,n=!1)=>t?.showNull&&e===null?`NULL`:e==null?`N/A`:e instanceof Date?r(e,{addSuffix:!0}):typeof e==`object`?n?JSON.stringify(e,null,2):JSON.stringify(e):String(e),isExcluded=e=>n!==void 0&&e in n&&n[e]===null,transformValue=(e,t,r,i=!1)=>{if(n&&e in n){let i=n[e];if(i)return i(t,r)}return formatValue(t,i)};if(!Array.isArray(e)){let t=renderTable(Object.entries(e).filter(([e])=>!isExcluded(e)).map(([t,n])=>[t,transformValue(t,n,e,!0)]),{singleLine:!1});process.stdout.write(renderFor(process.stdout,t));return}if(e.length===0)return;let i=Array.from(new Set(e.flatMap(e=>Object.keys(e)))).filter(e=>!isExcluded(e));if(i.length===0)return;let a=renderTable([i,...e.map(e=>i.map(t=>transformValue(t,e[t],e)))],{drawHorizontalLine:(e,t)=>e===0||e===1||e===t});process.stdout.write(renderFor(process.stdout,a))}};export{redactSecrets as a,parseBoolean as c,T as i,renderTable as l,m as n,h as o,interactiveTerminal as r,g as s,CIPromptError as t,renderFor as u};
9
+ //# sourceMappingURL=logger-Db-YRTwK.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger-Db-YRTwK.mjs","names":["styleText","name","text","color","forced","stream","stripVTControlCharacters","ANSI_ESCAPE_PATTERN","CARRIAGE_RETURN_PATTERN","graphemeSegmenter","values","value","max","fallback","codePoint","char","sgrSequences","chars","segment","result","i","cell","ZERO_WIDTH_CLUSTER_PATTERN","RGI_EMOJI_PATTERN","width","eastAsianWidth","cellLine","left","columnWidths","join","right","columnCount","rows","row","index","data","rowCount","rowsCellLines","col","line","config","lineIndex","lines","rowHeight","cellLines","columnLines","cells","rowIndex","TRUTHY_VALUES","FALSY_VALUES","normalized","JSON_OUTPUT_ENV_VAR","isCI","remedy","_jsonModeSource","reason","_jsonMode","message","styles","symbols","_verbose","_secrets","REDACTED_PLACEHOLDER","root","secret","secrets","node","ch","next","queue","head","parent","child","fail","_automaton","spans","protectedSpans","from","start","end","pStart","pEnd","a","b","merged","span","last","cursor","TYPE_ICONS","TYPE_COLORS","opts","indentPrefix","indent","colorFn","type","mode","icon","coloredOutput","timestamp","inspectOpts","output","formatWithOptions","logger","source","sizeBefore","jsonEscaped","formEncoded","display","options","formatDistanceToNowStrict","pretty","key","transformer","item","headers","h","t","header"],"sources":["../../shared/src/color.ts","../src/cli/shared/ascii-table.ts","../src/cli/shared/parse-boolean.ts","../src/cli/shared/logger.ts"],"sourcesContent":["import { stripVTControlCharacters, styleText } from \"node:util\";\n\n/** Applies a style to text */\nexport type StyleFn = (text: string) => string;\n\ntype StyleName = Exclude<Parameters<typeof styleText>[0], readonly unknown[] | unknown[]>;\n\nconst style =\n (name: StyleName): StyleFn =>\n (text) =>\n styleText(name, text, { validateStream: false });\n\n/**\n * Style functions by name, so call sites read `color.bold(text)`. Styling is\n * always applied; `renderFor` drops it again when the destination stream has no\n * color support. Add a name here when a package needs one that is not listed.\n */\nexport const color = {\n bold: style(\"bold\"),\n dim: style(\"dim\"),\n italic: style(\"italic\"),\n gray: style(\"gray\"),\n white: style(\"white\"),\n red: style(\"red\"),\n green: style(\"green\"),\n yellow: style(\"yellow\"),\n cyan: style(\"cyan\"),\n magenta: style(\"magenta\"),\n redBright: style(\"redBright\"),\n greenBright: style(\"greenBright\"),\n cyanBright: style(\"cyanBright\"),\n};\n\n// Node's rules for whether a destination gets colors, applied by hand. Asking\n// styleText instead would be shorter but only correct on Node: Bun ignores both\n// the stream option and NO_COLOR (reproduced on 1.3.14), so it reports every\n// destination as color-capable and escapes end up in redirected output.\n//\n// FORCE_COLOR decides on its own when set, which is how CI keeps colors through\n// a pipe. NO_COLOR counts as set at any non-empty value, \"0\" included.\nconst supportsColor = (stream: NodeJS.WriteStream): boolean => {\n const forced = process.env.FORCE_COLOR;\n if (forced !== undefined) return forced !== \"0\" && forced !== \"false\";\n if (process.env.NODE_DISABLE_COLORS !== undefined) return false;\n if ((process.env.NO_COLOR ?? \"\") !== \"\") return false;\n if (process.env.TERM === \"dumb\") return false;\n return stream.isTTY === true;\n};\n\n/**\n * Prepares styled text for the stream it is written to.\n * @param stream - Stream the text is written to\n * @param text - Styled text\n * @returns Text with styling removed when the stream has no color support\n */\nexport function renderFor(stream: NodeJS.WriteStream, text: string): string {\n return supportsColor(stream) ? text : stripVTControlCharacters(text);\n}\n","import { eastAsianWidth } from \"get-east-asian-width\";\n\n// eslint-disable-next-line no-control-regex\nconst ANSI_ESCAPE_PATTERN = /\\x1b\\[[0-9;]*m/g;\nconst CARRIAGE_RETURN_PATTERN = /\\r\\n?/g;\n\nconst graphemeSegmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n\nexport interface AsciiTableConfig {\n /** Suppress horizontal lines between rows, keeping only the outer border. */\n singleLine?: boolean;\n /** Decide whether to draw the horizontal line at `lineIndex` (range `[0, rowCount]` inclusive). */\n drawHorizontalLine?: (lineIndex: number, rowCount: number) => boolean;\n}\n\ninterface CellLine {\n text: string;\n width: number;\n}\n\nfunction maxOf(values: number[], fallback = 0): number {\n return values.reduce((max, value) => (value > max ? value : max), fallback);\n}\n\nconst TAB_WIDTH = 8;\n\nfunction isStrippableControlCharacter(char: string): boolean {\n const codePoint = char.codePointAt(0) ?? 0;\n if (char === \"\\n\") {\n return false;\n }\n return codePoint <= 0x1f || codePoint === 0x7f;\n}\n\n// Only SGR (color/style) escape sequences are meant to survive; a bare ESC\n// that isn't part of a recognized SGR sequence (e.g. a screen-clear CSI\n// sequence, or a BEL-terminated OSC sequence) is treated like any other\n// control character below and stripped, rather than passed through to the\n// terminal or left with its terminator removed.\nfunction normalizeControlCharacters(value: string): string {\n const sgrSequences = value.match(ANSI_ESCAPE_PATTERN) ?? [];\n return value\n .split(ANSI_ESCAPE_PATTERN)\n .map((segment) => {\n const chars: string[] = [];\n for (const char of segment) {\n if (char === \"\\t\") {\n chars.push(\" \".repeat(TAB_WIDTH));\n } else if (!isStrippableControlCharacter(char)) {\n chars.push(char);\n }\n }\n return chars.join(\"\");\n })\n .reduce((result, segment, i) => result + segment + (sgrSequences[i] ?? \"\"), \"\");\n}\n\nfunction sanitizeCell(cell: unknown): string {\n return normalizeControlCharacters(String(cell ?? \"\").replace(CARRIAGE_RETURN_PATTERN, \"\\n\"));\n}\n\n// Clusters made up entirely of non-printing code points (lone joiners,\n// variation selectors, combining marks, etc.) render with no visible glyph.\nconst ZERO_WIDTH_CLUSTER_PATTERN =\n /^(?:\\p{Default_Ignorable_Code_Point}|\\p{Control}|\\p{Format}|\\p{Nonspacing_Mark}|\\p{Enclosing_Mark}|\\p{Surrogate})+$/v;\n// RGI_Emoji covers flags, keycaps, and VS16-forced presentation sequences,\n// which render as 2 columns in terminals even though their first code point\n// alone would measure as narrow/neutral.\nconst RGI_EMOJI_PATTERN = /^\\p{RGI_Emoji}$/v;\n\nfunction displayWidth(value: string): number {\n let width = 0;\n for (const { segment } of graphemeSegmenter.segment(value.replace(ANSI_ESCAPE_PATTERN, \"\"))) {\n if (ZERO_WIDTH_CLUSTER_PATTERN.test(segment)) {\n continue;\n }\n if (RGI_EMOJI_PATTERN.test(segment)) {\n width += 2;\n continue;\n }\n const codePoint = segment.codePointAt(0);\n width += codePoint === undefined ? 0 : eastAsianWidth(codePoint);\n }\n return width;\n}\n\nfunction toCellLines(cell: string): CellLine[] {\n return cell.split(\"\\n\").map((text) => ({ text, width: displayWidth(text) }));\n}\n\nfunction padCell(cellLine: CellLine, width: number): string {\n return cellLine.text + \" \".repeat(Math.max(0, width - cellLine.width));\n}\n\nfunction renderBorder(left: string, join: string, right: string, columnWidths: number[]): string {\n return left + columnWidths.map((width) => \"─\".repeat(width + 2)).join(join) + right;\n}\n\nfunction validateConsistentColumnCount(rows: string[][]): void {\n const columnCount = rows[0]?.length;\n if (columnCount === undefined) {\n return;\n }\n rows.forEach((row, index) => {\n if (row.length !== columnCount) {\n throw new Error(\n `renderTable: all rows must have the same number of columns (expected ${columnCount}, row ${index} has ${row.length}).`,\n );\n }\n });\n}\n\n/**\n * Renders a 2D array of values as a table using single-line Unicode box-drawing borders.\n * Column widths account for East Asian wide characters (measured per grapheme cluster,\n * so combining marks and ZWJ emoji sequences aren't overcounted, non-printing clusters\n * such as a lone joiner or combining mark measure as 0, and flags, keycaps, and\n * VS16-forced emoji presentation are measured as 2 columns) and strip ANSI SGR (color/style)\n * escape codes before measuring. Use this instead of importing a table-rendering package\n * directly.\n * @param data - Table rows; every row must have the same number of columns. Each cell is\n * stringified (`null`/`undefined` become an empty string rather than the literal text\n * \"null\"/\"undefined\"), may contain embedded newlines, has `\\r`/`\\r\\n` normalized to `\\n`,\n * has tabs expanded to spaces, and has other control characters stripped.\n * @param config - Rendering options\n * @returns The rendered table terminated with a trailing newline, or `\"\"` when there are no\n * rows or no columns to display\n */\nexport function renderTable(data: unknown[][], config: AsciiTableConfig = {}): string {\n const rows = data.map((row) => row.map(sanitizeCell));\n validateConsistentColumnCount(rows);\n\n const rowCount = rows.length;\n const columnCount = rows[0]?.length ?? 0;\n if (rowCount === 0 || columnCount === 0) {\n return \"\";\n }\n\n const rowsCellLines = rows.map((row) =>\n Array.from({ length: columnCount }, (_, col) => toCellLines(row[col] ?? \"\")),\n );\n const columnWidths = Array.from({ length: columnCount }, (_, col) =>\n maxOf(rowsCellLines.map((row) => maxOf((row[col] ?? []).map((line) => line.width)))),\n );\n\n const shouldDrawLine = (lineIndex: number): boolean =>\n config.singleLine\n ? lineIndex === 0 || lineIndex === rowCount\n : (config.drawHorizontalLine ?? (() => true))(lineIndex, rowCount);\n\n const lines: string[] = [];\n if (shouldDrawLine(0)) {\n lines.push(renderBorder(\"┌\", \"┬\", \"┐\", columnWidths));\n }\n\n rowsCellLines.forEach((cellLines, rowIndex) => {\n const rowHeight = maxOf(\n cellLines.map((columnLines) => columnLines.length),\n 1,\n );\n for (let line = 0; line < rowHeight; line++) {\n const cells = cellLines.map((columnLines, col) =>\n padCell(columnLines[line] ?? { text: \"\", width: 0 }, columnWidths[col] ?? 0),\n );\n lines.push(`│ ${cells.join(\" │ \")} │`);\n }\n if (rowIndex < rowCount - 1 && shouldDrawLine(rowIndex + 1)) {\n lines.push(renderBorder(\"├\", \"┼\", \"┤\", columnWidths));\n }\n });\n\n if (shouldDrawLine(rowCount)) {\n lines.push(renderBorder(\"└\", \"┴\", \"┘\", columnWidths));\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n","const TRUTHY_VALUES = new Set([\"true\", \"t\", \"yes\", \"y\", \"on\", \"1\"]);\nconst FALSY_VALUES = new Set([\"false\", \"f\", \"no\", \"n\", \"off\", \"0\"]);\n\n/**\n * Parse a string value as a boolean.\n *\n * Recognized values (case-insensitive, trimmed) follow Python's\n * `distutils.util.strtobool` convention:\n * - truthy: `true, t, yes, y, on, 1`\n * - falsy: `false, f, no, n, off, 0`\n *\n * Undefined, empty strings, and unrecognized values return `undefined` so\n * that callers can fall back to their own defaults.\n * @param value - The input string (e.g. an environment variable or CLI flag value)\n * @returns `true`, `false`, or `undefined` when the value is unset or unrecognized\n */\nexport function parseBoolean(value: string | undefined): boolean | undefined {\n if (value === undefined) return undefined;\n const normalized = value.trim().toLowerCase();\n if (normalized === \"\") return undefined;\n if (TRUTHY_VALUES.has(normalized)) return true;\n if (FALSY_VALUES.has(normalized)) return false;\n return undefined;\n}\n","import { formatWithOptions, type InspectOptions } from \"node:util\";\nimport { color, renderFor } from \"@tailor-platform/shared/color\";\nimport { formatDistanceToNowStrict } from \"date-fns\";\nimport { isCI } from \"std-env\";\nimport { renderTable } from \"./ascii-table\";\nimport { parseBoolean } from \"./parse-boolean\";\n\n/** Environment variable selecting JSON as the default output for every command. */\nexport const JSON_OUTPUT_ENV_VAR = \"TAILOR_JSON_OUTPUT\";\n\n/**\n * Whether the process is attached to an interactive terminal outside CI.\n * @returns True when both stdin and stdout are TTYs and CI is not detected\n */\nexport function interactiveTerminal(): boolean {\n return !isCI && process.stdin.isTTY === true && process.stdout.isTTY === true;\n}\n\n/** What selected JSON output: an explicit `--json`, the environment, or both. */\nexport type JsonModeSource = \"flag\" | \"env\" | \"both\";\n\n/**\n * Error thrown when a prompt is attempted in a non-interactive environment.\n *\n * JSON mode suppresses prompts, so name whatever selected it: an explicit\n * `--json` stays enabled however the environment is set, while\n * `TAILOR_JSON_OUTPUT` leaves nothing in the command line to explain the\n * refusal.\n */\nexport class CIPromptError extends Error {\n constructor(message?: string) {\n const remedy =\n _jsonModeSource === \"flag\"\n ? \" JSON output is enabled by --json; drop it to restore prompts.\"\n : _jsonModeSource === \"env\"\n ? ` JSON output is enabled by ${JSON_OUTPUT_ENV_VAR}; unset it to restore prompts.`\n : ` JSON output is enabled by --json and ${JSON_OUTPUT_ENV_VAR}; drop the flag and unset the variable to restore prompts.`;\n const reason =\n _jsonMode && _jsonModeSource !== undefined && interactiveTerminal() ? remedy : \"\";\n super(\n (message ??\n \"Interactive prompts are not available in this environment. Provide the required options explicitly.\") +\n reason,\n );\n this.name = \"CIPromptError\";\n }\n}\n\n/**\n * Semantic style functions for inline text styling\n */\nexport const styles = {\n // Status colors\n success: color.green,\n error: color.red,\n warning: color.yellow,\n info: color.cyan,\n\n // Action colors (for change sets)\n create: color.green,\n update: color.yellow,\n delete: color.red,\n replace: color.magenta,\n unchanged: color.gray,\n\n // Emphasis\n bold: color.bold,\n dim: color.gray,\n highlight: color.cyanBright,\n successBright: color.greenBright,\n errorBright: color.redBright,\n\n // Resource types\n resourceType: color.bold,\n resourceName: color.cyan,\n\n // File paths\n path: color.cyan,\n\n // Values\n value: color.white,\n placeholder: (text: string) => color.italic(color.gray(text)),\n};\n\n/**\n * Standardized symbols for CLI output\n */\nexport const symbols = {\n success: styles.success(\"\\u2713\"),\n error: styles.error(\"\\u2716\"),\n warning: styles.warning(\"\\u26a0\"),\n info: styles.info(\"i\"),\n create: styles.create(\"+\"),\n update: styles.update(\"~\"),\n delete: styles.delete(\"-\"),\n replace: styles.replace(\"\\u00b1\"),\n bullet: styles.dim(\"\\u2022\"),\n arrow: styles.dim(\"\\u2192\"),\n};\n\n/**\n * Log output modes\n */\nexport type LogMode = \"default\" | \"stream\" | \"plain\";\n\nexport interface LogOptions {\n /** Output mode (default: \"default\") */\n mode?: LogMode;\n /** Number of spaces to indent the entire line (default: 0) */\n indent?: number;\n}\n\n/** Field transformer function. null excludes the field from table output. */\nexport type FieldTransformer = ((value: unknown, item: object) => string) | null;\n\nexport interface OutOptions {\n /** Table display field transform/exclude settings. Only applied in table mode (not JSON). */\n display?: Record<string, FieldTransformer>;\n\n /** Show null values in table output (default: false) */\n showNull?: boolean;\n}\n\n// In JSON mode, all logs go to stderr to keep stdout clean for JSON data\nlet _jsonMode = false;\nlet _jsonModeSource: JsonModeSource | undefined;\nlet _verbose = false;\n\n// Values registered via `logger.registerSecret()`, redacted from diagnostic log output\nconst _secrets = new Set<string>();\nconst REDACTED_PLACEHOLDER = \"<redacted>\";\n// Below this length, a registered value is too likely to match unrelated text.\nconst MIN_SECRET_LENGTH = 4;\n\n/**\n * Aho-Corasick trie node. Indexed by individual UTF-16 code units (not Unicode code\n * points), matching how `string.indexOf`/`.slice` already index this file's strings — a\n * surrogate-pair character occupies two nodes, same as it occupies two `string` indices.\n */\ninterface TrieNode {\n children: Map<string, TrieNode>;\n fail: TrieNode;\n /** Secrets ending at this node, including those reached via `fail` links (precomputed). */\n outputs: string[];\n}\n\n/**\n * Builds a multi-pattern matcher for every registered secret, so `findSecretSpans` below\n * can find all of their occurrences in one pass over the text (`O(text.length + matches)`)\n * instead of scanning the full text once per registered secret. Rebuilt only when\n * `registerSecret` adds a genuinely new value (see `_automaton` below), so its\n * `O(total secret length)` construction cost is amortized across every log line redacted\n * while the secret set doesn't change.\n * @param secrets - Currently registered secrets\n * @returns Root of the built trie\n */\nfunction buildAutomaton(secrets: ReadonlySet<string>): TrieNode {\n const root: TrieNode = {\n children: new Map(),\n fail: undefined as unknown as TrieNode,\n outputs: [],\n };\n root.fail = root;\n\n for (const secret of secrets) {\n let node = root;\n for (let i = 0; i < secret.length; i++) {\n const ch = secret[i] as string;\n let next = node.children.get(ch);\n if (!next) {\n next = { children: new Map(), fail: root, outputs: [] };\n node.children.set(ch, next);\n }\n node = next;\n }\n node.outputs.push(secret);\n }\n\n // A head index instead of Array#shift(): shift() re-indexes every remaining element on\n // each call, which would make this loop quadratic in the number of trie nodes rather than\n // the linear BFS this is meant to be.\n const queue: TrieNode[] = [...root.children.values()];\n for (let head = 0; head < queue.length; head++) {\n const parent = queue[head] as TrieNode;\n for (const [ch, child] of parent.children) {\n let fail = parent.fail;\n while (fail !== root && !fail.children.has(ch)) fail = fail.fail;\n child.fail = fail.children.get(ch) ?? root;\n child.outputs = child.outputs.concat(child.fail.outputs);\n queue.push(child);\n }\n }\n return root;\n}\n\n// Cached automaton for the current `_secrets` contents; `null` means rebuild on next use.\n// Invalidated only when `registerSecret` actually grows `_secrets` (Set#add on an existing\n// value is a no-op), so re-registering an already-known secret never triggers a rebuild.\nlet _automaton: TrieNode | null = null;\n\nfunction getAutomaton(): TrieNode {\n _automaton ??= buildAutomaton(_secrets);\n return _automaton;\n}\n\n/**\n * Finds every occurrence of every registered secret in `text`, including overlapping ones,\n * in a single pass over `text` via the Aho-Corasick automaton.\n * @param text - Text to search\n * @returns Match spans as `[start, end)` pairs, in the order found\n */\nfunction findSecretSpans(text: string): Array<[start: number, end: number]> {\n const spans: Array<[start: number, end: number]> = [];\n const root = getAutomaton();\n let node = root;\n for (let i = 0; i < text.length; i++) {\n const ch = text[i] as string;\n while (node !== root && !node.children.has(ch)) node = node.fail;\n node = node.children.get(ch) ?? root;\n for (const secret of node.outputs) {\n spans.push([i + 1 - secret.length, i + 1]);\n }\n }\n return spans;\n}\n\n/**\n * Redacts every registered secret from `text` in a single pass over the original text.\n *\n * Matches are found against the original text only - never against text a previous\n * replacement produced - and overlapping/adjacent matches (whether one secret contains\n * another, or two secrets merely cross, e.g. registering \"abcde\" and \"defghi\" against\n * \"abcdefghi\") are merged into one contiguous span before any substitution happens. This\n * avoids two failure modes an iterative \"replace one secret, then the next\" approach has:\n * a later secret re-matching inside a placeholder a previous replacement already inserted,\n * and a crossing (non-nested) overlap leaving a fragment of one secret unredacted.\n *\n * Idempotent: a match that falls inside an occurrence of `<redacted>` already present in\n * `text` is discarded rather than substituted again. Without this, calling this function\n * twice on the same text (which happens whenever something already redacted, such as a\n * `--json` error envelope, is later passed to a diagnostic log call) could corrupt the\n * placeholder itself if a registered secret happens to be one of its substrings (e.g. a\n * secret literally containing \"redact\").\n * @param text - Text to redact\n * @returns `text` with every registered secret occurrence replaced by `<redacted>`\n */\nexport function redactSecrets(text: string): string {\n if (_secrets.size === 0) return text;\n\n const protectedSpans: Array<[start: number, end: number]> = [];\n for (let from = 0, index: number; (index = text.indexOf(REDACTED_PLACEHOLDER, from)) !== -1;) {\n protectedSpans.push([index, index + REDACTED_PLACEHOLDER.length]);\n from = index + REDACTED_PLACEHOLDER.length;\n }\n\n // Only a match wholly inside a protected placeholder is discarded (it can only be the\n // placeholder's own text, e.g. a registered secret that is a substring of \"redacted\").\n // A match that merely overlaps one — extending outside it, e.g. a registered secret that\n // happens to be \"leak<redacted>\" — still has real secret content outside the placeholder\n // and must still be replaced.\n //\n // A registered secret wholly contained in the placeholder (up to and including a secret\n // equal to \"<redacted>\" itself) is indistinguishable from the placeholder in rendered\n // output either way: substituting REDACTED_PLACEHOLDER for text that already reads\n // REDACTED_PLACEHOLDER is a no-op. Discarding the match here (rather than \"fixing\" it to\n // substitute anyway) isn't a redaction gap — it just skips redundant work on text that's\n // already the safe, masked form.\n const spans = findSecretSpans(text).filter(\n ([start, end]) => !protectedSpans.some(([pStart, pEnd]) => start >= pStart && end <= pEnd),\n );\n if (spans.length === 0) return text;\n spans.sort(([a], [b]) => a - b);\n\n const merged: Array<[start: number, end: number]> = [];\n for (const span of spans) {\n const last = merged.at(-1);\n if (last && span[0] <= last[1]) {\n last[1] = Math.max(last[1], span[1]);\n } else {\n merged.push(span);\n }\n }\n\n let result = \"\";\n let cursor = 0;\n for (const [start, end] of merged) {\n result += text.slice(cursor, start) + REDACTED_PLACEHOLDER;\n cursor = end;\n }\n return result + text.slice(cursor);\n}\n\n/**\n * Reset the registered-secret redaction state. Used for testing.\n *\n * `_secrets` is process-lifetime, module-level state with no production unregister API\n * (a real process should never stop hiding a secret it once saw). Test files that call\n * `logger.registerSecret()` and run in a Vitest project with `isolate: false` share this\n * state across files, so a value registered in one file's test can still be redacted in an\n * unrelated later file's assertions unless cleared between tests.\n */\nexport function resetSecretRegistry(): void {\n _secrets.clear();\n _automaton = null;\n}\n\n// Type icons for log output\nconst TYPE_ICONS: Record<string, string> = {\n info: \"ℹ\",\n success: \"✔\",\n warn: \"⚠\",\n error: \"✖\",\n debug: \"⚙\",\n trace: \"→\",\n log: \"\",\n};\n\n// Color functions for icon and message text\nconst TYPE_COLORS: Record<string, (text: string) => string> = {\n info: styles.info,\n success: styles.success,\n warn: styles.warning,\n error: styles.error,\n debug: styles.dim,\n trace: styles.dim,\n log: (text) => text,\n};\n\ninterface FormatLogLineOptions {\n mode: string;\n indent: number;\n type: string;\n message: string;\n timestamp?: string;\n}\n\n/**\n * Formats a log line with the appropriate prefix and indentation\n * @param opts - Formatting options\n * @returns Formatted log line\n */\nexport function formatLogLine(opts: FormatLogLineOptions): string {\n const { mode, indent, type, message, timestamp } = opts;\n const indentPrefix = indent > 0 ? \" \".repeat(indent) : \"\";\n const colorFn = TYPE_COLORS[type] || ((text: string) => text);\n\n // Plain mode: color only, no icon, no timestamp\n if (mode === \"plain\") {\n return `${indentPrefix}${colorFn(message)}\\n`;\n }\n\n // Default/Stream mode: with icon and color\n const icon = TYPE_ICONS[type] || \"\";\n const prefix = icon ? `${icon} ` : \"\";\n const coloredOutput = colorFn(`${prefix}${message}`);\n const timestampPrefix = timestamp ?? \"\";\n\n return `${indentPrefix}${timestampPrefix}${coloredOutput}\\n`;\n}\n\n/**\n * Writes a formatted log line to stderr.\n * @param type - Log type (info, success, warn, error, log)\n * @param message - Log message\n * @param opts - Log options (mode and indent)\n */\nfunction writeLog(type: string, message: string, opts?: LogOptions): void {\n const mode = opts?.mode ?? \"default\";\n const indent = opts?.indent ?? 0;\n const inspectOpts: InspectOptions = {\n breakLength: process.stdout.columns || 80,\n };\n const formattedMessage = formatWithOptions(inspectOpts, message);\n const timestamp = mode === \"stream\" ? `${new Date().toLocaleTimeString()} ` : \"\";\n const output = formatLogLine({ mode, indent, type, message: formattedMessage, timestamp });\n process.stderr.write(renderFor(process.stderr, redactSecrets(output)));\n}\n\n/**\n * The CLI logger. Diagnostics go to stderr; `out()` writes primary output to\n * stdout as a table, or as JSON when `jsonMode` is on. `--json` and\n * `--verbose` feed the `jsonMode` / `verbose` state, which CLI plugins share\n * with the SDK code paths they call.\n */\nexport const logger = {\n get jsonMode(): boolean {\n return _jsonMode;\n },\n set jsonMode(value: boolean) {\n _jsonMode = value;\n if (!value) _jsonModeSource = undefined;\n },\n\n /**\n * Enable or disable JSON mode, recording what selected it so a suppressed\n * prompt can name the right remedy.\n * @param value - Whether JSON output is on\n * @param source - What turned it on; omit when turning it off\n */\n setJsonMode(value: boolean, source?: JsonModeSource): void {\n _jsonMode = value;\n _jsonModeSource = value ? source : undefined;\n },\n\n get verbose(): boolean {\n return _verbose || parseBoolean(process.env.DEBUG) === true || process.env.RUNNER_DEBUG === \"1\";\n },\n set verbose(value: boolean) {\n _verbose = value;\n },\n\n info(message: string, opts?: LogOptions): void {\n writeLog(\"info\", message, opts);\n },\n\n success(message: string, opts?: LogOptions): void {\n writeLog(\"success\", message, opts);\n },\n\n warn(message: string, opts?: LogOptions): void {\n writeLog(\"warn\", message, opts);\n },\n\n error(message: string, opts?: LogOptions): void {\n writeLog(\"error\", message, opts);\n },\n\n log(message: string): void {\n writeLog(\"log\", message, { mode: \"plain\" });\n },\n\n newline(): void {\n process.stderr.write(\"\\n\");\n },\n\n debug(message: string): void {\n if (logger.verbose) {\n writeLog(\"log\", styles.dim(message), { mode: \"plain\" });\n }\n },\n\n /**\n * Registers a value to be redacted from diagnostic log output (`info`/`success`/`warn`/\n * `error`/`log`/`debug`). Any occurrence of `value` — or of its JSON-string-escaped form\n * (so a value embedded in `JSON.stringify`d output, e.g. `--json` mode error envelopes, is\n * also caught) or its `application/x-www-form-urlencoded` form (so a value that reached the\n * process via a URL query string, e.g. an OAuth authorization code decoded from a callback\n * URL via `URLSearchParams`, is still caught if that same URL — still encoded — is later\n * echoed into a diagnostic message) — is replaced with `<redacted>` before it reaches\n * stderr. Does not affect `out()`, since some commands intentionally print secret values as\n * their primary result.\n *\n * Values shorter than 4 characters are ignored, since they are too likely to match\n * unrelated text. A non-string value (e.g. `undefined` from an unvalidated external\n * payload cast to a typed shape) is ignored the same way, rather than throwing, since a\n * logging call must never be what crashes the process.\n * @param value - The secret value to redact from future log output\n */\n registerSecret(value: string): void {\n // Counts Unicode code points, not UTF-16 code units, so a value made of surrogate-pair\n // characters (e.g. emoji) isn't undercounted as longer than it actually is.\n if (typeof value !== \"string\" || [...value].length < MIN_SECRET_LENGTH) return;\n const sizeBefore = _secrets.size;\n _secrets.add(value);\n const jsonEscaped = JSON.stringify(value).slice(1, -1);\n if (jsonEscaped !== value) _secrets.add(jsonEscaped);\n // Uses URLSearchParams rather than encodeURIComponent: form-urlencoding (what\n // URLSearchParams produces, and what a URL query string actually contains) encodes a\n // space as \"+\", not \"%20\", and unlike encodeURIComponent it never throws on a lone\n // surrogate (invalid UTF-16) — it substitutes U+FFFD instead, matching how the URL\n // itself would already have encoded that same malformed input.\n const formEncoded = new URLSearchParams([[\"v\", value]]).toString().slice(2);\n if (formEncoded !== value) _secrets.add(formEncoded);\n // Set#add on an already-registered value is a no-op, so this only invalidates the\n // cached automaton (see findSecretSpans) when a genuinely new secret was added.\n if (_secrets.size !== sizeBefore) _automaton = null;\n },\n\n out(data: string | object | object[], options?: OutOptions): void {\n if (typeof data === \"string\") {\n process.stdout.write(renderFor(process.stdout, data.endsWith(\"\\n\") ? data : data + \"\\n\"));\n return;\n }\n\n if (this.jsonMode) {\n // eslint-disable-next-line no-restricted-syntax\n console.log(JSON.stringify(data));\n return;\n }\n\n const display = options?.display;\n\n // Helper to format a value for table display\n const formatValue = (value: unknown, pretty = false): string => {\n if (options?.showNull && value === null) return \"NULL\";\n if (value === null || value === undefined) return \"N/A\";\n if (value instanceof Date) {\n return formatDistanceToNowStrict(value, { addSuffix: true });\n }\n if (typeof value === \"object\") {\n return pretty ? JSON.stringify(value, null, 2) : JSON.stringify(value);\n }\n return String(value);\n };\n\n // Helper to check if field should be excluded\n const isExcluded = (key: string): boolean => {\n return display !== undefined && key in display && display[key] === null;\n };\n\n // Helper to apply transformer or default formatting\n const transformValue = (key: string, value: unknown, item: object, pretty = false): string => {\n if (display && key in display) {\n const transformer = display[key];\n if (transformer) {\n return transformer(value, item);\n }\n }\n return formatValue(value, pretty);\n };\n\n if (!Array.isArray(data)) {\n const entries = Object.entries(data).filter(([key]) => !isExcluded(key));\n const formattedEntries = entries.map(([key, value]) => [\n key,\n transformValue(key, value, data, true),\n ]);\n const t = renderTable(formattedEntries, { singleLine: false });\n process.stdout.write(renderFor(process.stdout, t));\n return;\n }\n\n if (data.length === 0) {\n return;\n }\n\n const allHeaders = Array.from(new Set(data.flatMap((item) => Object.keys(item))));\n const headers = allHeaders.filter((h) => !isExcluded(h));\n if (headers.length === 0) {\n return;\n }\n const rows = data.map((item) =>\n headers.map((header) =>\n transformValue(header, (item as Record<string, unknown>)[header], item),\n ),\n );\n\n const t = renderTable([headers, ...rows], {\n drawHorizontalLine: (lineIndex, rowCount) => {\n return lineIndex === 0 || lineIndex === 1 || lineIndex === rowCount;\n },\n });\n process.stdout.write(renderFor(process.stdout, t));\n },\n};\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{t as e}from"./schema-CRtAmDcl.mjs";import{t}from"./assert-WeXvmG4j.mjs";import{n,r,t as i}from"./guards-DsX7dJCP.mjs";var PluginManager=class{plugins=/* @__PURE__ */ new Map;generatedExecutors=[];generatedTables=[];namespaceGeneratedTableKeys=/* @__PURE__ */ new Set;namespaceGeneratedExecutorKeys=/* @__PURE__ */ new Set;pluginExecutorFiles=[];constructor(e=[]){for(let t of e){if(this.plugins.has(t.id))throw Error(`Duplicate plugin ID "${t.id}" detected. Each plugin must have a unique ID.`);this.plugins.set(t.id,t)}}async processAttachment(e){let n=this.plugins.get(e.pluginId);if(!n)return{success:!1,error:`Plugin "${e.pluginId}" not found`};let r=n.tableConfigRequired;if((typeof r==`function`?r(n.pluginConfig):r===!0)&&(e.tableConfig===void 0||e.tableConfig===null))return{success:!1,error:`Plugin "${n.id}" requires tableConfig, but none was provided for table "${e.table.name}".`};if(!n.onTableLoaded)return{success:!1,error:`Plugin "${n.id}" does not support table-attached processing (missing onTableLoaded method). Use onNamespaceLoaded via definePlugins() instead.`};let i;try{i=await n.onTableLoaded({table:e.table,tableConfig:e.tableConfig,pluginConfig:n.pluginConfig,namespace:e.namespace})}catch(t){let r=t instanceof Error?t.message:String(t);return{success:!1,error:`Plugin "${n.id}" threw an error while processing table "${e.table.name}": ${r}`}}if(i.tables&&Object.keys(i.tables).length>0){let r=t(n.importPath,`plugin "${n.id}" missing importPath`);for(let[t,a]of Object.entries(i.tables))this.generatedTables.push({pluginId:e.pluginId,pluginImportPath:r,sourceTableName:e.table.name,kind:t,table:a,namespace:e.namespace,pluginConfig:n.pluginConfig})}if(i.executors&&i.executors.length>0)for(let t of i.executors)this.generatedExecutors.push({executor:t,pluginId:e.pluginId,namespace:e.namespace,sourceTableName:e.table.name});return{success:!0,output:i}}async processNamespacePlugins(e){let r=[];for(let[i,a]of this.plugins){if(!a.onNamespaceLoaded)continue;let o=a.pluginConfig,s={pluginConfig:o,namespace:e},c;try{c=await a.onNamespaceLoaded(s)}catch(t){let n=t instanceof Error?t.message:String(t);r.push({pluginId:i,config:o,result:{success:!1,error:`Plugin "${a.id}" threw an error during namespace processing for "${e}": ${n}`}});continue}if(c.executors&&c.executors.length>0)for(let t of c.executors){let n=`${i}:${t.name}`;this.namespaceGeneratedExecutorKeys.has(n)||(this.namespaceGeneratedExecutorKeys.add(n),this.generatedExecutors.push({executor:t,pluginId:i,namespace:e}))}if(c.tables&&Object.keys(c.tables).length>0){let r=t(a.importPath,`plugin "${a.id}" missing importPath`);for(let[t,o]of Object.entries(c.tables)){let s=`${i}:${t}:${n(o)??``}`;this.namespaceGeneratedTableKeys.has(s)||(this.namespaceGeneratedTableKeys.add(s),this.generatedTables.push({pluginId:i,pluginImportPath:r,sourceTableName:`(namespace)`,kind:t,table:o,namespace:e,pluginConfig:a.pluginConfig}))}}r.push({pluginId:i,config:o,result:{success:!0,output:c}})}return r}async processAttachmentsForTable(e){let{rawTable:t,attachments:r,namespace:i}=e,a=t,o,s=[],c=[];for(let e of r){let t=await this.processAttachment({table:a,tableConfig:e.config,namespace:i,pluginId:e.pluginId});if(!t.success)throw Error(t.error);let r=t.output,l=r.extends?.fields;l&&Object.keys(l).length>0&&(a=this.extendTable({originalTable:a,extendFields:l,pluginId:e.pluginId}),o=a,c.push({kind:`extended`,tableName:a.name,fieldCount:Object.keys(l).length,pluginId:e.pluginId}));let u=this.getPlugin(e.pluginId);for(let[t,i]of Object.entries(r.tables??{})){let r=n(i)??``;s.push({tableName:r,table:i,kind:t,pluginId:e.pluginId,pluginImportPath:this.getPluginImportPath(e.pluginId)??``,pluginConfig:u?.pluginConfig}),c.push({kind:`generated`,tableName:r,pluginId:e.pluginId})}}return{extendedTable:o,generatedTables:s,events:c}}getNamespacePluginIds(){return Array.from(this.plugins.entries()).filter(([,e])=>e.onNamespaceLoaded!==void 0).map(([e])=>e)}get pluginCount(){return this.plugins.size}getPlugin(e){return this.plugins.get(e)}getPluginImportPath(e){return this.plugins.get(e)?.importPath}getPluginGeneratedExecutors(){return this.generatedExecutors}getPluginGeneratedExecutorsWithImportPath(){return this.generatedExecutors.map(e=>({...e,pluginImportPath:this.getPluginImportPath(e.pluginId)??``}))}getPluginGeneratedTables(){return this.generatedTables}getPluginGeneratedExecutorsForNamespace(e){return this.generatedExecutors.filter(t=>t.namespace===e)}getPluginsWithGenerationHooks(){return Array.from(this.plugins.values()).filter(e=>r(e))}getPluginGenerationDependencies(e){let t=this.plugins.get(e);return t?i(t):/* @__PURE__ */ new Set}generatePluginFiles(e){let{outputDir:t,sourceTableInfoMap:n,configPath:r,tableGenerator:i,executorGenerator:a}=e,o=i(this.generatedTables,t),s=this.getPluginGeneratedExecutorsWithImportPath();return this.pluginExecutorFiles=a(s,t,o,n,r),this.pluginExecutorFiles}extendTable(t){let{originalTable:n,extendFields:r,pluginId:i}=t,a=Object.keys(n.fields),o=Object.keys(n.metadata.files),s=Object.keys(r),c=s.filter(e=>a.includes(e)),l=s.filter(e=>o.includes(e));if(c.length>0)throw Error(`Plugin "${i}" attempted to add fields that already exist in table "${n.name}": ${c.join(`, `)}. extendFields cannot overwrite existing fields.`);if(l.length>0)throw Error(`Plugin "${i}" attempted to add fields that collide with file keys already declared via .files() on table "${n.name}": ${l.join(`, `)}.`);let{id:u,...d}={...n.fields,...r},f=n.metadata.settings?.pluralForm,p=f?[n.name,f]:n.name;return copyMetadataToExtendedTable(n,e.table(p,d))}};function copyMetadataToExtendedTable(e,t){let n=t;e._description&&(n=n.description(e._description));let r=e.metadata;if(Object.keys(r.files).length>0&&(n=n.files(r.files)),r.settings){let{pluralForm:e,...t}=r.settings;Object.keys(t).length>0&&(n=n.features(t))}if(r.permissions.record&&(n=n.permission(r.permissions.record)),r.permissions.gql&&(n=n.gqlPermission(r.permissions.gql)),r.indexes&&Object.keys(r.indexes).length>0){let e=Object.entries(r.indexes).map(([e,t])=>({name:e,fields:t.fields,unique:t.unique}));n=n.indexes(...e)}if(r.typeHook&&(n=n.hooks(r.typeHook)),r.typeValidate&&(n=n.validate(r.typeValidate)),e.plugins.length>0)for(let t of e.plugins)n=n.plugin({[t.pluginId]:t.config});return n}export{PluginManager as t};
2
- //# sourceMappingURL=manager-C0dE7pd0.mjs.map
1
+ import{t as e}from"./schema-CRtAmDcl.mjs";import{t}from"./assert-WeXvmG4j.mjs";import{n,r,t as i}from"./guards-yDXyKC9F.mjs";var PluginManager=class{plugins=/* @__PURE__ */ new Map;generatedExecutors=[];generatedTables=[];namespaceGeneratedTableKeys=/* @__PURE__ */ new Set;namespaceGeneratedExecutorKeys=/* @__PURE__ */ new Set;pluginExecutorFiles=[];constructor(e=[]){for(let t of e){if(this.plugins.has(t.id))throw Error(`Duplicate plugin ID "${t.id}" detected. Each plugin must have a unique ID.`);this.plugins.set(t.id,t)}}async processAttachment(e){let n=this.plugins.get(e.pluginId);if(!n)return{success:!1,error:`Plugin "${e.pluginId}" not found`};let r=n.tableConfigRequired;if((typeof r==`function`?r(n.pluginConfig):r===!0)&&(e.tableConfig===void 0||e.tableConfig===null))return{success:!1,error:`Plugin "${n.id}" requires tableConfig, but none was provided for table "${e.table.name}".`};if(!n.onTableLoaded)return{success:!1,error:`Plugin "${n.id}" does not support table-attached processing (missing onTableLoaded method). Use onNamespaceLoaded via definePlugins() instead.`};let i;try{i=await n.onTableLoaded({table:e.table,tableConfig:e.tableConfig,pluginConfig:n.pluginConfig,namespace:e.namespace})}catch(t){let r=t instanceof Error?t.message:String(t);return{success:!1,error:`Plugin "${n.id}" threw an error while processing table "${e.table.name}": ${r}`}}if(i.tables&&Object.keys(i.tables).length>0){let r=t(n.importPath,`plugin "${n.id}" missing importPath`);for(let[t,a]of Object.entries(i.tables))this.generatedTables.push({pluginId:e.pluginId,pluginImportPath:r,sourceTableName:e.table.name,kind:t,table:a,namespace:e.namespace,pluginConfig:n.pluginConfig})}if(i.executors&&i.executors.length>0)for(let t of i.executors)this.generatedExecutors.push({executor:t,pluginId:e.pluginId,namespace:e.namespace,sourceTableName:e.table.name});return{success:!0,output:i}}async processNamespacePlugins(e){let r=[];for(let[i,a]of this.plugins){if(!a.onNamespaceLoaded)continue;let o=a.pluginConfig,s={pluginConfig:o,namespace:e},c;try{c=await a.onNamespaceLoaded(s)}catch(t){let n=t instanceof Error?t.message:String(t);r.push({pluginId:i,config:o,result:{success:!1,error:`Plugin "${a.id}" threw an error during namespace processing for "${e}": ${n}`}});continue}if(c.executors&&c.executors.length>0)for(let t of c.executors){let n=`${i}:${t.name}`;this.namespaceGeneratedExecutorKeys.has(n)||(this.namespaceGeneratedExecutorKeys.add(n),this.generatedExecutors.push({executor:t,pluginId:i,namespace:e}))}if(c.tables&&Object.keys(c.tables).length>0){let r=t(a.importPath,`plugin "${a.id}" missing importPath`);for(let[t,o]of Object.entries(c.tables)){let s=`${i}:${t}:${n(o)??``}`;this.namespaceGeneratedTableKeys.has(s)||(this.namespaceGeneratedTableKeys.add(s),this.generatedTables.push({pluginId:i,pluginImportPath:r,sourceTableName:`(namespace)`,kind:t,table:o,namespace:e,pluginConfig:a.pluginConfig}))}}r.push({pluginId:i,config:o,result:{success:!0,output:c}})}return r}async processAttachmentsForTable(e){let{rawTable:t,attachments:r,namespace:i}=e,a=t,o,s=[],c=[];for(let e of r){let t=await this.processAttachment({table:a,tableConfig:e.config,namespace:i,pluginId:e.pluginId});if(!t.success)throw Error(t.error);let r=t.output,l=r.extends?.fields;l&&Object.keys(l).length>0&&(a=this.extendTable({originalTable:a,extendFields:l,pluginId:e.pluginId}),o=a,c.push({kind:`extended`,tableName:a.name,fieldCount:Object.keys(l).length,pluginId:e.pluginId}));let u=this.getPlugin(e.pluginId);for(let[t,i]of Object.entries(r.tables??{})){let r=n(i)??``;s.push({tableName:r,table:i,kind:t,pluginId:e.pluginId,pluginImportPath:this.getPluginImportPath(e.pluginId)??``,pluginConfig:u?.pluginConfig}),c.push({kind:`generated`,tableName:r,pluginId:e.pluginId})}}return{extendedTable:o,generatedTables:s,events:c}}getNamespacePluginIds(){return Array.from(this.plugins.entries()).filter(([,e])=>e.onNamespaceLoaded!==void 0).map(([e])=>e)}get pluginCount(){return this.plugins.size}getPlugin(e){return this.plugins.get(e)}getPluginImportPath(e){return this.plugins.get(e)?.importPath}getPluginGeneratedExecutors(){return this.generatedExecutors}getPluginGeneratedExecutorsWithImportPath(){return this.generatedExecutors.map(e=>({...e,pluginImportPath:this.getPluginImportPath(e.pluginId)??``}))}getPluginGeneratedTables(){return this.generatedTables}getPluginGeneratedExecutorsForNamespace(e){return this.generatedExecutors.filter(t=>t.namespace===e)}getPluginsWithGenerationHooks(){return Array.from(this.plugins.values()).filter(e=>r(e))}getPluginGenerationDependencies(e){let t=this.plugins.get(e);return t?i(t):/* @__PURE__ */ new Set}generatePluginFiles(e){let{outputDir:t,sourceTableInfoMap:n,configPath:r,tableGenerator:i,executorGenerator:a}=e,o=i(this.generatedTables,t),s=this.getPluginGeneratedExecutorsWithImportPath();return this.pluginExecutorFiles=a(s,t,o,n,r),this.pluginExecutorFiles}extendTable(t){let{originalTable:n,extendFields:r,pluginId:i}=t,a=Object.keys(n.fields),o=Object.keys(n.metadata.files),s=Object.keys(r),c=s.filter(e=>a.includes(e)),l=s.filter(e=>o.includes(e));if(c.length>0)throw Error(`Plugin "${i}" attempted to add fields that already exist in table "${n.name}": ${c.join(`, `)}. extendFields cannot overwrite existing fields.`);if(l.length>0)throw Error(`Plugin "${i}" attempted to add fields that collide with file keys already declared via .files() on table "${n.name}": ${l.join(`, `)}.`);let{id:u,...d}={...n.fields,...r},f=n.metadata.settings?.pluralForm,p=f?[n.name,f]:n.name;return copyMetadataToExtendedTable(n,e.table(p,d))}};function copyMetadataToExtendedTable(e,t){let n=t;e._description&&(n=n.description(e._description));let r=e.metadata;if(Object.keys(r.files).length>0&&(n=n.files(r.files)),r.settings){let{pluralForm:e,...t}=r.settings;Object.keys(t).length>0&&(n=n.features(t))}if(r.permissions.record&&(n=n.permission(r.permissions.record)),r.permissions.gql&&(n=n.gqlPermission(r.permissions.gql)),r.indexes&&Object.keys(r.indexes).length>0){let e=Object.entries(r.indexes).map(([e,t])=>({name:e,fields:t.fields,unique:t.unique}));n=n.indexes(...e)}if(r.typeHook&&(n=n.hooks(r.typeHook)),r.typeValidate&&(n=n.validate(r.typeValidate)),e.plugins.length>0)for(let t of e.plugins)n=n.plugin({[t.pluginId]:t.config});return n}export{PluginManager as t};
2
+ //# sourceMappingURL=manager-8-JOvuLl.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager-8-JOvuLl.mjs","names":["db","getPluginGenerationDependencies","plugin","plugins","context","tableConfigRequired","output","error","message","importPath","assertDefined","kind","table","executor","results","pluginId","config","namespace","executorKey","tableKey","getRawPluginTableName","params","currentTable","rawTable","extendedTable","generatedTables","events","attachment","attachments","result","extendFields","tableName","id","info","hasGenerationHooks","tableGenerationResult","tableGenerator","outputDir","pluginExecutors","executorGenerator","sourceTableInfoMap","configPath","existingFieldNames","originalTable","existingFileNames","newFieldNames","duplicateFields","name","duplicateFiles","_id","fieldsWithoutId","pluralForm","extended","original","metadata","_pluralForm","features","indexDefs","def"],"sources":["../src/plugin/manager.ts"],"sourcesContent":["import { db, type TailorAnyDBType } from \"#/configure/services/tailordb/index\";\nimport {\n getPluginGenerationDependencies,\n getRawPluginTableName,\n hasGenerationHooks,\n} from \"#/plugin/guards\";\nimport { assertDefined } from \"#/utils/assert\";\nimport type {\n TailorTypePermission,\n TailorTypeGqlPermission,\n} from \"#/configure/services/tailordb/permission\";\nimport type {\n TailorAnyDBField,\n TypeHook,\n TypeValidateFn,\n} from \"#/configure/services/tailordb/types\";\nimport type {\n DependencyKind,\n Plugin,\n PluginAttachment,\n PluginGeneratedExecutor,\n PluginGeneratedTable,\n PluginNamespaceProcessContext,\n PluginOutput,\n TablePluginOutput,\n} from \"#/plugin/types\";\nimport type { TailorDBTypeRaw } from \"#/types/tailordb.generated\";\n\n/**\n * Context for processing a single plugin attachment on a raw TailorDBType\n */\nexport interface ProcessAttachmentContext {\n table: TailorAnyDBType;\n tableConfig: unknown;\n namespace: string;\n pluginId: string;\n}\n\n/**\n * Information about a plugin-generated table (for table file generation)\n */\nexport interface PluginGeneratedTableInfo {\n /** Plugin ID that generated this table */\n pluginId: string;\n /** Plugin import path for resolving executor files */\n pluginImportPath: string;\n /** Source table name that triggered the plugin */\n sourceTableName: string;\n /** Kind identifier for this generated table */\n kind: string;\n /** The generated TailorDB table object */\n table: PluginGeneratedTable;\n /** Namespace where this table was generated */\n namespace: string;\n /** Plugin config used to generate this table */\n pluginConfig?: unknown;\n}\n\n/**\n * Extended executor info with plugin import path\n */\nexport interface PluginExecutorInfoExtended extends PluginExecutorInfo {\n /** Plugin's import path for resolving executor files */\n pluginImportPath: string;\n}\n\n/**\n * Result of processing a table-attached plugin\n */\nexport type ProcessAttachmentResult =\n | { success: true; output: TablePluginOutput }\n | { success: false; error: string };\n\n/**\n * Result of processing a namespace plugin\n */\nexport type ProcessNamespaceResult =\n | { success: true; output: PluginOutput }\n | { success: false; error: string };\n\n/**\n * Parameters for processing all plugin attachments of a TailorDB table.\n */\nexport interface ProcessAttachmentsForTableParams {\n rawTable: TailorDBTypeRaw;\n attachments: PluginAttachment[];\n namespace: string;\n}\n\n/**\n * Progress event emitted while processing plugin attachments for a TailorDB table.\n * Plain data so the caller (typically the cli) can format and output it.\n */\ntype ProcessAttachmentEvent =\n | { kind: \"extended\"; tableName: string; fieldCount: number; pluginId: string }\n | { kind: \"generated\"; tableName: string; pluginId: string };\n\n/**\n * Generated table produced by a plugin during attachment processing.\n * `table` is raw plugin output; the caller must validate it before use.\n */\ninterface ProcessAttachmentsGeneratedTable {\n tableName: string;\n table: unknown;\n kind: string;\n pluginId: string;\n pluginImportPath: string;\n pluginConfig?: unknown;\n}\n\n/**\n * Result of {@link PluginManager.processAttachmentsForTable}.\n */\nexport interface ProcessAttachmentsForTableResult {\n /**\n * Final table after all extends are applied; undefined if no plugin extended the table.\n * Raw builder output; the caller must validate it before use.\n */\n extendedTable?: unknown;\n /** Tables newly generated by plugins for this attachment chain. */\n generatedTables: ProcessAttachmentsGeneratedTable[];\n /** Events for the caller to render. */\n events: ProcessAttachmentEvent[];\n}\n\n/**\n * Information about a plugin-generated executor\n */\nexport interface PluginExecutorInfo {\n /** The executor definition */\n executor: PluginGeneratedExecutor;\n /** Plugin ID that generated this executor */\n pluginId: string;\n /** Namespace where the executor was generated */\n namespace: string;\n /** Source table name (for table-attached executors, undefined for namespace) */\n sourceTableName?: string;\n}\n\n/**\n * Manages plugin registration and processing\n */\nexport class PluginManager {\n private plugins: Map<string, Plugin> = new Map();\n private generatedExecutors: PluginExecutorInfo[] = [];\n private generatedTables: PluginGeneratedTableInfo[] = [];\n private namespaceGeneratedTableKeys: Set<string> = new Set();\n private namespaceGeneratedExecutorKeys: Set<string> = new Set();\n\n /** Generated plugin executor file paths */\n private pluginExecutorFiles: string[] = [];\n\n constructor(plugins: Plugin[] = []) {\n for (const plugin of plugins) {\n if (this.plugins.has(plugin.id)) {\n throw new Error(\n `Duplicate plugin ID \"${plugin.id}\" detected. Each plugin must have a unique ID.`,\n );\n }\n this.plugins.set(plugin.id, plugin);\n }\n }\n\n /**\n * Process a single plugin attachment on a raw TailorDBType.\n * This method is called during table loading before parsing.\n * @param context - Context containing the raw table, config, namespace, and plugin ID\n * @returns Result with plugin output on success, or error message on failure\n */\n async processAttachment(context: ProcessAttachmentContext): Promise<ProcessAttachmentResult> {\n const plugin = this.plugins.get(context.pluginId);\n if (!plugin) {\n return {\n success: false,\n error: `Plugin \"${context.pluginId}\" not found`,\n };\n }\n\n const tableConfigRequired = plugin.tableConfigRequired;\n const resolvedRequired =\n typeof tableConfigRequired === \"function\"\n ? tableConfigRequired(plugin.pluginConfig)\n : tableConfigRequired === true;\n if (resolvedRequired && (context.tableConfig === undefined || context.tableConfig === null)) {\n return {\n success: false,\n error: `Plugin \"${plugin.id}\" requires tableConfig, but none was provided for table \"${context.table.name}\".`,\n };\n }\n\n // Check if plugin supports table-attached processing\n if (!plugin.onTableLoaded) {\n return {\n success: false,\n error: `Plugin \"${plugin.id}\" does not support table-attached processing (missing onTableLoaded method). Use onNamespaceLoaded via definePlugins() instead.`,\n };\n }\n\n // Execute plugin onTableLoaded with the raw TailorDB table\n let output: TablePluginOutput;\n try {\n output = await plugin.onTableLoaded({\n table: context.table,\n tableConfig: context.tableConfig,\n pluginConfig: plugin.pluginConfig,\n namespace: context.namespace,\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n success: false,\n error: `Plugin \"${plugin.id}\" threw an error while processing table \"${context.table.name}\": ${message}`,\n };\n }\n\n // Collect generated tables\n if (output.tables && Object.keys(output.tables).length > 0) {\n // importPath is guaranteed by schema validation for plugins with definition-time hooks\n const importPath = assertDefined(\n plugin.importPath,\n `plugin \"${plugin.id}\" missing importPath`,\n );\n for (const [kind, table] of Object.entries(output.tables)) {\n this.generatedTables.push({\n pluginId: context.pluginId,\n pluginImportPath: importPath,\n sourceTableName: context.table.name,\n kind,\n table,\n namespace: context.namespace,\n pluginConfig: plugin.pluginConfig,\n });\n }\n }\n\n // Collect generated executors\n if (output.executors && output.executors.length > 0) {\n for (const executor of output.executors) {\n this.generatedExecutors.push({\n executor,\n pluginId: context.pluginId,\n namespace: context.namespace,\n sourceTableName: context.table.name,\n });\n }\n }\n\n return { success: true, output };\n }\n\n /**\n * Process namespace plugins that don't require a source table.\n * This method is called once per namespace for plugins with onNamespaceLoaded method.\n * @param namespace - The target namespace for generated tables\n * @returns Array of results with plugin outputs and configs\n */\n async processNamespacePlugins(\n namespace: string,\n ): Promise<Array<{ pluginId: string; config: unknown; result: ProcessNamespaceResult }>> {\n const results: Array<{ pluginId: string; config: unknown; result: ProcessNamespaceResult }> =\n [];\n\n for (const [pluginId, plugin] of this.plugins) {\n // Skip plugins without onNamespaceLoaded method\n if (!plugin.onNamespaceLoaded) {\n continue;\n }\n\n // Use stored plugin config (from definePlugins)\n const config = plugin.pluginConfig;\n\n // Execute plugin onNamespaceLoaded\n const context: PluginNamespaceProcessContext = {\n pluginConfig: config,\n namespace,\n };\n\n let output: Awaited<ReturnType<NonNullable<Plugin[\"onNamespaceLoaded\"]>>>;\n try {\n output = await plugin.onNamespaceLoaded(context);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n results.push({\n pluginId,\n config,\n result: {\n success: false,\n error: `Plugin \"${plugin.id}\" threw an error during namespace processing for \"${namespace}\": ${message}`,\n },\n });\n continue;\n }\n\n // Collect generated executors (namespace - no source table)\n if (output.executors && output.executors.length > 0) {\n for (const executor of output.executors) {\n const executorKey = `${pluginId}:${executor.name}`;\n if (this.namespaceGeneratedExecutorKeys.has(executorKey)) {\n continue;\n }\n this.namespaceGeneratedExecutorKeys.add(executorKey);\n this.generatedExecutors.push({\n executor,\n pluginId,\n namespace,\n });\n }\n }\n\n // Collect generated tables (namespace - no source table)\n if (output.tables && Object.keys(output.tables).length > 0) {\n // importPath is guaranteed by schema validation for plugins with definition-time hooks\n const importPath = assertDefined(\n plugin.importPath,\n `plugin \"${plugin.id}\" missing importPath`,\n );\n for (const [kind, table] of Object.entries(output.tables)) {\n const tableKey = `${pluginId}:${kind}:${getRawPluginTableName(table) ?? \"\"}`;\n if (this.namespaceGeneratedTableKeys.has(tableKey)) {\n continue;\n }\n this.namespaceGeneratedTableKeys.add(tableKey);\n this.generatedTables.push({\n pluginId,\n pluginImportPath: importPath,\n sourceTableName: \"(namespace)\",\n kind,\n table,\n namespace,\n pluginConfig: plugin.pluginConfig,\n });\n }\n }\n\n results.push({\n pluginId,\n config,\n result: { success: true, output },\n });\n }\n\n return results;\n }\n\n /**\n * Run every plugin attachment for a single TailorDB table in order, threading the\n * extended table through the chain. Returns plain data (no logging, no shared state)\n * so the caller decides how to apply updates and render progress.\n * @param params - The raw table, its attachments, and the target namespace\n * @returns Final extended table (if any), generated tables, and render events\n */\n async processAttachmentsForTable(\n params: ProcessAttachmentsForTableParams,\n ): Promise<ProcessAttachmentsForTableResult> {\n const { rawTable, attachments, namespace } = params;\n // The runtime value is a configure-layer builder instance; we accept the structural\n // TailorDBTypeRaw at the boundary so callers (cli) don't need to depend on TailorAnyDBType.\n let currentTable: TailorAnyDBType = rawTable as unknown as TailorAnyDBType;\n let extendedTable: TailorAnyDBType | undefined;\n const generatedTables: ProcessAttachmentsGeneratedTable[] = [];\n const events: ProcessAttachmentEvent[] = [];\n\n for (const attachment of attachments) {\n const result = await this.processAttachment({\n table: currentTable,\n tableConfig: attachment.config,\n namespace,\n pluginId: attachment.pluginId,\n });\n if (!result.success) {\n throw new Error(result.error);\n }\n\n const output = result.output;\n const extendFields = output.extends?.fields;\n if (extendFields && Object.keys(extendFields).length > 0) {\n currentTable = this.extendTable({\n originalTable: currentTable,\n extendFields,\n pluginId: attachment.pluginId,\n });\n extendedTable = currentTable;\n events.push({\n kind: \"extended\",\n tableName: currentTable.name,\n fieldCount: Object.keys(extendFields).length,\n pluginId: attachment.pluginId,\n });\n }\n\n const plugin = this.getPlugin(attachment.pluginId);\n for (const [kind, table] of Object.entries(output.tables ?? {})) {\n const tableName = getRawPluginTableName(table) ?? \"\";\n generatedTables.push({\n tableName,\n table,\n kind,\n pluginId: attachment.pluginId,\n pluginImportPath: this.getPluginImportPath(attachment.pluginId) ?? \"\",\n pluginConfig: plugin?.pluginConfig,\n });\n events.push({ kind: \"generated\", tableName, pluginId: attachment.pluginId });\n }\n }\n\n return { extendedTable, generatedTables, events };\n }\n\n /**\n * Get plugins that have onNamespaceLoaded method\n * @returns Array of plugin IDs that support namespace processing\n */\n getNamespacePluginIds(): string[] {\n return Array.from(this.plugins.entries())\n .filter(([, plugin]) => plugin.onNamespaceLoaded !== undefined)\n .map(([id]) => id);\n }\n\n /**\n * Get the count of registered plugins\n * @returns Number of registered plugins\n */\n get pluginCount(): number {\n return this.plugins.size;\n }\n\n /**\n * Get a plugin by its ID\n * @param pluginId - The plugin ID to look up\n * @returns The plugin instance, or undefined if not found\n */\n getPlugin(pluginId: string): Plugin | undefined {\n return this.plugins.get(pluginId);\n }\n\n /**\n * Get the import path for a plugin\n * @param pluginId - The plugin ID to look up\n * @returns The plugin's import path, or undefined if not found\n */\n getPluginImportPath(pluginId: string): string | undefined {\n return this.plugins.get(pluginId)?.importPath;\n }\n\n /**\n * Get all plugin-generated executors\n * @returns Array of plugin-generated executor info\n */\n getPluginGeneratedExecutors(): ReadonlyArray<PluginExecutorInfo> {\n return this.generatedExecutors;\n }\n\n /**\n * Get all plugin-generated executors with import paths\n * @returns Array of plugin-generated executor info with import paths\n */\n getPluginGeneratedExecutorsWithImportPath(): ReadonlyArray<PluginExecutorInfoExtended> {\n return this.generatedExecutors.map((info) => ({\n ...info,\n pluginImportPath: this.getPluginImportPath(info.pluginId) ?? \"\",\n }));\n }\n\n /**\n * Get all plugin-generated tables\n * @returns Array of plugin-generated table info\n */\n getPluginGeneratedTables(): ReadonlyArray<PluginGeneratedTableInfo> {\n return this.generatedTables;\n }\n\n /**\n * Get plugin-generated executors for a specific namespace\n * @param namespace - The namespace to filter by\n * @returns Array of plugin-generated executor info for the namespace\n */\n getPluginGeneratedExecutorsForNamespace(namespace: string): ReadonlyArray<PluginExecutorInfo> {\n return this.generatedExecutors.filter((info) => info.namespace === namespace);\n }\n\n /**\n * Get plugins that have any generation-time hooks.\n * @returns Array of plugins with generation hooks\n */\n getPluginsWithGenerationHooks(): Plugin[] {\n return Array.from(this.plugins.values()).filter((plugin) => hasGenerationHooks(plugin));\n }\n\n /**\n * Get the generation-time dependencies for a specific plugin.\n * @param pluginId - The plugin ID to look up\n * @returns Set of dependency kinds, or empty set if plugin not found\n */\n getPluginGenerationDependencies(pluginId: string): Set<DependencyKind> {\n const plugin = this.plugins.get(pluginId);\n if (!plugin) return new Set();\n return getPluginGenerationDependencies(plugin);\n }\n\n /**\n * Generate plugin files (tables and executors) and store the executor file paths.\n * @param params - Parameters for file generation\n * @returns Generated executor file paths\n */\n generatePluginFiles(params: GeneratePluginFilesParams): string[] {\n const { outputDir, sourceTableInfoMap, configPath, tableGenerator, executorGenerator } = params;\n\n // Generate table files\n const tableGenerationResult = tableGenerator(this.generatedTables, outputDir);\n\n // Generate executor files\n const pluginExecutors = this.getPluginGeneratedExecutorsWithImportPath();\n this.pluginExecutorFiles = executorGenerator(\n pluginExecutors,\n outputDir,\n tableGenerationResult,\n sourceTableInfoMap,\n configPath,\n );\n\n return this.pluginExecutorFiles;\n }\n\n /**\n * Extend a TailorDB table with new fields.\n * This method handles the `db.table()` call and metadata copying internally.\n * @param params - Parameters for table extension\n * @returns The extended TailorDB table\n */\n extendTable(params: ExtendTableParams): TailorAnyDBType {\n const { originalTable, extendFields, pluginId } = params;\n const existingFieldNames = Object.keys(originalTable.fields);\n const existingFileNames = Object.keys(originalTable.metadata.files);\n const newFieldNames = Object.keys(extendFields);\n const duplicateFields = newFieldNames.filter((name) => existingFieldNames.includes(name));\n const duplicateFiles = newFieldNames.filter((name) => existingFileNames.includes(name));\n\n if (duplicateFields.length > 0) {\n throw new Error(\n `Plugin \"${pluginId}\" attempted to add fields that already exist in table \"${originalTable.name}\": ${duplicateFields.join(\", \")}. ` +\n `extendFields cannot overwrite existing fields.`,\n );\n }\n\n if (duplicateFiles.length > 0) {\n throw new Error(\n `Plugin \"${pluginId}\" attempted to add fields that collide with file keys already declared via .files() on table \"${originalTable.name}\": ${duplicateFiles.join(\", \")}.`,\n );\n }\n\n const mergedFields = {\n ...originalTable.fields,\n ...extendFields,\n };\n\n const { id: _id, ...fieldsWithoutId } = mergedFields;\n const pluralForm = originalTable.metadata.settings?.pluralForm;\n const tableName = pluralForm\n ? ([originalTable.name, pluralForm] as [string, string])\n : originalTable.name;\n const extendedTable = db.table(tableName, fieldsWithoutId);\n return copyMetadataToExtendedTable(originalTable, extendedTable);\n }\n}\n\n/**\n * Source info for user-defined tables\n */\nexport type SourceTableInfo = {\n filePath: string;\n exportName: string;\n};\n\n/**\n * Result of generating plugin table files\n */\nexport interface PluginTableGenerationResult {\n /** Map of table name to generated file path (relative to outputDir) */\n tableFilePaths: Map<string, string>;\n /** List of all generated file paths (absolute) */\n generatedFiles: string[];\n}\n\n/**\n * Parameters for generating plugin files\n */\nexport interface GeneratePluginFilesParams {\n /** Base output directory (e.g., .tailor/plugin) */\n outputDir: string;\n /** Map of source table names to their source info */\n sourceTableInfoMap: Map<string, SourceTableInfo>;\n /** Path to tailor.config.ts (used for resolving plugin import paths) */\n configPath: string;\n /** Function to generate table files */\n tableGenerator: (\n tables: ReadonlyArray<PluginGeneratedTableInfo>,\n outputDir: string,\n ) => PluginTableGenerationResult;\n /** Function to generate executor files */\n executorGenerator: (\n executors: ReadonlyArray<PluginExecutorInfoExtended>,\n outputDir: string,\n tableGenerationResult: PluginTableGenerationResult,\n sourceTableInfoMap: Map<string, SourceTableInfo>,\n configPath: string,\n ) => string[];\n}\n\n/**\n * Parameters for extending a TailorDB table\n */\nexport interface ExtendTableParams {\n /** The original TailorDB table to extend */\n originalTable: TailorAnyDBType;\n /** New fields to add to the table */\n extendFields: Record<string, unknown>;\n /** The ID of the plugin extending the table */\n pluginId: string;\n}\n\n/**\n * Copy metadata from original table to extended table.\n * Preserves files, settings, permissions, indexes, and plugins.\n * @param original - The original TailorDB table with metadata\n * @param extended - The newly created extended table\n * @returns The extended table with copied metadata\n */\nfunction copyMetadataToExtendedTable(\n original: TailorAnyDBType,\n extended: TailorAnyDBType,\n): TailorAnyDBType {\n let result = extended;\n\n // Copy description\n if (original._description) {\n result = result.description(original._description);\n }\n\n // Copy files metadata\n const metadata = original.metadata;\n if (Object.keys(metadata.files).length > 0) {\n result = result.files(metadata.files);\n }\n\n // Copy settings/features (excluding pluralForm which is set during construction)\n if (metadata.settings) {\n const { pluralForm: _pluralForm, ...features } = metadata.settings;\n if (Object.keys(features).length > 0) {\n result = result.features(\n features as typeof features & { aggregation?: true; bulkUpsert?: true },\n );\n }\n }\n\n // Copy permissions from metadata\n // Zod schema operand types are wider unions than the configure layer's discriminated PermissionCondition,\n // so type assertions are needed here.\n if (metadata.permissions.record) {\n result = result.permission(metadata.permissions.record as TailorTypePermission);\n }\n if (metadata.permissions.gql) {\n result = result.gqlPermission(metadata.permissions.gql as TailorTypeGqlPermission);\n }\n\n // Copy indexes from metadata (indexes are stored in metadata, not as a direct property)\n if (metadata.indexes && Object.keys(metadata.indexes).length > 0) {\n const indexDefs = Object.entries(metadata.indexes).map(([name, def]) => ({\n name,\n // Cast fields array to tuple type (IndexDef expects [T, T, ...T[]])\n fields: def.fields as [string, string, ...string[]],\n unique: def.unique,\n }));\n result = result.indexes(...indexDefs);\n }\n\n if (metadata.typeHook) {\n result = result.hooks(metadata.typeHook as TypeHook<Record<string, TailorAnyDBField>>);\n }\n if (metadata.typeValidate) {\n result = result.validate(\n metadata.typeValidate as TypeValidateFn<Record<string, TailorAnyDBField>>,\n );\n }\n\n // Copy plugins (but don't re-process them)\n if (original.plugins.length > 0) {\n for (const plugin of original.plugins) {\n // Use type assertion as plugin ID is dynamic at runtime\n result = result.plugin({\n [plugin.pluginId]: plugin.config,\n });\n }\n }\n\n return result;\n}\n"],"mappings":"6HA8IA,IAAa,cAAb,KAA2B,CACzB,wBAAuC,IAAI,IAC3C,mBAAmD,CAAC,EACpD,gBAAsD,CAAC,EACvD,4CAAmD,IAAI,IACvD,+CAAsD,IAAI,IAG1D,oBAAwC,CAAC,EAEzC,YAAY,EAAoB,CAAC,EAAG,CAClC,IAAK,IAAME,KAAUC,EAAS,CAC5B,GAAI,KAAK,QAAQ,IAAID,EAAO,EAAE,EAC5B,MAAU,MACR,wBAAwBA,EAAO,GAAG,+CACpC,EAEF,KAAK,QAAQ,IAAIA,EAAO,GAAIA,CAAM,CACpC,CACF,CAQA,MAAM,kBAAkB,EAAqE,CAC3F,IAAMA,EAAS,KAAK,QAAQ,IAAIE,EAAQ,QAAQ,EAChD,GAAI,CAACF,EACH,MAAO,CACL,QAAS,GACT,MAAO,WAAWE,EAAQ,SAAS,YACrC,EAGF,IAAMC,EAAsBH,EAAO,oBAKnC,IAHE,OAAOG,GAAwB,WAC3BA,EAAoBH,EAAO,YAAY,EACvCG,IAAwB,MACLD,EAAQ,cAAgB,IAAA,IAAaA,EAAQ,cAAgB,MACpF,MAAO,CACL,QAAS,GACT,MAAO,WAAWF,EAAO,GAAG,2DAA2DE,EAAQ,MAAM,KAAK,GAC5G,EAIF,GAAI,CAACF,EAAO,cACV,MAAO,CACL,QAAS,GACT,MAAO,WAAWA,EAAO,GAAG,gIAC9B,EAIF,IAAII,EACJ,GAAI,CACF,EAAS,MAAMJ,EAAO,cAAc,CAClC,MAAOE,EAAQ,MACf,YAAaA,EAAQ,YACrB,aAAcF,EAAO,aACrB,UAAWE,EAAQ,SACrB,CAAC,CACH,OAASG,EAAO,CACd,IAAMC,EAAUD,aAAiB,MAAQA,EAAM,QAAU,OAAOA,CAAK,EACrE,MAAO,CACL,QAAS,GACT,MAAO,WAAWL,EAAO,GAAG,2CAA2CE,EAAQ,MAAM,KAAK,KAAKI,GACjG,CACF,CAGA,GAAIF,EAAO,QAAU,OAAO,KAAKA,EAAO,MAAM,CAAC,CAAC,OAAS,EAAG,CAE1D,IAAMG,EAAaC,EACjBR,EAAO,WACP,WAAWA,EAAO,GAAG,qBACvB,EACA,IAAK,GAAM,CAACS,EAAMC,KAAU,OAAO,QAAQN,EAAO,MAAM,EACtD,KAAK,gBAAgB,KAAK,CACxB,SAAUF,EAAQ,SAClB,iBAAkBK,EAClB,gBAAiBL,EAAQ,MAAM,KAC/B,OACA,QACA,UAAWA,EAAQ,UACnB,aAAcF,EAAO,YACvB,CAAC,CAEL,CAGA,GAAII,EAAO,WAAaA,EAAO,UAAU,OAAS,EAChD,IAAK,IAAMO,KAAYP,EAAO,UAC5B,KAAK,mBAAmB,KAAK,CAC3B,WACA,SAAUF,EAAQ,SAClB,UAAWA,EAAQ,UACnB,gBAAiBA,EAAQ,MAAM,IACjC,CAAC,EAIL,MAAO,CAAE,QAAS,GAAM,QAAO,CACjC,CAQA,MAAM,wBACJ,EACuF,CACvF,IAAMU,EACJ,CAAC,EAEH,IAAK,GAAM,CAACC,EAAUb,KAAW,KAAK,QAAS,CAE7C,GAAI,CAACA,EAAO,kBACV,SAIF,IAAMc,EAASd,EAAO,aAGhBE,EAAyC,CAC7C,aAAcY,EACd,WACF,EAEIV,EACJ,GAAI,CACF,EAAS,MAAMJ,EAAO,kBAAkBE,CAAO,CACjD,OAASG,EAAO,CACd,IAAMC,EAAUD,aAAiB,MAAQA,EAAM,QAAU,OAAOA,CAAK,EACrEO,EAAQ,KAAK,CACX,WACA,SACA,OAAQ,CACN,QAAS,GACT,MAAO,WAAWZ,EAAO,GAAG,oDAAoDe,EAAU,KAAKT,GACjG,CACF,CAAC,EACD,QACF,CAGA,GAAIF,EAAO,WAAaA,EAAO,UAAU,OAAS,EAChD,IAAK,IAAMO,KAAYP,EAAO,UAAW,CACvC,IAAMY,EAAc,GAAGH,EAAS,GAAGF,EAAS,OACxC,KAAK,+BAA+B,IAAIK,CAAW,IAGvD,KAAK,+BAA+B,IAAIA,CAAW,EACnD,KAAK,mBAAmB,KAAK,CAC3B,WACA,WACA,WACF,CAAC,EACH,CAIF,GAAIZ,EAAO,QAAU,OAAO,KAAKA,EAAO,MAAM,CAAC,CAAC,OAAS,EAAG,CAE1D,IAAMG,EAAaC,EACjBR,EAAO,WACP,WAAWA,EAAO,GAAG,qBACvB,EACA,IAAK,GAAM,CAACS,EAAMC,KAAU,OAAO,QAAQN,EAAO,MAAM,EAAG,CACzD,IAAMa,EAAW,GAAGJ,EAAS,GAAGJ,EAAK,GAAGS,EAAsBR,CAAK,GAAK,KACpE,KAAK,4BAA4B,IAAIO,CAAQ,IAGjD,KAAK,4BAA4B,IAAIA,CAAQ,EAC7C,KAAK,gBAAgB,KAAK,CACxB,WACA,iBAAkBV,EAClB,gBAAiB,cACjB,OACA,QACA,YACA,aAAcP,EAAO,YACvB,CAAC,EACH,CACF,CAEAY,EAAQ,KAAK,CACX,WACA,SACA,OAAQ,CAAE,QAAS,GAAM,QAAO,CAClC,CAAC,CACH,CAEA,OAAOA,CACT,CASA,MAAM,2BACJ,EAC2C,CAC3C,GAAM,CAAE,WAAU,cAAa,aAAcO,EAGzCC,EAAgCC,EAChCC,EACEC,EAAsD,CAAC,EACvDC,EAAmC,CAAC,EAE1C,IAAK,IAAMC,KAAcC,EAAa,CACpC,IAAMC,EAAS,MAAM,KAAK,kBAAkB,CAC1C,MAAOP,EACP,YAAaK,EAAW,OACxB,YACA,SAAUA,EAAW,QACvB,CAAC,EACD,GAAI,CAACE,EAAO,QACV,MAAU,MAAMA,EAAO,KAAK,EAG9B,IAAMvB,EAASuB,EAAO,OAChBC,EAAexB,EAAO,SAAS,OACjCwB,GAAgB,OAAO,KAAKA,CAAY,CAAC,CAAC,OAAS,IACrD,EAAe,KAAK,YAAY,CAC9B,cAAeR,EACf,eACA,SAAUK,EAAW,QACvB,CAAC,EACD,EAAgBL,EAChBI,EAAO,KAAK,CACV,KAAM,WACN,UAAWJ,EAAa,KACxB,WAAY,OAAO,KAAKQ,CAAY,CAAC,CAAC,OACtC,SAAUH,EAAW,QACvB,CAAC,GAGH,IAAMzB,EAAS,KAAK,UAAUyB,EAAW,QAAQ,EACjD,IAAK,GAAM,CAAChB,EAAMC,KAAU,OAAO,QAAQN,EAAO,QAAU,CAAC,CAAC,EAAG,CAC/D,IAAMyB,EAAYX,EAAsBR,CAAK,GAAK,GAClDa,EAAgB,KAAK,CACnB,YACA,QACA,OACA,SAAUE,EAAW,SACrB,iBAAkB,KAAK,oBAAoBA,EAAW,QAAQ,GAAK,GACnE,aAAczB,GAAQ,YACxB,CAAC,EACDwB,EAAO,KAAK,CAAE,KAAM,YAAa,YAAW,SAAUC,EAAW,QAAS,CAAC,CAC7E,CACF,CAEA,MAAO,CAAE,gBAAe,kBAAiB,QAAO,CAClD,CAMA,uBAAkC,CAChC,OAAO,MAAM,KAAK,KAAK,QAAQ,QAAQ,CAAC,CAAC,CACtC,QAAQ,EAAGzB,KAAYA,EAAO,oBAAsB,IAAA,EAAS,CAAC,CAC9D,KAAK,CAAC8B,KAAQA,CAAE,CACrB,CAMA,IAAI,aAAsB,CACxB,OAAO,KAAK,QAAQ,IACtB,CAOA,UAAU,EAAsC,CAC9C,OAAO,KAAK,QAAQ,IAAIjB,CAAQ,CAClC,CAOA,oBAAoB,EAAsC,CACxD,OAAO,KAAK,QAAQ,IAAIA,CAAQ,CAAC,EAAE,UACrC,CAMA,6BAAiE,CAC/D,OAAO,KAAK,kBACd,CAMA,2CAAuF,CACrF,OAAO,KAAK,mBAAmB,IAAK,IAAU,CAC5C,GAAGkB,EACH,iBAAkB,KAAK,oBAAoBA,EAAK,QAAQ,GAAK,EAC/D,EAAE,CACJ,CAMA,0BAAoE,CAClE,OAAO,KAAK,eACd,CAOA,wCAAwC,EAAsD,CAC5F,OAAO,KAAK,mBAAmB,OAAQ,GAASA,EAAK,YAAchB,CAAS,CAC9E,CAMA,+BAA0C,CACxC,OAAO,MAAM,KAAK,KAAK,QAAQ,OAAO,CAAC,CAAC,CAAC,OAAQ,GAAWiB,EAAmBhC,CAAM,CAAC,CACxF,CAOA,gCAAgC,EAAuC,CACrE,IAAMA,EAAS,KAAK,QAAQ,IAAIa,CAAQ,EAExC,OADKb,EACED,EAAgCC,CAAM,kBADzB,IAAI,GAE1B,CAOA,oBAAoB,EAA6C,CAC/D,GAAM,CAAE,YAAW,qBAAoB,aAAY,iBAAgB,qBAAsBmB,EAGnFc,EAAwBC,EAAe,KAAK,gBAAiBC,CAAS,EAGtEC,EAAkB,KAAK,0CAA0C,EASvE,MARA,MAAK,oBAAsBC,EACzBD,EACAD,EACAF,EACAK,EACAC,CACF,EAEO,KAAK,mBACd,CAQA,YAAY,EAA4C,CACtD,GAAM,CAAE,gBAAe,eAAc,YAAapB,EAC5CqB,EAAqB,OAAO,KAAKC,EAAc,MAAM,EACrDC,EAAoB,OAAO,KAAKD,EAAc,SAAS,KAAK,EAC5DE,EAAgB,OAAO,KAAKf,CAAY,EACxCgB,EAAkBD,EAAc,OAAQ,GAASH,EAAmB,SAASK,CAAI,CAAC,EAClFC,EAAiBH,EAAc,OAAQ,GAASD,EAAkB,SAASG,CAAI,CAAC,EAEtF,GAAID,EAAgB,OAAS,EAC3B,MAAU,MACR,WAAW/B,EAAS,yDAAyD4B,EAAc,KAAK,KAAKG,EAAgB,KAAK,IAAI,EAAE,iDAElI,EAGF,GAAIE,EAAe,OAAS,EAC1B,MAAU,MACR,WAAWjC,EAAS,gGAAgG4B,EAAc,KAAK,KAAKK,EAAe,KAAK,IAAI,EAAE,EACxK,EAQF,GAAM,CAAE,GAAIC,EAAK,GAAGC,GAAoB,CAJtC,GAAGP,EAAc,OACjB,GAAGb,CAG8C,EAC7CqB,EAAaR,EAAc,SAAS,UAAU,WAC9CZ,EAAYoB,EACb,CAACR,EAAc,KAAMQ,CAAU,EAChCR,EAAc,KAElB,OAAO,4BAA4BA,EADb3C,EAAG,MAAM+B,EAAWmB,CACoB,CAAC,CACjE,CACF,EAgEA,SAAS,4BACP,EACA,EACiB,CACjB,IAAIrB,EAASuB,EAGTC,EAAS,eACX,EAASxB,EAAO,YAAYwB,EAAS,YAAY,GAInD,IAAMC,EAAWD,EAAS,SAM1B,GALI,OAAO,KAAKC,EAAS,KAAK,CAAC,CAAC,OAAS,IACvC,EAASzB,EAAO,MAAMyB,EAAS,KAAK,GAIlCA,EAAS,SAAU,CACrB,GAAM,CAAE,WAAYC,EAAa,GAAGC,GAAaF,EAAS,SACtD,OAAO,KAAKE,CAAQ,CAAC,CAAC,OAAS,IACjC,EAAS3B,EAAO,SACd2B,CACF,EAEJ,CAaA,GARIF,EAAS,YAAY,SACvB,EAASzB,EAAO,WAAWyB,EAAS,YAAY,MAA8B,GAE5EA,EAAS,YAAY,MACvB,EAASzB,EAAO,cAAcyB,EAAS,YAAY,GAA8B,GAI/EA,EAAS,SAAW,OAAO,KAAKA,EAAS,OAAO,CAAC,CAAC,OAAS,EAAG,CAChE,IAAMG,EAAY,OAAO,QAAQH,EAAS,OAAO,CAAC,CAAC,KAAK,CAACP,EAAMW,MAAU,CACvE,OAEA,OAAQA,EAAI,OACZ,OAAQA,EAAI,MACd,EAAE,EACF,EAAS7B,EAAO,QAAQ,GAAG4B,CAAS,CACtC,CAYA,GAVIH,EAAS,WACX,EAASzB,EAAO,MAAMyB,EAAS,QAAsD,GAEnFA,EAAS,eACX,EAASzB,EAAO,SACdyB,EAAS,YACX,GAIED,EAAS,QAAQ,OAAS,EAC5B,IAAK,IAAMnD,KAAUmD,EAAS,QAE5B,EAASxB,EAAO,OAAO,EACpB3B,EAAO,UAAWA,EAAO,MAC5B,CAAC,EAIL,OAAO2B,CACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"multiline-EyzjEwn9.mjs","names":[],"sources":["../src/utils/multiline.ts"],"sourcesContent":["/**\n * Tag function which strips the common leading indent from a multi-line\n * template literal and trims surrounding blank lines, while indenting each\n * line of interpolated values to match the placeholder's indent.\n *\n * Mirrors the behaviour of the `multiline-ts` package, which we used to\n * depend on. We replaced it with this in-tree implementation because the\n * upstream package ships a `preinstall: npx only-allow pnpm` hook that\n * makes `npx create-tailor-sdk@latest` (and any other npm-based install\n * path that resolves a fresh copy) abort with `ECOMPROMISED`.\n * @param value - Template strings array, or a plain string for non-tagged usage\n * @param inputs - Interpolated values\n * @returns The dedented and trimmed string\n */\nexport default function multiline(\n value: TemplateStringsArray | string,\n ...inputs: string[]\n): string {\n const strings = typeof value === \"string\" ? value.split(/(?=\\r\\n|\\r|\\n)/) : Array.from(value);\n\n let currentIndent = \"\";\n const joined = strings\n .map((segment, i) => {\n if (/\\r\\n|\\r|\\n/.test(segment)) {\n currentIndent = getFinalIndent(segment) || currentIndent;\n }\n const input = inputs[i] ?? \"\";\n return segment + input.replace(/\\r\\n|\\r|\\n/g, `\\n${currentIndent}`);\n })\n .join(\"\");\n\n const lines = joined.split(/\\r\\n|\\r|\\n/);\n const indents = lines.filter((line) => /[^ \\t]/.test(line)).map((line) => getIndent(line).length);\n const minIndent = indents.length === 0 ? 0 : Math.min(...indents);\n return lines\n .map((line) => line.slice(minIndent))\n .join(\"\\n\")\n .replace(/^\\n|\\n[ \\t]*$/g, \"\");\n}\n\nfunction getIndent(line: string): string {\n const match = line.match(/^[ \\t]+/);\n return match ? match[0] : \"\";\n}\n\nfunction getFinalIndent(value: string): string {\n const match = value.match(/(?<=(\\r\\n|\\r|\\n))[ \\t]+$/);\n return match ? match[0] : \"\";\n}\n"],"mappings":"AAcA,SAAwB,UACtB,EACA,GAAG,EACK,CACR,IAAM,EAAU,OAAO,GAAU,SAAW,EAAM,MAAM,gBAAgB,EAAI,MAAM,KAAK,CAAK,EAExF,EAAgB,GAWd,EAVS,EACZ,KAAK,EAAS,KACT,aAAa,KAAK,CAAO,IAC3B,EAAgB,eAAe,CAAO,GAAK,GAGtC,GADO,EAAO,IAAM,GAAA,CACJ,QAAQ,cAAe,KAAK,GAAe,EACnE,CAAC,CACD,KAAK,EAEW,CAAC,CAAC,MAAM,YAAY,EACjC,EAAU,EAAM,OAAQ,GAAS,SAAS,KAAK,CAAI,CAAC,CAAC,CAAC,IAAK,GAAS,UAAU,CAAI,CAAC,CAAC,MAAM,EAC1F,EAAY,EAAQ,SAAW,EAAI,EAAI,KAAK,IAAI,GAAG,CAAO,EAChE,OAAO,EACJ,IAAK,GAAS,EAAK,MAAM,CAAS,CAAC,CAAC,CACpC,KAAK;CAAI,CAAC,CACV,QAAQ,iBAAkB,EAAE,CACjC,CAEA,SAAS,UAAU,EAAsB,CACvC,IAAM,EAAQ,EAAK,MAAM,SAAS,EAClC,OAAO,EAAQ,EAAM,GAAK,EAC5B,CAEA,SAAS,eAAe,EAAuB,CAC7C,IAAM,EAAQ,EAAM,MAAM,0BAA0B,EACpD,OAAO,EAAQ,EAAM,GAAK,EAC5B"}
1
+ {"version":3,"file":"multiline-EyzjEwn9.mjs","names":["inputs","strings","value","currentIndent","lines","segment","i","indents","line","minIndent","match"],"sources":["../src/utils/multiline.ts"],"sourcesContent":["/**\n * Tag function which strips the common leading indent from a multi-line\n * template literal and trims surrounding blank lines, while indenting each\n * line of interpolated values to match the placeholder's indent.\n *\n * Mirrors the behaviour of the `multiline-ts` package, which we used to\n * depend on. We replaced it with this in-tree implementation because the\n * upstream package ships a `preinstall: npx only-allow pnpm` hook that\n * makes `npx create-tailor-sdk@latest` (and any other npm-based install\n * path that resolves a fresh copy) abort with `ECOMPROMISED`.\n * @param value - Template strings array, or a plain string for non-tagged usage\n * @param inputs - Interpolated values\n * @returns The dedented and trimmed string\n */\nexport default function multiline(\n value: TemplateStringsArray | string,\n ...inputs: string[]\n): string {\n const strings = typeof value === \"string\" ? value.split(/(?=\\r\\n|\\r|\\n)/) : Array.from(value);\n\n let currentIndent = \"\";\n const joined = strings\n .map((segment, i) => {\n if (/\\r\\n|\\r|\\n/.test(segment)) {\n currentIndent = getFinalIndent(segment) || currentIndent;\n }\n const input = inputs[i] ?? \"\";\n return segment + input.replace(/\\r\\n|\\r|\\n/g, `\\n${currentIndent}`);\n })\n .join(\"\");\n\n const lines = joined.split(/\\r\\n|\\r|\\n/);\n const indents = lines.filter((line) => /[^ \\t]/.test(line)).map((line) => getIndent(line).length);\n const minIndent = indents.length === 0 ? 0 : Math.min(...indents);\n return lines\n .map((line) => line.slice(minIndent))\n .join(\"\\n\")\n .replace(/^\\n|\\n[ \\t]*$/g, \"\");\n}\n\nfunction getIndent(line: string): string {\n const match = line.match(/^[ \\t]+/);\n return match ? match[0] : \"\";\n}\n\nfunction getFinalIndent(value: string): string {\n const match = value.match(/(?<=(\\r\\n|\\r|\\n))[ \\t]+$/);\n return match ? match[0] : \"\";\n}\n"],"mappings":"AAcA,SAAwB,UACtB,EACA,GAAGA,EACK,CACR,IAAMC,EAAU,OAAOC,GAAU,SAAWA,EAAM,MAAM,gBAAgB,EAAI,MAAM,KAAKA,CAAK,EAExFC,EAAgB,GAWdC,EAVSH,EACZ,KAAK,EAAS,KACT,aAAa,KAAKI,CAAO,IAC3B,EAAgB,eAAeA,CAAO,GAAKF,GAGtCE,GADOL,EAAOM,IAAM,GAAA,CACJ,QAAQ,cAAe,KAAKH,GAAe,EACnE,CAAC,CACD,KAAK,EAEW,CAAC,CAAC,MAAM,YAAY,EACjCI,EAAUH,EAAM,OAAQ,GAAS,SAAS,KAAKI,CAAI,CAAC,CAAC,CAAC,IAAK,GAAS,UAAUA,CAAI,CAAC,CAAC,MAAM,EAC1FC,EAAYF,EAAQ,SAAW,EAAI,EAAI,KAAK,IAAI,GAAGA,CAAO,EAChE,OAAOH,EACJ,IAAK,GAASI,EAAK,MAAMC,CAAS,CAAC,CAAC,CACpC,KAAK;CAAI,CAAC,CACV,QAAQ,iBAAkB,EAAE,CACjC,CAEA,SAAS,UAAU,EAAsB,CACvC,IAAMC,EAAQF,EAAK,MAAM,SAAS,EAClC,OAAOE,EAAQA,EAAM,GAAK,EAC5B,CAEA,SAAS,eAAe,EAAuB,CAC7C,IAAMA,EAAQR,EAAM,MAAM,0BAA0B,EACpD,OAAOQ,EAAQA,EAAM,GAAK,EAC5B"}
@@ -1 +1 @@
1
- {"version":3,"file":"node-builtins-DYfhPBnz.mjs","names":[],"sources":["../../shared/src/node-builtins.ts"],"sourcesContent":["import { isBuiltin } from \"node:module\";\n\n/**\n * Node-only ambient globals that the Tailor Platform runtime never defines.\n * The SDK derives the same set from the `globals` package at runtime and pins\n * it to this list in its tests, so the lint plugin can ship the names without\n * depending on `globals`.\n */\nexport const NODE_ONLY_GLOBAL_NAMES: readonly string[] = [\n \"__dirname\",\n \"__filename\",\n \"Buffer\",\n \"clearImmediate\",\n \"exports\",\n \"global\",\n \"module\",\n \"process\",\n \"require\",\n \"setImmediate\",\n];\n\nconst SUGGESTIONS: Record<string, string> = {\n crypto: \"Use the Web Crypto API (globalThis.crypto) instead.\",\n buffer: \"Use Uint8Array or ArrayBuffer instead.\",\n fs: \"File system access is not available in the Tailor Platform runtime.\",\n \"fs/promises\": \"File system access is not available in the Tailor Platform runtime.\",\n path: \"Use URL or URLPattern for path manipulation.\",\n http: \"Use the Fetch API (globalThis.fetch) for HTTP requests instead.\",\n https: \"Use the Fetch API (globalThis.fetch) for HTTPS requests instead.\",\n url: \"Use the URL and URLSearchParams Web APIs instead.\",\n util: \"Use Web Standard APIs instead.\",\n stream: \"Use Web Streams API (ReadableStream, WritableStream, TransformStream) instead.\",\n \"stream/web\": \"Use Web Streams API (ReadableStream, WritableStream, TransformStream) instead.\",\n events: \"Use EventTarget instead.\",\n zlib: \"Use CompressionStream and DecompressionStream Web APIs instead.\",\n querystring: \"Use URLSearchParams instead.\",\n string_decoder: \"Use TextDecoder instead.\",\n};\n\n// Friendly suggestions for the most common members of NODE_ONLY_GLOBAL_NAMES.\n// A name without an entry here still gets flagged, just with the generic\n// message below instead of a targeted one.\nconst GLOBAL_SUGGESTIONS: Record<string, string> = {\n process:\n \"Use `defineConfig({ env })` and the `env` argument passed into the body function instead.\",\n Buffer: \"Use Uint8Array or ArrayBuffer instead.\",\n global: \"Use globalThis instead.\",\n __dirname: \"File system paths are not available in the Tailor Platform runtime.\",\n __filename: \"File system paths are not available in the Tailor Platform runtime.\",\n require: \"Use a static `import` instead.\",\n module: \"CommonJS module semantics are not available in the Tailor Platform runtime.\",\n exports: \"CommonJS module semantics are not available in the Tailor Platform runtime.\",\n setImmediate: \"Use setTimeout instead.\",\n clearImmediate: \"Use clearTimeout instead.\",\n};\n\nexport function describeUnavailable(name: string): string {\n return `\"${name}\" is not available in the Tailor Platform runtime.`;\n}\n\nfunction withSuggestion(name: string, suggestion: string | undefined): string {\n const base = describeUnavailable(name);\n return suggestion ? `${base} ${suggestion}` : base;\n}\n\nexport function isNodeBuiltinImport(specifier: string): boolean {\n return isBuiltin(specifier);\n}\n\nexport function getNodeBuiltinMessage(specifier: string): string {\n const bare = specifier.startsWith(\"node:\") ? specifier.slice(5) : specifier;\n return withSuggestion(specifier, SUGGESTIONS[bare]);\n}\n\nexport function getForbiddenGlobalMessage(name: string): string {\n return withSuggestion(\n name,\n Object.hasOwn(GLOBAL_SUGGESTIONS, name) ? GLOBAL_SUGGESTIONS[name] : undefined,\n );\n}\n"],"mappings":"wCAqBA,MAAM,EAAsC,CAC1C,OAAQ,sDACR,OAAQ,yCACR,GAAI,sEACJ,cAAe,sEACf,KAAM,+CACN,KAAM,kEACN,MAAO,mEACP,IAAK,oDACL,KAAM,iCACN,OAAQ,iFACR,aAAc,iFACd,OAAQ,2BACR,KAAM,kEACN,YAAa,+BACb,eAAgB,0BAClB,EAKM,EAA6C,CACjD,QACE,4FACF,OAAQ,yCACR,OAAQ,0BACR,UAAW,sEACX,WAAY,sEACZ,QAAS,iCACT,OAAQ,8EACR,QAAS,8EACT,aAAc,0BACd,eAAgB,2BAClB,EAEA,SAAgB,oBAAoB,EAAsB,CACxD,MAAO,IAAI,EAAK,mDAClB,CAEA,SAAS,eAAe,EAAc,EAAwC,CAC5E,IAAM,EAAO,oBAAoB,CAAI,EACrC,OAAO,EAAa,GAAG,EAAK,GAAG,IAAe,CAChD,CAEA,SAAgB,oBAAoB,EAA4B,CAC9D,OAAO,EAAU,CAAS,CAC5B,CAEA,SAAgB,sBAAsB,EAA2B,CAC/D,IAAM,EAAO,EAAU,WAAW,OAAO,EAAI,EAAU,MAAM,CAAC,EAAI,EAClE,OAAO,eAAe,EAAW,EAAY,EAAK,CACpD,CAEA,SAAgB,0BAA0B,EAAsB,CAC9D,OAAO,eACL,EACA,OAAO,OAAO,EAAoB,CAAI,EAAI,EAAmB,GAAQ,IAAA,EACvE,CACF"}
1
+ {"version":3,"file":"node-builtins-DYfhPBnz.mjs","names":["SUGGESTIONS","GLOBAL_SUGGESTIONS","name","base","suggestion","isBuiltin","specifier","bare"],"sources":["../../shared/src/node-builtins.ts"],"sourcesContent":["import { isBuiltin } from \"node:module\";\n\n/**\n * Node-only ambient globals that the Tailor Platform runtime never defines.\n * The SDK derives the same set from the `globals` package at runtime and pins\n * it to this list in its tests, so the lint plugin can ship the names without\n * depending on `globals`.\n */\nexport const NODE_ONLY_GLOBAL_NAMES: readonly string[] = [\n \"__dirname\",\n \"__filename\",\n \"Buffer\",\n \"clearImmediate\",\n \"exports\",\n \"global\",\n \"module\",\n \"process\",\n \"require\",\n \"setImmediate\",\n];\n\nconst SUGGESTIONS: Record<string, string> = {\n crypto: \"Use the Web Crypto API (globalThis.crypto) instead.\",\n buffer: \"Use Uint8Array or ArrayBuffer instead.\",\n fs: \"File system access is not available in the Tailor Platform runtime.\",\n \"fs/promises\": \"File system access is not available in the Tailor Platform runtime.\",\n path: \"Use URL or URLPattern for path manipulation.\",\n http: \"Use the Fetch API (globalThis.fetch) for HTTP requests instead.\",\n https: \"Use the Fetch API (globalThis.fetch) for HTTPS requests instead.\",\n url: \"Use the URL and URLSearchParams Web APIs instead.\",\n util: \"Use Web Standard APIs instead.\",\n stream: \"Use Web Streams API (ReadableStream, WritableStream, TransformStream) instead.\",\n \"stream/web\": \"Use Web Streams API (ReadableStream, WritableStream, TransformStream) instead.\",\n events: \"Use EventTarget instead.\",\n zlib: \"Use CompressionStream and DecompressionStream Web APIs instead.\",\n querystring: \"Use URLSearchParams instead.\",\n string_decoder: \"Use TextDecoder instead.\",\n};\n\n// Friendly suggestions for the most common members of NODE_ONLY_GLOBAL_NAMES.\n// A name without an entry here still gets flagged, just with the generic\n// message below instead of a targeted one.\nconst GLOBAL_SUGGESTIONS: Record<string, string> = {\n process:\n \"Use `defineConfig({ env })` and the `env` argument passed into the body function instead.\",\n Buffer: \"Use Uint8Array or ArrayBuffer instead.\",\n global: \"Use globalThis instead.\",\n __dirname: \"File system paths are not available in the Tailor Platform runtime.\",\n __filename: \"File system paths are not available in the Tailor Platform runtime.\",\n require: \"Use a static `import` instead.\",\n module: \"CommonJS module semantics are not available in the Tailor Platform runtime.\",\n exports: \"CommonJS module semantics are not available in the Tailor Platform runtime.\",\n setImmediate: \"Use setTimeout instead.\",\n clearImmediate: \"Use clearTimeout instead.\",\n};\n\nexport function describeUnavailable(name: string): string {\n return `\"${name}\" is not available in the Tailor Platform runtime.`;\n}\n\nfunction withSuggestion(name: string, suggestion: string | undefined): string {\n const base = describeUnavailable(name);\n return suggestion ? `${base} ${suggestion}` : base;\n}\n\nexport function isNodeBuiltinImport(specifier: string): boolean {\n return isBuiltin(specifier);\n}\n\nexport function getNodeBuiltinMessage(specifier: string): string {\n const bare = specifier.startsWith(\"node:\") ? specifier.slice(5) : specifier;\n return withSuggestion(specifier, SUGGESTIONS[bare]);\n}\n\nexport function getForbiddenGlobalMessage(name: string): string {\n return withSuggestion(\n name,\n Object.hasOwn(GLOBAL_SUGGESTIONS, name) ? GLOBAL_SUGGESTIONS[name] : undefined,\n );\n}\n"],"mappings":"wCAqBA,MAAMA,EAAsC,CAC1C,OAAQ,sDACR,OAAQ,yCACR,GAAI,sEACJ,cAAe,sEACf,KAAM,+CACN,KAAM,kEACN,MAAO,mEACP,IAAK,oDACL,KAAM,iCACN,OAAQ,iFACR,aAAc,iFACd,OAAQ,2BACR,KAAM,kEACN,YAAa,+BACb,eAAgB,0BAClB,EAKMC,EAA6C,CACjD,QACE,4FACF,OAAQ,yCACR,OAAQ,0BACR,UAAW,sEACX,WAAY,sEACZ,QAAS,iCACT,OAAQ,8EACR,QAAS,8EACT,aAAc,0BACd,eAAgB,2BAClB,EAEA,SAAgB,oBAAoB,EAAsB,CACxD,MAAO,IAAIC,EAAK,mDAClB,CAEA,SAAS,eAAe,EAAc,EAAwC,CAC5E,IAAMC,EAAO,oBAAoBD,CAAI,EACrC,OAAOE,EAAa,GAAGD,EAAK,GAAGC,IAAeD,CAChD,CAEA,SAAgB,oBAAoB,EAA4B,CAC9D,OAAOE,EAAUC,CAAS,CAC5B,CAEA,SAAgB,sBAAsB,EAA2B,CAC/D,IAAMC,EAAOD,EAAU,WAAW,OAAO,EAAIA,EAAU,MAAM,CAAC,EAAIA,EAClE,OAAO,eAAeA,EAAWN,EAAYO,EAAK,CACpD,CAEA,SAAgB,0BAA0B,EAAsB,CAC9D,OAAO,eACLL,EACA,OAAO,OAAOD,EAAoBC,CAAI,EAAID,EAAmBC,GAAQ,IAAA,EACvE,CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"package-json-C690ceex.mjs","names":[],"sources":["../src/cli/shared/package-json.ts"],"sourcesContent":["import { readPackageJSON, type PackageJson } from \"pkg-types\";\n\nlet packageJson: PackageJson | null = null;\n\n/**\n * Read and cache the package.json of the SDK package.\n * @returns Parsed package.json contents\n */\nexport async function readPackageJson() {\n if (packageJson) {\n return packageJson;\n }\n packageJson = await readPackageJSON(import.meta.url);\n return packageJson;\n}\n"],"mappings":"4CAEA,IAAI,EAAkC,KAMtC,eAAsB,iBAAkB,CAKtC,OAJI,IAGJ,EAAc,MAAM,EAAgB,YAAY,GAAG,EAC5C,EACT"}
1
+ {"version":3,"file":"package-json-C690ceex.mjs","names":["packageJson","readPackageJSON"],"sources":["../src/cli/shared/package-json.ts"],"sourcesContent":["import { readPackageJSON, type PackageJson } from \"pkg-types\";\n\nlet packageJson: PackageJson | null = null;\n\n/**\n * Read and cache the package.json of the SDK package.\n * @returns Parsed package.json contents\n */\nexport async function readPackageJson() {\n if (packageJson) {\n return packageJson;\n }\n packageJson = await readPackageJSON(import.meta.url);\n return packageJson;\n}\n"],"mappings":"4CAEA,IAAIA,EAAkC,KAMtC,eAAsB,iBAAkB,CAKtC,OAJIA,IAGJ,EAAc,MAAMC,EAAgB,YAAY,GAAG,EAC5CD,EACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"platform-serialize-DkiTdHOt.mjs","names":[],"sources":["../src/utils/test/platform-serialize.ts"],"sourcesContent":["/**\n * Validate and serialize a value as it would cross the Platform JSON boundary.\n *\n * Mirrors the runtime checks the platform performs on workflow arguments,\n * wait payloads, and trigger inputs so that local tests fail in the same\n * places production fails.\n *\n * Throws on:\n * - `NaN` / `Infinity` / `-Infinity` (`JSON.stringify` would silently emit `null`)\n * - `BigInt` (TypeError is thrown by `JSON.stringify`; we emit a clearer message)\n * - Non-plain objects (class instances, including `Date`, `Map`, `Set`, `Error`,\n * and user-defined DTOs whose prototype is not `Object.prototype`)\n *\n * The replacer reads `this[key]` so the check sees the original value before\n * any `toJSON` conversion (e.g. `Date.prototype.toJSON`).\n * @param value - Value to validate and round-trip\n * @returns The JSON-normalized value (undefined/function properties stripped, etc.)\n */\nexport function platformSerialize<T>(value: T): T {\n // Top-level undefined is allowed (jobs may take no input).\n if (value === undefined) return undefined as T;\n\n // Root function/symbol stringify to `undefined`; throw a specific message here.\n if (typeof value === \"function\") {\n throw new TypeError(\"platformSerialize: function is not JSON-serializable at <root>\");\n }\n if (typeof value === \"symbol\") {\n throw new TypeError(\"platformSerialize: Symbol is not JSON-serializable at <root>\");\n }\n\n const serialized = JSON.stringify(value, function (key, val) {\n if (typeof val === \"number\" && !Number.isFinite(val)) {\n throw new TypeError(\n `platformSerialize: non-finite number at ${formatPath(key)}: ${String(val)}`,\n );\n }\n if (typeof val === \"bigint\") {\n throw new TypeError(\n `platformSerialize: BigInt is not JSON-serializable at ${formatPath(key)}`,\n );\n }\n // Look at the pre-toJSON value so Date/Map/Set/etc. can be detected.\n const raw = (this as Record<string, unknown>)[key];\n if (raw !== null && typeof raw === \"object\" && !Array.isArray(raw)) {\n const proto = Object.getPrototypeOf(raw);\n if (proto !== Object.prototype && proto !== null) {\n const ctor = (raw as { constructor?: { name?: string } }).constructor?.name ?? \"anonymous\";\n throw new TypeError(\n `platformSerialize: non-plain object at ${formatPath(key)} (${ctor} instance)`,\n );\n }\n }\n return val;\n });\n\n // `JSON.stringify` returns `undefined` when the root collapses (e.g. a `toJSON`\n // returning `undefined`); parsing that would throw opaquely.\n // JSON.stringify returns undefined for non-serializable values\n // oxlint-disable-next-line typescript/no-unnecessary-condition\n if (serialized === undefined) {\n throw new TypeError(\"platformSerialize: value is not JSON-serializable at <root>\");\n }\n\n return JSON.parse(serialized) as T;\n}\n\nfunction formatPath(key: string): string {\n return key === \"\" ? \"<root>\" : `\"${key}\"`;\n}\n"],"mappings":"AAkBA,SAAgB,kBAAqB,EAAa,CAEhD,GAAI,IAAU,IAAA,GAAW,OAGzB,GAAI,OAAO,GAAU,WACnB,MAAU,UAAU,gEAAgE,EAEtF,GAAI,OAAO,GAAU,SACnB,MAAU,UAAU,8DAA8D,EAGpF,IAAM,EAAa,KAAK,UAAU,EAAO,SAAU,EAAK,EAAK,CAC3D,GAAI,OAAO,GAAQ,UAAY,CAAC,OAAO,SAAS,CAAG,EACjD,MAAU,UACR,2CAA2C,WAAW,CAAG,EAAE,IAAI,OAAO,CAAG,GAC3E,EAEF,GAAI,OAAO,GAAQ,SACjB,MAAU,UACR,yDAAyD,WAAW,CAAG,GACzE,EAGF,IAAM,EAAO,KAAiC,GAC9C,GAAoB,OAAO,GAAQ,UAA/B,GAA2C,CAAC,MAAM,QAAQ,CAAG,EAAG,CAClE,IAAM,EAAQ,OAAO,eAAe,CAAG,EACvC,GAAI,IAAU,OAAO,WAAa,IAAU,KAAM,CAChD,IAAM,EAAQ,EAA4C,aAAa,MAAQ,YAC/E,MAAU,UACR,0CAA0C,WAAW,CAAG,EAAE,IAAI,EAAK,WACrE,CACF,CACF,CACA,OAAO,CACT,CAAC,EAMD,GAAI,IAAe,IAAA,GACjB,MAAU,UAAU,6DAA6D,EAGnF,OAAO,KAAK,MAAM,CAAU,CAC9B,CAEA,SAAS,WAAW,EAAqB,CACvC,OAAO,IAAQ,GAAK,SAAW,IAAI,EAAI,EACzC"}
1
+ {"version":3,"file":"platform-serialize-DkiTdHOt.mjs","names":["value","serialized","val","key","raw","proto","ctor"],"sources":["../src/utils/test/platform-serialize.ts"],"sourcesContent":["/**\n * Validate and serialize a value as it would cross the Platform JSON boundary.\n *\n * Mirrors the runtime checks the platform performs on workflow arguments,\n * wait payloads, and trigger inputs so that local tests fail in the same\n * places production fails.\n *\n * Throws on:\n * - `NaN` / `Infinity` / `-Infinity` (`JSON.stringify` would silently emit `null`)\n * - `BigInt` (TypeError is thrown by `JSON.stringify`; we emit a clearer message)\n * - Non-plain objects (class instances, including `Date`, `Map`, `Set`, `Error`,\n * and user-defined DTOs whose prototype is not `Object.prototype`)\n *\n * The replacer reads `this[key]` so the check sees the original value before\n * any `toJSON` conversion (e.g. `Date.prototype.toJSON`).\n * @param value - Value to validate and round-trip\n * @returns The JSON-normalized value (undefined/function properties stripped, etc.)\n */\nexport function platformSerialize<T>(value: T): T {\n // Top-level undefined is allowed (jobs may take no input).\n if (value === undefined) return undefined as T;\n\n // Root function/symbol stringify to `undefined`; throw a specific message here.\n if (typeof value === \"function\") {\n throw new TypeError(\"platformSerialize: function is not JSON-serializable at <root>\");\n }\n if (typeof value === \"symbol\") {\n throw new TypeError(\"platformSerialize: Symbol is not JSON-serializable at <root>\");\n }\n\n const serialized = JSON.stringify(value, function (key, val) {\n if (typeof val === \"number\" && !Number.isFinite(val)) {\n throw new TypeError(\n `platformSerialize: non-finite number at ${formatPath(key)}: ${String(val)}`,\n );\n }\n if (typeof val === \"bigint\") {\n throw new TypeError(\n `platformSerialize: BigInt is not JSON-serializable at ${formatPath(key)}`,\n );\n }\n // Look at the pre-toJSON value so Date/Map/Set/etc. can be detected.\n const raw = (this as Record<string, unknown>)[key];\n if (raw !== null && typeof raw === \"object\" && !Array.isArray(raw)) {\n const proto = Object.getPrototypeOf(raw);\n if (proto !== Object.prototype && proto !== null) {\n const ctor = (raw as { constructor?: { name?: string } }).constructor?.name ?? \"anonymous\";\n throw new TypeError(\n `platformSerialize: non-plain object at ${formatPath(key)} (${ctor} instance)`,\n );\n }\n }\n return val;\n });\n\n // `JSON.stringify` returns `undefined` when the root collapses (e.g. a `toJSON`\n // returning `undefined`); parsing that would throw opaquely.\n // JSON.stringify returns undefined for non-serializable values\n // oxlint-disable-next-line typescript/no-unnecessary-condition\n if (serialized === undefined) {\n throw new TypeError(\"platformSerialize: value is not JSON-serializable at <root>\");\n }\n\n return JSON.parse(serialized) as T;\n}\n\nfunction formatPath(key: string): string {\n return key === \"\" ? \"<root>\" : `\"${key}\"`;\n}\n"],"mappings":"AAkBA,SAAgB,kBAAqB,EAAa,CAEhD,GAAIA,IAAU,IAAA,GAAW,OAGzB,GAAI,OAAOA,GAAU,WACnB,MAAU,UAAU,gEAAgE,EAEtF,GAAI,OAAOA,GAAU,SACnB,MAAU,UAAU,8DAA8D,EAGpF,IAAMC,EAAa,KAAK,UAAUD,EAAO,SAAU,EAAK,EAAK,CAC3D,GAAI,OAAOE,GAAQ,UAAY,CAAC,OAAO,SAASA,CAAG,EACjD,MAAU,UACR,2CAA2C,WAAWC,CAAG,EAAE,IAAI,OAAOD,CAAG,GAC3E,EAEF,GAAI,OAAOA,GAAQ,SACjB,MAAU,UACR,yDAAyD,WAAWC,CAAG,GACzE,EAGF,IAAMC,EAAO,KAAiCD,GAC9C,GAAoB,OAAOC,GAAQ,UAA/BA,GAA2C,CAAC,MAAM,QAAQA,CAAG,EAAG,CAClE,IAAMC,EAAQ,OAAO,eAAeD,CAAG,EACvC,GAAIC,IAAU,OAAO,WAAaA,IAAU,KAAM,CAChD,IAAMC,EAAQF,EAA4C,aAAa,MAAQ,YAC/E,MAAU,UACR,0CAA0C,WAAWD,CAAG,EAAE,IAAIG,EAAK,WACrE,CACF,CACF,CACA,OAAOJ,CACT,CAAC,EAMD,GAAID,IAAe,IAAA,GACjB,MAAU,UAAU,6DAA6D,EAGnF,OAAO,KAAK,MAAMA,CAAU,CAC9B,CAEA,SAAS,WAAW,EAAqB,CACvC,OAAOE,IAAQ,GAAK,SAAW,IAAIA,EAAI,EACzC"}