@tailor-platform/sdk 2.18.0 → 2.19.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 (53) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/{application-DEkgf2w1.mjs → application-BYlhYQyh.mjs} +2 -2
  3. package/dist/{application-DEkgf2w1.mjs.map → application-BYlhYQyh.mjs.map} +1 -1
  4. package/dist/application-KZRJHv2j.mjs +1 -0
  5. package/dist/cli/commands/deploy/event-subscriptions.d.mts +1 -0
  6. package/dist/cli/commands/generate/service.d.mts +1 -0
  7. package/dist/cli/lib.mjs +1 -1
  8. package/dist/cli/main.mjs +3 -3
  9. package/dist/cli/services/executor/service.d.mts +1 -0
  10. package/dist/completion/zsh-worker.zsh +1 -1
  11. package/dist/configure/index.d.mts +7 -7
  12. package/dist/configure/index.mjs +1 -1
  13. package/dist/configure/index.mjs.map +1 -1
  14. package/dist/configure/types/field.types.d.mts +24 -4
  15. package/dist/configure/types/type.d.mts +1 -0
  16. package/dist/date-B7-oyTGE.mjs +2 -0
  17. package/dist/date-B7-oyTGE.mjs.map +1 -0
  18. package/dist/field-parse-BbNyotv5.mjs +2 -0
  19. package/dist/field-parse-BbNyotv5.mjs.map +1 -0
  20. package/dist/{manager-C26Gi1bX.mjs → manager-qfbUL7ru.mjs} +2 -2
  21. package/dist/{manager-C26Gi1bX.mjs.map → manager-qfbUL7ru.mjs.map} +1 -1
  22. package/dist/parser/service/auth/schema.d.mts +1 -0
  23. package/dist/plugin/index.mjs +1 -1
  24. package/dist/{register-ts-hook-BD3ArLqY.mjs → register-ts-hook-Djjnj5R8.mjs} +3 -3
  25. package/dist/{register-ts-hook-BD3ArLqY.mjs.map → register-ts-hook-Djjnj5R8.mjs.map} +1 -1
  26. package/dist/runtime/date.d.mts +3 -3
  27. package/dist/runtime/field-parse.d.mts +1 -0
  28. package/dist/runtime/index.d.mts +2 -1
  29. package/dist/runtime/index.mjs +1 -1
  30. package/dist/runtime/temporal.d.mts +31 -0
  31. package/dist/{schema-DRyQEabV.mjs → schema-BKvcWdVf.mjs} +2 -2
  32. package/dist/{schema-DRyQEabV.mjs.map → schema-BKvcWdVf.mjs.map} +1 -1
  33. package/dist/service-BgrEteZ2.mjs +1 -0
  34. package/dist/service-CuqkHP1r.mjs +7 -0
  35. package/dist/service-CuqkHP1r.mjs.map +1 -0
  36. package/dist/types/field.generated.d.mts +1 -1
  37. package/dist/types/helpers.d.mts +8 -6
  38. package/dist/utils/test/index.mjs +1 -1
  39. package/dist/vitest/environment.mjs +1 -1
  40. package/dist/vitest/environment.mjs.map +1 -1
  41. package/docs/github-actions.md +22 -15
  42. package/docs/migration/v3.md +0 -33
  43. package/docs/services/resolver.md +53 -1
  44. package/docs/testing.md +17 -0
  45. package/package.json +5 -3
  46. package/dist/application-Dl94fzpm.mjs +0 -1
  47. package/dist/date-CGBZbMW5.mjs +0 -2
  48. package/dist/date-CGBZbMW5.mjs.map +0 -1
  49. package/dist/field-parse-CzlKC4b7.mjs +0 -2
  50. package/dist/field-parse-CzlKC4b7.mjs.map +0 -1
  51. package/dist/service-B3OiWCYg.mjs +0 -1
  52. package/dist/service-eM7Fd8zS.mjs +0 -7
  53. package/dist/service-eM7Fd8zS.mjs.map +0 -1
@@ -1,4 +1,4 @@
1
- import{t as e}from"./wait-point-registry-B-ESkTZX.mjs";import{$ as t,At as n,B as r,Bt as i,C as a,D as o,Dt as s,Et as c,Ft as l,G as u,Gt as d,I as f,J as p,Jt as m,K as h,Kt as g,L as _,Lt as v,M as y,Mt as b,N as x,Nt as S,O as C,Ot as w,P as ee,Pt as te,R as ne,Rt as re,S as ie,St as ae,Tt as oe,U as se,V as ce,W as le,Wt as ue,X as de,Xt as fe,Yt as pe,Z as me,Zt as he,_ as ge,_t as _e,a as ve,at as ye,b as be,bt as xe,ct as Se,d as Ce,dt as we,et as T,f as Te,ft as Ee,g as De,gt as Oe,h as E,ht as ke,i as Ae,in as je,it as Me,j as Ne,jt as Pe,k as Fe,kt as Ie,l as D,lt as Le,mt as Re,nn as ze,nt as Be,o as Ve,ot as He,p as Ue,pt as We,r as Ge,rn as Ke,rt as qe,s as Je,st as Ye,t as Xe,tn as Ze,tt as O,u as Qe,ut as $e,v as et,vt as tt,w as nt,wt as rt,x as it,xt as at,y as ot,yt as st,zt as ct}from"./workspace_resource_pb-BOoRts_z.mjs";import{t as k}from"./assert-WeXvmG4j.mjs";import{a as A,c as lt,i as j,n as M,o as ut,r as dt,s as ft,t as pt}from"./logger-72hM4JWZ.mjs";import{$ as mt,A as ht,B as gt,C as _t,D as vt,E as yt,G as bt,H as xt,J as St,K as Ct,L as wt,M as Tt,N as Et,O as Dt,Q as Ot,R as kt,S as At,T as jt,U as Mt,W as N,X as Nt,Y as Pt,Z as P,a as Ft,at as It,c as Lt,ct as Rt,et as F,f as zt,g as Bt,i as Vt,it as Ht,j as Ut,k as Wt,l as Gt,lt as Kt,n as qt,nt as Jt,ot as Yt,p as Xt,r as Zt,rt as Qt,s as $t,st as en,t as tn,tt as nn,u as rn,ut as an,v as on,w as sn,x as cn,y as ln,z as un}from"./application-DEkgf2w1.mjs";import{_ as dn,d as fn,g as pn,l as mn,t as hn,v as gn,x as _n,y as vn}from"./service-eM7Fd8zS.mjs";import{a as yn}from"./guards-ForsrxnH.mjs";import{t as I}from"./multiline-EyzjEwn9.mjs";import{t as bn}from"./package-json-C690ceex.mjs";import{t as xn}from"./user-agent-vdHYF3QL.mjs";import{a as L,c as Sn,o as Cn,r as wn,s as Tn,t as R}from"./errors-BjJnpXkK.mjs";import{n as En,r as Dn}from"./secret-file-C9wp_FCX.mjs";import{r as z}from"./telemetry-Bklv9kQY.mjs";import{t as On}from"./manager-C26Gi1bX.mjs";import{n as kn,r as An,t as jn}from"./tailordb-ddl-Fgm2cNvT.mjs";import{a as Mn,i as Nn,o as Pn,r as Fn,s as In,t as Ln}from"./seed-C3P_T_Eh.mjs";import*as Rn from"node:module";import{arg as B,createDefineCommand as zn,defineCommand as Bn,runCommand as Vn}from"@politty/zod";import*as V from"pathe";import{basename as Hn,dirname as Un,isAbsolute as Wn,join as Gn,relative as Kn,resolve as qn,sep as Jn}from"pathe";import{resolveTSConfig as Yn}from"pkg-types";import{z as H}from"zod";import{create as Xn,createRegistry as Zn,fromJson as Qn,toJson as $n}from"@bufbuild/protobuf";import*as U from"node:fs";import{mkdirSync as er,readFileSync as tr,realpathSync as nr,renameSync as rr,rmSync as ir,statSync as ar,utimesSync as or,writeFileSync as sr}from"node:fs";import{parseEnv as cr,stripVTControlCharacters as lr}from"node:util";import{ValueSchema as ur,timestampDate as W}from"@bufbuild/protobuf/wkt";import{formatDistanceToNowStrict as dr}from"date-fns";import{pathToFileURL as fr}from"node:url";import{parseYAML as pr,stringifyYAML as mr}from"confbox";import{findUpSync as hr}from"find-up-simple";import{lt as gr}from"semver";import{xdgConfig as _r}from"xdg-basedir";import{Code as G,ConnectError as K}from"@connectrpc/connect";import vr from"p-limit";import*as yr from"node:crypto";import{createHash as br,randomUUID as xr}from"node:crypto";import{ExitPromptError as Sr}from"@inquirer/core";import{confirm as Cr,input as wr,password as Tr,select as Er}from"@inquirer/prompts";import{isCI as Dr}from"std-env";import*as Or from"rolldown";import{parseSync as kr}from"oxc-parser";import*as Ar from"inflection";import{tmpdir as jr}from"node:os";import{pathToString as Mr,usedTypes as Nr}from"@bufbuild/protobuf/reflect";import{createValidator as Pr}from"@bufbuild/protovalidate";import*as q from"node:fs/promises";import{mkdir as Fr,readFile as Ir,rename as Lr,rm as Rr,writeFile as zr}from"node:fs/promises";import{setTimeout as Br}from"timers/promises";import{setTimeout as Vr}from"node:timers/promises";import{spawn as Hr}from"node:child_process";import*as Ur from"fs";import{lookup as Wr}from"mime-types";import{createPrompt as Gr}from"@toiroakr/read-multiline";import{astVisitor as Kr,parse as qr}from"pgsql-ast-parser";import{parse as Jr}from"@0no-co/graphql.web";const Yr={ms:1,s:1e3,m:6e4},Xr=/^(\d+)(ms|s|m)$/,Zr=H.string().refine(e=>Xr.test(e),{message:`Invalid duration format. Expected format: '3s', '500ms', '1m'`}).refine(e=>{let t=e.match(Xr);if(!t)return!1;let n=t[1];return n!==void 0&&parseInt(n,10)>0},{message:`Duration must be greater than 0`});function parseDuration(e){let t=k(e.match(Xr),`invalid duration format: ${e}`),n=parseInt(k(t[1],`duration digits group missing`),10),r=k(t[2],`duration unit group missing`);return n*Yr[r]}const Qr=H.coerce.number().int().positive(),$r=H.coerce.number().int().nonnegative(),ei=H.enum([`asc`,`desc`]);function toPageDirection(e){if(e!==void 0)return e===`asc`?je.ASC:je.DESC}function hasMachineUserFlag(e){return e.slice(0,e.indexOf(`--`)===-1?e.length:e.indexOf(`--`)).some(e=>e===`-m`||e.startsWith(`-m=`)||e===`--machine-user`||e.startsWith(`--machine-user=`)||e===`--machineUser`||e.startsWith(`--machineUser=`)||e===`--machineuser`||e.startsWith(`--machineuser=`))}function resolveMachineUserInputSource(e,t=process.argv.slice(2),n={}){if(e!==void 0)return n.valueIsExplicit||hasMachineUserFlag(t)?`option`:process.env.TAILOR_PLATFORM_MACHINE_USER_NAME===e?`env`:`option`}function loadEnvFiles(e,t){let n=new Set(Object.keys(process.env)),load=(e,t)=>{for(let r of[e??[]].flat()){let e=V.resolve(process.cwd(),r);if(!U.existsSync(e)){if(t)throw Error(`Environment file not found: ${e}`);continue}let i=U.readFileSync(e,`utf-8`),a=cr(i);for(let[e,t]of Object.entries(a))n.has(e)||(process.env[e]=t)}};load(e,!0),load(t,!1)}function createCommonArgs(e={}){return{"env-file":B(H.string().optional(),{alias:`e`,description:`Path to the environment file (error if not found)`,completion:{type:`file`,matcher:[`.env.*`,`.env`]}}),"env-file-if-exists":B(H.string().optional(),{description:`Path to the environment file (ignored if not found)`,completion:{type:`file`,matcher:[`.env.*`,`.env`]},effect:(e,{args:t})=>{loadEnvFiles(t[`env-file`],t[`env-file-if-exists`])}}),verbose:B(H.boolean().default(!1),{...e.verboseAlias===void 0?{}:{alias:e.verboseAlias},description:`Enable verbose logging`,effect:e=>{M.verbose=e}}),json:B(H.boolean().default(!1),{alias:`j`,description:`Output as JSON`,effect:e=>{M.jsonMode=e}})}}const ti=createCommonArgs(),J={"workspace-id":B(H.string().optional(),{alias:`w`,description:`Workspace ID`,env:`TAILOR_PLATFORM_WORKSPACE_ID`,completion:{type:`none`}}),profile:B(H.string().optional(),{alias:`p`,description:`Workspace profile`,env:`TAILOR_PLATFORM_PROFILE`,completion:{type:`none`}})},ni=`tailor.config.ts`;function formatConfigArg(e){if(!e)return;let t=V.relative(process.cwd(),e);if(t!==`tailor.config.ts`)return`--config=${t}`}function recoveryContextArgs(e){return[...e.workspaceId?[`--workspace-id=${e.workspaceId}`]:[],...e.profile?[`--profile=${e.profile}`]:[]]}const ri={config:B(H.string().default(ni),{alias:`c`,description:`Path to Tailor config file`,env:`TAILOR_CONFIG_PATH`,completion:{type:`file`,extensions:[`ts`]}})},ii={config:B(H.string().default(ni),{alias:`c`,description:`Path to SDK config file. Use comma-separated paths to deploy multiple apps together.`,env:`TAILOR_PLATFORM_SDK_CONFIG_PATH`,completion:{type:`file`,extensions:[`ts`]}})},ai={...J,...ri},oi={yes:B(H.boolean().default(!1),{alias:`y`,description:`Skip confirmation prompts`})},si={"organization-id":B(H.string(),{alias:`o`,description:`Organization ID`,env:`TAILOR_PLATFORM_ORGANIZATION_ID`,completion:{type:`none`}})},paginationArgs=(e=`desc`)=>({order:B(ei.default(e),{description:`Sort order (asc or desc)`}),limit:B($r.optional(),{alias:`l`,description:`Maximum number of items to return (0 or omit: unlimited)`})}),ci={order:B(ei.default(`desc`),{description:`Sort order (asc or desc)`}),limit:B($r.default(50),{alias:`l`,description:`Maximum number of items to return (0: unlimited)`})},li={"folder-id":B(H.string(),{alias:`f`,description:`Folder ID`,env:`TAILOR_PLATFORM_FOLDER_ID`,completion:{type:`none`}})},Y=zn();async function runDefaultSubCommand(e,t=[]){let n=await Vn(e,t);if(!n.success)throw n.error}const ui=H.union([H.string(),H.number(),H.boolean()]),di=H.union([H.string(),H.number()]),fi=H.union([ui,H.strictObject({value:di,allowSecretReason:H.string().min(1,{message:`'allowSecretReason' must state why the value is safe to keep in 'env'.`})})]),pi=H.enum(an),mi=/^[a-z][a-z0-9_-]{0,62}$/,hi=/^$|^[a-z][a-z0-9_-]{0,62}$/,gi=`sdk-`,_i=H.string().regex(hi,{message:`'metadata' values must match ${hi.source}.`}),vi=H.record(H.string(),_i).superRefine((e,t)=>{let n=Object.keys(e);n.length>17&&t.addIssue({code:`custom`,message:`'metadata' can hold at most 17 entries.`});for(let e of n)mi.test(e)?e.startsWith(gi)&&t.addIssue({code:`custom`,path:[e],message:`'metadata' keys starting with '${gi}' are reserved for the SDK.`}):t.addIssue({code:`custom`,path:[e],message:`'metadata' keys must match ${mi.source}.`})}),yi=H.string().refine(e=>pi.safeParse(e.trim().toUpperCase()).success,{message:`'logLevel' must be one of: ${an.join(`, `)}.`}),bi=H.strictObject({id:H.uuid({message:`'id' must be a UUID.`}).optional(),name:H.string().min(1,{message:`'name' must be a non-empty string.`}),env:H.record(H.string(),fi).optional(),cors:H.array(H.string()).optional(),allowedIpAddresses:H.array(H.string()).optional(),disableIntrospection:H.boolean().optional(),inlineSourcemap:H.boolean().optional(),logLevel:yi.optional(),metadata:vi.optional(),db:H.unknown().optional(),resolver:H.unknown().optional(),idp:H.unknown().optional(),auth:H.unknown().optional(),executor:H.unknown().optional(),workflow:H.unknown().optional(),httpAdapter:H.unknown().optional(),staticWebsites:H.unknown().optional(),aiGateways:H.unknown().optional(),secrets:H.unknown().optional()}),xi=H.looseObject({id:H.string(),description:H.string(),importPath:H.string().optional(),pluginConfig:H.unknown().optional(),tableConfigRequired:H.union([H.boolean(),_n]).optional(),onTableLoaded:_n.optional(),onNamespaceLoaded:_n.optional(),onTailorDBReady:_n.optional(),onResolverReady:_n.optional(),onExecutorReady:_n.optional()}).refine(e=>!(e.onTableLoaded||e.onNamespaceLoaded)||!!e.importPath,{message:`importPath is required when plugin has definition-time hooks (onTableLoaded/onNamespaceLoaded)`}).transform(e=>e),Si=`tailor-platform-cli`;let Ci;async function getEntryClass(){if(Ci!==void 0)return Ci;try{Ci=(await import(`@napi-rs/keyring`)).Entry}catch{M.warn(`System keyring is not available. Tokens will be stored in the config file. Set TAILOR_PLATFORM_TOKEN environment variable for CI environments.`),Ci=!1}return Ci}async function isKeyringAvailable(){return await getEntryClass()!==!1}async function loadKeyringTokens(e){let t=await getEntryClass();if(!t)throw Error(`System keyring is not available.`);let n=new t(Si,e).getPassword();if(n!==null)try{return JSON.parse(n)}catch{return}}async function saveKeyringTokens(e,t){let n=await getEntryClass();if(!n)throw Error(`System keyring is not available.`);new n(Si,e).setPassword(JSON.stringify(t))}async function deleteKeyringTokens(e){let t=await getEntryClass();if(t)try{new t(Si,e).deletePassword()}catch{}}const wi=H.object({user:H.string(),workspace_id:H.string(),readonly:H.boolean().optional(),machine_user:H.string().optional(),machine_user_override:H.enum([`allow`,`deny`]).optional(),platform_url:H.url().optional(),oauth2_client_id:H.string().optional(),console_url:H.url().optional()}),Ti=H.object({access_token:H.string(),refresh_token:H.string().optional(),token_expires_at:H.string()}),Ei=H.object({storage:H.literal(`keyring`),token_expires_at:H.string()}),Di=H.object({storage:H.literal(`file`),token_expires_at:H.string(),access_token:H.string(),refresh_token:H.string().optional()}),Oi=H.discriminatedUnion(`storage`,[Ei,Di]),ki=Ei.extend({email:H.string().optional()}),Ai=Di.extend({email:H.string().optional()}),ji=H.discriminatedUnion(`storage`,[ki,Ai]),Mi=H.object({version:H.literal(1),users:H.partialRecord(H.string(),Ti),profiles:H.partialRecord(H.string(),wi),current_user:H.string().nullable()}),Ni=`2.0.0`,Pi=H.templateLiteral([H.number().int(),`.`,H.number().int(),`.`,H.number().int()]),Fi=H.object({version:H.literal(2),min_sdk_version:Pi,latest_version:H.number().int().optional(),latest_min_sdk_version:Pi.optional(),users:H.partialRecord(H.string(),Oi),profiles:H.partialRecord(H.string(),wi),current_user:H.string().nullable()}),Ii=H.object({version:H.literal(3),min_sdk_version:Pi,latest_version:H.number().int().optional(),latest_min_sdk_version:Pi.optional(),users:H.partialRecord(H.string(),ji),profiles:H.partialRecord(H.string(),wi),current_user:H.string().nullable()});function platformConfigPath(){if(!_r)throw Error(`User home directory not found`);return V.join(_r,`tailor-platform`,`config.yaml`)}function platformConfigFromProfile(e){let t={...e?.platform_url?{platformUrl:e.platform_url}:{},...e?.oauth2_client_id?{oauth2ClientId:e.oauth2_client_id}:{},...e?.console_url?{consoleUrl:e.console_url}:{}};return Object.keys(t).length>0?t:void 0}function platformUserKey(e,t){let n=Ot(t);return n===Qt(`https://api.tailor.tech`)?e:`${n}|${e}`}function userFromPlatformUserKey(e,t){let n=`${Ot(t)}|`;return e.startsWith(n)?e.slice(n.length):e}function canUseLegacyUserKey(e){try{return Ot()===e}catch{return!1}}function findUserByEmail(e,t,n){let r=Ot(n),i=`${r}|`,a=r===Qt(xt);return Object.entries(e).find(([e,n])=>n?.email===t?a?!e.includes(`|`):e.startsWith(i):!1)}function findUserEntry(e,t,n,r={}){let i=platformUserKey(t,n),a=e.users[i];if(a)return{userKey:i,userEntry:a};let o=findUserByEmail(e.users,t,n);if(o?.[1])return{userKey:o[0],userEntry:o[1]};let s=Ot(n);if(i!==t&&(r.allowLegacyUserKey===!1||!canUseLegacyUserKey(s)))return{userKey:i,userEntry:a};let c=e.users[t];return c?{userKey:t,userEntry:c}:{userKey:i,userEntry:a}}function resolveUserTokenKey(e,t,n,r){return findUserEntry(e,t,n,r).userKey}function resolveConfigUser(e,t,n,r){let{userKey:i,userEntry:a}=findUserEntry(e,t,n,r);return a?userFromPlatformUserKey(i,n):void 0}function hasUserTokenEntry(e,t,n,r){return findUserEntry(e,t,n,r).userEntry!==void 0}function hasUserKeyForName(e,t){return e[t]!==void 0||Object.keys(e).some(e=>e.endsWith(`|${t}`))}function hasUserEmailEntry(e,t){return Object.values(e).some(e=>e?.email===t)}function hasAnyUserTokenEntry(e,t){return hasUserKeyForName(e.users,t)||hasUserEmailEntry(e.users,t)}function hasCurrentUserEntry(e,t){return hasUserKeyForName(e,t)}function migrateV1ToV2(e){let t={};for(let[n,r]of Object.entries(e.users))r&&(t[n]={access_token:r.access_token,refresh_token:r.refresh_token,token_expires_at:r.token_expires_at,storage:`file`});return{version:2,min_sdk_version:`1.29.0`,users:t,profiles:e.profiles,current_user:e.current_user}}function inferEmailFromUserId(e){return H.email().safeParse(e).success?e:void 0}function migrateV2ToV3(e){let t={};for(let[n,r]of Object.entries(e.users)){if(!r)continue;let e=inferEmailFromUserId(n);t[n]={...r,...e?{email:e}:{}}}return{version:3,min_sdk_version:Ni,users:t,profiles:e.profiles,current_user:e.current_user}}function migrateV1ToV3(e){return migrateV2ToV3(migrateV1ToV2(e))}function formatUnknownError(e){return e instanceof Error?e.message:String(e)}async function trySaveTokensInKeyring(e,t){if(!await isKeyringAvailable())return!1;try{return await saveKeyringTokens(e,t),!0}catch(e){return M.warn(`System keyring failed to store credentials. Tokens will be stored in the config file. ${formatUnknownError(e)}`),!1}}async function warnIfNewerConfigAvailable(e){if(!e.latest_min_sdk_version)return;let t=(await bn()).version??`0.0.0`;gr(t,e.latest_min_sdk_version)&&M.warn(I`
1
+ import{t as e}from"./wait-point-registry-B-ESkTZX.mjs";import{$ as t,At as n,B as r,Bt as i,C as a,D as o,Dt as s,Et as c,Ft as l,G as u,Gt as d,I as f,J as p,Jt as m,K as h,Kt as g,L as _,Lt as v,M as y,Mt as b,N as x,Nt as S,O as C,Ot as w,P as ee,Pt as te,R as ne,Rt as re,S as ie,St as ae,Tt as oe,U as se,V as ce,W as le,Wt as ue,X as de,Xt as fe,Yt as pe,Z as me,Zt as he,_ as ge,_t as _e,a as ve,at as ye,b as be,bt as xe,ct as Se,d as Ce,dt as we,et as T,f as Te,ft as Ee,g as De,gt as Oe,h as E,ht as ke,i as Ae,in as je,it as Me,j as Ne,jt as Pe,k as Fe,kt as Ie,l as D,lt as Le,mt as Re,nn as ze,nt as Be,o as Ve,ot as He,p as Ue,pt as We,r as Ge,rn as Ke,rt as qe,s as Je,st as Ye,t as Xe,tn as Ze,tt as O,u as Qe,ut as $e,v as et,vt as tt,w as nt,wt as rt,x as it,xt as at,y as ot,yt as st,zt as ct}from"./workspace_resource_pb-BOoRts_z.mjs";import{t as k}from"./assert-WeXvmG4j.mjs";import{a as A,c as lt,i as j,n as M,o as ut,r as dt,s as ft,t as pt}from"./logger-72hM4JWZ.mjs";import{$ as mt,A as ht,B as gt,C as _t,D as vt,E as yt,G as bt,H as xt,J as St,K as Ct,L as wt,M as Tt,N as Et,O as Dt,Q as Ot,R as kt,S as At,T as jt,U as Mt,W as N,X as Nt,Y as Pt,Z as P,a as Ft,at as It,c as Lt,ct as Rt,et as F,f as zt,g as Bt,i as Vt,it as Ht,j as Ut,k as Wt,l as Gt,lt as Kt,n as qt,nt as Jt,ot as Yt,p as Xt,r as Zt,rt as Qt,s as $t,st as en,t as tn,tt as nn,u as rn,ut as an,v as on,w as sn,x as cn,y as ln,z as un}from"./application-BYlhYQyh.mjs";import{_ as dn,d as fn,g as pn,l as mn,t as hn,v as gn,x as _n,y as vn}from"./service-CuqkHP1r.mjs";import{a as yn}from"./guards-ForsrxnH.mjs";import{t as I}from"./multiline-EyzjEwn9.mjs";import{t as bn}from"./package-json-C690ceex.mjs";import{t as xn}from"./user-agent-vdHYF3QL.mjs";import{a as L,c as Sn,o as Cn,r as wn,s as Tn,t as R}from"./errors-BjJnpXkK.mjs";import{n as En,r as Dn}from"./secret-file-C9wp_FCX.mjs";import{r as z}from"./telemetry-Bklv9kQY.mjs";import{t as On}from"./manager-qfbUL7ru.mjs";import{n as kn,r as An,t as jn}from"./tailordb-ddl-Fgm2cNvT.mjs";import{a as Mn,i as Nn,o as Pn,r as Fn,s as In,t as Ln}from"./seed-C3P_T_Eh.mjs";import*as Rn from"node:module";import{arg as B,createDefineCommand as zn,defineCommand as Bn,runCommand as Vn}from"@politty/zod";import*as V from"pathe";import{basename as Hn,dirname as Un,isAbsolute as Wn,join as Gn,relative as Kn,resolve as qn,sep as Jn}from"pathe";import{resolveTSConfig as Yn}from"pkg-types";import{z as H}from"zod";import{create as Xn,createRegistry as Zn,fromJson as Qn,toJson as $n}from"@bufbuild/protobuf";import*as U from"node:fs";import{mkdirSync as er,readFileSync as tr,realpathSync as nr,renameSync as rr,rmSync as ir,statSync as ar,utimesSync as or,writeFileSync as sr}from"node:fs";import{parseEnv as cr,stripVTControlCharacters as lr}from"node:util";import{ValueSchema as ur,timestampDate as W}from"@bufbuild/protobuf/wkt";import{formatDistanceToNowStrict as dr}from"date-fns";import{pathToFileURL as fr}from"node:url";import{parseYAML as pr,stringifyYAML as mr}from"confbox";import{findUpSync as hr}from"find-up-simple";import{lt as gr}from"semver";import{xdgConfig as _r}from"xdg-basedir";import{Code as G,ConnectError as K}from"@connectrpc/connect";import vr from"p-limit";import*as yr from"node:crypto";import{createHash as br,randomUUID as xr}from"node:crypto";import{ExitPromptError as Sr}from"@inquirer/core";import{confirm as Cr,input as wr,password as Tr,select as Er}from"@inquirer/prompts";import{isCI as Dr}from"std-env";import*as Or from"rolldown";import{parseSync as kr}from"oxc-parser";import*as Ar from"inflection";import{tmpdir as jr}from"node:os";import{pathToString as Mr,usedTypes as Nr}from"@bufbuild/protobuf/reflect";import{createValidator as Pr}from"@bufbuild/protovalidate";import*as q from"node:fs/promises";import{mkdir as Fr,readFile as Ir,rename as Lr,rm as Rr,writeFile as zr}from"node:fs/promises";import{setTimeout as Br}from"timers/promises";import{setTimeout as Vr}from"node:timers/promises";import{spawn as Hr}from"node:child_process";import*as Ur from"fs";import{lookup as Wr}from"mime-types";import{createPrompt as Gr}from"@toiroakr/read-multiline";import{astVisitor as Kr,parse as qr}from"pgsql-ast-parser";import{parse as Jr}from"@0no-co/graphql.web";const Yr={ms:1,s:1e3,m:6e4},Xr=/^(\d+)(ms|s|m)$/,Zr=H.string().refine(e=>Xr.test(e),{message:`Invalid duration format. Expected format: '3s', '500ms', '1m'`}).refine(e=>{let t=e.match(Xr);if(!t)return!1;let n=t[1];return n!==void 0&&parseInt(n,10)>0},{message:`Duration must be greater than 0`});function parseDuration(e){let t=k(e.match(Xr),`invalid duration format: ${e}`),n=parseInt(k(t[1],`duration digits group missing`),10),r=k(t[2],`duration unit group missing`);return n*Yr[r]}const Qr=H.coerce.number().int().positive(),$r=H.coerce.number().int().nonnegative(),ei=H.enum([`asc`,`desc`]);function toPageDirection(e){if(e!==void 0)return e===`asc`?je.ASC:je.DESC}function hasMachineUserFlag(e){return e.slice(0,e.indexOf(`--`)===-1?e.length:e.indexOf(`--`)).some(e=>e===`-m`||e.startsWith(`-m=`)||e===`--machine-user`||e.startsWith(`--machine-user=`)||e===`--machineUser`||e.startsWith(`--machineUser=`)||e===`--machineuser`||e.startsWith(`--machineuser=`))}function resolveMachineUserInputSource(e,t=process.argv.slice(2),n={}){if(e!==void 0)return n.valueIsExplicit||hasMachineUserFlag(t)?`option`:process.env.TAILOR_PLATFORM_MACHINE_USER_NAME===e?`env`:`option`}function loadEnvFiles(e,t){let n=new Set(Object.keys(process.env)),load=(e,t)=>{for(let r of[e??[]].flat()){let e=V.resolve(process.cwd(),r);if(!U.existsSync(e)){if(t)throw Error(`Environment file not found: ${e}`);continue}let i=U.readFileSync(e,`utf-8`),a=cr(i);for(let[e,t]of Object.entries(a))n.has(e)||(process.env[e]=t)}};load(e,!0),load(t,!1)}function createCommonArgs(e={}){return{"env-file":B(H.string().optional(),{alias:`e`,description:`Path to the environment file (error if not found)`,completion:{type:`file`,matcher:[`.env.*`,`.env`]}}),"env-file-if-exists":B(H.string().optional(),{description:`Path to the environment file (ignored if not found)`,completion:{type:`file`,matcher:[`.env.*`,`.env`]},effect:(e,{args:t})=>{loadEnvFiles(t[`env-file`],t[`env-file-if-exists`])}}),verbose:B(H.boolean().default(!1),{...e.verboseAlias===void 0?{}:{alias:e.verboseAlias},description:`Enable verbose logging`,effect:e=>{M.verbose=e}}),json:B(H.boolean().default(!1),{alias:`j`,description:`Output as JSON`,effect:e=>{M.jsonMode=e}})}}const ti=createCommonArgs(),J={"workspace-id":B(H.string().optional(),{alias:`w`,description:`Workspace ID`,env:`TAILOR_PLATFORM_WORKSPACE_ID`,completion:{type:`none`}}),profile:B(H.string().optional(),{alias:`p`,description:`Workspace profile`,env:`TAILOR_PLATFORM_PROFILE`,completion:{type:`none`}})},ni=`tailor.config.ts`;function formatConfigArg(e){if(!e)return;let t=V.relative(process.cwd(),e);if(t!==`tailor.config.ts`)return`--config=${t}`}function recoveryContextArgs(e){return[...e.workspaceId?[`--workspace-id=${e.workspaceId}`]:[],...e.profile?[`--profile=${e.profile}`]:[]]}const ri={config:B(H.string().default(ni),{alias:`c`,description:`Path to Tailor config file`,env:`TAILOR_CONFIG_PATH`,completion:{type:`file`,extensions:[`ts`]}})},ii={config:B(H.string().default(ni),{alias:`c`,description:`Path to SDK config file. Use comma-separated paths to deploy multiple apps together.`,env:`TAILOR_PLATFORM_SDK_CONFIG_PATH`,completion:{type:`file`,extensions:[`ts`]}})},ai={...J,...ri},oi={yes:B(H.boolean().default(!1),{alias:`y`,description:`Skip confirmation prompts`})},si={"organization-id":B(H.string(),{alias:`o`,description:`Organization ID`,env:`TAILOR_PLATFORM_ORGANIZATION_ID`,completion:{type:`none`}})},paginationArgs=(e=`desc`)=>({order:B(ei.default(e),{description:`Sort order (asc or desc)`}),limit:B($r.optional(),{alias:`l`,description:`Maximum number of items to return (0 or omit: unlimited)`})}),ci={order:B(ei.default(`desc`),{description:`Sort order (asc or desc)`}),limit:B($r.default(50),{alias:`l`,description:`Maximum number of items to return (0: unlimited)`})},li={"folder-id":B(H.string(),{alias:`f`,description:`Folder ID`,env:`TAILOR_PLATFORM_FOLDER_ID`,completion:{type:`none`}})},Y=zn();async function runDefaultSubCommand(e,t=[]){let n=await Vn(e,t);if(!n.success)throw n.error}const ui=H.union([H.string(),H.number(),H.boolean()]),di=H.union([H.string(),H.number()]),fi=H.union([ui,H.strictObject({value:di,allowSecretReason:H.string().min(1,{message:`'allowSecretReason' must state why the value is safe to keep in 'env'.`})})]),pi=H.enum(an),mi=/^[a-z][a-z0-9_-]{0,62}$/,hi=/^$|^[a-z][a-z0-9_-]{0,62}$/,gi=`sdk-`,_i=H.string().regex(hi,{message:`'metadata' values must match ${hi.source}.`}),vi=H.record(H.string(),_i).superRefine((e,t)=>{let n=Object.keys(e);n.length>17&&t.addIssue({code:`custom`,message:`'metadata' can hold at most 17 entries.`});for(let e of n)mi.test(e)?e.startsWith(gi)&&t.addIssue({code:`custom`,path:[e],message:`'metadata' keys starting with '${gi}' are reserved for the SDK.`}):t.addIssue({code:`custom`,path:[e],message:`'metadata' keys must match ${mi.source}.`})}),yi=H.string().refine(e=>pi.safeParse(e.trim().toUpperCase()).success,{message:`'logLevel' must be one of: ${an.join(`, `)}.`}),bi=H.strictObject({id:H.uuid({message:`'id' must be a UUID.`}).optional(),name:H.string().min(1,{message:`'name' must be a non-empty string.`}),env:H.record(H.string(),fi).optional(),cors:H.array(H.string()).optional(),allowedIpAddresses:H.array(H.string()).optional(),disableIntrospection:H.boolean().optional(),inlineSourcemap:H.boolean().optional(),logLevel:yi.optional(),metadata:vi.optional(),db:H.unknown().optional(),resolver:H.unknown().optional(),idp:H.unknown().optional(),auth:H.unknown().optional(),executor:H.unknown().optional(),workflow:H.unknown().optional(),httpAdapter:H.unknown().optional(),staticWebsites:H.unknown().optional(),aiGateways:H.unknown().optional(),secrets:H.unknown().optional()}),xi=H.looseObject({id:H.string(),description:H.string(),importPath:H.string().optional(),pluginConfig:H.unknown().optional(),tableConfigRequired:H.union([H.boolean(),_n]).optional(),onTableLoaded:_n.optional(),onNamespaceLoaded:_n.optional(),onTailorDBReady:_n.optional(),onResolverReady:_n.optional(),onExecutorReady:_n.optional()}).refine(e=>!(e.onTableLoaded||e.onNamespaceLoaded)||!!e.importPath,{message:`importPath is required when plugin has definition-time hooks (onTableLoaded/onNamespaceLoaded)`}).transform(e=>e),Si=`tailor-platform-cli`;let Ci;async function getEntryClass(){if(Ci!==void 0)return Ci;try{Ci=(await import(`@napi-rs/keyring`)).Entry}catch{M.warn(`System keyring is not available. Tokens will be stored in the config file. Set TAILOR_PLATFORM_TOKEN environment variable for CI environments.`),Ci=!1}return Ci}async function isKeyringAvailable(){return await getEntryClass()!==!1}async function loadKeyringTokens(e){let t=await getEntryClass();if(!t)throw Error(`System keyring is not available.`);let n=new t(Si,e).getPassword();if(n!==null)try{return JSON.parse(n)}catch{return}}async function saveKeyringTokens(e,t){let n=await getEntryClass();if(!n)throw Error(`System keyring is not available.`);new n(Si,e).setPassword(JSON.stringify(t))}async function deleteKeyringTokens(e){let t=await getEntryClass();if(t)try{new t(Si,e).deletePassword()}catch{}}const wi=H.object({user:H.string(),workspace_id:H.string(),readonly:H.boolean().optional(),machine_user:H.string().optional(),machine_user_override:H.enum([`allow`,`deny`]).optional(),platform_url:H.url().optional(),oauth2_client_id:H.string().optional(),console_url:H.url().optional()}),Ti=H.object({access_token:H.string(),refresh_token:H.string().optional(),token_expires_at:H.string()}),Ei=H.object({storage:H.literal(`keyring`),token_expires_at:H.string()}),Di=H.object({storage:H.literal(`file`),token_expires_at:H.string(),access_token:H.string(),refresh_token:H.string().optional()}),Oi=H.discriminatedUnion(`storage`,[Ei,Di]),ki=Ei.extend({email:H.string().optional()}),Ai=Di.extend({email:H.string().optional()}),ji=H.discriminatedUnion(`storage`,[ki,Ai]),Mi=H.object({version:H.literal(1),users:H.partialRecord(H.string(),Ti),profiles:H.partialRecord(H.string(),wi),current_user:H.string().nullable()}),Ni=`2.0.0`,Pi=H.templateLiteral([H.number().int(),`.`,H.number().int(),`.`,H.number().int()]),Fi=H.object({version:H.literal(2),min_sdk_version:Pi,latest_version:H.number().int().optional(),latest_min_sdk_version:Pi.optional(),users:H.partialRecord(H.string(),Oi),profiles:H.partialRecord(H.string(),wi),current_user:H.string().nullable()}),Ii=H.object({version:H.literal(3),min_sdk_version:Pi,latest_version:H.number().int().optional(),latest_min_sdk_version:Pi.optional(),users:H.partialRecord(H.string(),ji),profiles:H.partialRecord(H.string(),wi),current_user:H.string().nullable()});function platformConfigPath(){if(!_r)throw Error(`User home directory not found`);return V.join(_r,`tailor-platform`,`config.yaml`)}function platformConfigFromProfile(e){let t={...e?.platform_url?{platformUrl:e.platform_url}:{},...e?.oauth2_client_id?{oauth2ClientId:e.oauth2_client_id}:{},...e?.console_url?{consoleUrl:e.console_url}:{}};return Object.keys(t).length>0?t:void 0}function platformUserKey(e,t){let n=Ot(t);return n===Qt(`https://api.tailor.tech`)?e:`${n}|${e}`}function userFromPlatformUserKey(e,t){let n=`${Ot(t)}|`;return e.startsWith(n)?e.slice(n.length):e}function canUseLegacyUserKey(e){try{return Ot()===e}catch{return!1}}function findUserByEmail(e,t,n){let r=Ot(n),i=`${r}|`,a=r===Qt(xt);return Object.entries(e).find(([e,n])=>n?.email===t?a?!e.includes(`|`):e.startsWith(i):!1)}function findUserEntry(e,t,n,r={}){let i=platformUserKey(t,n),a=e.users[i];if(a)return{userKey:i,userEntry:a};let o=findUserByEmail(e.users,t,n);if(o?.[1])return{userKey:o[0],userEntry:o[1]};let s=Ot(n);if(i!==t&&(r.allowLegacyUserKey===!1||!canUseLegacyUserKey(s)))return{userKey:i,userEntry:a};let c=e.users[t];return c?{userKey:t,userEntry:c}:{userKey:i,userEntry:a}}function resolveUserTokenKey(e,t,n,r){return findUserEntry(e,t,n,r).userKey}function resolveConfigUser(e,t,n,r){let{userKey:i,userEntry:a}=findUserEntry(e,t,n,r);return a?userFromPlatformUserKey(i,n):void 0}function hasUserTokenEntry(e,t,n,r){return findUserEntry(e,t,n,r).userEntry!==void 0}function hasUserKeyForName(e,t){return e[t]!==void 0||Object.keys(e).some(e=>e.endsWith(`|${t}`))}function hasUserEmailEntry(e,t){return Object.values(e).some(e=>e?.email===t)}function hasAnyUserTokenEntry(e,t){return hasUserKeyForName(e.users,t)||hasUserEmailEntry(e.users,t)}function hasCurrentUserEntry(e,t){return hasUserKeyForName(e,t)}function migrateV1ToV2(e){let t={};for(let[n,r]of Object.entries(e.users))r&&(t[n]={access_token:r.access_token,refresh_token:r.refresh_token,token_expires_at:r.token_expires_at,storage:`file`});return{version:2,min_sdk_version:`1.29.0`,users:t,profiles:e.profiles,current_user:e.current_user}}function inferEmailFromUserId(e){return H.email().safeParse(e).success?e:void 0}function migrateV2ToV3(e){let t={};for(let[n,r]of Object.entries(e.users)){if(!r)continue;let e=inferEmailFromUserId(n);t[n]={...r,...e?{email:e}:{}}}return{version:3,min_sdk_version:Ni,users:t,profiles:e.profiles,current_user:e.current_user}}function migrateV1ToV3(e){return migrateV2ToV3(migrateV1ToV2(e))}function formatUnknownError(e){return e instanceof Error?e.message:String(e)}async function trySaveTokensInKeyring(e,t){if(!await isKeyringAvailable())return!1;try{return await saveKeyringTokens(e,t),!0}catch(e){return M.warn(`System keyring failed to store credentials. Tokens will be stored in the config file. ${formatUnknownError(e)}`),!1}}async function warnIfNewerConfigAvailable(e){if(!e.latest_min_sdk_version)return;let t=(await bn()).version??`0.0.0`;gr(t,e.latest_min_sdk_version)&&M.warn(I`
2
2
  A newer config version (${String(e.latest_version)}) is available.
3
3
  Please update your SDK to >= ${e.latest_min_sdk_version}: pnpm update @tailor-platform/sdk
4
4
  `)}async function readPlatformConfig(){let e=platformConfigPath();if(!U.existsSync(e)){let e={version:3,min_sdk_version:Ni,users:{},profiles:{},current_user:null};return writePlatformConfig(e),e}let t=pr(U.readFileSync(e,`utf-8`));En(e);let n=typeof t==`object`&&t&&`version`in t?t.version:void 0;if(typeof n==`number`&&n>3){let e=`min_sdk_version`in t?String(t.min_sdk_version):void 0,r=e?`Please update your SDK to >= ${e}: pnpm update @tailor-platform/sdk`:`Please update your SDK: pnpm update @tailor-platform/sdk`;throw Error(I`
@@ -563,7 +563,7 @@ ${n===`throw`?` if (records.length > 1) {
563
563
  }
564
564
  lastId = rows[rows.length - 1]!.id;
565
565
  }
566
- }`}function markMigrationScriptSkipped(e){let{migrationsDir:t,migrationNumber:n,reason:r}=e,i=formatMigrationNumber(n),a=r.trim();if(!a)throw R({code:`MIGRATION_SCRIPT_REASON_REQUIRED`,message:`Migration script skip reason must not be empty.`,command:`tailordb migration script`});let o=getMigrationFilePath(t,n,`diff`);if(!U.existsSync(o))throw R({code:`MIGRATION_NOT_FOUND`,message:`Migration ${i} not found in ${t}. Expected ${o}.`});let s=loadDiff(o);if(!s.requiresMigrationScript&&!s.hasWarnings)throw R({code:`MIGRATION_SCRIPT_NOT_REQUIRED`,message:`Migration ${i} does not require a migration script and has no data-loss warnings; nothing to skip.`});if(s.scriptSkipped)throw R({code:`MIGRATION_SCRIPT_SKIP_EXISTS`,message:`Migration ${i} already has a script skip recorded (${s.scriptSkipped.acknowledgedAt}: ${s.scriptSkipped.reason}).`});let c=getMigrationFilePath(t,n,`migrate`);if(U.existsSync(c))throw R({code:`MIGRATION_SCRIPT_EXISTS`,message:`Migration script exists at ${c}.`,suggestion:`Delete migrate.ts first if this migration should run without a script.`});let l={reason:a,acknowledgedAt:new Date().toISOString()},u=JSON.parse(U.readFileSync(o,`utf-8`));return u.scriptSkipped=l,U.writeFileSync(o,JSON.stringify(u,null,2)),l}function clearMigrationScriptSkipped(e){let t=JSON.parse(U.readFileSync(e,`utf-8`));Object.hasOwn(t,`scriptSkipped`)&&(delete t.scriptSkipped,U.writeFileSync(e,JSON.stringify(t,null,2)))}async function addMigrationScriptFiles(e){let{migrationsDir:t,migrationNumber:n,withTest:r=!1,pgliteAvailable:i=!1}=e,a=formatMigrationNumber(n),o=getMigrationFilePath(t,n,`diff`);if(!U.existsSync(o))throw R({code:`MIGRATION_NOT_FOUND`,message:`Migration ${a} not found in ${t}. Expected ${o}.`});let s=loadDiff(o),c=getMigrationFilePath(t,n,`migrate`),l=U.existsSync(c),u={};if(l&&s.scriptSkipped){if(clearMigrationScriptSkipped(o),u.clearedScriptSkip=!0,!r)return u}else if(l&&!r)throw R({code:`MIGRATION_SCRIPT_EXISTS`,message:`Migration script already exists at ${c}.`});let d=getMigrationFilePath(t,n,`test`),f=getMigrationFilePath(t,n,`pgliteTest`),p=getMigrationFilePath(t,n,`pgliteSchema`),m=r&&!U.existsSync(d),h=r&&i&&!U.existsSync(f);if(r&&!m&&!h)throw R({code:`MIGRATION_TEST_EXISTS`,message:i?`Migration tests already exist at ${d} and ${f}.`:`Migration test already exists at ${d}.`});if(l&&r){let e=getMigrationFilePath(t,n,`db`);if(!U.existsSync(e))throw R({code:`GENERATED_TYPES_NOT_FOUND`,message:`Generated types not found at ${e}.`,suggestion:`The test scaffold imports Database from ./db; restore db.ts before adding a test.`})}let g=!l||r&&!U.existsSync(p),_=g?reconstructSnapshotFromMigrations(t,n-1):null;if(g&&!_)throw R({code:`MIGRATION_HISTORY_INVALID`,message:`Could not reconstruct previous schema for migration ${a}.`,suggestion:`Make sure migration 0 exists.`});if(!l&&_){await q.writeFile(c,generateMigrationScript(s)),u.migratePath=c;let e=await writeMigrationTypeFiles({previousSnapshot:_,diff:s,migrationsDir:t,migrationNumber:n});u.dbTypesPath=e.dbTypesPath,u.pgliteSchemaPath=e.pgliteSchemaPath,u.pgliteSchemaError=e.pgliteSchemaError,clearMigrationScriptSkipped(o)}else r&&_&&Object.assign(u,await tryWritePgliteSchemaFile(_,s,t,n));return m&&(await q.writeFile(d,generateMigrationTestScript(s)),u.testPath=d),u.pgliteTestRequested=h,h&&U.existsSync(p)&&(await q.writeFile(f,generateMigrationPgliteTestScript(s)),u.pgliteTestPath=f),u}function isPgliteAvailable(e){let t=V.resolve(e);for(;;){if(U.existsSync(V.join(t,`node_modules`,`@electric-sql`,`pglite`,`package.json`)))return!0;let e=V.dirname(t);if(e===t)return!1;t=e}}async function script(e){logBetaWarning(`tailordb migration`);let t=parseMigrationNumberArg(e.number);if(t===0)throw R({code:`MIGRATION_SCRIPT_NOT_ALLOWED`,message:`Migration ${e.number} is the initial schema snapshot and cannot have a migration script.`});let{config:n}=await loadConfig(e.configPath),r=getNamespacesWithMigrations(n,V.dirname(n.path));if(r.length===0)throw migrationConfigNotFoundError();let i=resolveTargetNamespace(r,e.namespace),{migrationsDir:a}=k(r.find(e=>e.namespace===i),`namespace with migrations not found`);if(e.noScript){if(e.withTest)throw R({code:`MIGRATION_SCRIPT_OPTIONS_CONFLICT`,message:`--with-test cannot be used together with --no-script.`,command:`tailordb migration script`});let n=e.reason?.trim();if(!n)throw R({code:`MIGRATION_SCRIPT_REASON_REQUIRED`,message:`--reason is required with --no-script.`,command:`tailordb migration script`});let r=markMigrationScriptSkipped({migrationsDir:a,migrationNumber:t,reason:n});M.success(`Recorded that migration ${j.bold(e.number)} in namespace ${j.bold(i)} intentionally has no migration script`),M.info(` Reason: ${r.reason}`),M.info(` Diff file: ${getMigrationFilePath(a,t,`diff`)}`);return}if(e.reason!==void 0)throw R({code:`MIGRATION_SCRIPT_OPTIONS_CONFLICT`,message:`--reason can only be used together with --no-script.`,command:`tailordb migration script`});let o=isPgliteAvailable(a),s=await addMigrationScriptFiles({migrationsDir:a,migrationNumber:t,withTest:e.withTest,pgliteAvailable:o});if(s.clearedScriptSkip&&(M.success(`Cleared the stale script skip record for migration ${j.bold(e.number)} in namespace ${j.bold(i)}`),!s.testPath&&!s.pgliteTestRequested)){M.info(` Migration script: ${getMigrationFilePath(a,t,`migrate`)}`);return}let c=[s.testPath,s.pgliteTestPath].filter(Boolean).length,l=[s.migratePath&&`migration script`,c>0&&(c>1?`migration tests`:`migration test`)].filter(Boolean).join(` and `),u=`for migration ${j.bold(e.number)} in namespace ${j.bold(i)}`;l?M.success(`Added ${l} ${u}`):M.warn(`Added no files ${u}`),s.migratePath&&(M.info(` Migration script: ${s.migratePath}`),M.info(` DB types: ${s.dbTypesPath}`)),s.pgliteSchemaPath&&M.info(` PGlite schema: ${s.pgliteSchemaPath}`),s.pgliteSchemaError&&M.warn(` PGlite schema skipped: ${s.pgliteSchemaError}`),s.testPath&&M.info(` Migration test: ${s.testPath}`),s.pgliteTestPath?M.info(` PGlite test: ${s.pgliteTestPath}`):s.testPath&&!o?M.info(` Install @electric-sql/pglite as a devDependency to also scaffold a PGlite test (migrate.pglite.test.ts).`):s.pgliteTestRequested&&s.pgliteSchemaError&&M.info(` PGlite test skipped: it needs the db.pglite.ts that could not be generated.`),M.newline(),s.migratePath&&(M.log(`Edit the script to implement your data migration logic.`),M.log(`It will be executed by 'tailor deploy' between Pre and Post phases.`)),s.testPath&&M.log(`Fill in the test with the rows to stage and the statements to assert.`);let d=s.migratePath??s.testPath;if(!d)return;let f=getConfiguredEditorCommand();if(f){M.newline(),M.info(`Opening ${V.basename(d)} in ${f}...`);try{await openInConfiguredEditor(d)}catch{return}}}function resolveTargetNamespace(e,t){if(t){if(!e.some(e=>e.namespace===t))throw R({code:`TAILORDB_NAMESPACE_NOT_FOUND`,message:`Namespace "${t}" not found or does not have migrations configured`});return t}if(e.length===1){let[t]=e;return k(t,`namespace with migrations missing`).namespace}throw R({code:`MIGRATION_NAMESPACE_REQUIRED`,message:`Multiple TailorDB services found. Please specify namespace with --namespace flag: ${e.map(e=>e.namespace).join(`, `)}`,command:`tailordb migration script`})}const _c=Y({name:`script`,description:`Add a migration script (migrate.ts) template to an existing migration directory, or record with --no-script that a migration intentionally has none.`,notes:"When `migrate.ts` already exists, running the command clears a previously recorded `--no-script` acknowledgment, and `--with-test` adds only the tests that do not exist yet (writing `db.pglite.ts` if it is missing). `migrate.pglite.test.ts` is scaffolded only when `@electric-sql/pglite` is installed in the project.",args:H.strictObject({...ri,number:B(H.string(),{positional:!0,description:`Migration number to add a script to (e.g., 0001 or 1)`}),namespace:B(H.string().optional(),{alias:`n`,description:`Target TailorDB namespace (required if multiple namespaces exist)`}),"no-script":B(H.boolean().optional(),{description:`Record that this migration intentionally runs without a migration script (requires --reason)`}),reason:B(H.string().optional(),{description:`Reason why no migration script is needed (used with --no-script)`}),"with-test":B(H.boolean().optional(),{description:`Also add the migrate.test.ts and migrate.pglite.test.ts scaffolds`})}),run:async e=>{await script({configPath:e.config,number:e.number,namespace:e.namespace,noScript:e[`no-script`],reason:e.reason,withTest:e[`with-test`]})}});function getUnsupportedMigrationHintLines(){return[`These changes require a manual 3-step migration process:`,` Migration 1: Add an optional temporary field with the desired structure`,` If the old field is required, make the old field optional`,` For each non-null old value, copy and convert it to the temporary field`,` and set the old field to null in the same update`,` Verify every old value is null before continuing`,` Migration 2: Remove the old field`,` Migration 3: Add the field with the original name and new structure,`,` migrate data from the temporary field, then remove it`,` Important: Reusing the name while stored old values remain can make subsequent reads fail`]}async function handleInitOption(e,t){let n=e.filter(({migrationsDir:e})=>U.existsSync(e));if(n.length===0){M.info(`No existing migration directories found.`);return}M.newline(),M.warn(`This will DELETE all existing migration files:`);for(let{namespace:e,migrationsDir:t}of n)M.log(` - ${e}: ${t}`);M.newline(),t||(await X.confirm({message:`Are you sure you want to delete these directories and start fresh?`,default:!1})||(M.info(`Operation cancelled.`),process.exit(0)),M.newline());for(let{namespace:e,migrationsDir:t}of n)try{await q.rm(t,{recursive:!0,force:!0}),M.success(`Deleted migration directory for ${j.bold(e)}`)}catch(e){throw M.error(`Failed to delete ${t}: ${e}`),e}M.newline(),M.info(`Migration directories cleared. Generating initial snapshot...`),M.newline()}async function generate(e){logBetaWarning(`tailordb migration`);let{config:t,plugins:n}=await loadConfig(e.configPath),r=getNamespacesWithMigrations(t,V.dirname(t.path));if(r.length===0){M.warn(`No TailorDB namespaces with migrations config found.`),M.info(`Add "migration: { directory: \\"./migrations\\" }" to your db config to enable migrations.`);return}let i=[],a=[],o=[];for(let t of e.renames??[]){let e=targetDepth(t);e>=2?o.push({raw:t,spec:parseNestedMemberRenameOption(t)}):e===1?i.push({raw:t,spec:parseRenameOption(t)}):a.push({raw:t,spec:parseTypeRenameOption(t)})}let s=[],c=[],l=[];for(let t of e.drops??[]){let e=targetDepth(t);e>=2?l.push({raw:t,spec:parseNestedMemberDropOption(t)}):e===1?s.push({raw:t,spec:parseDropOption(t)}):c.push({raw:t,spec:parseTypeDropOption(t)})}let u=(e.expandContracts??[]).map(e=>({raw:e,spec:parseExpandContractOption(e)})),d=i.length>0||a.length>0||o.length>0||s.length>0||c.length>0||l.length>0;if(e.init&&(d||u.length>0))throw R({code:`MIGRATION_GENERATE_OPTIONS_CONFLICT`,message:`--rename, --drop, and --expand-contract cannot be used together with --init.`,command:`tailordb migration generate`});let f=new Set(s.map(({spec:e})=>`${e.tableName}.${e.fieldName}`)),p=i.filter(({spec:e})=>f.has(`${e.tableName}.${e.previousFieldName}`));if(p.length>0)throw R({code:`MIGRATION_RENAME_DROP_CONFLICT`,message:`--rename and --drop conflict for: ${p.map(({spec:e})=>`${e.tableName}.${e.previousFieldName}`).join(`, `)}`,command:`tailordb migration generate`});let m=new Set(l.map(({spec:e})=>nestedMemberKey(e))),h=o.filter(({spec:e})=>m.has(nestedMemberKey({...e,path:e.previousPath})));if(h.length>0)throw R({code:`MIGRATION_RENAME_DROP_CONFLICT`,message:`--rename and --drop conflict for: ${h.map(({spec:e})=>nestedMemberKey({...e,path:e.previousPath})).join(`, `)}`,command:`tailordb migration generate`});let g=new Set(c.map(({spec:e})=>e.tableName)),_=a.filter(({spec:e})=>g.has(e.previousTableName));if(_.length>0)throw R({code:`MIGRATION_RENAME_DROP_CONFLICT`,message:`--rename and --drop conflict for: ${_.map(({spec:e})=>e.previousTableName).join(`, `)}`,command:`tailordb migration generate`});if(e.namespace!==void 0&&!e.dataOnly)throw R({code:`MIGRATION_GENERATE_OPTIONS_CONFLICT`,message:`--namespace can only be used together with --data-only.`,command:`tailordb migration generate`});if(e.dataOnly&&(e.init||d||u.length>0))throw R({code:`MIGRATION_GENERATE_OPTIONS_CONFLICT`,message:`--init, --rename, --drop, and --expand-contract cannot be used together with --data-only.`,command:`tailordb migration generate`});let v=e.dataOnly?resolveTargetNamespace(r,e.namespace):void 0,y=v===void 0?r:r.filter(({namespace:e})=>e===v);e.init&&await handleInitOption(r,e.yes);let b;n.length>0&&(b=new On(n));let{defineApplication:x}=await import(`./application-Dl94fzpm.mjs`),S=x({config:t,pluginManager:b}),C=[];for(let{namespace:e,migrationsDir:t}of y){M.info(`Processing namespace: ${j.bold(e)}`),assertValidMigrationFiles(t,e);let n=S.tailorDBServices.find(t=>t.namespace===e);if(!n){M.warn(`No TailorDB service found for namespace "${e}"`);continue}await n.loadTypes(),await n.processNamespacePlugins();let r=n.types;C.push({namespace:e,migrationsDir:t,currentSnapshot:createSnapshotFromLocalTypes(r,e),previousSnapshot:reconstructSnapshotFromMigrations(t)})}if(v!==void 0){await generateDataOnlyMigration(C,v,e);return}let w=matchFlagsToNamespaces(i,C,renameSpecApplies,`--rename does not match a removed + added field pair`),ee=matchFlagsToNamespaces(a,C,typeRenameSpecApplies,`--rename does not match a removed + added table pair`),te=matchFlagsToNamespaces(s,C,dropSpecApplies,`--drop does not match a removed field`),ne=matchFlagsToNamespaces(c,C,typeDropSpecApplies,`--drop does not match a removed table`),re=matchFlagsToNamespaces(o,C,nestedMemberRenameSpecApplies,`--rename does not match a removed + added nested member pair`),ie=matchFlagsToNamespaces(l,C,nestedMemberDropSpecApplies,`--drop does not match a removed nested member`),ae=new Map,oe=new Set,se=[];for(let{namespace:e,previousSnapshot:t,currentSnapshot:n}of C){if(!t)continue;let r=[];for(let i of u){let{spec:a}=i,o=t.tables[a.tableName]?.fields[a.fieldName],s=n.tables[a.tableName]?.fields[a.fieldName];if(!o||!s||!hasFieldShapeChange(o,s))continue;oe.add(i);let c=getExpandContractEligibility({previous:t,current:n,tableName:a.tableName,fieldName:a.fieldName});if(!c.eligible){se.push(`--expand-contract cannot convert ${i.raw} (namespace: ${e}): ${c.reason}`);continue}r.push(i)}ae.set(e,new Set(r.map(({spec:e})=>fieldKey(e.tableName,e.fieldName))))}let ce=u.filter(e=>!oe.has(e));if(ce.length>0)throw R({code:`MIGRATION_EXPAND_CONTRACT_UNMATCHED`,message:`--expand-contract does not match a field whose type or array-ness changed: ${ce.map(e=>e.raw).join(`, `)}`,command:`tailordb migration generate`});if(se.length>0)throw R({code:`MIGRATION_EXPAND_CONTRACT_INELIGIBLE`,message:se.join(`
566
+ }`}function markMigrationScriptSkipped(e){let{migrationsDir:t,migrationNumber:n,reason:r}=e,i=formatMigrationNumber(n),a=r.trim();if(!a)throw R({code:`MIGRATION_SCRIPT_REASON_REQUIRED`,message:`Migration script skip reason must not be empty.`,command:`tailordb migration script`});let o=getMigrationFilePath(t,n,`diff`);if(!U.existsSync(o))throw R({code:`MIGRATION_NOT_FOUND`,message:`Migration ${i} not found in ${t}. Expected ${o}.`});let s=loadDiff(o);if(!s.requiresMigrationScript&&!s.hasWarnings)throw R({code:`MIGRATION_SCRIPT_NOT_REQUIRED`,message:`Migration ${i} does not require a migration script and has no data-loss warnings; nothing to skip.`});if(s.scriptSkipped)throw R({code:`MIGRATION_SCRIPT_SKIP_EXISTS`,message:`Migration ${i} already has a script skip recorded (${s.scriptSkipped.acknowledgedAt}: ${s.scriptSkipped.reason}).`});let c=getMigrationFilePath(t,n,`migrate`);if(U.existsSync(c))throw R({code:`MIGRATION_SCRIPT_EXISTS`,message:`Migration script exists at ${c}.`,suggestion:`Delete migrate.ts first if this migration should run without a script.`});let l={reason:a,acknowledgedAt:new Date().toISOString()},u=JSON.parse(U.readFileSync(o,`utf-8`));return u.scriptSkipped=l,U.writeFileSync(o,JSON.stringify(u,null,2)),l}function clearMigrationScriptSkipped(e){let t=JSON.parse(U.readFileSync(e,`utf-8`));Object.hasOwn(t,`scriptSkipped`)&&(delete t.scriptSkipped,U.writeFileSync(e,JSON.stringify(t,null,2)))}async function addMigrationScriptFiles(e){let{migrationsDir:t,migrationNumber:n,withTest:r=!1,pgliteAvailable:i=!1}=e,a=formatMigrationNumber(n),o=getMigrationFilePath(t,n,`diff`);if(!U.existsSync(o))throw R({code:`MIGRATION_NOT_FOUND`,message:`Migration ${a} not found in ${t}. Expected ${o}.`});let s=loadDiff(o),c=getMigrationFilePath(t,n,`migrate`),l=U.existsSync(c),u={};if(l&&s.scriptSkipped){if(clearMigrationScriptSkipped(o),u.clearedScriptSkip=!0,!r)return u}else if(l&&!r)throw R({code:`MIGRATION_SCRIPT_EXISTS`,message:`Migration script already exists at ${c}.`});let d=getMigrationFilePath(t,n,`test`),f=getMigrationFilePath(t,n,`pgliteTest`),p=getMigrationFilePath(t,n,`pgliteSchema`),m=r&&!U.existsSync(d),h=r&&i&&!U.existsSync(f);if(r&&!m&&!h)throw R({code:`MIGRATION_TEST_EXISTS`,message:i?`Migration tests already exist at ${d} and ${f}.`:`Migration test already exists at ${d}.`});if(l&&r){let e=getMigrationFilePath(t,n,`db`);if(!U.existsSync(e))throw R({code:`GENERATED_TYPES_NOT_FOUND`,message:`Generated types not found at ${e}.`,suggestion:`The test scaffold imports Database from ./db; restore db.ts before adding a test.`})}let g=!l||r&&!U.existsSync(p),_=g?reconstructSnapshotFromMigrations(t,n-1):null;if(g&&!_)throw R({code:`MIGRATION_HISTORY_INVALID`,message:`Could not reconstruct previous schema for migration ${a}.`,suggestion:`Make sure migration 0 exists.`});if(!l&&_){await q.writeFile(c,generateMigrationScript(s)),u.migratePath=c;let e=await writeMigrationTypeFiles({previousSnapshot:_,diff:s,migrationsDir:t,migrationNumber:n});u.dbTypesPath=e.dbTypesPath,u.pgliteSchemaPath=e.pgliteSchemaPath,u.pgliteSchemaError=e.pgliteSchemaError,clearMigrationScriptSkipped(o)}else r&&_&&Object.assign(u,await tryWritePgliteSchemaFile(_,s,t,n));return m&&(await q.writeFile(d,generateMigrationTestScript(s)),u.testPath=d),u.pgliteTestRequested=h,h&&U.existsSync(p)&&(await q.writeFile(f,generateMigrationPgliteTestScript(s)),u.pgliteTestPath=f),u}function isPgliteAvailable(e){let t=V.resolve(e);for(;;){if(U.existsSync(V.join(t,`node_modules`,`@electric-sql`,`pglite`,`package.json`)))return!0;let e=V.dirname(t);if(e===t)return!1;t=e}}async function script(e){logBetaWarning(`tailordb migration`);let t=parseMigrationNumberArg(e.number);if(t===0)throw R({code:`MIGRATION_SCRIPT_NOT_ALLOWED`,message:`Migration ${e.number} is the initial schema snapshot and cannot have a migration script.`});let{config:n}=await loadConfig(e.configPath),r=getNamespacesWithMigrations(n,V.dirname(n.path));if(r.length===0)throw migrationConfigNotFoundError();let i=resolveTargetNamespace(r,e.namespace),{migrationsDir:a}=k(r.find(e=>e.namespace===i),`namespace with migrations not found`);if(e.noScript){if(e.withTest)throw R({code:`MIGRATION_SCRIPT_OPTIONS_CONFLICT`,message:`--with-test cannot be used together with --no-script.`,command:`tailordb migration script`});let n=e.reason?.trim();if(!n)throw R({code:`MIGRATION_SCRIPT_REASON_REQUIRED`,message:`--reason is required with --no-script.`,command:`tailordb migration script`});let r=markMigrationScriptSkipped({migrationsDir:a,migrationNumber:t,reason:n});M.success(`Recorded that migration ${j.bold(e.number)} in namespace ${j.bold(i)} intentionally has no migration script`),M.info(` Reason: ${r.reason}`),M.info(` Diff file: ${getMigrationFilePath(a,t,`diff`)}`);return}if(e.reason!==void 0)throw R({code:`MIGRATION_SCRIPT_OPTIONS_CONFLICT`,message:`--reason can only be used together with --no-script.`,command:`tailordb migration script`});let o=isPgliteAvailable(a),s=await addMigrationScriptFiles({migrationsDir:a,migrationNumber:t,withTest:e.withTest,pgliteAvailable:o});if(s.clearedScriptSkip&&(M.success(`Cleared the stale script skip record for migration ${j.bold(e.number)} in namespace ${j.bold(i)}`),!s.testPath&&!s.pgliteTestRequested)){M.info(` Migration script: ${getMigrationFilePath(a,t,`migrate`)}`);return}let c=[s.testPath,s.pgliteTestPath].filter(Boolean).length,l=[s.migratePath&&`migration script`,c>0&&(c>1?`migration tests`:`migration test`)].filter(Boolean).join(` and `),u=`for migration ${j.bold(e.number)} in namespace ${j.bold(i)}`;l?M.success(`Added ${l} ${u}`):M.warn(`Added no files ${u}`),s.migratePath&&(M.info(` Migration script: ${s.migratePath}`),M.info(` DB types: ${s.dbTypesPath}`)),s.pgliteSchemaPath&&M.info(` PGlite schema: ${s.pgliteSchemaPath}`),s.pgliteSchemaError&&M.warn(` PGlite schema skipped: ${s.pgliteSchemaError}`),s.testPath&&M.info(` Migration test: ${s.testPath}`),s.pgliteTestPath?M.info(` PGlite test: ${s.pgliteTestPath}`):s.testPath&&!o?M.info(` Install @electric-sql/pglite as a devDependency to also scaffold a PGlite test (migrate.pglite.test.ts).`):s.pgliteTestRequested&&s.pgliteSchemaError&&M.info(` PGlite test skipped: it needs the db.pglite.ts that could not be generated.`),M.newline(),s.migratePath&&(M.log(`Edit the script to implement your data migration logic.`),M.log(`It will be executed by 'tailor deploy' between Pre and Post phases.`)),s.testPath&&M.log(`Fill in the test with the rows to stage and the statements to assert.`);let d=s.migratePath??s.testPath;if(!d)return;let f=getConfiguredEditorCommand();if(f){M.newline(),M.info(`Opening ${V.basename(d)} in ${f}...`);try{await openInConfiguredEditor(d)}catch{return}}}function resolveTargetNamespace(e,t){if(t){if(!e.some(e=>e.namespace===t))throw R({code:`TAILORDB_NAMESPACE_NOT_FOUND`,message:`Namespace "${t}" not found or does not have migrations configured`});return t}if(e.length===1){let[t]=e;return k(t,`namespace with migrations missing`).namespace}throw R({code:`MIGRATION_NAMESPACE_REQUIRED`,message:`Multiple TailorDB services found. Please specify namespace with --namespace flag: ${e.map(e=>e.namespace).join(`, `)}`,command:`tailordb migration script`})}const _c=Y({name:`script`,description:`Add a migration script (migrate.ts) template to an existing migration directory, or record with --no-script that a migration intentionally has none.`,notes:"When `migrate.ts` already exists, running the command clears a previously recorded `--no-script` acknowledgment, and `--with-test` adds only the tests that do not exist yet (writing `db.pglite.ts` if it is missing). `migrate.pglite.test.ts` is scaffolded only when `@electric-sql/pglite` is installed in the project.",args:H.strictObject({...ri,number:B(H.string(),{positional:!0,description:`Migration number to add a script to (e.g., 0001 or 1)`}),namespace:B(H.string().optional(),{alias:`n`,description:`Target TailorDB namespace (required if multiple namespaces exist)`}),"no-script":B(H.boolean().optional(),{description:`Record that this migration intentionally runs without a migration script (requires --reason)`}),reason:B(H.string().optional(),{description:`Reason why no migration script is needed (used with --no-script)`}),"with-test":B(H.boolean().optional(),{description:`Also add the migrate.test.ts and migrate.pglite.test.ts scaffolds`})}),run:async e=>{await script({configPath:e.config,number:e.number,namespace:e.namespace,noScript:e[`no-script`],reason:e.reason,withTest:e[`with-test`]})}});function getUnsupportedMigrationHintLines(){return[`These changes require a manual 3-step migration process:`,` Migration 1: Add an optional temporary field with the desired structure`,` If the old field is required, make the old field optional`,` For each non-null old value, copy and convert it to the temporary field`,` and set the old field to null in the same update`,` Verify every old value is null before continuing`,` Migration 2: Remove the old field`,` Migration 3: Add the field with the original name and new structure,`,` migrate data from the temporary field, then remove it`,` Important: Reusing the name while stored old values remain can make subsequent reads fail`]}async function handleInitOption(e,t){let n=e.filter(({migrationsDir:e})=>U.existsSync(e));if(n.length===0){M.info(`No existing migration directories found.`);return}M.newline(),M.warn(`This will DELETE all existing migration files:`);for(let{namespace:e,migrationsDir:t}of n)M.log(` - ${e}: ${t}`);M.newline(),t||(await X.confirm({message:`Are you sure you want to delete these directories and start fresh?`,default:!1})||(M.info(`Operation cancelled.`),process.exit(0)),M.newline());for(let{namespace:e,migrationsDir:t}of n)try{await q.rm(t,{recursive:!0,force:!0}),M.success(`Deleted migration directory for ${j.bold(e)}`)}catch(e){throw M.error(`Failed to delete ${t}: ${e}`),e}M.newline(),M.info(`Migration directories cleared. Generating initial snapshot...`),M.newline()}async function generate(e){logBetaWarning(`tailordb migration`);let{config:t,plugins:n}=await loadConfig(e.configPath),r=getNamespacesWithMigrations(t,V.dirname(t.path));if(r.length===0){M.warn(`No TailorDB namespaces with migrations config found.`),M.info(`Add "migration: { directory: \\"./migrations\\" }" to your db config to enable migrations.`);return}let i=[],a=[],o=[];for(let t of e.renames??[]){let e=targetDepth(t);e>=2?o.push({raw:t,spec:parseNestedMemberRenameOption(t)}):e===1?i.push({raw:t,spec:parseRenameOption(t)}):a.push({raw:t,spec:parseTypeRenameOption(t)})}let s=[],c=[],l=[];for(let t of e.drops??[]){let e=targetDepth(t);e>=2?l.push({raw:t,spec:parseNestedMemberDropOption(t)}):e===1?s.push({raw:t,spec:parseDropOption(t)}):c.push({raw:t,spec:parseTypeDropOption(t)})}let u=(e.expandContracts??[]).map(e=>({raw:e,spec:parseExpandContractOption(e)})),d=i.length>0||a.length>0||o.length>0||s.length>0||c.length>0||l.length>0;if(e.init&&(d||u.length>0))throw R({code:`MIGRATION_GENERATE_OPTIONS_CONFLICT`,message:`--rename, --drop, and --expand-contract cannot be used together with --init.`,command:`tailordb migration generate`});let f=new Set(s.map(({spec:e})=>`${e.tableName}.${e.fieldName}`)),p=i.filter(({spec:e})=>f.has(`${e.tableName}.${e.previousFieldName}`));if(p.length>0)throw R({code:`MIGRATION_RENAME_DROP_CONFLICT`,message:`--rename and --drop conflict for: ${p.map(({spec:e})=>`${e.tableName}.${e.previousFieldName}`).join(`, `)}`,command:`tailordb migration generate`});let m=new Set(l.map(({spec:e})=>nestedMemberKey(e))),h=o.filter(({spec:e})=>m.has(nestedMemberKey({...e,path:e.previousPath})));if(h.length>0)throw R({code:`MIGRATION_RENAME_DROP_CONFLICT`,message:`--rename and --drop conflict for: ${h.map(({spec:e})=>nestedMemberKey({...e,path:e.previousPath})).join(`, `)}`,command:`tailordb migration generate`});let g=new Set(c.map(({spec:e})=>e.tableName)),_=a.filter(({spec:e})=>g.has(e.previousTableName));if(_.length>0)throw R({code:`MIGRATION_RENAME_DROP_CONFLICT`,message:`--rename and --drop conflict for: ${_.map(({spec:e})=>e.previousTableName).join(`, `)}`,command:`tailordb migration generate`});if(e.namespace!==void 0&&!e.dataOnly)throw R({code:`MIGRATION_GENERATE_OPTIONS_CONFLICT`,message:`--namespace can only be used together with --data-only.`,command:`tailordb migration generate`});if(e.dataOnly&&(e.init||d||u.length>0))throw R({code:`MIGRATION_GENERATE_OPTIONS_CONFLICT`,message:`--init, --rename, --drop, and --expand-contract cannot be used together with --data-only.`,command:`tailordb migration generate`});let v=e.dataOnly?resolveTargetNamespace(r,e.namespace):void 0,y=v===void 0?r:r.filter(({namespace:e})=>e===v);e.init&&await handleInitOption(r,e.yes);let b;n.length>0&&(b=new On(n));let{defineApplication:x}=await import(`./application-KZRJHv2j.mjs`),S=x({config:t,pluginManager:b}),C=[];for(let{namespace:e,migrationsDir:t}of y){M.info(`Processing namespace: ${j.bold(e)}`),assertValidMigrationFiles(t,e);let n=S.tailorDBServices.find(t=>t.namespace===e);if(!n){M.warn(`No TailorDB service found for namespace "${e}"`);continue}await n.loadTypes(),await n.processNamespacePlugins();let r=n.types;C.push({namespace:e,migrationsDir:t,currentSnapshot:createSnapshotFromLocalTypes(r,e),previousSnapshot:reconstructSnapshotFromMigrations(t)})}if(v!==void 0){await generateDataOnlyMigration(C,v,e);return}let w=matchFlagsToNamespaces(i,C,renameSpecApplies,`--rename does not match a removed + added field pair`),ee=matchFlagsToNamespaces(a,C,typeRenameSpecApplies,`--rename does not match a removed + added table pair`),te=matchFlagsToNamespaces(s,C,dropSpecApplies,`--drop does not match a removed field`),ne=matchFlagsToNamespaces(c,C,typeDropSpecApplies,`--drop does not match a removed table`),re=matchFlagsToNamespaces(o,C,nestedMemberRenameSpecApplies,`--rename does not match a removed + added nested member pair`),ie=matchFlagsToNamespaces(l,C,nestedMemberDropSpecApplies,`--drop does not match a removed nested member`),ae=new Map,oe=new Set,se=[];for(let{namespace:e,previousSnapshot:t,currentSnapshot:n}of C){if(!t)continue;let r=[];for(let i of u){let{spec:a}=i,o=t.tables[a.tableName]?.fields[a.fieldName],s=n.tables[a.tableName]?.fields[a.fieldName];if(!o||!s||!hasFieldShapeChange(o,s))continue;oe.add(i);let c=getExpandContractEligibility({previous:t,current:n,tableName:a.tableName,fieldName:a.fieldName});if(!c.eligible){se.push(`--expand-contract cannot convert ${i.raw} (namespace: ${e}): ${c.reason}`);continue}r.push(i)}ae.set(e,new Set(r.map(({spec:e})=>fieldKey(e.tableName,e.fieldName))))}let ce=u.filter(e=>!oe.has(e));if(ce.length>0)throw R({code:`MIGRATION_EXPAND_CONTRACT_UNMATCHED`,message:`--expand-contract does not match a field whose type or array-ness changed: ${ce.map(e=>e.raw).join(`, `)}`,command:`tailordb migration generate`});if(se.length>0)throw R({code:`MIGRATION_EXPAND_CONTRACT_INELIGIBLE`,message:se.join(`
567
567
  `)});let le=[];for(let t of C){let{namespace:n,previousSnapshot:r,currentSnapshot:i}=t;if(!r)continue;let a=compareSnapshots(r,i);if(!hasChanges(a)){t.diff=a;continue}let o=await resolveRenames(r,i,a,e,{fieldRenames:w.get(n)??[],typeRenames:ee.get(n)??[],fieldDrops:te.get(n)??[],typeDrops:ne.get(n)??[],nestedMemberRenames:re.get(n)??[],nestedMemberDrops:ie.get(n)??[]});t.diff=o.diff,le.push(...o.unresolved),t.expandPlans=await resolveExpandContractPlans({previousSnapshot:r,currentSnapshot:i,diff:o.diff,options:e,confirmedKeys:ae.get(n)??new Set})}if(le.length>0){let e=le.map(({namespace:e,label:t,targets:n})=>` - ${t} → ${n.join(`, `)}? (namespace: ${e})`).join(`
568
568
  `);throw R({code:`MIGRATION_RENAME_UNRESOLVED`,message:`Possible rename(s) detected:\n${e}`,suggestion:`Re-run with --rename "Table.oldField:newField" (field), --rename "OldTable:NewTable" (table), or --rename "Table.field.oldMember:newMember" (nested member) to record a rename and scaffold a data copy script, or --drop "Table.field" / --drop "Table" / --drop "Table.field.member" to confirm the removal.`,command:`tailordb migration generate`})}for(let{migrationsDir:t,currentSnapshot:n,previousSnapshot:r,diff:i,expandPlans:a}of C)r?await generateDiffFromSnapshot(r,k(i,`Migration diff was not resolved during preflight`),t,e,n,a??[]):await generateInitialSnapshot(n,t)}async function generateDataOnlyMigration(e,t,n){let r=e.find(e=>e.namespace===t);if(!r)throw R({code:`TAILORDB_NAMESPACE_NOT_FOUND`,message:`No TailorDB service found for namespace "${t}"`});let{migrationsDir:i,previousSnapshot:a,currentSnapshot:o}=r;if(!a)throw R({code:`MIGRATION_BASELINE_NOT_FOUND`,message:`Namespace "${t}" has no migration baseline.`,suggestion:`Create the initial schema snapshot first.`});let s=compareSnapshots(a,o);if(hasChanges(s))throw M.newline(),M.log(formatMigrationDiff(s)),M.newline(),R({code:`MIGRATION_SCHEMA_CHANGES_PENDING`,message:`Namespace "${t}" has schema changes that are not in migration files.`,suggestion:`Generate the schema migration first by running without --data-only.`});let c=getNextMigrationNumber(i),l=await generateDataOnlyMigrationFiles({diff:{...s,requiresMigrationScript:!0},migrationsDir:i,migrationNumber:c,snapshot:a,description:n.name});M.success(`Generated data-only migration ${j.bold(formatMigrationNumber(l.migrationNumber))}`),M.info(` Diff file: ${l.diffFilePath}`),M.info(` Migration script: ${l.migrateFilePath}`),M.info(` DB types: ${l.dbTypesFilePath}`),logPgliteSchemaResult(l),M.newline(),M.log(`This migration carries no schema changes.`),M.log(`Edit the script to implement the data transformation before running 'tailor deploy'.`),await openMigrationScriptInEditor(l.migrateFilePath)}function logPgliteSchemaResult(e){e.pgliteSchemaFilePath&&M.info(` PGlite schema: ${e.pgliteSchemaFilePath}`),e.pgliteSchemaError&&M.warn(` PGlite schema skipped: ${e.pgliteSchemaError}`)}async function openMigrationScriptInEditor(e){let t=getConfiguredEditorCommand();if(t){try{await q.access(e)}catch{return}M.newline(),M.info(`Opening ${V.basename(e)} in ${t}...`);try{await openInConfiguredEditor(e)}catch{return}}}async function resolveExpandContractPlans(e){let{previousSnapshot:t,currentSnapshot:n,diff:r,options:i,confirmedKeys:a}=e,o=new Set(a);if(!i.yes&&canPrompt())for(let e of r.changes){if(!isExpandContractCandidate(e))continue;let r=fieldKey(e.tableName,e.fieldName);o.has(r)||canConvertField({previous:t,current:n,tableName:e.tableName,fieldName:e.fieldName})&&(M.newline(),M.info(`${e.tableName}.${e.fieldName} changes from ${formatFieldShape(e.before)} to ${formatFieldShape(e.after)}, which cannot be applied in one step.`),await X.confirm({message:`Generate two migrations to convert ${e.tableName}.${e.fieldName} through a temporary field?`,default:!0})&&o.add(r))}return planExpandContract({previous:t,current:n,diff:r,confirmed:o}).plans}async function generateInitialSnapshot(e,t){let n=await generateSchemaFile(e,t,0);M.success(`Generated initial schema snapshot`),M.info(` File: ${n.filePath}`),M.info(` Tables: ${Object.keys(e.tables).length}`),M.log(`
569
569
  This is the baseline schema. Future changes will be tracked as diffs.`)}function targetDepth(e){return(e.split(`:`)[0]??``).split(`.`).length-1}function nestedMemberKey(e){return`${e.tableName}.${e.fieldName}.${e.path.join(`.`)}`}function matchFlagsToNamespaces(e,t,n,r){let i=new Map,a=new Set;for(let{namespace:r,previousSnapshot:o,currentSnapshot:s}of t){if(!o)continue;let t=e.filter(({spec:e})=>n(e,o,s));for(let e of t)a.add(e);i.set(r,t.map(e=>e.spec))}let o=e.filter(e=>!a.has(e));if(o.length>0)throw R({code:`MIGRATION_FLAG_UNMATCHED`,message:`${r}: ${o.map(e=>e.raw).join(`, `)}`,command:`tailordb migration generate`});return i}function availableNestedMemberRenameTargets(e,t){let n=e.previousPath.slice(0,-1);return e.added.filter(r=>!t.has(nestedMemberKey({...e,path:[...n,r]})))}async function promptNestedMemberRenameCandidate(e,t){let n=nestedMemberKey({...e,path:e.previousPath}),r=e.previousPath[e.previousPath.length-1]??``,[i]=t;return t.length===1&&i?await X.confirm({message:`${n} was removed and ${i} was added with a compatible type. Was it renamed to ${i}?`,default:!0})?i:void 0:await X.select({message:`${n} was removed. Was it renamed to one of these added members?`,choices:[...t.map(e=>({name:`Yes, renamed to ${e}`,value:e})),{name:`No, ${r} was removed`,value:null}]})??void 0}function availableRenameTargets(e,t){return e.added.filter(n=>!t.has(`${e.tableName}.${n.fieldName}`)).map(e=>e.fieldName)}async function promptRenameCandidate(e,t){let n=`${e.tableName}.${e.removed.fieldName}`,[r]=t;return t.length===1&&r?await X.confirm({message:`${n} was removed and ${r} was added with a compatible type. Was it renamed to ${r}?`,default:!0})?r:void 0:await X.select({message:`${n} was removed. Was it renamed to one of these added fields?`,choices:[...t.map(e=>({name:`Yes, renamed to ${e}`,value:e})),{name:`No, ${e.removed.fieldName} was removed`,value:null}]})??void 0}function availableTypeRenameTargets(e,t){return e.added.filter(e=>!t.has(e.tableName)).map(e=>e.tableName)}async function promptTypeRenameCandidate(e,t){let n=e.removed.tableName,[r]=t;return t.length===1&&r?await X.confirm({message:`${n} was removed and ${r} was added with a compatible schema. Was it renamed to ${r}?`,default:!0})?r:void 0:await X.select({message:`${n} was removed. Was it renamed to one of these added tables?`,choices:[...t.map(e=>({name:`Yes, renamed to ${e}`,value:e})),{name:`No, ${n} was removed`,value:null}]})??void 0}async function resolveRenames(e,t,n,r,i){let a=[...i.fieldRenames],o=new Set(a.flatMap(e=>[`${e.tableName}.${e.previousFieldName}`,`${e.tableName}.${e.fieldName}`])),s=new Set(i.fieldDrops.map(e=>`${e.tableName}.${e.fieldName}`)),c=[...i.typeRenames],l=new Set(c.flatMap(e=>[e.previousTableName,e.tableName])),u=new Set(i.typeDrops.map(e=>e.tableName)),d=[...i.nestedMemberRenames],f=new Set(d.flatMap(e=>[nestedMemberKey({...e,path:e.previousPath}),nestedMemberKey(e)])),p=new Set(i.nestedMemberDrops.map(e=>nestedMemberKey(e))),m=findTypeRenameCandidates(n).filter(e=>!u.has(e.removed.tableName)&&!l.has(e.removed.tableName)&&availableTypeRenameTargets(e,l).length>0),h=findRenameCandidates(n).filter(e=>!s.has(`${e.tableName}.${e.removed.fieldName}`)&&!o.has(`${e.tableName}.${e.removed.fieldName}`)&&availableRenameTargets(e,o).length>0),g=findNestedMemberRenameCandidates(n).filter(e=>{let t=nestedMemberKey({...e,path:e.previousPath});return!p.has(t)&&!f.has(t)&&availableNestedMemberRenameTargets(e,f).length>0}),_=[];if(r.yes||!canPrompt()){for(let e of m)_.push({namespace:n.namespace,label:e.removed.tableName,targets:availableTypeRenameTargets(e,l)});for(let e of h)_.push({namespace:n.namespace,label:`${e.tableName}.${e.removed.fieldName}`,targets:availableRenameTargets(e,o)});for(let e of g)_.push({namespace:n.namespace,label:nestedMemberKey({...e,path:e.previousPath}),targets:availableNestedMemberRenameTargets(e,f)})}else{for(let e of m){let t=availableTypeRenameTargets(e,l);if(t.length===0)continue;let n=await promptTypeRenameCandidate(e,t);n&&(c.push({previousTableName:e.removed.tableName,tableName:n}),l.add(e.removed.tableName),l.add(n))}for(let e of h){let t=availableRenameTargets(e,o);if(t.length===0)continue;let n=await promptRenameCandidate(e,t);n&&(a.push({tableName:e.tableName,previousFieldName:e.removed.fieldName,fieldName:n}),o.add(`${e.tableName}.${e.removed.fieldName}`),o.add(`${e.tableName}.${n}`))}for(let e of g){let t=availableNestedMemberRenameTargets(e,f);if(t.length===0)continue;let n=await promptNestedMemberRenameCandidate(e,t);if(n){let t={tableName:e.tableName,fieldName:e.fieldName,previousPath:e.previousPath,path:[...e.previousPath.slice(0,-1),n]};d.push(t),f.add(nestedMemberKey({...t,path:t.previousPath})),f.add(nestedMemberKey(t))}}}return a.length===0&&c.length===0&&d.length===0?{diff:n,unresolved:_}:{diff:compareSnapshots(e,t,{fieldRenames:a,typeRenames:c,nestedMemberRenames:d}),unresolved:_}}async function generateDiffFromSnapshot(e,t,n,r,i,a=[]){if(!hasChanges(t)){M.info(`No schema differences detected.`);return}M.newline(),M.log(formatMigrationDiff(t)),M.newline(),M.info(`Summary: ${formatDiffSummary(t)}`);let o=new Set(a.map(e=>fieldKey(e.tableName,e.fieldName))),s=t.breakingChanges.filter(e=>e.unsupported&&!(e.fieldName&&o.has(fieldKey(e.tableName,e.fieldName))));if(s.length>0){for(let e of s)M.newline(),M.error(`Unsupported change: ${e.tableName}.${e.fieldName}`),M.error(` ${e.reason}`);let t=new Set;for(let{tableName:n,fieldName:r}of s)r!==void 0&&canConvertField({previous:e,current:i,tableName:n,fieldName:r})&&t.add(fieldKey(n,r));if(t.size>0){M.newline(),M.info(`Convert these fields through a temporary field with:`);for(let e of t)M.info(` --expand-contract "${e}"`)}if(s.some(e=>e.showThreeStepHint)){M.newline();for(let e of getUnsupportedMigrationHintLines())M.info(e)}let n=s.map(e=>` - ${e.tableName}.${e.fieldName}: ${e.reason}`).join(`
@@ -914,4 +914,4 @@ This is the baseline schema. Future changes will be tracked as diffs.`)}function
914
914
  `).at(0)?.trim();return R({code:`invalid_sql`,message:`SQL parse error.`,suggestion:e??`The SQL query contains unsupported syntax.`})}return e.error instanceof Error?e.error:Error(t)}function isGraphQLInputComplete(e){if(e.trim().length===0)return!1;try{return Jr(e),!0}catch{return!1}}function isSqlInputComplete(e){let t=!1,n=!1,r=!1,i=0,a=null,o=!1;for(let s=0;s<e.length;s+=1){let c=k(e[s],`character at index ${s} missing`),l=e[s+1];if(r){c===`
915
915
  `&&(r=!1);continue}if(i>0){if(c===`/`&&l===`*`){i+=1,s+=1;continue}c===`*`&&l===`/`&&(--i,s+=1);continue}if(a!=null){e.startsWith(a,s)&&(s+=a.length-1,a=null);continue}if(t){if(c===`'`&&l===`'`){s+=1;continue}c===`'`&&(t=!1);continue}if(n){if(c===`"`&&l===`"`){s+=1;continue}c===`"`&&(n=!1);continue}if(c===`-`&&l===`-`){r=!0,s+=1;continue}if(c===`/`&&l===`*`){i=1,s+=1;continue}if(c===`'`){o=!1,t=!0;continue}if(c===`"`){o=!1,n=!0;continue}if(c===`$`){let t=e.slice(s),n=t.match(/^\$[A-Za-z_][A-Za-z0-9_]*\$/)??t.match(/^\$\$/);if(n!=null){o=!1,a=n[0],s+=n[0].length-1;continue}}if(c===`;`){o=!0;continue}/\s/.test(c)||(o=!1)}return o&&!t&&!n&&i===0&&a==null}function extractTableNamesFromSql(e){let t;try{t=qr(e)}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`SQL parse error: ${t}\nIf your table name is a reserved keyword (e.g. User), wrap it in double quotes: SELECT * FROM "User"`,{cause:e})}let n=new Set,r=Kr(e=>({tableRef:t=>(n.add(t.name),e.super().tableRef(t),t)}));for(let e of t)r.statement(e);return[...n]}function collectAliasMap(e){let t=new Map;for(let n of e)if(n.type===`table`){let e=n.name.name,r=n.name.alias??e;t.set(r,e)}return t}function extractColumnTemplate(e){try{let t=qr(e);for(let e of t){if(e.type!==`select`||!e.columns)continue;let t=collectAliasMap(e.from??[]),n=[],r=!1;for(let i of e.columns)if(i.expr.type===`ref`&&i.expr.name===`*`){if(r=!0,i.expr.table){let e=t.get(i.expr.table.name);n.push({type:`wildcard`,tableNames:e?[e]:[]})}else n.push({type:`wildcard`,tableNames:[...new Set(t.values())]})}else{let e=i.alias?.name??(i.expr.type===`ref`?i.expr.name:null);e&&n.push({type:`explicit`,name:e})}return r?n:null}return null}catch{return null}}async function loadTypeFieldOrder(e,t){let n=new Map,r=e.db?.[t];if(!r||!(`files`in r)||r.files.length===0)return n;let i=V.dirname(e.path),a=pn(r,i);return await Promise.all(a.map(async e=>{try{let t=await import(fr(e).href);for(let e of Object.values(t)){let t=fn.safeParse(mn(e));t.success&&n.set(t.data.name,Object.keys(t.data.fields))}}catch{}})),n}const Hc=H.enum([`sql`,`gql`]),Uc=H.object({workspaceId:H.string().optional(),profile:H.string().optional(),configPath:H.string().optional(),engine:Hc,machineUser:H.string().optional(),machineUserSource:H.enum([`option`,`env`]).optional()}),Wc=Uc.extend({query:H.string()});async function getNamespaceFromSqlQuery(e,t,n,r){if(r.length===0)throw Error(`No namespaces found in configuration.`);if(r.length===1)return k(r[0],`namespace missing`);let i=extractTableNamesFromSql(t);if(i.length===0)throw Error(`Could not infer namespace from query. Detected namespaces: ${r.join(`, `)}.`);let a=await resolveTableNamespaces({workspaceId:e,namespaces:r,tableNames:i,client:n}),o=i.filter(e=>!a.has(e));if(o.length>0)throw Error(`Could not find namespace for tables in query: ${o.join(`, `)}.`);let s=new Set(a.values());if(s.size===1)return k([...s][0],`namespace from types missing`);throw Error(`Query references tables from multiple namespaces: ${[...s].join(`, `)}.`)}async function loadOptions(e){let t=parseOptions(Uc,e),n=await loadMachineUserName({machineUser:t.machineUser,machineUserSource:t.machineUserSource,profile:t.profile});if(!n)throw Error(`Machine user is required. Specify --machine-user, set TAILOR_PLATFORM_MACHINE_USER_NAME, or set a profile default with 'tailor profile update <profile> --machine-user <name>'.`);let r=await loadAccessToken({profile:t.profile}),i=await F(r),a=await loadWorkspaceId({workspaceId:t.workspaceId,profile:t.profile}),{config:o}=await loadConfig(e.configPath),s=extractAllNamespaces(o),{application:c}=await i.getApplication({workspaceId:a,applicationName:o.name});if(!c?.authNamespace)throw Error(`Application ${o.name} does not have an auth configuration.`);let{machineUser:l}=await i.getAuthMachineUser({workspaceId:a,authNamespace:c.authNamespace,name:n});if(!l)throw Error(`Machine user ${n} not found.`);return{engine:t.engine,client:i,workspaceId:a,config:o,application:c,machineUserResource:l,namespaces:s}}async function sqlQuery(e,t,n){let r=splitSqlStatements(n.query),i=await executeScript({client:e,workspaceId:n.workspaceId,name:`query-sql-${n.namespace}.js`,code:n.bundledCode,arg:{namespace:n.namespace,queries:r},invoker:t});if(!i.success)throw Error(i.error);return{engine:`sql`,namespace:n.namespace,query:n.query,result:parseExecutionResult(i.result)}}async function gqlQuery(e,t,n,r,i){let{access_token:a}=await bt(n.url,r.clientId,r.clientSecret),o=await executeScript({client:e,workspaceId:i.workspaceId,name:`query-gql.js`,code:i.bundledCode,arg:{endpoint:`${n.url}/query`,accessToken:a,query:i.query},invoker:t});if(!o.success)throw Error(o.error);return{engine:`gql`,query:i.query,result:parseExecutionResult(o.result)}}function parseExecutionResult(e){if(!e)return null;try{return JSON.parse(e)}catch{return e}}async function resolveQueryCommandInput(e){return e.query==null?e.file==null?e.edit?await resolveEditedQueryInput(e.engine):{mode:`repl`}:{mode:`query`,query:await q.readFile(e.file,`utf-8`)}:{mode:`query`,query:e.query}}async function resolveEditedQueryInput(e){if(!process.stdin.isTTY||!process.stdout.isTTY)throw Error(`Non-interactive terminals are not supported. Pass -q/--query or -f/--file to run a query.`);let t=getEditorCommand(),n=await q.mkdtemp(V.join(jr(),`tailor-query-`)),r=e===`sql`?`sql`:`graphql`,i=V.join(n,`query.${r}`);try{await q.writeFile(i,``,`utf-8`);try{await openInEditor(i,t)}catch(e){throw Error(`Failed to open query editor "${t}": ${e instanceof Error?e.message:String(e)}`,{cause:e})}let e=await q.readFile(i,`utf-8`);return e.trim().length===0||e===``?{mode:`abort`}:{mode:`query`,query:e}}finally{await q.rm(n,{recursive:!0,force:!0})}}async function query(e){let t=parseOptions(Wc,e);return await(await prepareQueryExecutor(t))(t.query)}async function prepareQueryExecutor(e){let{client:t,workspaceId:n,config:r,application:i,machineUserResource:a,engine:o,namespaces:s}=await loadOptions(e),c=await bundleQueryScript(o,V.dirname(r.path)),l=Xn(Ie,{namespace:i.authNamespace,machineUserName:a.name});return async e=>{let u;try{switch(o){case`sql`:return u=await getNamespaceFromSqlQuery(n,e,t,s),reorderSqlColumns(await sqlQuery(t,l,{workspaceId:n,namespace:u,bundledCode:c,query:e}),r,u,e);case`gql`:return await gqlQuery(t,l,i,a,{workspaceId:n,bundledCode:c,query:e});default:throw Error(`Unsupported query engine: ${o}`)}}catch(e){throw mapQueryExecutionError({error:e,engine:o,namespace:u,machineUser:a.name})}}}function resolveReplCommand(e){let t=e.trim();return t.startsWith(`\\`)?t===`\\q`||t===`\\quit`?`quit`:t===`\\help`||t===`\\h`||t===`\\?`?`help`:t===`\\clear`||t===`\\c`?`clear`:`unknown`:null}function clearReplScreen(){process.stdout.write(`\x1Bc`)}function sanitizeHistoryScope(e){return e.replace(/[^a-zA-Z0-9._-]/g,`_`)}function getReplHistoryPath(e,t,n){if(!_r)return;let r=[t,n].filter(e=>!!e).map(sanitizeHistoryScope).join(`-`),i=e===`sql`?`sql`:`gql`,a=r?`-${r}`:``;return V.join(_r,`tailor-platform`,`query-history-${i}${a}.json`)}function createReplValidator(e){return t=>{let n=t.trim();if(n!==``&&resolveReplCommand(n)===null)return e===`sql`?isSqlInputComplete(t)?void 0:`SQL statement is incomplete (missing ';').`:isGraphQLInputComplete(t)?void 0:`GraphQL document is incomplete.`}}async function runRepl(e){if(!process.stdin.isTTY||!process.stdout.isTTY)throw Error(`Non-interactive terminals are not supported. Pass -q/--query or -f/--file to run a query.`);let t=await prepareQueryExecutor(e),n=getReplHistoryPath(e.engine,e.profile,e.workspaceId),r=createReplValidator(e.engine),{highlightSqlLine:i,highlightGraphqlLine:a,replTransform:o}=await import(`./repl-editor-BG1aDOfH.mjs`),s=e.engine===`sql`?i:a,c=Gr({prefix:``,preferNewlineOnEnter:e.newlineOnEnter,validate:r,highlight:s,transform:o,theme:{submitRender:`preserve`},history:n?{filePath:n,maxEntries:100}:[],helpFooter:{items:[`submit`,`newline`],maxLines:1}});for(M.info(`Entering ${e.engine.toUpperCase()} REPL mode.`),M.info(`Type \\help for usage, \\q to quit.`);;){let[n,r]=await c(`${e.engine}> `);if(r?.kind===`cancel`){if(n.length===0)return;continue}if(r?.kind===`eof`)return;let i=n.trim();if(i===``)continue;let a=resolveReplCommand(i);if(a===`quit`)return;if(a===`help`){printReplHelp(e.engine);continue}if(a===`clear`){clearReplScreen();continue}if(a===`unknown`){M.warn(`Unknown command: ${i}`);continue}try{let n=await t(i);n.engine===`sql`?printSqlResult(n,{json:e.json}):printGqlResult(n,{json:e.json})}catch(e){if(Cn(e)){M.log(e.format());continue}if(e instanceof Error){M.error(e.message);continue}M.error(String(e))}}}function printReplHelp(e){M.log(`REPL commands:`),M.log(` \\help, \\h, \\? Show this help`),M.log(` \\q, \\quit Exit REPL`),M.log(` \\clear, \\c Clear the screen`),M.log(``),M.log(`Key bindings (see footer for terminal-specific submit/newline keys):`),M.log(` Ctrl+J Insert newline (always available)`),M.log(` Ctrl+C Cancel current input`),M.log(` Ctrl+D Exit REPL (on empty input)`),M.log(` Ctrl+Z / Ctrl+Y Undo / Redo`),M.log(` Up/Down (first/last line) Navigate history`),M.log(``),M.log(`Editing aids:`),M.log(` Syntax highlighting Enabled for the current engine`),M.log(` ( [ { Auto-inserts the matching closing bracket`),M.log(` Enter after open bracket Adds one indent level and closes the block`),M.log(``),M.log(e===`sql`?`Input must end with ';' to submit.`:`Input must be a complete GraphQL document to submit.`)}async function querySql(e){let t=await query({...e,engine:`sql`});if(t.engine!==`sql`)throw Error(`Expected sql engine result but got: ${t.engine}`);return t}async function queryGql(e){let t=await query({...e,engine:`gql`});if(t.engine!==`gql`)throw Error(`Expected gql engine result but got: ${t.engine}`);return t}async function reorderSqlColumns(e,t,n,r){if(!isSQLExecutionResult(e.result)||e.result.rows.length===0)return e;let i=extractColumnTemplate(r);if(!i)return e;try{let r=buildExpectedColumnOrder(i,await loadTypeFieldOrder(t,n));if(r.length===0)return e;let a=e.result.rows.map(e=>reorderRowByTemplate(e,r));return{...e,result:{...e.result,rows:a}}}catch{return e}}const Gc=[`id`];function buildExpectedColumnOrder(e,t){let n=[];for(let r of e)if(r.type===`explicit`)n.push(r.name);else for(let e of r.tableNames)n.push(...Gc),n.push(...t.get(e)??[]);return n}function reorderRowByTemplate(e,t){let n={},r=new Set(Object.keys(e)),i=new Map;for(let e of r)i.set(e.toLowerCase(),e);for(let a of t){let t=i.get(a.toLowerCase());t!=null&&r.has(t)&&(n[t]=e[t],r.delete(t),i.delete(a.toLowerCase()))}for(let t of r)n[t]=e[t];return n}const Kc=Y({name:`query`,description:`Run SQL/GraphQL query.`,args:H.strictObject({...ai,engine:B(Hc,{description:`Query engine (sql or gql)`}),query:B(H.string().optional(),{alias:`q`,description:`Query string to execute directly; omit to start REPL mode`}),file:B(H.string().optional(),{alias:`f`,description:`Read query string from file; omit to start REPL mode`}),edit:B(H.boolean().default(!1),{description:`Open a temporary file in your editor; omit to start REPL mode`}),"machine-user":B(H.string().optional(),{alias:`m`,description:`Machine user name for query execution. Falls back to the active profile's default machine user.`,env:`TAILOR_PLATFORM_MACHINE_USER_NAME`}),"newline-on-enter":B(H.boolean().optional(),{description:`REPL: when true, Enter inserts a newline and Shift+Enter submits. Use --no-newline-on-enter to swap.`})}).superRefine((e,t)=>{e.query!=null&&e.file!=null&&t.addIssue({code:`custom`,path:[`file`],message:`Pass either -q/--query or -f/--file, not both.`}),e.edit&&e.query!=null&&t.addIssue({code:`custom`,path:[`edit`],message:`Pass only one of --edit, -q/--query, or -f/--file.`}),e.edit&&e.file!=null&&t.addIssue({code:`custom`,path:[`edit`],message:`Pass only one of --edit, -q/--query, or -f/--file.`})}),run:async e=>{let t=await resolveQueryCommandInput({query:e.query,file:e.file,edit:e.edit,engine:e.engine}),n={workspaceId:e[`workspace-id`],profile:e.profile,configPath:e.config,engine:e.engine,machineUser:e[`machine-user`],machineUserSource:resolveMachineUserInputSource(e[`machine-user`])};if(t.mode===`abort`){M.info(`Editor closed without a query. Nothing was executed.`);return}if(t.mode===`repl`){let t=e[`newline-on-enter`]??ut(process.env.TAILOR_QUERY_NEWLINE_ON_ENTER)??!0;await runRepl({...n,json:e.json,newlineOnEnter:t});return}let r=t.query;if(e.engine===`sql`){printSqlResult(await querySql({...n,query:r}),{json:e.json});return}printGqlResult(await queryGql({...n,query:r}),{json:e.json})}});function isSQLExecutionResult(e){if(!e||typeof e!=`object`)return!1;let t=e;return Array.isArray(t.rows)&&typeof t.rowCount==`number`}function printSingleSqlResult(e,t={}){if(e.rows.length===0){if(t.json){M.out({results:[],rowCount:0});return}M.info(`No rows returned.`);return}if(t.json){M.out({results:e.rows,rowCount:e.rowCount});return}M.out(e.rows,{showNull:!0}),M.out(`rows: ${e.rowCount}`)}function splitSqlStatements(e){let t=qr(e,{locationTracking:!0});return t.map((n,r)=>{let i=k(n._location,`SQL statement location missing`).start,a=t[r+1],o=a===void 0?e.length:k(a._location,`SQL statement location missing`).start;return e.substring(i,o)})}function isSQLExecutionResultArray(e){return Array.isArray(e)&&e.length>0&&e.every(isSQLExecutionResult)}function printSqlResult(e,t={}){if(isSQLExecutionResultArray(e.result)){if(t.json){M.out(e.result.map(e=>({results:e.rows,rowCount:e.rowCount})));return}let n=splitSqlStatements(e.query);for(let r=0;r<e.result.length;r++)r>0&&M.log(``),M.info(n[r]??`Statement ${r+1}`),printSingleSqlResult(k(e.result[r],`SQL result at index ${r} missing`),t);return}if(isSQLExecutionResult(e.result)){printSingleSqlResult(e.result,t);return}M.out({engine:e.engine,query:e.query,result:e.result})}function printGqlResult(e,t={}){if(t.json){M.out({result:e.result});return}M.out(JSON.stringify(e.result,null,2))}function escapeData(e){return e.replaceAll(`%`,`%25`).replaceAll(`\r`,`%0D`).replaceAll(`
916
916
  `,`%0A`)}function escapeProperty(e){return escapeData(e).replaceAll(`:`,`%3A`).replaceAll(`,`,`%2C`)}function jsonRequestedInArgv(){let e=process.argv.slice(2),t=e.indexOf(`--`);return(t===-1?e:e.slice(0,t)).some(e=>{let t=e.indexOf(`=`),n=t===-1?e:e.slice(0,t);return n!==`--json`&&n!==`-j`?!1:t===-1||ut(e.slice(t+1))!==!1})}function annotationsEnabled(e){return e||jsonRequestedInArgv()||process.env.GITHUB_ACTIONS!==`true`?!1:ut(process.env.TAILOR_GITHUB_ACTIONS_ANNOTATIONS)!==!1}function realPath(e){try{return nr(qn(e))}catch{return qn(e)}}function workspaceRelativePath(e){let t=process.env.GITHUB_WORKSPACE;if(!t||!Wn(e))return;let n=Kn(realPath(t),realPath(e));if(n===``||Wn(n))return;let r=n.split(Jn);if(r[0]!==`..`)return r.join(`/`)}function formatAnnotation(e,t,n={}){let r=[];return n.title!==void 0&&r.push(`title=${escapeProperty(lr(n.title))}`),n.file!==void 0&&r.push(`file=${escapeProperty(n.file)}`),n.line!==void 0&&r.push(`line=${n.line}`),`::${e}${r.length>0?` ${r.join(`,`)}`:``}::${escapeData(lr(t))}\n`}function formattedMessage(e){let t=e.format;if(typeof t!=`function`)return;let n=t.call(e);return typeof n==`string`?n:void 0}function describeTerminalError(e,t){if(Cn(e))return{message:e.format(),title:e.code||`CLI_ERROR`};if(e instanceof Error){let n=Yt(e).code??(e.name||`Error`),r=formattedMessage(e);if(r!==void 0)return{message:r,title:n};let i=t?`\nSuggestion: ${t}`:``;return{message:`${e.message}${i}`,title:n}}return{message:`Unknown error: ${String(e)}`,title:`UNKNOWN_ERROR`}}function withSourceLocation(e,t){return en(e,{location:t})}function annotateTerminalError(e,t){if(!annotationsEnabled(t.jsonMode))return;let{message:n,title:r}=describeTerminalError(e,t.suggestion);process.stderr.write(formatAnnotation(`error`,n,{title:r,...sourceLocation(e)}))}function sourceLocation(e){if(!(e instanceof Error))return{};let t=Yt(e).location;if(!t)return{};let n=workspaceRelativePath(t.file);return n===void 0?{}:t.line===void 0?{file:n}:{file:n,line:t.line}}function isNativeTypeScriptRuntime(){return isBun()||isDeno()}function isBun(){return`Bun`in globalThis}function isDeno(){return`Deno`in globalThis}async function registerTsHook(e){if(isNativeTypeScriptRuntime())return;let{resolveSync:t,loadSync:n}=await import(e.href);Rn.registerHooks({resolve:t,load:n})}export{ac as $,protoGqlPermission as $n,apiCall as $r,formatWaitError as $t,listWorkflows as A,Zr as Ai,us as An,loadSnapshot as Ar,waitForExecution as At,hc as B,checkMigrationDiffs as Bn,formatMigrationNumber as Br,listExecutors as Bt,getAppHealth as C,runDefaultSubCommand as Ci,humanizeRelativeTime as Cn,assertMigrationNumberExists as Cr,serializeError as Ct,xc as D,oi as Di,ms as Dn,getMigrationFiles as Dr,extractAllNamespaces as Dt,waitWorkflowExecution as E,ri as Ei,writeWorkspaceExpiry as En,getMigrationFilePath as Er,loadTailorDBNamespaces as Et,bundleSeedDumpScript as F,parseDuration as Fi,parseAppIds as Fn,sanitizeMigrationLabel as Fr,listWebhookExecutors as Ft,show as G,toTailorDBDeployInput as Gn,subscribesToEvents as Gr,watchExecutorJob as Gt,logBetaWarning as H,formatRemoteVerificationResults as Hn,formatDiffSummary as Hr,getExecutorWaitFailureMessage as Ht,bundleSeedScript as I,recoveryContextArgs as Ii,planAppIds as In,compareLocalTypesWithSnapshot as Ir,Rs as It,lc as J,updateMigrationLabel as Jn,zi as Jr,As as Jt,dc as K,verifyRemoteSchema as Kn,resourceTrn as Kr,js as Kt,generate as L,resolveMachineUserInputSource as Li,removeAdoptedConfigIds as Ln,compareSnapshots as Lr,Is as Lt,yc as M,ii as Mi,Q as Mn,ya as Mr,listFunctionRegistries as Mt,loadSeedContext as N,ci as Ni,os as Nn,createMigrationHistoryId as Nr,Bs as Nt,resumeWorkflow as O,createCommonArgs as Oi,parseAge as On,getNextMigrationNumber as Or,extractOwnedNamespaces as Ot,chunkSeedData as P,paginationArgs as Pi,findAppIdLock as Pn,handleOptionalToRequiredError as Pr,getFunctionRegistry as Pt,oc as Q,generateAllTypeManifestsFromSnapshot as Qn,loadOperatorWorkspaceContext as Qr,listWorkflowExecutions as Qt,vc as R,toPageDirection as Ri,ensureConfigId as Rn,ia as Rr,triggerExecutor as Rt,Ec as S,Y as Si,formatTimestamp as Sn,xo as Sr,errorToJson as St,Sc as T,ti as Ti,fetchWorkspaceExpiry as Tn,getMigrationDirPath as Tr,loadApplicationNamespaces as Tt,pc as U,logMissingCheckpointGuidance as Un,formatMigrationDiff as Ur,Ms as Ut,generateSchemaFile as V,fetchRemoteSchemaSnapshot as Vn,parseMigrationNumberArg as Vr,getExecutorJob as Vt,deployStaticWebsite as W,logRemoteDriftGuidance as Wn,hasChanges as Wr,listExecutorJobs as Wt,updateOrganization as X,bundleMigrationScript as Xn,writeMetadataLabels as Xr,ks as Xt,cc as Y,formatMigrationScriptCommand as Yn,Bi as Yr,getWorkflow as Yt,organizationTree as Z,compareSnapshotWithRemote as Zn,X as Zr,getWorkflowExecution as Zt,getWorkspace as _,removeLegacyUserAlias as _i,createWorkspace$1 as _n,Co as _r,getMachineUserToken as _t,Kc as a,hasUserTokenEntry as ai,isFunctionExecutionTerminalStatus as an,captureFileState as ar,ec as at,removeProfilesForWorkspaces as b,saveUserTokens as bi,_s as bn,ko as br,listMachineUsers as bt,zc as c,loadConfigPath as ci,getExecutor as cn,formatSchemaDrifts as cr,getFolder as ct,listUsers as d,loadPlatformClientConfig as di,deployMigrationTestBaseline as dn,assertValidMigrationFiles as dr,Js as dt,assertWritable as ei,isRetryableWaitError as en,fetchRemoteMigrationNumber as er,listOrganizations as et,Fc as f,loadStoredUserTokens as fi,deployMigrationTestTarget as fn,reconstructSnapshotFromMigrations as fr,createFolder as ft,Ac as g,registerTokenSecrets as gi,createValidatedWorkspaceWithClient as gn,bo as gr,getOAuth2Client as gt,restoreWorkspace as h,readPlatformConfig as hi,ys as hn,So as hr,Gs as ht,query as i,hasAnyUserTokenEntry as ii,functionExecutionStatusToString as in,selectTargetNamespace as ir,updateFolder as it,truncate as j,loadEnvFiles as ji,parseOptions as jn,ba as jr,Hs as jt,bc as k,ai as ki,ds as kn,loadDiff as kr,executeScript as kt,removeUser as l,loadConsoleBaseUrl as li,deploy as ln,createSnapshotFromLocalTypes as lr,Xs as lt,Mc as m,platformConfigFromProfile as mi,listWorkspaces as mn,To as mr,listOAuth2Clients as mt,annotateTerminalError as n,deleteUserTokens as ni,formatFunctionLogEntry as nn,getNamespacesWithMigrations as nr,getOrganization as nt,Vc as o,loadAccessToken as oi,toFunctionLogEntryInfo as on,captureMigrationFileState as or,listFolders as ot,inviteUser as p,loadWorkspaceId as pi,bs as pn,Eo as pr,Ks as pt,remove as q,getMigrationMachineUser as qn,Vi as qr,startWorkflow as qt,withSourceLocation as r,fetchLatestToken as ri,formatFunctionLogLines as rn,migrationConfigNotFoundError as rr,nc as rt,updateUser as s,loadAuthStatus as si,ws as sn,createRemoteComparableSnapshot as sr,Qs as st,registerTsHook as t,loadConfig as ti,colorizeFunctionExecutionStatus as tn,fetchRemoteMigrationState as tr,ic as tt,Lc as u,loadMachineUserName as ui,deployFromCLI as un,createSnapshotType as ur,deleteFolder as ut,Oc as v,resolveConfigUser as vi,workspaceDisplayName as vn,Do as vr,Ws as vt,wc as w,ni as wi,clearWorkspaceExpiry as wn,getLatestMigrationNumber as wr,resolvePluginConfig as wt,listApps as x,writePlatformConfig as xi,formatKeyValueTable as xn,Oo as xr,generate$1 as xt,deleteWorkspace as y,resolveUserTokenKey as yi,workspaceInfosWithFolderNames as yn,wo as yr,Us as yt,_c as z,J as zi,generateUserTypes as zn,normalizeSchemaSnapshot as zr,Ns as zt};
917
- //# sourceMappingURL=register-ts-hook-BD3ArLqY.mjs.map
917
+ //# sourceMappingURL=register-ts-hook-Djjnj5R8.mjs.map