@tailor-platform/sdk 2.37.0 → 2.39.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 (113) hide show
  1. package/CHANGELOG.md +124 -0
  2. package/dist/{application-83WVdH85.mjs → application-OeNMQzOC.mjs} +1 -1
  3. package/dist/application-mNOJx9Y2.mjs +207 -0
  4. package/dist/application-mNOJx9Y2.mjs.map +1 -0
  5. package/dist/cli/commands/deploy/deploy.d.mts +1 -0
  6. package/dist/cli/commands/deploy/tailordb/migration-validation.d.mts +2 -0
  7. package/dist/cli/commands/executor/trigger.d.mts +1 -0
  8. package/dist/cli/commands/generate/seed/bundler.d.mts +7 -5
  9. package/dist/cli/commands/workspace/transform.d.mts +1 -2
  10. package/dist/cli/lib.d.mts +5 -3
  11. package/dist/cli/lib.mjs +1 -1
  12. package/dist/cli/lib.mjs.map +1 -1
  13. package/dist/cli/main.mjs +67 -61
  14. package/dist/cli/main.mjs.map +1 -1
  15. package/dist/cli/shared/args.d.mts +14 -5
  16. package/dist/cli/shared/build-options.d.mts +13 -0
  17. package/dist/cli/shared/client.d.mts +15 -3
  18. package/dist/cli/shared/error-json.d.mts +12 -26
  19. package/dist/cli/shared/script-workflow.d.mts +65 -0
  20. package/dist/cli/shared/seed-chunker.d.mts +3 -3
  21. package/dist/client-CqiPQgMG.mjs +2 -0
  22. package/dist/client-CqiPQgMG.mjs.map +1 -0
  23. package/dist/client-DO2_Xz_z.mjs +1 -0
  24. package/dist/completion/zsh-worker.zsh +193 -74
  25. package/dist/configure/index.mjs +1 -1
  26. package/dist/configure/index.mjs.map +1 -1
  27. package/dist/configure/services/auth/types.d.mts +20 -3
  28. package/dist/configure/services/executor/operation.d.mts +5 -4
  29. package/dist/configure/services/executor/trigger/webhook.d.mts +8 -1
  30. package/dist/configure/services/http-adapter/http-adapter.d.mts +1 -1
  31. package/dist/configure/services/index.d.mts +0 -1
  32. package/dist/configure/services/tailordb/types.d.mts +9 -0
  33. package/dist/context-CYBcQZyO.mjs +1 -0
  34. package/dist/context-aAgFGDBD.mjs +23 -0
  35. package/dist/context-aAgFGDBD.mjs.map +1 -0
  36. package/dist/{crashreport-D_wf4GZh.mjs → crashreport-CQTAlnbA.mjs} +2 -2
  37. package/dist/{crashreport-D_wf4GZh.mjs.map → crashreport-CQTAlnbA.mjs.map} +1 -1
  38. package/dist/crashreport-GRnWyDnF.mjs +1 -0
  39. package/dist/{errors-Dmdnq0zi.mjs → errors-9OOL3xOM.mjs} +6 -5
  40. package/dist/errors-9OOL3xOM.mjs.map +1 -0
  41. package/dist/field_behavior_pb-B196sUx6.mjs +2 -0
  42. package/dist/field_behavior_pb-B196sUx6.mjs.map +1 -0
  43. package/dist/{kysely-type-DVL90_oX.mjs → kysely-type-DhAZqdQg.mjs} +14 -10
  44. package/dist/kysely-type-DhAZqdQg.mjs.map +1 -0
  45. package/dist/notification_resource_pb-BZ0hCA01.mjs +1 -0
  46. package/dist/notification_resource_pb-Dwzah7gO.mjs +2 -0
  47. package/dist/notification_resource_pb-Dwzah7gO.mjs.map +1 -0
  48. package/dist/plugin/builtin/kysely-type/index.mjs +1 -1
  49. package/dist/register-ts-hook-CORbtrSN.mjs +1105 -0
  50. package/dist/register-ts-hook-CORbtrSN.mjs.map +1 -0
  51. package/dist/repl-editor-Bposemei.mjs +2 -0
  52. package/dist/repl-editor-Bposemei.mjs.map +1 -0
  53. package/dist/resource_pb-elY668ZB.mjs +2 -0
  54. package/dist/resource_pb-elY668ZB.mjs.map +1 -0
  55. package/dist/{secret-file-DiuEcLFP.mjs → secret-file-CSXzcg4c.mjs} +2 -2
  56. package/dist/{secret-file-DiuEcLFP.mjs.map → secret-file-CSXzcg4c.mjs.map} +1 -1
  57. package/dist/service-B2vx6CGM.mjs +2 -0
  58. package/dist/{service-DDrbdyd-.mjs.map → service-B2vx6CGM.mjs.map} +1 -1
  59. package/dist/service-Bkz_TB5v.mjs +9 -0
  60. package/dist/service-Bkz_TB5v.mjs.map +1 -0
  61. package/dist/service-Dffd4how.mjs +1 -0
  62. package/dist/service_pb-Bethc2NW.mjs +1 -0
  63. package/dist/service_pb-CfpSriCy.mjs +2 -0
  64. package/dist/service_pb-CfpSriCy.mjs.map +1 -0
  65. package/dist/syntax-diagnostic-BQgOV8Fz.mjs +2 -0
  66. package/dist/syntax-diagnostic-BQgOV8Fz.mjs.map +1 -0
  67. package/dist/validation-errors-ChvCG6wT.mjs +3 -0
  68. package/dist/validation-errors-ChvCG6wT.mjs.map +1 -0
  69. package/{LICENSE → dist/vendor/graphql/LICENSE} +6 -6
  70. package/dist/vendor/graphql/language/KindTypeMap.d.mts +3 -0
  71. package/dist/vendor/graphql/language/ast.d.mts +784 -0
  72. package/dist/vendor/graphql/language/kinds_.d.mts +203 -0
  73. package/dist/vendor/graphql/language/source.d.mts +46 -0
  74. package/dist/vendor/graphql/language/tokenKind.d.mts +35 -0
  75. package/dist/vitest/index.mjs +1 -1
  76. package/dist/vitest/index.mjs.map +1 -1
  77. package/dist/workspace_resource_pb-Cow7mrJY.mjs +2 -0
  78. package/dist/workspace_resource_pb-Cow7mrJY.mjs.map +1 -0
  79. package/docs/cli/application.md +16 -12
  80. package/docs/cli/executor.md +13 -17
  81. package/docs/cli/function.md +1 -1
  82. package/docs/cli/notification.md +128 -0
  83. package/docs/cli/tailordb.md +26 -57
  84. package/docs/cli/workspace.md +3 -4
  85. package/docs/cli-reference.md +228 -48
  86. package/docs/configuration.md +28 -0
  87. package/docs/github-actions.md +241 -38
  88. package/docs/migration/v2.md +5 -3
  89. package/docs/services/auth.md +5 -0
  90. package/docs/services/executor.md +2 -0
  91. package/docs/services/tailordb/index.md +6 -2
  92. package/docs/services/tailordb/migration.md +54 -57
  93. package/docs/testing.md +0 -1
  94. package/package.json +25 -21
  95. package/dist/application-Cida-j1g.mjs +0 -207
  96. package/dist/application-Cida-j1g.mjs.map +0 -1
  97. package/dist/configure/services/http-adapter/index.d.mts +0 -2
  98. package/dist/crashreport-C2AcQNTe.mjs +0 -1
  99. package/dist/errors-Dmdnq0zi.mjs.map +0 -1
  100. package/dist/kysely-type-DVL90_oX.mjs.map +0 -1
  101. package/dist/register-ts-hook-Ht4zCseV.mjs +0 -1115
  102. package/dist/register-ts-hook-Ht4zCseV.mjs.map +0 -1
  103. package/dist/repl-editor-DkrCZmmg.mjs +0 -2
  104. package/dist/repl-editor-DkrCZmmg.mjs.map +0 -1
  105. package/dist/service-CZ0EdD2-.mjs +0 -10
  106. package/dist/service-CZ0EdD2-.mjs.map +0 -1
  107. package/dist/service-DDrbdyd-.mjs +0 -2
  108. package/dist/service-WhSyhaho.mjs +0 -1
  109. package/dist/service_pb-BMHhVot2.mjs +0 -1
  110. package/dist/service_pb-BxMSK0gg.mjs +0 -2
  111. package/dist/service_pb-BxMSK0gg.mjs.map +0 -1
  112. package/dist/workspace_resource_pb-7smKERdZ.mjs +0 -2
  113. package/dist/workspace_resource_pb-7smKERdZ.mjs.map +0 -1
package/dist/cli/main.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import{r as e}from"../field-parse-BQhUAbpM.mjs";import{Bt as t,D as n,J as r,Nt as i,X as a,qt as o}from"../workspace_resource_pb-7smKERdZ.mjs";import{t as s}from"../assert-WeXvmG4j.mjs";import{_ as c,i as l,j as u,r as d,x as f}from"../service-CZ0EdD2-.mjs";import{_ as p,a as m,c as h,i as g,n as _,o as v,p as y,r as b,s as x,t as S,u as C,v as w}from"../errors-Dmdnq0zi.mjs";import{$i as T,$n as ee,$r as E,$t as te,Ai as D,Ar as ne,Bi as re,Bn as ie,Br as ae,Ca as oe,Ci as se,Cn as ce,Cr as le,D as ue,Da as de,Di as fe,Dr as pe,Dt as me,Ea as he,Ei as ge,Er as _e,F as ve,Fi as O,Fn as ye,Fr as be,G as xe,Gi as Se,Gn as Ce,Gr as k,Gt as we,H as Te,Hi as Ee,Hn as De,Hr as A,I as Oe,Ii as j,Ir as ke,It as Ae,J as je,Ji as Me,Jn as Ne,Jt as Pe,K as Fe,Ki as Ie,Kn as Le,Kt as Re,L as ze,Li as Be,Ln as Ve,Lr as He,M as Ue,Mi as M,Mr as We,Ni as N,Nr as Ge,Oa as P,Oi as Ke,Or as qe,P as Je,Pi as Ye,Pr as Xe,Pt as Ze,Q as Qe,Qi as $e,Qn as et,Ri as tt,Rn as nt,Rr as rt,Rt as it,S as at,Sa as ot,Si as st,Sr as ct,T as lt,Ta as ut,Ti as dt,Tr as ft,Tt as pt,Ui as mt,Un as ht,Ur as gt,Ut as _t,V as vt,Vi as yt,Vn as bt,Vr as xt,Vt as St,Wi as Ct,Wn as wt,Wr as Tt,Wt as Et,X as Dt,Xi as Ot,Xn as kt,Yi as At,Yn as jt,Zi as F,Zn as Mt,Zt as Nt,_i as Pt,_n as Ft,_r as It,_t as Lt,a as Rt,aa as I,ai as zt,an as Bt,ar as Vt,b as Ht,ba as Ut,bi as Wt,bn as Gt,br as Kt,c as qt,ci as Jt,cn as Yt,cr as Xt,ct as Zt,da as L,di as Qt,dn as $t,dr as en,dt as tn,ea as nn,ei as rn,en as an,er as on,et as sn,f as cn,fi as ln,fn as un,fr as dn,ft as fn,g as pn,ga as mn,gn as hn,gr as gn,gt as _n,ha as vn,hi as yn,hn as bn,hr as xn,ia as Sn,in as Cn,ir as wn,it as Tn,ji as R,jr as En,jt as Dn,k as On,ki as kn,kr as An,la as jn,li as Mn,ln as Nn,lr as Pn,m as Fn,ma as In,mi as Ln,mn as Rn,mr as zn,mt as Bn,n as Vn,na as Hn,ni as Un,nn as Wn,nr as Gn,nt as Kn,o as qn,oa as z,oi as Jn,or as Yn,ot as Xn,pa as B,pi as Zn,pn as Qn,pr as $n,qi as er,qn as tr,qt as nr,ra as rr,ri as ir,rr as ar,sn as or,sr,t as cr,ta as lr,tn as ur,tr as dr,u as fr,ua as pr,un as mr,ur as hr,v as gr,va as _r,vi as V,vn as vr,vr as yr,vt as br,w as xr,wa as H,wi as U,wn as Sr,wr as Cr,wt as wr,xa as Tr,xi as Er,xr as Dr,xt as Or,ya as kr,yi as Ar,yn as jr,yr as Mr,yt as Nr,z as Pr,zi as Fr,zn as Ir,zr as Lr}from"../register-ts-hook-Ht4zCseV.mjs";import{B as Rr,D as zr,E as Br,F as Vr,H as Hr,I as Ur,J as Wr,K as Gr,L as Kr,R as qr,T as Jr,U as Yr,W as Xr,Y as Zr,_ as Qr,at as $r,c as ei,dt as ti,et as ni,ht as ri,l as ii,lt as ai,m as oi,mt as si,nt as ci,ot as li,pt as ui,q as di,rt as fi,s as pi,st as mi,tt as hi,u as gi,ut as _i,v as vi,w as yi,wt as bi,x as xi,y as Si,z as Ci}from"../application-Cida-j1g.mjs";import{t as W}from"../multiline-EyzjEwn9.mjs";import{t as wi}from"../package-json-C690ceex.mjs";import{t as Ti}from"../user-agent-vdHYF3QL.mjs";import{t as Ei}from"../service_pb-BxMSK0gg.mjs";import{a as Di,i as Oi,o as ki,r as Ai,t as ji}from"../crashreport-D_wf4GZh.mjs";import{t as Mi}from"../manager-B813m43t.mjs";import{a as Ni,i as Pi,n as Fi}from"../kysely-type-DVL90_oX.mjs";import{arg as G,defineCommand as K,extractFields as Ii,runMain as Li,toCamelCase as Ri}from"@politty/zod";import{withCompletionCommand as zi}from"@politty/zod/completion";import{withSkillCommand as Bi}from"@politty/zod/skill";import*as q from"pathe";import{dirname as Vi,resolve as Hi}from"pathe";import{resolvePackageJSON as Ui}from"pkg-types";import{z as J}from"zod";import{ScalarType as Y,create as Wi}from"@bufbuild/protobuf";import*as X from"node:fs";import{accessSync as Gi,constants as Ki,readdirSync as qi}from"node:fs";import{timestampDate as Ji}from"@bufbuild/protobuf/wkt";import{Code as Z,ConnectError as Q}from"@connectrpc/connect";import{generateCodeVerifier as Yi}from"@badgateway/oauth2-client";import*as Xi from"node:crypto";import{randomBytes as Zi}from"node:crypto";import*as Qi from"node:os";import*as $i from"node:http";import ea from"open";import*as ta from"rolldown";import{parseSync as na}from"oxc-parser";import*as $ from"node:fs/promises";import{setTimeout as ra}from"node:timers/promises";import{spawn as ia,spawnSync as aa}from"node:child_process";import{TraceMap as oa,generatedPositionFor as sa,originalPositionFor as ca}from"@jridgewell/trace-mapping";const la=Ei.methods.filter(e=>e.methodKind===`unary`);function listMethodNames(){return la.map(e=>e.name).toSorted()}function listMethodChoices(){return la.flatMap(e=>[e.name,`${Ei.typeName}/${e.name}`]).toSorted()}function getMethodDescriptor(e){return la.find(t=>t.name===e)}function extractMethodName(e){return e.includes(`/`)?e.split(`/`).pop()??e:e}function nestedMessage(e){if(e.fieldKind===`message`||e.fieldKind===`list`&&e.listKind===`message`||e.fieldKind===`map`&&e.mapKind===`message`)return e.message}function isWellKnownType(e){return e.typeName.startsWith(`google.protobuf.`)}const ua=/* @__PURE__ */ new Set([`google.protobuf.Struct`,`google.protobuf.Value`,`google.protobuf.ListValue`,`google.protobuf.NullValue`,`google.protobuf.Any`,`google.protobuf.Empty`]);function isUnrepresentableWellKnownType(e){return ua.has(e.typeName)}function enumerateAllFieldCompletions(e){let t=getMethodDescriptor(e);if(!t)return[];let n=[],r=/* @__PURE__ */ new Set;function walk(e,t){r.add(e);for(let i of e.fields){if(i.fieldKind===`list`||i.fieldKind===`map`)continue;let e=t+i.localName;if(i.fieldKind===`message`){if(isUnrepresentableWellKnownType(i.message))continue;if(!isWellKnownType(i.message)){let t=i.message;n.push({value:`${e}.`,description:`${e} (message)`}),r.has(t)||walk(t,`${e}.`);continue}}if(n.push({value:`${e}=`,description:`Set ${e}`}),i.fieldKind===`enum`)for(let t of i.enum.values)n.push({value:`${e}=${t.name}`,description:t.name});else i.fieldKind===`scalar`&&i.scalar===Y.BOOL&&(n.push({value:`${e}=true`,description:`true`}),n.push({value:`${e}=false`,description:`false`}))}r.delete(e)}return walk(t.input,``),n}function resolveLeafField(e,t){let n=e;for(let e=0;e<t.length;e++){let r=n.fields.find(n=>n.localName===t[e]);if(!r)return;if(e===t.length-1)return r.fieldKind===`message`&&isUnrepresentableWellKnownType(r.message)?void 0:r;if(r.fieldKind!==`message`||isWellKnownType(r.message))return;n=r.message}}const da={[Y.DOUBLE]:`double`,[Y.FLOAT]:`float`,[Y.INT64]:`int64`,[Y.UINT64]:`uint64`,[Y.INT32]:`int32`,[Y.FIXED64]:`fixed64`,[Y.FIXED32]:`fixed32`,[Y.BOOL]:`bool`,[Y.STRING]:`string`,[Y.BYTES]:`bytes`,[Y.UINT32]:`uint32`,[Y.SFIXED32]:`sfixed32`,[Y.SFIXED64]:`sfixed64`,[Y.SINT32]:`sint32`,[Y.SINT64]:`sint64`};function shortName(e){let t=e.lastIndexOf(`.`);return t<0?e:e.slice(t+1)}function scalarLabel(e){return da[e]??`scalar(${e})`}function enumLabel(e){return`enum ${shortName(e.typeName)}`}function enumOf(e){if(e.fieldKind===`enum`||e.fieldKind===`list`&&e.listKind===`enum`)return e.enum}function describeFieldType(e){switch(e.fieldKind){case`scalar`:return scalarLabel(e.scalar);case`enum`:return enumLabel(e.enum);case`message`:return shortName(e.message.typeName);case`list`:{let t;return t=e.listKind===`scalar`?scalarLabel(e.scalar):e.listKind===`enum`?enumLabel(e.enum):shortName(e.message.typeName),`repeated ${t}`}case`map`:{let t=scalarLabel(e.mapKey),n;return n=e.mapKind===`scalar`?scalarLabel(e.scalar):e.mapKind===`enum`?enumLabel(e.enum):shortName(e.message.typeName),`map<${t}, ${n}>`}default:return`<unknown>`}}function fieldToJson(e,t){let n={name:e.localName,protoName:e.name,type:describeFieldType(e),fieldKind:e.fieldKind,repeated:e.fieldKind===`list`};e.oneof&&(n.oneof=e.oneof.name);let r=enumOf(e);r&&(n.enumValues=r.values.map(e=>e.name));let i=nestedMessage(e);return i&&!t.has(i)?(t.add(i),n.message={typeName:i.typeName,fields:i.fields.map(e=>fieldToJson(e,t))},t.delete(i)):i&&(n.message={typeName:i.typeName,fields:[],recursive:!0}),n}function renderInspectJson(e){let t=/* @__PURE__ */ new Set([e.input]);return{method:e.name,input:{typeName:e.input.typeName,fields:e.input.fields.map(e=>fieldToJson(e,t))},output:{typeName:e.output.typeName}}}function renderFieldText(e,t,n){let r=[],i=e.oneof?` (oneof ${e.oneof.name})`:``;r.push(`${t}${e.localName}: ${describeFieldType(e)}${i}`);let a=enumOf(e);if(a){let e=a.values.map(e=>e.name).join(`, `);r.push(`${t} values: ${e}`)}let o=nestedMessage(e);if(o&&!n.has(o)){n.add(o);for(let e of o.fields)r.push(...renderFieldText(e,`${t} `,n));n.delete(o)}else o&&r.push(`${t} …(recursive ${o.typeName})`);return r}function renderInspectText(e){let t=[];t.push(`${e.name}`),t.push(` request: ${e.input.typeName}`);let n=/* @__PURE__ */ new Set([e.input]);for(let r of e.input.fields)t.push(...renderFieldText(r,` `,n));return t.push(` response: ${e.output.typeName}`),t.join(`
3
- `)}const fa=z({name:`inspect`,description:`Print the input message tree of an OperatorService endpoint.`,notes:"Combine with the global `--json` flag for a machine-readable descriptor. Recursive type references and `oneof` membership are annotated. Use `tailor api list` to discover endpoint names.",examples:[{cmd:`GetApplication`,desc:`Show fields of GetApplicationRequest.`},{cmd:`CreateExecutorExecutor`,desc:"Inspect a deeply nested input with `(oneof config)` annotations."}],args:J.strictObject({endpoint:G(J.string(),{positional:!0,description:`API endpoint to inspect (e.g., 'GetApplication' or 'tailor.v1.OperatorService/GetApplication').`,completion:{custom:{choices:listMethodNames()}}})}),run:e=>{let t=extractMethodName(e.endpoint),n=getMethodDescriptor(t);if(!n)throw S({code:`API_METHOD_UNKNOWN`,message:`unknown method: ${t}`,suggestion:"Run `tailor api list` to see available methods.",command:`api inspect`});y.jsonMode?y.out(renderInspectJson(n)):y.out(renderInspectText(n))}}),pa=z({name:`list`,description:`List all invocable OperatorService methods.`,notes:`Only single-request (non-streaming) methods are listed, because the CLI issues a single JSON request and reads one JSON response.`,args:J.strictObject({}),run:()=>{let e=listMethodNames();if(y.jsonMode)y.out(e);else for(let t of e)y.out(t)}});function resolveNamespaceName(e,t){if(/Auth|Tenant|UserProfile/.test(e))return t.auth?.name;if(/IdP/.test(e))return t.idp?.length===1?s(t.idp[0],`idp config missing`).name:void 0;if(/TailorDB/.test(e)){let e=Object.keys(t.db??{});return e.length===1?e[0]:void 0}if(/Pipeline/.test(e)){let e=Object.keys(t.resolver??{});return e.length===1?e[0]:void 0}}function parseBodyAsObject(e){let t;try{t=JSON.parse(e)}catch{return}if(typeof t==`object`&&t&&!Array.isArray(t))return t}function setNestedPath(e,t,n){let r=e;for(let e=0;e<t.length-1;e++){let n=s(t[e],`path segment missing`),i=r[n];(typeof i!=`object`||!i||Array.isArray(i))&&(r[n]={}),r=r[n]}r[s(t[t.length-1],`path last segment missing`)]=n}function coerceFieldValue(e,t){if(e&&e.fieldKind===`scalar`&&e.scalar===Y.BOOL){if(t===`true`)return!0;if(t===`false`)return!1;throw S({code:`API_FIELD_VALUE_INVALID`,message:`Invalid value for bool field: '${t}'. Expected 'true' or 'false'.`,command:`api`})}return t}function normalizeBodyFieldKeys(e,t){let n=/* @__PURE__ */ new Map;for(let e of t)n.set(e.name,e.localName),n.set(e.jsonName,e.localName);let r=!1;for(let t of Object.keys(e)){let i=n.get(t);i&&i!==t&&(Object.hasOwn(e,i)||(e[i]=e[t]),delete e[t],r=!0)}return r}const ma=/* @__PURE__ */ new Set([`__proto__`,`constructor`,`prototype`]),ha=J.string().transform((e,t)=>{let n=e.indexOf(`=`);if(n<0)return t.addIssue({code:`custom`,message:`Invalid field format: '${e}'. Expected format: 'key=value' or 'a.b.c=value'`}),J.NEVER;let r=e.slice(0,n);if(r.length===0)return t.addIssue({code:`custom`,message:`Field key cannot be empty`}),J.NEVER;let i=r.split(`.`);if(i.some(e=>e.length===0))return t.addIssue({code:`custom`,message:`Invalid field key: '${r}'. Dotted segments cannot be empty`}),J.NEVER;let a=i.find(e=>ma.has(e));return a?(t.addIssue({code:`custom`,message:`Invalid field key: '${r}'. Segment '${a}' is not allowed.`}),J.NEVER):{path:i,value:e.slice(n+1)}}),ga=z({name:`api`,description:`Call Tailor Platform API endpoints directly.`,notes:"Use `tailor api list` to enumerate invocable methods and `tailor api inspect <endpoint>` to print an endpoint's input message tree (combine with `--json` for machine-readable output).\n\nThe request body is inferred from the target endpoint's request schema, and commonly required fields are auto-injected so they can be omitted from `--body`:\n\n- `workspaceId` — resolved from `-w` / `TAILOR_PLATFORM_WORKSPACE_ID` / the selected profile.\n- `namespaceName` — resolved from `tailor.config.ts` based on the endpoint's service:\n - Auth / Tenant / UserProfile endpoints use `auth.name`.\n - IdP / TailorDB / Pipeline endpoints use the sole configured namespace when exactly one is defined.\n\nValues already present in `--body` are never overridden. If a value cannot be resolved (e.g. no config found), injection is silently skipped and the server-side validation error takes precedence.\n\nUse `--field key=value` (repeatable) to set request body fields without writing JSON. Dotted keys (e.g. `application.name=foo`) build nested objects. `--field` overrides matching fields in `--body` and tab-completes from the endpoint's request schema.",examples:[{cmd:`GetApplication -b '{"applicationName":"app-1"}'`,desc:`Call an endpoint; workspaceId is auto-injected.`},{cmd:`GetApplication -f applicationName=app-1`,desc:`Same as above, using --field instead of --body.`},{cmd:`list`,desc:`List all invocable OperatorService methods.`},{cmd:`inspect GetApplication`,desc:`Show the input message tree for an endpoint.`}],subCommands:{list:pa,inspect:fa},args:J.strictObject({...P,...pr,body:G(J.string().default(`{}`),{alias:`b`,description:`Request body as JSON.`}),field:G(ha.array().optional(),{alias:`f`,description:"Set a body field as `key=value` (repeatable; dotted keys nest). Overrides --body.",completion:{custom:{expand:{dependsOn:[`endpoint`],enumerate:({endpoint:e})=>enumerateAllFieldCompletions(extractMethodName(e??``))}}}}),endpoint:G(J.string(),{positional:!0,description:`API endpoint to call (e.g., 'GetApplication' or 'tailor.v1.OperatorService/GetApplication').`,completion:{custom:{choices:listMethodChoices()}}})}),run:async e=>{await O({profile:e.profile});let t=extractMethodName(e.endpoint),n=getMethodDescriptor(t),r=parseBodyAsObject(e.body),i=!1;if(e.field&&e.field.length>0){if(!r)throw S({code:`API_OPTIONS_INVALID`,message:`--field requires --body to be a JSON object (or omitted).`,command:`api`});for(let t of e.field){let e=n?resolveLeafField(n.input,t.path):void 0;setNestedPath(r,t.path,coerceFieldValue(e,t.value))}i=!0}if(r&&n){normalizeBodyFieldKeys(r,n.input.fields)&&(i=!0);let a=n.input.fields.map(e=>e.localName);if(a.includes(`workspaceId`)&&!Object.hasOwn(r,`workspaceId`))try{r.workspaceId=await Me({workspaceId:e[`workspace-id`],profile:e.profile}),i=!0}catch{}if(a.includes(`namespaceName`)&&!Object.hasOwn(r,`namespaceName`))try{let{config:n}=await j(e.config),a=resolveNamespaceName(t,n);a&&(r.namespaceName=a,i=!0)}catch{}}let a=await Ye({profile:e.profile,endpoint:e.endpoint,body:i&&r?JSON.stringify(r):e.body});y.out(JSON.stringify(a.data,null,2))}}),_a=z({name:`status`,description:`Show the active Tailor Platform authentication status without printing tokens.`,args:J.strictObject({profile:P.profile}),run:async({profile:e})=>{let t=await Ee({profile:e});if(y.out(t),!t.authenticated)throw S({code:`NOT_AUTHENTICATED`,message:`Not authenticated.`,suggestion:`Log in and try again.`,next:{command:`tailor`,args:[`login`,...H({profile:e})]}})}}),va=z({name:`token`,description:`Print a valid Tailor Platform access token to stdout, refreshing it first if it expires within five minutes.`,args:J.strictObject({profile:P.profile}),run:async({profile:e})=>{let t=await yt({profile:e});y.out(t)}}),ya=K({name:`auth`,description:`Authentication helpers for scripts and plugins.`,subCommands:{status:_a,token:va}}),ba={"&":`&amp;`,"<":`&lt;`,">":`&gt;`,'"':`&quot;`,"'":`&#39;`};function escapeHtml(e){return e.replace(/[&<>"']/g,e=>ba[e])}const xa={success:`<svg viewBox="0 0 24 24" width="28" height="28" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg>`,failure:`<svg viewBox="0 0 24 24" width="28" height="28" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18"/></svg>`},Sa=`
2
+ import{r as e}from"../field-parse-BQhUAbpM.mjs";import{t}from"../assert-WeXvmG4j.mjs";import{c as n}from"../validation-errors-ChvCG6wT.mjs";import{C as r,S as i,_ as a,a as o,b as s,c,d as l,i as u,l as d,n as f,o as p,p as m,r as h,s as g,t as _,u as v,v as y,x as b,y as x}from"../errors-9OOL3xOM.mjs";import{B as S,D as C,F as w,G as T,I as E,L as ee,M as te,N as D,O,S as ne,T as re,U as ie,W as ae,X as oe,Y as se,Z as ce,_ as le,a as ue,at as de,b as fe,c as pe,et as me,f as he,g as ge,i as _e,it as ve,j as ye,l as be,m as xe,n as Se,nt as k,o as Ce,ot as we,r as Te,rt as Ee,s as De,st as A,t as Oe,tt as ke,u as Ae,v as j,w as je,x as Me,y as Ne,z as Pe}from"../context-aAgFGDBD.mjs";import{$n as Fe,$r as Ie,$t as Le,Ai as Re,Ar as ze,Bi as Be,Bn as Ve,Br as He,Ci as Ue,Cn as We,Cr as Ge,D as Ke,Di as qe,Dr as Je,Dt as Ye,Ei as Xe,Er as Ze,F as Qe,Fi as $e,Fn as et,Fr as tt,G as nt,Gi as M,Gn as rt,Gr as it,Gt as at,H as ot,Hi as st,Hn as ct,Hr as lt,I as ut,Ii as dt,Ir as ft,It as pt,J as mt,Ji as N,Jn as ht,Jr as gt,Jt as _t,K as vt,Ki as P,Kn as yt,Kr as bt,Kt as xt,L as St,Li as Ct,Ln as wt,Lr as Tt,M as Et,Mi as Dt,Mr as Ot,Ni as F,Nr as kt,Oi as At,Or as jt,P as Mt,Pi as Nt,Pr as Pt,Pt as Ft,Q as It,Qi as I,Qn as Lt,Qr as Rt,Ri as zt,Rn as Bt,Rr as Vt,Rt as Ht,S as Ut,Sr as Wt,T as Gt,Tr as Kt,Tt as qt,Ui as Jt,Un as Yt,Ur as Xt,Ut as Zt,V as Qt,Vi as $t,Vn as en,Vr as tn,Vt as nn,Wi as rn,Wn as an,Wr as on,Wt as sn,X as cn,Xi as L,Xn as ln,Xr as un,Yi as dn,Yn as fn,Yr as pn,Zi as R,Zn as mn,Zr as hn,Zt as gn,_i as _n,_n as vn,_r as yn,_t as bn,a as xn,ai as z,an as Sn,b as Cn,bi as wn,bn as Tn,br as En,c as Dn,cn as On,cr as kn,ct as An,dn as jn,dr as Mn,dt as Nn,ei as Pn,en as Fn,et as In,f as Ln,fn as Rn,fr as zn,ft as Bn,g as Vn,gn as Hn,gr as Un,gt as Wn,hi as Gn,hn as Kn,hr as qn,ii as Jn,in as Yn,it as Xn,jr as Zn,jt as Qn,k as $n,ki as er,kr as tr,ln as nr,lr as rr,m as ir,mi as ar,mn as or,mr as sr,mt as cr,n as lr,ni as ur,nn as dr,nt as fr,o as pr,oi as mr,ot as hr,pn as gr,pr as _r,qi as B,qn as vr,qr as yr,qt as br,ri as xr,sn as Sr,sr as Cr,t as wr,ti as V,tn as Tr,u as Er,un as Dr,ur as Or,v as kr,vi as Ar,vn as jr,vr as Mr,vt as Nr,w as Pr,wi as Fr,wn as Ir,wr as Lr,wt as Rr,xi as zr,xr as Br,xt as Vr,yn as Hr,yr as Ur,yt as Wr,z as Gr,zi as Kr,zn as qr,zr as Jr}from"../register-ts-hook-CORbtrSN.mjs";import{B as Yr,D as Xr,E as Zr,F as Qr,H as $r,I as ei,J as ti,K as ni,L as ri,R as ii,T as ai,U as oi,W as si,Y as ci,_ as li,c as ui,l as di,m as fi,q as pi,s as mi,u as hi,v as gi,w as _i,x as vi,y as yi,z as bi}from"../application-mNOJx9Y2.mjs";import{_ as xi,i as Si,r as Ci,x as wi}from"../service-Bkz_TB5v.mjs";import{t as H}from"../multiline-EyzjEwn9.mjs";import{C as Ti,D as Ei,E as Di,S as Oi,T as ki,_ as Ai,a as ji,f as Mi,g as Ni,h as Pi,p as Fi,u as Ii,x as Li,z as Ri}from"../client-CqiPQgMG.mjs";import{t as zi}from"../package-json-C690ceex.mjs";import{t as Bi}from"../user-agent-vdHYF3QL.mjs";import{Bt as Vi,D as Hi,J as Ui,Nt as Wi,X as Gi,qt as Ki}from"../workspace_resource_pb-Cow7mrJY.mjs";import{t as qi}from"../service_pb-CfpSriCy.mjs";import{n as U,o as W}from"../notification_resource_pb-Dwzah7gO.mjs";import{a as Ji,i as Yi,o as Xi,r as Zi,t as Qi}from"../crashreport-CQTAlnbA.mjs";import{t as $i}from"../manager-B813m43t.mjs";import{a as ea,i as ta,n as na}from"../kysely-type-DhAZqdQg.mjs";import{arg as G,defineCommand as K,extractFields as ra,runMain as ia}from"@politty/zod";import{withCompletionCommand as aa}from"@politty/zod/completion";import{withSkillCommand as oa}from"@politty/zod/skill";import*as q from"pathe";import{dirname as sa,resolve as ca}from"pathe";import{resolvePackageJSON as la}from"pkg-types";import{z as J}from"zod";import{ScalarType as Y,create as ua}from"@bufbuild/protobuf";import*as X from"node:fs";import{accessSync as da,constants as fa,readdirSync as pa}from"node:fs";import{timestampDate as ma}from"@bufbuild/protobuf/wkt";import{Code as Z,ConnectError as Q}from"@connectrpc/connect";import{xdgConfig as ha}from"xdg-basedir";import{generateCodeVerifier as ga}from"@badgateway/oauth2-client";import*as _a from"node:crypto";import{randomBytes as va}from"node:crypto";import*as ya from"node:os";import*as ba from"node:http";import xa from"open";import*as Sa from"rolldown";import{parseSync as Ca}from"oxc-parser";import*as $ from"node:fs/promises";import{setTimeout as wa}from"node:timers/promises";import{spawn as Ta,spawnSync as Ea}from"node:child_process";import{TraceMap as Da,generatedPositionFor as Oa,originalPositionFor as ka}from"@jridgewell/trace-mapping";const Aa=qi.methods.filter(e=>e.methodKind===`unary`);function listMethodNames(){return Aa.map(e=>e.name).toSorted()}function listMethodChoices(){return Aa.flatMap(e=>[e.name,`${qi.typeName}/${e.name}`]).toSorted()}function getMethodDescriptor(e){return Aa.find(t=>t.name===e)}function extractMethodName(e){return e.includes(`/`)?e.split(`/`).pop()??e:e}function nestedMessage(e){if(e.fieldKind===`message`||e.fieldKind===`list`&&e.listKind===`message`||e.fieldKind===`map`&&e.mapKind===`message`)return e.message}function isWellKnownType(e){return e.typeName.startsWith(`google.protobuf.`)}const ja=/* @__PURE__ */ new Set([`google.protobuf.Struct`,`google.protobuf.Value`,`google.protobuf.ListValue`,`google.protobuf.NullValue`,`google.protobuf.Any`,`google.protobuf.Empty`]);function isUnrepresentableWellKnownType(e){return ja.has(e.typeName)}function enumerateAllFieldCompletions(e){let t=getMethodDescriptor(e);if(!t)return[];let n=[],r=/* @__PURE__ */ new Set;function walk(e,t){r.add(e);for(let i of e.fields){if(i.fieldKind===`list`||i.fieldKind===`map`)continue;let e=t+i.localName;if(i.fieldKind===`message`){if(isUnrepresentableWellKnownType(i.message))continue;if(!isWellKnownType(i.message)){let t=i.message;n.push({value:`${e}.`,description:`${e} (message)`}),r.has(t)||walk(t,`${e}.`);continue}}if(n.push({value:`${e}=`,description:`Set ${e}`}),i.fieldKind===`enum`)for(let t of i.enum.values)n.push({value:`${e}=${t.name}`,description:t.name});else i.fieldKind===`scalar`&&i.scalar===Y.BOOL&&(n.push({value:`${e}=true`,description:`true`}),n.push({value:`${e}=false`,description:`false`}))}r.delete(e)}return walk(t.input,``),n}function resolveLeafField(e,t){let n=e;for(let e=0;e<t.length;e++){let r=n.fields.find(n=>n.localName===t[e]);if(!r)return;if(e===t.length-1)return r.fieldKind===`message`&&isUnrepresentableWellKnownType(r.message)?void 0:r;if(r.fieldKind!==`message`||isWellKnownType(r.message))return;n=r.message}}const Ma={[Y.DOUBLE]:`double`,[Y.FLOAT]:`float`,[Y.INT64]:`int64`,[Y.UINT64]:`uint64`,[Y.INT32]:`int32`,[Y.FIXED64]:`fixed64`,[Y.FIXED32]:`fixed32`,[Y.BOOL]:`bool`,[Y.STRING]:`string`,[Y.BYTES]:`bytes`,[Y.UINT32]:`uint32`,[Y.SFIXED32]:`sfixed32`,[Y.SFIXED64]:`sfixed64`,[Y.SINT32]:`sint32`,[Y.SINT64]:`sint64`};function shortName(e){let t=e.lastIndexOf(`.`);return t<0?e:e.slice(t+1)}function scalarLabel(e){return Ma[e]??`scalar(${e})`}function enumLabel(e){return`enum ${shortName(e.typeName)}`}function enumOf(e){if(e.fieldKind===`enum`||e.fieldKind===`list`&&e.listKind===`enum`)return e.enum}function describeFieldType(e){switch(e.fieldKind){case`scalar`:return scalarLabel(e.scalar);case`enum`:return enumLabel(e.enum);case`message`:return shortName(e.message.typeName);case`list`:{let t;return t=e.listKind===`scalar`?scalarLabel(e.scalar):e.listKind===`enum`?enumLabel(e.enum):shortName(e.message.typeName),`repeated ${t}`}case`map`:{let t=scalarLabel(e.mapKey),n;return n=e.mapKind===`scalar`?scalarLabel(e.scalar):e.mapKind===`enum`?enumLabel(e.enum):shortName(e.message.typeName),`map<${t}, ${n}>`}default:return`<unknown>`}}function fieldToJson(e,t){let n={name:e.localName,protoName:e.name,type:describeFieldType(e),fieldKind:e.fieldKind,repeated:e.fieldKind===`list`};e.oneof&&(n.oneof=e.oneof.name);let r=enumOf(e);r&&(n.enumValues=r.values.map(e=>e.name));let i=nestedMessage(e);return i&&!t.has(i)?(t.add(i),n.message={typeName:i.typeName,fields:i.fields.map(e=>fieldToJson(e,t))},t.delete(i)):i&&(n.message={typeName:i.typeName,fields:[],recursive:!0}),n}function renderInspectJson(e){let t=/* @__PURE__ */ new Set([e.input]);return{method:e.name,input:{typeName:e.input.typeName,fields:e.input.fields.map(e=>fieldToJson(e,t))},output:{typeName:e.output.typeName}}}function renderFieldText(e,t,n){let r=[],i=e.oneof?` (oneof ${e.oneof.name})`:``;r.push(`${t}${e.localName}: ${describeFieldType(e)}${i}`);let a=enumOf(e);if(a){let e=a.values.map(e=>e.name).join(`, `);r.push(`${t} values: ${e}`)}let o=nestedMessage(e);if(o&&!n.has(o)){n.add(o);for(let e of o.fields)r.push(...renderFieldText(e,`${t} `,n));n.delete(o)}else o&&r.push(`${t} …(recursive ${o.typeName})`);return r}function renderInspectText(e){let t=[];t.push(`${e.name}`),t.push(` request: ${e.input.typeName}`);let n=/* @__PURE__ */ new Set([e.input]);for(let r of e.input.fields)t.push(...renderFieldText(r,` `,n));return t.push(` response: ${e.output.typeName}`),t.join(`
3
+ `)}const Na=I({name:`inspect`,description:`Print the input message tree of an OperatorService endpoint.`,notes:"Combine with the global `--json` flag for a machine-readable descriptor. Recursive type references and `oneof` membership are annotated. Use `tailor api list` to discover endpoint names.",examples:[{cmd:`GetApplication`,desc:`Show fields of GetApplicationRequest.`},{cmd:`CreateExecutorExecutor`,desc:"Inspect a deeply nested input with `(oneof config)` annotations."}],args:J.strictObject({endpoint:G(J.string(),{positional:!0,description:`API endpoint to inspect (e.g., 'GetApplication' or 'tailor.v1.OperatorService/GetApplication').`,completion:{custom:{choices:listMethodNames()}}})}),run:e=>{let t=extractMethodName(e.endpoint),n=getMethodDescriptor(t);if(!n)throw _({code:`API_METHOD_UNKNOWN`,message:`unknown method: ${t}`,suggestion:"Run `tailor api list` to see available methods.",command:`api inspect`});m.jsonMode?m.out(renderInspectJson(n)):m.out(renderInspectText(n))}}),Pa=I({name:`list`,description:`List all invocable OperatorService methods.`,notes:`Only single-request (non-streaming) methods are listed, because the CLI issues a single JSON request and reads one JSON response.`,args:J.strictObject({}),run:()=>{let e=listMethodNames();if(m.jsonMode)m.out(e);else for(let t of e)m.out(t)}});function resolveNamespaceName(e,n){if(/Auth|Tenant|UserProfile/.test(e))return n.auth?.name;if(/IdP/.test(e))return n.idp?.length===1?t(n.idp[0],`idp config missing`).name:void 0;if(/TailorDB/.test(e)){let e=Object.keys(n.db??{});return e.length===1?e[0]:void 0}if(/Pipeline/.test(e)){let e=Object.keys(n.resolver??{});return e.length===1?e[0]:void 0}}function parseBodyAsObject(e){let t;try{t=JSON.parse(e)}catch{return}if(typeof t==`object`&&t&&!Array.isArray(t))return t}function setNestedPath(e,n,r){let i=e;for(let e=0;e<n.length-1;e++){let r=t(n[e],`path segment missing`),a=i[r];(typeof a!=`object`||!a||Array.isArray(a))&&(i[r]={}),i=i[r]}i[t(n[n.length-1],`path last segment missing`)]=r}function coerceFieldValue(e,t){if(e&&e.fieldKind===`scalar`&&e.scalar===Y.BOOL){if(t===`true`)return!0;if(t===`false`)return!1;throw _({code:`API_FIELD_VALUE_INVALID`,message:`Invalid value for bool field: '${t}'. Expected 'true' or 'false'.`,command:`api`})}return t}function normalizeBodyFieldKeys(e,t){let n=/* @__PURE__ */ new Map;for(let e of t)n.set(e.name,e.localName),n.set(e.jsonName,e.localName);let r=!1;for(let t of Object.keys(e)){let i=n.get(t);i&&i!==t&&(Object.hasOwn(e,i)||(e[i]=e[t]),delete e[t],r=!0)}return r}const Fa=/* @__PURE__ */ new Set([`__proto__`,`constructor`,`prototype`]),Ia=J.string().transform((e,t)=>{let n=e.indexOf(`=`);if(n<0)return t.addIssue({code:`custom`,message:`Invalid field format: '${e}'. Expected format: 'key=value' or 'a.b.c=value'`}),J.NEVER;let r=e.slice(0,n);if(r.length===0)return t.addIssue({code:`custom`,message:`Field key cannot be empty`}),J.NEVER;let i=r.split(`.`);if(i.some(e=>e.length===0))return t.addIssue({code:`custom`,message:`Invalid field key: '${r}'. Dotted segments cannot be empty`}),J.NEVER;let a=i.find(e=>Fa.has(e));return a?(t.addIssue({code:`custom`,message:`Invalid field key: '${r}'. Segment '${a}' is not allowed.`}),J.NEVER):{path:i,value:e.slice(n+1)}}),La=I({name:`api`,description:`Call Tailor Platform API endpoints directly.`,notes:"Use `tailor api list` to enumerate invocable methods and `tailor api inspect <endpoint>` to print an endpoint's input message tree (combine with `--json` for machine-readable output).\n\nThe request body is inferred from the target endpoint's request schema, and commonly required fields are auto-injected so they can be omitted from `--body`:\n\n- `workspaceId` — resolved from `-w` / `TAILOR_PLATFORM_WORKSPACE_ID` / the selected profile.\n- `namespaceName` — resolved from `tailor.config.ts` based on the endpoint's service:\n - Auth / Tenant / UserProfile endpoints use `auth.name`.\n - IdP / TailorDB / Pipeline endpoints use the sole configured namespace when exactly one is defined.\n\nValues already present in `--body` are never overridden. If a value cannot be resolved (e.g. no config found), injection is silently skipped and the server-side validation error takes precedence.\n\nUse `--field key=value` (repeatable) to set request body fields without writing JSON. Dotted keys (e.g. `application.name=foo`) build nested objects. `--field` overrides matching fields in `--body` and tab-completes from the endpoint's request schema.",examples:[{cmd:`GetApplication -b '{"applicationName":"app-1"}'`,desc:`Call an endpoint; workspaceId is auto-injected.`},{cmd:`GetApplication -f applicationName=app-1`,desc:`Same as above, using --field instead of --body.`},{cmd:`list`,desc:`List all invocable OperatorService methods.`},{cmd:`inspect GetApplication`,desc:`Show the input message tree for an endpoint.`}],subCommands:{list:Pa,inspect:Na},args:J.strictObject({...A,...te,body:G(J.string().default(`{}`),{alias:`b`,description:`Request body as JSON.`}),field:G(Ia.array().optional(),{alias:`f`,description:"Set a body field as `key=value` (repeatable; dotted keys nest). Overrides --body.",completion:{custom:{expand:{dependsOn:[`endpoint`],enumerate:({endpoint:e})=>enumerateAllFieldCompletions(extractMethodName(e??``))}}}}),endpoint:G(J.string(),{positional:!0,description:`API endpoint to call (e.g., 'GetApplication' or 'tailor.v1.OperatorService/GetApplication').`,completion:{custom:{choices:listMethodChoices()}}})}),run:async e=>{await L({profile:e.profile});let t=extractMethodName(e.endpoint),n=getMethodDescriptor(t),r=parseBodyAsObject(e.body),i=!1;if(e.field&&e.field.length>0){if(!r)throw _({code:`API_OPTIONS_INVALID`,message:`--field requires --body to be a JSON object (or omitted).`,command:`api`});for(let t of e.field){let e=n?resolveLeafField(n.input,t.path):void 0;setNestedPath(r,t.path,coerceFieldValue(e,t.value))}i=!0}if(r&&n){normalizeBodyFieldKeys(r,n.input.fields)&&(i=!0);let a=n.input.fields.map(e=>e.localName);if(a.includes(`workspaceId`)&&!Object.hasOwn(r,`workspaceId`))try{r.workspaceId=await xe({workspaceId:e[`workspace-id`],profile:e.profile}),i=!0}catch{}if(a.includes(`namespaceName`)&&!Object.hasOwn(r,`namespaceName`))try{let{config:n}=await R(e.config),a=resolveNamespaceName(t,n);a&&(r.namespaceName=a,i=!0)}catch{}}let a=await dn({profile:e.profile,endpoint:e.endpoint,body:i&&r?JSON.stringify(r):e.body});m.out(JSON.stringify(a.data,null,2))}}),Ra=I({name:`status`,description:`Show the active Tailor Platform authentication status without printing tokens.`,args:J.strictObject({profile:A.profile}),run:async({profile:e})=>{let t=await Ce({profile:e});if(m.out(t),!t.authenticated)throw _({code:`NOT_AUTHENTICATED`,message:`Not authenticated.`,suggestion:`Log in and try again.`,next:{command:`tailor`,args:[`login`,...k({profile:e})]}})}}),za=I({name:`token`,description:`Print a valid Tailor Platform access token to stdout, refreshing it first if it expires within five minutes.`,args:J.strictObject({profile:A.profile}),run:async({profile:e})=>{let t=await ue({profile:e});m.out(t)}}),Ba=K({name:`auth`,description:`Authentication helpers for scripts and plugins.`,subCommands:{status:Ra,token:za}}),Va={"&":`&amp;`,"<":`&lt;`,">":`&gt;`,'"':`&quot;`,"'":`&#39;`};function escapeHtml(e){return e.replace(/[&<>"']/g,e=>Va[e])}const Ha={success:`<svg viewBox="0 0 24 24" width="28" height="28" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg>`,failure:`<svg viewBox="0 0 24 24" width="28" height="28" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18"/></svg>`},Ua=`
4
4
  :root{color-scheme:light dark;--bg:#f5f6f8;--card:#fff;--text:#16181d;--muted:#5d6470;--border:#e2e5ea;--ok:#15803d;--ok-bg:#dcfce7;--ng:#b91c1c;--ng-bg:#fee2e2}
5
5
  @media (prefers-color-scheme: dark){:root{--bg:#0f1115;--card:#181b21;--text:#f2f4f8;--muted:#9aa3b2;--border:#2a2f38;--ok:#4ade80;--ok-bg:#12301d;--ng:#f87171;--ng-bg:#3a1717}}
6
6
  *{box-sizing:border-box}
@@ -11,100 +11,105 @@ main{width:100%;max-width:420px;padding:32px 28px;text-align:center;background:v
11
11
  .failure .icon{color:var(--ng);background:var(--ng-bg)}
12
12
  h1{margin:16px 0 8px;font-size:20px}
13
13
  p{margin:0;color:var(--muted);overflow-wrap:anywhere}
14
- `.replace(/\n/g,``);function renderCallbackPage(e){let t=escapeHtml(e.title),n=escapeHtml(e.message),r=e.status===`success`?`<script>window.close()<\/script>`:``;return`<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>${t}</title><style>${Sa}</style></head><body class="${e.status}"><main><div class="icon">${xa[e.status]}</div><h1>${t}</h1><p>${n}</p></main>${r}</body></html>`}const Ca={"Content-Type":`text/html; charset=utf-8`};function sendCallbackSuccess(e,t){e.writeHead(200,Ca),e.end(renderCallbackPage({status:`success`,title:t,message:`You can close this tab and return to the terminal.`}))}function sendCallbackFailure(e,t,n,r){e.writeHead(t,Ca),e.end(renderCallbackPage({status:`failure`,title:n,message:m(r)?r.message:`Return to the terminal for details.`}))}const wa={name:G(J.string(),{alias:`n`,description:`Auth connection name`})};async function fetchOIDCDiscovery(e){let t=e.replace(/\/$/,``)+`/.well-known/openid-configuration`,n=await fetch(t).catch(e=>{throw S({code:`OIDC_DISCOVERY_FAILED`,message:`Failed to fetch OIDC discovery from ${t}: ${x(e).message}`,cause:e})});if(!n.ok)throw S({code:`OIDC_DISCOVERY_FAILED`,message:`Failed to fetch OIDC discovery from ${t}: ${n.status}`});return n.json()}function randomState$1(){return Xi.randomBytes(32).toString(`base64url`)}const Ta=z({name:`authorize`,description:`Authorize an auth connection via OAuth2 flow.`,args:J.strictObject({...P,...wa,scopes:J.string().optional().default(`openid,profile,email`).describe(`OAuth2 scopes to request (comma-separated)`),port:J.coerce.number().optional().default(8080).describe(`Local callback server port`),"no-browser":J.boolean().optional().default(!1).describe(`Don't open browser automatically`)}),run:async e=>{await O({profile:e.profile});let t=b({command:`tailor`,args:[`authconnection`,`open`,...H({profile:e.profile,workspaceId:e[`workspace-id`]})]}),{client:n,workspaceId:r}=await M({profile:e.profile,workspaceId:e[`workspace-id`]}),i=(await ci(async(e,t)=>{let{connections:i,nextPageToken:a}=await n.listAuthConnections({workspaceId:r,pageToken:e,pageSize:t});return[i,a]})).find(t=>t.name===e.name);if(!i)throw S({code:`AUTH_CONNECTION_NOT_FOUND`,message:`Auth connection "${e.name}" not found.`});if(i.config.case!==`oauth2`)throw S({code:`AUTH_CONNECTION_NOT_OAUTH2`,message:`Auth connection "${e.name}" is not an OAuth2 connection.`});let a=i.config.value,o=`http://localhost:${e.port}/callback`,s=randomState$1(),c;c=a.authUrl?a.authUrl:(await fetchOIDCDiscovery(a.providerUrl)).authorization_endpoint;let l=new URL(c);l.searchParams.set(`client_id`,a.clientId),l.searchParams.set(`redirect_uri`,o),l.searchParams.set(`response_type`,`code`),l.searchParams.set(`scope`,e.scopes.replace(/,/g,` `)),l.searchParams.set(`state`,s),l.searchParams.set(`access_type`,`offline`),await new Promise((i,a)=>{let handleCallback=async(t,l)=>{if(!t.url?.startsWith(`/callback`))l.writeHead(404),l.end(`Not found`);else try{let a=new URL(t.url,`http://localhost:${e.port}`),u=a.searchParams.get(`code`),d=a.searchParams.get(`state`),f=a.searchParams.get(`error`);if(f)throw S({code:`AUTHORIZATION_FAILED`,message:`Authorization failed: ${f}`});if(d!==s)throw S({code:`AUTHORIZATION_STATE_MISMATCH`,message:`State mismatch — possible CSRF attack.`});if(!u)throw S({code:`AUTHORIZATION_CODE_MISSING`,message:`No authorization code received.`});y.registerSecret(u),await n.exchangeAuthConnectionAuthorizationCode({workspaceId:r,connectionName:e.name,authorizationCode:u,redirectUri:o}),sendCallbackSuccess(l,`Authorization successful`),c.close(),i()}catch(e){sendCallbackFailure(l,400,`Authorization failed`,e),c.close(),a(x(e))}},c=$i.createServer((e,t)=>void handleCallback(e,t)),u=setTimeout(()=>{c.close(),a(S({code:`AUTHORIZATION_TIMEOUT`,message:`Authorization timeout exceeded (5 minutes).`}))},3e5);c.on(`close`,()=>{clearTimeout(u)}),c.on(`error`,n=>{clearTimeout(u);let r=n.code,i=r===`EADDRINUSE`||r===`EACCES`?`Try a different port with --port, or authorize via the Console instead:`:`Authorize via the Console instead:`;y.warn(`Could not start the local callback server on port ${e.port}${r?` (${r})`:``}.\n${i}\n ${t}`),a(n)});let announceAuthorizeUrl=async()=>{let n=l.toString();if(y.info(e[`no-browser`]?`Open this URL in your browser to authorize:\n\n${n}\n`:`Opening browser for authorization:\n\n${n}\n`),y.info(`If this flow doesn't complete, you can authorize via the Console instead:\n ${t}`),!e[`no-browser`])try{await ea(n)}catch{y.warn(`Failed to open browser automatically. Please open the URL above manually.`)}};c.listen(e.port,()=>void announceAuthorizeUrl())}),y.success(`Auth connection "${e.name}" authorized successfully.`),N({changed:!0,workspaceId:r,name:e.name})}}),Ea=z({name:`delete`,description:`Delete an auth connection entirely.`,args:J.strictObject({...P,...wa,...L}),run:async e=>{await O({profile:e.profile});let{client:t,workspaceId:n}=await M({profile:e.profile,workspaceId:e[`workspace-id`]});if(!e.yes&&await R.text({message:`Enter the connection name to confirm deletion ("${e.name}"):`,suggestion:`Pass --yes to skip the confirmation.`})!==e.name)throw S({code:`AUTH_CONNECTION_DELETION_CANCELLED`,message:`Auth connection deletion cancelled: the entered name did not match.`,suggestion:`Run the command again and enter the name exactly as shown, or pass --yes to skip the confirmation.`});try{await t.deleteAuthConnection({workspaceId:n,connectionName:e.name})}catch(t){throw t instanceof Q&&t.code===Z.NotFound?S({code:`AUTH_CONNECTION_NOT_FOUND`,message:`Auth connection "${e.name}" not found.`,cause:t}):t}y.success(`Auth connection "${e.name}" deleted.`),N({changed:!0,workspaceId:n,name:e.name})}});function connectionInfo(e){let t=e.config.case===`oauth2`?e.config.value:void 0;return{name:e.name,type:e.config.case??`unknown`,providerUrl:t?.providerUrl??``,issuerUrl:t?.issuerUrl??``,clientId:t?.clientId??``,authUrl:t?.authUrl??``,tokenUrl:t?.tokenUrl??``,createdAt:e.createdAt?Ji(e.createdAt):null}}const Da=z({name:`list`,description:`List all auth connections.`,args:J.strictObject({...P,...Tr()}),run:async e=>{let{client:t,workspaceId:n}=await M({profile:e.profile,workspaceId:e[`workspace-id`]});try{let r=de(e.order),i=await kn(e.limit,e=>$r(async(e,i)=>{let{connections:a,nextPageToken:o}=await t.listAuthConnections({workspaceId:n,pageToken:e,pageSize:i,pageDirection:r});return[a,o]},{limit:e}));y.out(i.items.map(connectionInfo)),await D(i,e.limit)}catch(e){if(e instanceof Q&&e.code===Z.NotFound){y.out([]);return}throw e}}}),Oa=z({name:`open`,description:`Open the auth connections page in the Tailor Platform Console.`,args:J.strictObject({...P}),run:async e=>{let t=await Me({workspaceId:e[`workspace-id`],profile:e.profile}),n=`/workspaces/${t}/services/auth-connections`,r=await Ct({profile:e.profile,...e[`workspace-id`]===void 0?{}:{allowMissingProfile:!0}}),i=new URL(n,r).toString(),a=y.jsonMode;y.info(`Opening auth connections page in Tailor Platform Console...`);let o=!0;try{await ea(i)}catch{o=!1}a?y.out({consoleUrl:i,workspaceId:t,opened:o}):o?(y.out(`Console URL: ${i}`),y.out(`Workspace ID: ${t}`)):y.warn(`Failed to open browser automatically. Please open this URL manually:\n${i}`)}}),ka=z({name:`revoke`,description:`Revoke an auth connection's tokens (keeps the connection; use 'delete' to remove it).`,notes:"Revoke invalidates the connection's active session and tokens but keeps the connection and its stored credentials, so it can be re-authorized later. Use `delete` to remove the connection entirely.",args:J.strictObject({...P,...wa,...L}),run:async e=>{await O({profile:e.profile});let{client:t,workspaceId:n}=await M({profile:e.profile,workspaceId:e[`workspace-id`]});if(!e.yes&&await R.text({message:`Enter the connection name to confirm revocation ("${e.name}"):`,suggestion:`Pass --yes to skip the confirmation.`})!==e.name)throw S({code:`AUTH_CONNECTION_REVOCATION_CANCELLED`,message:`Auth connection revocation cancelled: the entered name did not match.`,suggestion:`Run the command again and enter the name exactly as shown, or pass --yes to skip the confirmation.`});try{await t.revokeAuthConnection({workspaceId:n,connectionName:e.name})}catch(t){throw t instanceof Q&&t.code===Z.NotFound?S({code:`AUTH_CONNECTION_NOT_FOUND`,message:`Auth connection "${e.name}" not found.`,cause:t}):t}y.success(`Auth connection "${e.name}" revoked.`),N({changed:!0,workspaceId:n,name:e.name})}}),Aa=K({name:`authconnection`,description:`Manage auth connections.`,subCommands:{authorize:Ta,list:Da,open:Oa,revoke:ka,delete:Ea},defaultSubCommand:`list`});function orderAndLimitCrashReports(e,t){let n=e.filter(e=>e.endsWith(Oi)).toSorted(),r=t.order===`asc`?n:n.toReversed();return t.limit&&t.limit>0?r.slice(0,t.limit):r}function formatCrashReportFiles(e,t){return e.map(e=>({file:e,path:q.join(t,e)}))}const ja=z({name:`list`,description:`List local crash report files.`,args:J.strictObject({...Tr()}),run:async e=>{let t=ki(),n=y.jsonMode;if(!t.localDir){y.info(`Crash report directory not available.`),n&&y.out([]);return}let r;try{r=X.readdirSync(t.localDir)}catch{y.info(`No crash reports found.`),n&&y.out([]);return}let i=await kn(e.limit,async t=>orderAndLimitCrashReports(r,{order:e.order,limit:t})),a=i.items;if(a.length===0)y.info(`No crash reports found.`),n&&y.out([]);else if(n)y.out(formatCrashReportFiles(a,t.localDir)),await D(i,e.limit);else{y.info(`${a.length} crash report(s) in ${t.localDir}:`);for(let e of a)y.log(` ${e}`);await D(i,e.limit)}}}),Ma=z({name:`send`,description:`Submit a crash report to help improve the SDK.`,args:J.strictObject({file:G(J.string(),{description:`Path to the crash report file`,required:!0,completion:{type:`file`,extensions:[`log`]}})}),run:async e=>{let t;try{t=X.readFileSync(e.file,`utf-8`)}catch{y.error(`Crash report file not found: ${e.file}`),process.exit(1)}let n=parseCrashLogFile(t);n||(y.error(`Failed to parse crash report file. The file may be corrupted.`),process.exit(1));let r=await Ti();y.info(`Sending crash report...`),await Ai(n,r)?(y.success(`Crash report submitted successfully. Thank you!`),N({changed:!0,id:n.id,file:e.file})):(y.error(`Failed to submit crash report. The server may be unavailable.`),process.exit(1))}});function parseCrashLogFile(e){try{let t=e.replace(/\r\n/g,`
15
- `),n=`\n${Di}\n`,r=t.lastIndexOf(n);if(r===-1)return;let i=t.slice(r+n.length).split(`
16
- `)[0];return i?JSON.parse(i):void 0}catch{return}}const Na=K({name:`crashreport`,description:`Manage crash reports.`,subCommands:{list:ja,send:Ma},defaultSubCommand:`list`});function delay(e){return e>0?new Promise(t=>setTimeout(t,e)):Promise.resolve()}function assertSeedDataDirectory(e){let t;try{t=X.statSync(e)}catch(t){throw t.code===`ENOENT`?S({code:`SEED_DATA_NOT_FOUND`,message:`Seed data directory not found: ${e}.`,suggestion:`Generate seed data before testing migrations.`,cause:t}):t}if(!t.isDirectory())throw S({code:`SEED_DATA_INVALID`,message:`Seed data path is not a directory: ${e}`})}function assertAssertionScript(e){let t=q.resolve(e),n;try{n=X.statSync(t)}catch(e){throw e.code===`ENOENT`?S({code:`MIGRATION_ASSERTION_SCRIPT_NOT_FOUND`,message:`Migration assertion script not found: ${t}`,cause:e}):e}if(!n.isFile())throw S({code:`MIGRATION_ASSERTION_SCRIPT_INVALID`,message:`Migration assertion path is not a file: ${t}`})}function assertCloneTargetRegion(e,t){if(e!==t)throw S({code:`MIGRATION_TEST_REGION_MISMATCH`,message:`Clone mode requires source and target workspaces in the same region (source: ${e}, target: ${t}).`})}function assertTargetWorkspaceDiffers(e,t){if(t?.toLowerCase()===e.toLowerCase())throw S({code:`MIGRATION_TEST_TARGET_INVALID`,message:`The migration test target workspace must differ from the source workspace.`,command:`tailordb migration test`})}function resolveAssertionNamespace(e,t){let n=t??(e.length===1?e[0]:void 0);if(!n)throw S({code:`MIGRATION_TEST_ASSERT_NAMESPACE_REQUIRED`,message:`--assert-namespace is required when pending migrations span multiple namespaces.`,command:`tailordb migration test`});if(!e.includes(n))throw S({code:`MIGRATION_TEST_NO_PENDING_MIGRATIONS`,message:`Assertion namespace "${n}" has no pending migrations.`});return n}async function createMigrationTestBaselineSnapshots(e){let t=new Map([...e.baselines].map(([e,t])=>[e,t.snapshot]));if(e.dataMode!==`clone`)return t;let n=e.inputs.filter(e=>!t.has(e.namespace)),r=await Promise.all(n.map(t=>en(e.client,e.workspaceId,t.namespace)));return n.forEach((e,n)=>{t.set(e.namespace,s(r[n],`remote snapshot missing for "${e.namespace}"`))}),t}async function waitForCloneApplicationData(e,t){let n=t.pollInterval??3e3,r=t.timeout??18e5,i=t.errorCodePrefix??`MIGRATION_TEST_CLONE`,a=Date.now()+r,s;for(let c=r;c>0;c=a-Date.now()){let r;try{r=await e.getCloneApplicationDataOperation({sourceWorkspaceId:t.sourceWorkspaceId,targetWorkspaceId:t.targetWorkspaceId,operationId:t.operationId},Number.isFinite(c)?{timeoutMs:c}:void 0)}catch(e){if(e instanceof Q&&e.code===Z.DeadlineExceeded&&Date.now()>=a-100)break;throw e}if(r.status===o.COMPLETED)return;if(r.status===o.FAILED)throw S({code:`${i}_FAILED`,message:`Application data clone failed: ${r.errorMessage||`unknown platform error`}`});if(r.status!==o.PENDING&&r.status!==o.PROCESSING)throw g(`Application data clone returned unexpected status ${r.status}.`);r.status!==s&&(s=r.status,t.onStatus?.(r.status)),await delay(Math.min(n,Math.max(a-Date.now(),0)))}throw S({code:`${i}_TIMEOUT`,message:`Application data clone timed out after ${r<1e3?`${r} ms`:`${Math.round(r/1e3)} seconds`}.`,context:{operationId:t.operationId,sourceWorkspaceId:t.sourceWorkspaceId,targetWorkspaceId:t.targetWorkspaceId}})}function loadSnapshotSeedData(e,t,n){let r={};for(let i of t){let t=n?.tables[i],a=q.join(e,`${i}.jsonl`),o;try{o=X.readFileSync(a,`utf8`).trim()}catch(e){if(e.code===`ENOENT`){r[i]=[];continue}throw e}r[i]=o?o.split(`
17
- `).map((e,n)=>{let r;try{r=JSON.parse(e)}catch(e){throw S({code:`SEED_DATA_INVALID`,message:`Invalid JSON in ${a} at line ${n+1}: ${e instanceof Error?e.message:String(e)}`,cause:e})}if(typeof r!=`object`||!r||Array.isArray(r))throw S({code:`SEED_DATA_INVALID`,message:`Invalid seed row in ${a} at line ${n+1}: expected a JSON object`});let i=r;return t?projectSeedObject(i,t.fields,/* @__PURE__ */ new Set([`id`])):i}):[]}return r}function projectSeedObject(e,t,n=/* @__PURE__ */ new Set){return Object.fromEntries(Object.entries(e).flatMap(([e,r])=>{let i=t[e];return i?[[e,projectSeedValue(r,i)]]:n.has(e)?[[e,r]]:[]}))}function projectSeedValue(e,t){let n=t.fields;return n?t.array?Array.isArray(e)?e.map(e=>isJsonObject(e)?projectSeedObject(e,n):e):e:isJsonObject(e)?projectSeedObject(e,n):e:e}function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function sortSeedTypesForSnapshot(e){let t=Object.keys(e.tables),n=new Set(t),r=/* @__PURE__ */ new Map,i=[];for(let[t,a]of Object.entries(e.tables)){let e=/* @__PURE__ */ new Set;for(let r of yn(a.fields))r===t?i.push(t):n.has(r)&&e.add(r);r.set(t,[...e])}let a=/* @__PURE__ */ new Set,o=[],visit=e=>{if(!a.has(e)){a.add(e);for(let t of r.get(e)??[])visit(t);o.push(e)}};for(let e of t)visit(e);return{order:o,selfRefTypes:i}}function temporaryWorkspaceName(){return`migration-test-${(/* @__PURE__ */ new Date()).toISOString().replace(/[-:T.Z]/g,``).slice(0,14)}-${Zi(3).toString(`hex`)}`}function stateOrThrow(e){return s(e,`migration test runtime was used before preparation`)}async function resolveTemporaryWorkspaceLocation(e,t,n){if(!n.organizationId&&!n.folderId)return{...t.organizationId?{organizationId:t.organizationId}:{},...t.folderId?{folderId:t.folderId}:{}};let{folderId:r}=n,i=n.organizationId??(t.organizationId||void 0);if(r&&!i)throw S({code:`MIGRATION_TEST_OPTIONS_INVALID`,message:`--folder-id requires --organization-id.`,details:`The source workspace is not in an organization.`,suggestion:`Pass --organization-id together with --folder-id.`});if(r&&i&&!await _i(async()=>{let{folder:t}=await e.getOrganizationFolder({organizationId:i,folderId:r});return t}))throw S({code:`MIGRATION_TEST_OPTIONS_INVALID`,message:`Folder "${r}" was not found in organization "${i}"${n.organizationId?``:` (the source workspace's organization)`}.`,details:`The folder does not exist there, belongs to a different organization, or is not accessible.`,suggestion:n.organizationId?`Pass a --folder-id that belongs to --organization-id.`:`Pass --organization-id together with --folder-id if the folder is in another organization.`});return{...i?{organizationId:i}:{},...r?{folderId:r}:{}}}function assertTargetMatchesLocation(e,t){let n=[{flag:`--organization-id`,kind:`organization`,wanted:t.organizationId,actual:e.organizationId},{flag:`--folder-id`,kind:`folder`,wanted:t.folderId,actual:e.folderId}];for(let{flag:t,kind:r,wanted:i,actual:a}of n)if(i!==void 0&&i.toLowerCase()!==a?.toLowerCase())throw S({code:`MIGRATION_TEST_OPTIONS_INVALID`,message:`${t} "${i}" does not match the designated target workspace "${e.id}", which ${a?`is in ${r} "${a}"`:`has no ${r}`}.`,suggestion:`Pass the ${r} the target workspace is in, or omit ${t}.`})}function assertSourceMatchesCheckpoints(e,t){let n=e.find(e=>e.hasDrift||e.checkpointMissingLocal);if(n?.checkpointUnset)throw S({code:`MIGRATION_TEST_SOURCE_INVALID`,message:`Source namespace "${n.namespace}" has no migration label and its schema differs from the initial migration snapshot (0000).`,details:rt(n.drifts),suggestion:`Bring the source schema in line with 0000 or set its migration label.`});if(n){let e={...k(t),namespace:n.namespace},r=Tt({...e,subcommand:[`status`]}),i=Tt({...e,subcommand:[`validate`]});throw S({code:`MIGRATION_TEST_SOURCE_INVALID`,message:`Source namespace "${n.namespace}" does not match its migration checkpoint.`,...n.hasDrift?{details:rt(n.drifts)}:{},suggestion:n.checkpointMissingLocal?`${Pn} Otherwise run ${r} to compare the source workspace's checkpoint and migration history with the local ones.`:`Run ${i} to check the migration history and source schema, or ${r} to inspect the source workspace's checkpoint.`})}let r=e.find(e=>e.checkpointRepair);if(r)throw S({code:`MIGRATION_TEST_SOURCE_REPAIR_PENDING`,message:`Source namespace "${r.namespace}" has a pending migration checkpoint repair.`,suggestion:`Deploy to the source workspace first.`})}function resolveSourceMigrationNumber(e){if(e.skipped===`not_deployed`)throw S({code:`MIGRATION_TEST_SOURCE_CHECKPOINT_MISSING`,message:`Source namespace "${e.namespace}" has not been deployed.`,suggestion:`Deploy to the source workspace before testing.`});return e.remoteMigrationNumber}function findSourceCheck(e,t){return s(e.find(e=>e.namespace===t),`remote schema check result missing for namespace "${t}"`)}async function assertSourceBaselineFresh(e,t,n){let r=e.loaded,i=k({workspaceId:n,profile:e.options.profile,configPath:r.config.path}),a=We(r.config,q.dirname(r.config.path)),o=r.application.tailorDBServices.map(It),s=await Mr(e.client,n,a,r.config,o),c=s.find(e=>e.hasDrift||e.checkpointMissingLocal||e.checkpointRepair);if(c)throw S({code:`MIGRATION_TEST_SOURCE_CHANGED`,message:`Source namespace "${c.namespace}" changed after migration test preparation.`,suggestion:`Run the migration test again.`});for(let r of a){let a=t.baselines.get(r.namespace);if(!a)continue;let o=await _e(e.client,U(n,`tailordb`,r.namespace));Cr(o,r.namespace,i);let c=resolveSourceMigrationNumber(findSourceCheck(s,r.namespace));if(c!==a.migrationNumber)throw S({code:`MIGRATION_TEST_SOURCE_CHANGED`,message:`Source namespace "${r.namespace}" moved from migration ${a.migrationNumber} to ${c} after migration test preparation.`,suggestion:`Run the migration test again.`})}let l=o.filter(e=>!t.baselines.has(e.namespace));for(let r of l){let i=t.baselineSnapshots.get(r.namespace);if(!i)continue;let a=await en(e.client,n,r.namespace);if(Ln(i,a).changes.length>0)throw S({code:`MIGRATION_TEST_SOURCE_CHANGED`,message:`Source namespace "${r.namespace}" schema changed after migration test preparation.`,suggestion:`Run the migration test again.`})}}async function deleteExistingUserProfileConfig(e,t){let n=e.loaded.application.authService;if(!n)return;let r=n.config.name;await _i(()=>e.client.getUserProfileConfig({workspaceId:t,namespaceName:r}))&&await e.client.deleteUserProfileConfig({workspaceId:t,namespaceName:r})}function migrationConfig(e,t){return e.config.db?.[t]?.migration}function authExecutionContext(e,t,n){let r=e.loaded.application.authService;if(!r)throw S({code:`AUTH_CONFIG_REQUIRED`,message:`Auth configuration is required to execute migration test scripts.`});let i=n??Ir(migrationConfig(e.loaded,t),r.config.machineUsers?Object.keys(r.config.machineUsers):void 0);if(!i)throw S({code:`MACHINE_USER_REQUIRED`,message:`No machine user is available for namespace "${t}".`,suggestion:`Pass --machine-user or configure one in auth or db.${t}.migration.`});return{authNamespace:r.config.name,machineUserName:i}}async function prepareMigrationTest(e){let t=await Et({configPath:e.configPath}),n=q.dirname(t.config.path),r=We(t.config,n);if(r.length===0)throw Ge();for(let e of r)xt(e.migrationsDir,e.namespace,t.config.path);let i;e.data===`seed`&&(i=await _t({configPath:t.config.path}),assertSeedDataDirectory(q.join(i.distPath,`data`))),e.assertionPath&&assertAssertionScript(e.assertionPath);let a=t.application.tailorDBServices.map(It),o=await yt({profile:e.profile}),c=await Ie({profile:e.profile}),l=await si(o,c),u=await Me({workspaceId:e.workspaceId,profile:e.profile});assertTargetWorkspaceDiffers(u,e.targetWorkspaceId);let[d,f,p]=await Promise.all([l.getWorkspace({workspaceId:u}),l.getApplication({workspaceId:u,applicationName:t.config.name}),e.targetWorkspaceId?l.getWorkspace({workspaceId:e.targetWorkspaceId}):Promise.resolve(void 0)]),m=s(d.workspace,`source workspace "${u}" not found`);s(f.application,`application "${t.config.name}" not found in source workspace`);let h=p?s(p.workspace,`target workspace "${e.targetWorkspaceId}" not found`):void 0;h&&assertTargetMatchesLocation(h,e);let g=await resolveTemporaryWorkspaceLocation(l,m,h?{}:e),_=await Mr(l,u,r,t.config,a),v={workspaceId:u,profile:e.profile,configPath:t.config.path};assertSourceMatchesCheckpoints(_,v);let y=/* @__PURE__ */ new Map,b=/* @__PURE__ */ new Map,x=[];for(let e of r){let t=await _e(l,U(u,`tailordb`,e.namespace));Cr(t,e.namespace,k(v));let n=resolveSourceMigrationNumber(findSourceCheck(_,e.namespace)),r=ir(e.migrationsDir);if(n>r)throw S({code:`MIGRATION_TEST_SOURCE_AHEAD`,message:`Source namespace "${e.namespace}" is at migration ${n}, but the local history ends at ${r}.`});let i=A(e.migrationsDir,n);if(!i)throw S({code:`MIGRATION_BASELINE_NOT_FOUND`,message:`No migration baseline snapshot found for namespace "${e.namespace}".`});y.set(e.namespace,{migrationNumber:n,snapshot:i,historyId:i.rebaseline?.historyId??null});let a=A(e.migrationsDir,r);if(!a)throw S({code:`MIGRATION_TEST_SNAPSHOT_NOT_FOUND`,message:`No target migration snapshot found for namespace "${e.namespace}".`});b.set(e.namespace,a),n<r&&x.push(e.namespace)}if(x.length===0)throw S({code:`MIGRATION_TEST_NO_PENDING_MIGRATIONS`,message:`No pending TailorDB migrations found in the source workspace.`});let C=await createMigrationTestBaselineSnapshots({client:l,workspaceId:u,dataMode:e.data,inputs:a,baselines:y}),w={sourceWorkspaceId:u,sourceApplicationName:t.config.name,temporaryWorkspace:{name:temporaryWorkspaceName(),region:m.region,...g},baselines:y,baselineSnapshots:C,targetSnapshots:b,pendingNamespaces:x,...h?{designatedTarget:{id:h.id,region:h.region}}:{}};return{state:{client:l,loaded:t,options:e,...i?{seedContext:i}:{}},prepared:w}}function createMigrationTestDependencies(){let e;return{prepare:async t=>{let{state:n,prepared:r}=await prepareMigrationTest(t);return e=n,r},createWorkspace:async t=>{let n=stateOrThrow(e),r=await Bt(n.client,t.temporaryWorkspace);return y.info(`Created temporary workspace ${r.name} (${r.id}).`),{id:r.id,name:r.name,...r.createdAt?{createdAt:r.createdAt}:{}}},recordWorkspaceExpiry:async(t,n,r=/* @__PURE__ */ new Date)=>{let i=stateOrThrow(e);await hn(i.client,t,new Date(r.getTime()+vr(n)))},deployBaseline:async({prepared:t,targetWorkspaceId:n})=>{let r=stateOrThrow(e);await deleteExistingUserProfileConfig(r,n),await an({configPath:r.loaded.config.path,profile:r.options.profile,workspaceId:n,yes:!0},t.baselines,t.baselineSnapshots);for(let[e,i]of t.baselines)await bt(r.client,n,e,i.migrationNumber,i.historyId??void 0)},seedData:async({prepared:t,targetWorkspaceId:n})=>{let r=stateOrThrow(e),i=s(r.seedContext,`seed context missing after migration test preparation`),a=q.join(i.distPath,`data`);assertSeedDataDirectory(a);let o=new Map(r.loaded.application.tailorDBServices.map(e=>{let n=t.baselines.get(e.namespace),r=It(e);return[e.namespace,n?.snapshot??Pt({version:1,namespace:e.namespace,createdAt:(/* @__PURE__ */ new Date()).toISOString(),tables:r.types})]}));for(let[e,t]of o){let{order:o,selfRefTypes:s}=sortSeedTypesForSnapshot(t),c=loadSnapshotSeedData(a,o,t),l=o.filter(e=>(c[e]?.length??0)>0);if(l.length===0)continue;let u=await Nt(e,l,q.dirname(r.loaded.config.path)),d=nr({data:c,order:o,codeByteSize:new TextEncoder().encode(u.bundledCode).length}),f=authExecutionContext(r,e,r.options.machineUser??i.machineUserName);for(let t of d){let i=await Pe({client:r.client,workspaceId:n,name:`migration-test-seed-${e}.ts`,code:u.bundledCode,arg:{data:t.data,order:t.order,selfRefTypes:s,upsert:!1},invoker:{namespace:f.authNamespace,machineUserName:f.machineUserName}});if(!i.success)throw S({code:`MIGRATION_TEST_SEED_FAILED`,message:i.error??`Seed execution failed for namespace "${e}".`});if(JSON.parse(i.result||`{}`).success!==!0)throw S({code:`MIGRATION_TEST_SEED_FAILED`,message:`Seed execution reported failure for namespace "${e}".`})}}},cloneData:async({prepared:t,sourceWorkspaceId:n,targetWorkspaceId:r,applicationName:i,cloneTimeout:a})=>{let o=stateOrThrow(e);await assertSourceBaselineFresh(o,t,n),y.warn(`Clone mode copies TailorDB records only; IdP users and file blobs are not copied.`);let s;try{s=(await o.client.cloneApplicationData({sourceWorkspaceId:n,sourceApplicationName:i,targetWorkspaceId:r,targetApplicationName:i})).operationId}catch(e){throw e instanceof Q&&e.code===Z.Unimplemented?S({code:`MIGRATION_TEST_CLONE_UNAVAILABLE`,message:`Application data clone is not enabled for this platform.`,suggestion:`Retry with --data seed.`,cause:e}):e}if(!s)throw g(`Application data clone returned no operation ID.`);await waitForCloneApplicationData(o.client,{sourceWorkspaceId:n,targetWorkspaceId:r,operationId:s,timeout:a})},deployMigrations:async({prepared:t,targetWorkspaceId:n,machineUser:r})=>{let i=stateOrThrow(e);await ur({configPath:i.loaded.config.path,profile:i.options.profile,workspaceId:n,yes:!0},t.targetSnapshots,r)},runAssertion:async({prepared:t,targetWorkspaceId:n,assertionPath:r,assertionNamespace:i,machineUser:a})=>{let o=stateOrThrow(e),s=resolveAssertionNamespace(t.pendingNamespaces,i),c=authExecutionContext(o,s,a),l=await wn(r,s,0,o.loaded.config.env??{},q.dirname(o.loaded.config.path),Re(o.loaded.plugins,`@tailor-platform/kysely-type`)?.temporal??!1,ei(o.loaded.config)),u=await Pe({client:o.client,workspaceId:n,name:`migration-test-assert-${s}.ts`,code:l.bundledCode,invoker:{namespace:c.authNamespace,machineUserName:c.machineUserName}});if(!u.success)throw S({code:`MIGRATION_TEST_ASSERTION_FAILED`,message:u.error??`Migration assertion failed for namespace "${s}".`})},deleteWorkspace:async t=>{await stateOrThrow(e).client.deleteWorkspace({workspaceId:t})}}}const Pa={from:G(J.string(),{description:`Workspace ID to copy data from`,completion:{type:`none`}}),to:G(J.string(),{description:`Workspace ID to copy data to`,completion:{type:`none`}})};function resumeCommandArgs(e){return[`data`,`operation`,`get`,`--from`,e.sourceWorkspaceId,`--to`,e.targetWorkspaceId,`--operation-id`,e.operationId,`--wait`,...H({profile:e.profile})]}function resumeHint(e){return b({command:`tailor`,args:resumeCommandArgs(e)})}async function hintOnInterrupt(e,t){let onInterrupt=()=>{y.info(`Stopped waiting. The clone keeps running on the platform. To wait for it: ${resumeHint(e)}`)};process.once(`SIGINT`,onInterrupt);try{return await t()}finally{process.off(`SIGINT`,onInterrupt)}}const Fa={[o.PENDING]:`pending`,[o.PROCESSING]:`processing`,[o.COMPLETED]:`completed`,[o.FAILED]:`failed`};function statusName(e){return Fa[e]??`unknown`}function reportStatus(e){y.info(`status: ${statusName(e)}`,{mode:`stream`})}function formatElapsed(e){let t=Math.floor(e/1e3),n=Math.floor(t/3600),r=Math.floor(t%3600/60),i=t%60;return n>0?`${n}h ${r}m`:r>0?`${r}m ${i}s`:`${i}s`}async function $clone(e){let t=vn(e.config),n=t?[t]:[];if(e.sourceWorkspaceId===e.targetWorkspaceId)throw S({code:`DATA_CLONE_SAME_WORKSPACE`,message:`The source and target workspaces must be different.`,command:`data clone`});let r=await si(await yt({profile:e.profile}));try{await r.getApplication({workspaceId:e.targetWorkspaceId,applicationName:e.name})}catch(t){throw t instanceof Q&&t.code===Z.NotFound?S({code:`DATA_CLONE_TARGET_APPLICATION_NOT_FOUND`,message:`Application "${e.name}" was not found in the target workspace "${e.targetWorkspaceId}".`,suggestion:e.nameFromConfig?`Check --to and that you have access to the target workspace, and deploy the application to it first so it has the same namespaces and schema.`:`Check --to and that you have access to the target workspace, and deploy the application "${e.name}" to it first so it has the same namespaces and schema.`,...e.nameFromConfig?{next:{command:`tailor`,args:[`deploy`,...H({workspaceId:e.targetWorkspaceId,profile:e.profile}),...n]}}:{},command:`data clone`,cause:t}):t}if(!e.yes&&!await R.confirm({message:`This will copy the data of application "${e.name}" from workspace "${e.sourceWorkspaceId}" to workspace "${e.targetWorkspaceId}". Continue?`,default:!1}))throw S({code:`DATA_CLONE_CANCELLED`,message:`Data clone cancelled.`});let i;try{i=(await r.cloneApplicationData({sourceWorkspaceId:e.sourceWorkspaceId,sourceApplicationName:e.name,targetWorkspaceId:e.targetWorkspaceId,targetApplicationName:e.name,copyFiles:e.copyFiles,copyIdpUsers:e.copyIdpUsers})).operationId}catch(t){throw t instanceof Q&&t.code===Z.Unimplemented?S({code:`DATA_CLONE_UNAVAILABLE`,message:`Application data clone is not enabled for this platform.`,command:`data clone`,cause:t}):t instanceof Q&&t.code===Z.FailedPrecondition?S({code:`DATA_CLONE_PRECONDITION_FAILED`,message:t.rawMessage,suggestion:`A clone needs both workspaces in the same region with the same namespaces, a matching TailorDB schema (deploy the same version to the target first), and an empty target for every copy type in scope. ${e.nameFromConfig?`To empty the target's TailorDB records, run ${b({command:`tailor`,args:[`tailordb`,`truncate`,`--all`,...H({workspaceId:e.targetWorkspaceId,profile:e.profile}),...n]})}.`:`To empty the target's TailorDB records, run tailor tailordb truncate for the namespaces of this application (see tailor tailordb truncate --help).`} That does not remove IdP users or files: with --copy-idp-users or --copy-files, remove those from the target separately.`,command:`data clone`,cause:t}):t instanceof Q&&t.code===Z.NotFound?S({code:`DATA_CLONE_NOT_FOUND`,message:t.rawMessage,suggestion:`Check that --from and --to are workspace IDs you can access and that the application exists in the source workspace.`,command:`data clone`,cause:t}):t}if(!i)throw g(`Application data clone returned no operation ID.`);y.info(`Clone started (operation: ${i})`);let a={sourceWorkspaceId:e.sourceWorkspaceId,targetWorkspaceId:e.targetWorkspaceId,operationId:i,profile:e.profile};if(e.noWait)return y.info(`The clone keeps running on the platform. To wait for it: ${resumeHint(a)}`),{operationId:i,status:`started`};let o=Date.now();return await hintOnInterrupt(a,()=>waitForCloneApplicationData(r,{sourceWorkspaceId:a.sourceWorkspaceId,targetWorkspaceId:a.targetWorkspaceId,operationId:i,timeout:1/0,errorCodePrefix:`DATA_CLONE`,onStatus:reportStatus})),y.success(`Cloned data of application "${e.name}" from "${e.sourceWorkspaceId}" to "${e.targetWorkspaceId}" in ${formatElapsed(Date.now()-o)}`),{operationId:i,status:`completed`}}const Ia=z({name:`clone`,description:`Clone the data of an application (TailorDB namespaces registered in its subgraph) from one workspace to another.`,notes:"\nThe platform rejects the clone with a failed precondition unless all of the following hold:\n- The source and target workspaces are in the same region.\n- The target workspace has the same namespaces as the source.\n- The TailorDB schema of the target matches the source, so deploy the same version to the target first.\n- The target is empty for every namespace and copy type in scope (TailorDB records, plus files and IdP users when `--copy-files` / `--copy-idp-users` are given).\n\nThe command waits until the clone finishes. Pressing Ctrl+C or passing --no-wait does not stop the clone, which keeps running on the platform. Use `tailor data operation get --wait` with the operation ID printed at the start to keep waiting, or without --wait to check the status once.\n\nWith --json, the result carries `status`: `completed` once the clone has finished, or `started` with --no-wait.\n",args:J.strictObject({...L,profile:G(J.string().optional(),{alias:`p`,description:`Workspace profile`,env:`TAILOR_PLATFORM_PROFILE`,completion:{type:`none`}}),...Pa,name:G(J.string().optional(),{alias:`n`,description:`Application name, the same in the source and the target workspace (default: the name in the config file)`,completion:{type:`none`}}),...pr,"copy-files":G(J.boolean().default(!1),{description:`Also copy TailorDB file content`}),"copy-idp-users":G(J.boolean().default(!1),{description:`Also copy IdP users, including their passwords`}),"no-wait":G(J.boolean().default(!1),{description:`Start the clone and exit without waiting for it to finish`})}),run:async e=>{await O({profile:e.profile});let t=e.name??(await j(e.config)).config.name,{operationId:n,status:r}=await $clone({sourceWorkspaceId:e.from,targetWorkspaceId:e.to,name:t,config:e.config,nameFromConfig:e.name===void 0,copyFiles:e[`copy-files`],copyIdpUsers:e[`copy-idp-users`],noWait:e[`no-wait`],profile:e.profile,yes:e.yes});N({changed:!0,sourceWorkspaceId:e.from,targetWorkspaceId:e.to,operationId:n,status:r})}}),La=z({name:`get`,description:`Show the status of a data clone, or wait for it to finish.`,notes:`Without --wait, the command prints the current status once and exits. With --wait, it waits until the clone completes or fails, and exits with an error if it fails. Pressing Ctrl+C stops waiting; the clone keeps running on the platform.`,args:J.strictObject({profile:G(J.string().optional(),{alias:`p`,description:`Workspace profile`,env:`TAILOR_PLATFORM_PROFILE`,completion:{type:`none`}}),...Pa,"operation-id":G(J.string(),{description:`Operation ID printed when the clone started`,completion:{type:`none`}}),wait:G(J.boolean().default(!1),{description:`Wait until the clone completes or fails`})}),run:async e=>{let t=await si(await yt({profile:e.profile})),n={sourceWorkspaceId:e.from,targetWorkspaceId:e.to,operationId:e[`operation-id`],profile:e.profile};if(!e.wait){let e=await t.getCloneApplicationDataOperation({sourceWorkspaceId:n.sourceWorkspaceId,targetWorkspaceId:n.targetWorkspaceId,operationId:n.operationId}),r=statusName(e.status);y.info(`Clone operation ${n.operationId}: ${r}`),e.errorMessage&&y.info(`Message: ${e.errorMessage}`),y.out({operationId:n.operationId,status:r,...e.errorMessage?{errorMessage:e.errorMessage}:{}});return}let r=Date.now();await hintOnInterrupt(n,()=>waitForCloneApplicationData(t,{sourceWorkspaceId:n.sourceWorkspaceId,targetWorkspaceId:n.targetWorkspaceId,operationId:n.operationId,timeout:1/0,errorCodePrefix:`DATA_CLONE`,onStatus:reportStatus})),y.success(`Clone operation ${n.operationId} completed (waited ${formatElapsed(Date.now()-r)})`),y.out({operationId:n.operationId,status:`completed`})}}),Ra=K({name:`operation`,description:`Inspect asynchronous application data operations.`,subCommands:{get:La}}),za=K({name:`data`,description:`Manage application data across workspaces.`,subCommands:{clone:Ia,operation:Ra}}),Ba=z({name:`deploy`,description:`Deploy your application by applying the Tailor configuration.`,notes:"Every workspace belongs to an organization; when none is given or set as a default, interactive runs ask for one and non-interactive runs fail. Workspace creation uses the selected user's default organization and folder set by `user update` when neither location is given and TAILOR_PLATFORM_TOKEN is not set. Giving --organization-id or --folder-id replaces both defaults. Organization and folder IDs loaded by --env-file also replace the defaults; command-line options take precedence, and empty env-file values are ignored. With --create-workspace, an existing workspace must match the resolved name, region, organization, and folder to be reused.",args:J.strictObject({...P,...kr,...L,"create-workspace":G(J.boolean().optional(),{description:`Create a workspace when the account has none`}),"workspace-name":G(J.string().optional(),{description:`Name for a workspace created during deploy`}),"workspace-region":G(J.string().optional(),{description:`Region for a workspace created during deploy`}),"organization-id":G(J.string().optional(),{description:`Organization ID for a workspace created during deploy`,env:`TAILOR_PLATFORM_ORGANIZATION_ID`}),"folder-id":G(J.string().optional(),{description:`Folder ID for a workspace created during deploy`,env:`TAILOR_PLATFORM_FOLDER_ID`}),"dry-run":G(J.boolean().optional(),{alias:`d`,description:`Run the command without making any changes`}),"no-schema-check":G(J.boolean().optional(),{description:`Skip schema diff check against migration snapshots (beta)`}),"migration-skip-steps":G(J.string().optional(),{description:`Skip steps of a partially applied multi-step migration that already succeeded, as comma-separated namespace/step entries (beta)`}),"no-validate":G(J.boolean().optional(),{description:`Skip client-side validation against platform resource constraints`}),"no-cache":G(J.boolean().optional(),{description:`Disable bundle caching for this run`}),"clean-cache":G(J.boolean().optional(),{description:`Clean the bundle cache before building`})}),run:async e=>{await O({profile:e.profile});let{initTelemetry:t}=await import(`../telemetry-nqOtDWNO.mjs`);await t(),await te({workspaceId:e[`workspace-id`],profile:e.profile,configPath:e.$source?.(`config`)===`cli`?e.config:oe()??`tailor.config.ts`,dryRun:e[`dry-run`],yes:e.yes,createWorkspace:e[`create-workspace`],workspaceName:e[`workspace-name`],workspaceRegion:e[`workspace-region`],..._r(e),noSchemaCheck:e[`no-schema-check`],migrationSkipSteps:Ve(e[`migration-skip-steps`]),noValidate:e[`no-validate`],noCache:e[`no-cache`],cleanCache:e[`clean-cache`]},{envFile:e[`env-file`],envFileIfExists:e[`env-file-if-exists`],verbose:e.verbose,json:e.json})}}),Va=K({name:`executor`,description:`Manage executors`,subCommands:{trigger:pt,jobs:Dn,list:me,get:St,webhook:wr},defaultSubCommand:`list`});function scriptNameToRegistryName(e,t){if(t===a.JOB)return`workflow--${e}`;let n=/^([^.]+)\.(.+)\.body\.js$/.exec(e);if(n){let[,e,t]=n;return`resolver--${e}--${t}`}let r=/^(.+)\.operation\.js$/.exec(e);if(r){let[,e]=r;return`executor--${e}`}let i=/^([^.]+)\.([^.]+)\.hook\.js$/.exec(e);if(i){let[,e,t]=i;return`auth-hook--${e}--${t}`}return t===a.UNSPECIFIED&&!e.includes(`.`)?`workflow--${e}`:null}async function downloadFunctionScript(e){let{client:t,workspaceId:n,name:r,contentHash:i}=e;try{let e=[];for await(let a of t.downloadFunctionRegistryScript({workspaceId:n,name:r,contentHash:i}))a.payload.case===`chunk`&&e.push(a.payload.value);return e.length===0?null:{code:Buffer.concat(e).toString(`utf-8`)}}catch(t){return y.debug(`Failed to download function script "${e.name}": ${t}`),null}}const Ha=/^\s+at\s+(?:(.+?)\s+\()?(file:\/\/\/.+?):(\d+):(\d+)\)?$/;function parseStackTrace(e){let t=e.split(`
18
- `),n=[],r=[];for(let e of t)/^\s+at\s+/.test(e)?r.push(e):r.length===0&&n.push(e);let i=n.join(`
19
- `);i.startsWith(`rpc error: code = Aborted desc = `)&&(i=i.slice(33));let a=[];for(let e of r){let t=Ha.exec(e);t&&a.push({functionName:t[1]||`<anonymous>`,file:s(t[2],`stack frame file missing`),line:Number(s(t[3],`stack frame line missing`)),column:Number(s(t[4],`stack frame column missing`))})}return{errorMessage:i,frames:a}}const Ua=/\/\/[#@]\s*sourceMappingURL=data:application\/json[^,]*;base64,(.+)$/m;function extractInlineSourcemap(e){let t=Ua.exec(e);if(!t)return null;try{let e=Buffer.from(s(t[1],`sourcemap base64 data missing`),`base64`).toString(`utf-8`),n=JSON.parse(e);return new oa(n)}catch{return null}}function mapStackFrames(e,t){return e.map(e=>{if(!t)return{original:e,mapped:null};try{for(let n=t.sources.length-1;n>=0;n--){let r=t.sources[n];if(r==null)continue;let i=sa(t,{source:r,line:e.line,column:e.column-1});if(i.line==null)continue;let a=ca(t,{line:i.line,column:i.column});if(a.source===r&&a.line===e.line&&a.column===e.column-1)return{original:e,mapped:{source:r,line:e.line,column:e.column,name:null}}}return{original:e,mapped:null}}catch{return{original:e,mapped:null}}})}function detectEditorScheme(){let e=process.env.VISUAL||process.env.EDITOR||``;return/\bcode\b/.test(e)?`vscode`:null}function osc8Link(e,t){return`\x1b]8;;${e}\x07${t}\x1b]8;;\x07`}function buildSourceLink(e,t,n,r){let i=`${e}:${n}:${r}`;return detectEditorScheme()===`vscode`?osc8Link(`vscode://file${t}:${n}:${r}`,i):osc8Link(`file://${t}`,i)}function buildCodeSnippet(e,t){let n=e.split(`
20
- `),r=Math.max(0,t-1-2),i=Math.min(n.length,t+2),a=String(i).length,o=[];for(let e=r;e<i;e++){let r=e+1,i=String(r).padStart(a),s=n[e];r===t?o.push(` ${w.error(`>`)} ${w.error(`${i} | ${s}`)}`):o.push(` ${w.dim(`${i} | ${s}`)}`)}return o.join(`
21
- `)}function readInstalledSource(e){try{let t=X.realpathSync(e);return qr(t)?X.readFileSync(t,`utf-8`):void 0}catch{return}}function formatMappedError(e,t,n,r){let i=[` ${w.error(e)}`];for(let e of t)if(e.mapped){let{source:t,line:a,column:o,name:s}=e.mapped,c=r?q.resolve(r,t):q.resolve(t),l=q.relative(process.cwd(),c),u=l.startsWith(`..`)?l:`./${l}`,d=s??e.original.functionName,f=buildSourceLink(u,c,a,o);if(i.push(`\n at ${d} (${f})`),n){let e=n.sources.indexOf(t),r=(e===-1?void 0:n.sourcesContent?.[e])||readInstalledSource(c);r&&i.push(buildCodeSnippet(r,a))}}else{let t=`${e.original.file.replace(/^file:\/\/\//,``)}:${e.original.line}:${e.original.column}`;i.push(`\n ${w.dim(`at ${e.original.functionName} (${t})`)}`)}return i.join(`
22
- `)}function formatErrorWithSourcemap(e,t,n){try{let{errorMessage:r,frames:i}=parseStackTrace(e);if(i.length===0)return null;let a=extractInlineSourcemap(t);if(!a)return null;let o=mapStackFrames(i,a);return o.some(e=>e.mapped!==null)?formatMappedError(r,o,a,n):null}catch{return null}}function functionExecutionTypeToString(e){return ar(a,e)??`UNSPECIFIED`}function functionErrorKindToString(e){return ar(r,e)??`UNSPECIFIED`}function toFunctionExecutionListInfo(e){return{id:e.id,scriptName:e.scriptName,status:et(e.status),type:functionExecutionTypeToString(e.type),startedAt:e.startedAt?Ji(e.startedAt):null,finishedAt:e.finishedAt?Ji(e.finishedAt):null,errorKind:functionErrorKindToString(e.errorKind),errorName:e.error?.name||null,errorMessage:e.error?.message||null,hasPlatformLogs:e.hasPlatformLogs}}function toFunctionExecutionDetailInfo(e){return{...toFunctionExecutionListInfo(e),logs:on(e.logEntries),logEntries:e.logEntries.map(dr),result:e.result,error:e.error?{name:e.error.name,message:e.error.message,stackTrace:e.error.stackTrace}:null}}function composeExecutionErrorString(e){let{name:t,message:n,stackTrace:r}=e,i=t&&n?`${t}: ${n}`:t||n;if(!r)return i;let a=r.split(`
14
+ `.replace(/\n/g,``);function renderCallbackPage(e){let t=escapeHtml(e.title),n=escapeHtml(e.message),r=e.status===`success`?`<script>window.close()<\/script>`:``;return`<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>${t}</title><style>${Ua}</style></head><body class="${e.status}"><main><div class="icon">${Ha[e.status]}</div><h1>${t}</h1><p>${n}</p></main>${r}</body></html>`}const Wa={"Content-Type":`text/html; charset=utf-8`};function sendCallbackSuccess(e,t){e.writeHead(200,Wa),e.end(renderCallbackPage({status:`success`,title:t,message:`You can close this tab and return to the terminal.`}))}function sendCallbackFailure(e,t,n,r){e.writeHead(t,Wa),e.end(renderCallbackPage({status:`failure`,title:n,message:o(r)?r.message:`Return to the terminal for details.`}))}const Ga={name:G(J.string(),{alias:`n`,description:`Auth connection name`})};async function fetchOIDCDiscovery(e){let t=e.replace(/\/$/,``)+`/.well-known/openid-configuration`,n=await fetch(t).catch(e=>{throw _({code:`OIDC_DISCOVERY_FAILED`,message:`Failed to fetch OIDC discovery from ${t}: ${g(e).message}`,cause:e})});if(!n.ok)throw _({code:`OIDC_DISCOVERY_FAILED`,message:`Failed to fetch OIDC discovery from ${t}: ${n.status}`});return n.json()}function randomState$1(){return _a.randomBytes(32).toString(`base64url`)}const Ka=I({name:`authorize`,description:`Authorize an auth connection via OAuth2 flow.`,args:J.strictObject({...A,...Ga,scopes:J.string().optional().default(`openid,profile,email`).describe(`OAuth2 scopes to request (comma-separated)`),port:J.coerce.number().optional().default(8080).describe(`Local callback server port`),"no-browser":J.boolean().optional().default(!1).describe(`Don't open browser automatically`)}),run:async e=>{await L({profile:e.profile});let t=h({command:`tailor`,args:[`authconnection`,`open`,...k({profile:e.profile,workspaceId:e[`workspace-id`]})]}),{client:n,workspaceId:r}=await B({profile:e.profile,workspaceId:e[`workspace-id`]}),i=(await Mi(async(e,t)=>{let{connections:i,nextPageToken:a}=await n.listAuthConnections({workspaceId:r,pageToken:e,pageSize:t});return[i,a]})).find(t=>t.name===e.name);if(!i)throw _({code:`AUTH_CONNECTION_NOT_FOUND`,message:`Auth connection "${e.name}" not found.`});if(i.config.case!==`oauth2`)throw _({code:`AUTH_CONNECTION_NOT_OAUTH2`,message:`Auth connection "${e.name}" is not an OAuth2 connection.`});let a=i.config.value,o=`http://localhost:${e.port}/callback`,s=randomState$1(),c;c=a.authUrl?a.authUrl:(await fetchOIDCDiscovery(a.providerUrl)).authorization_endpoint;let l=new URL(c);l.searchParams.set(`client_id`,a.clientId),l.searchParams.set(`redirect_uri`,o),l.searchParams.set(`response_type`,`code`),l.searchParams.set(`scope`,e.scopes.replace(/,/g,` `)),l.searchParams.set(`state`,s),l.searchParams.set(`access_type`,`offline`),await new Promise((i,a)=>{let handleCallback=async(t,l)=>{if(!t.url?.startsWith(`/callback`))l.writeHead(404),l.end(`Not found`);else try{let a=new URL(t.url,`http://localhost:${e.port}`),u=a.searchParams.get(`code`),d=a.searchParams.get(`state`),f=a.searchParams.get(`error`);if(f)throw _({code:`AUTHORIZATION_FAILED`,message:`Authorization failed: ${f}`});if(d!==s)throw _({code:`AUTHORIZATION_STATE_MISMATCH`,message:`State mismatch — possible CSRF attack.`});if(!u)throw _({code:`AUTHORIZATION_CODE_MISSING`,message:`No authorization code received.`});m.registerSecret(u),await n.exchangeAuthConnectionAuthorizationCode({workspaceId:r,connectionName:e.name,authorizationCode:u,redirectUri:o}),sendCallbackSuccess(l,`Authorization successful`),c.close(),i()}catch(e){sendCallbackFailure(l,400,`Authorization failed`,e),c.close(),a(g(e))}},c=ba.createServer((e,t)=>void handleCallback(e,t)),u=setTimeout(()=>{c.close(),a(_({code:`AUTHORIZATION_TIMEOUT`,message:`Authorization timeout exceeded (5 minutes).`}))},3e5);c.on(`close`,()=>{clearTimeout(u)}),c.on(`error`,n=>{clearTimeout(u);let r=n.code,i=r===`EADDRINUSE`||r===`EACCES`?`Try a different port with --port, or authorize via the Console instead:`:`Authorize via the Console instead:`;m.warn(`Could not start the local callback server on port ${e.port}${r?` (${r})`:``}.\n${i}\n ${t}`),a(n)});let announceAuthorizeUrl=async()=>{let n=l.toString();if(m.info(e[`no-browser`]?`Open this URL in your browser to authorize:\n\n${n}\n`:`Opening browser for authorization:\n\n${n}\n`),m.info(`If this flow doesn't complete, you can authorize via the Console instead:\n ${t}`),!e[`no-browser`])try{await xa(n)}catch{m.warn(`Failed to open browser automatically. Please open the URL above manually.`)}};c.listen(e.port,()=>void announceAuthorizeUrl())}),m.success(`Auth connection "${e.name}" authorized successfully.`),N({changed:!0,workspaceId:r,name:e.name})}}),qa=I({name:`delete`,description:`Delete an auth connection entirely.`,args:J.strictObject({...A,...Ga,...D}),run:async e=>{await L({profile:e.profile});let{client:t,workspaceId:n}=await B({profile:e.profile,workspaceId:e[`workspace-id`]});if(!e.yes&&await P.text({message:`Enter the connection name to confirm deletion ("${e.name}"):`,suggestion:`Pass --yes to skip the confirmation.`})!==e.name)throw _({code:`AUTH_CONNECTION_DELETION_CANCELLED`,message:`Auth connection deletion cancelled: the entered name did not match.`,suggestion:`Run the command again and enter the name exactly as shown, or pass --yes to skip the confirmation.`});try{await t.deleteAuthConnection({workspaceId:n,connectionName:e.name})}catch(t){throw t instanceof Q&&t.code===Z.NotFound?_({code:`AUTH_CONNECTION_NOT_FOUND`,message:`Auth connection "${e.name}" not found.`,cause:t}):t}m.success(`Auth connection "${e.name}" deleted.`),N({changed:!0,workspaceId:n,name:e.name})}});function connectionInfo(e){let t=e.config.case===`oauth2`?e.config.value:void 0;return{name:e.name,type:e.config.case??`unknown`,providerUrl:t?.providerUrl??``,issuerUrl:t?.issuerUrl??``,clientId:t?.clientId??``,authUrl:t?.authUrl??``,tokenUrl:t?.tokenUrl??``,createdAt:e.createdAt?ma(e.createdAt):null}}const Ja=I({name:`list`,description:`List all auth connections.`,args:J.strictObject({...A,...oe()}),run:async e=>{let{client:t,workspaceId:n}=await B({profile:e.profile,workspaceId:e[`workspace-id`]});try{let r=we(e.order),i=await rn(e.limit,e=>Pi(async(e,i)=>{let{connections:a,nextPageToken:o}=await t.listAuthConnections({workspaceId:n,pageToken:e,pageSize:i,pageDirection:r});return[a,o]},{limit:e}));m.out(i.items.map(connectionInfo)),await M(i,e.limit)}catch(e){if(e instanceof Q&&e.code===Z.NotFound){m.out([]);return}throw e}}}),Ya=I({name:`open`,description:`Open the auth connections page in the Tailor Platform Console.`,args:J.strictObject({...A}),run:async e=>{let t=await xe({workspaceId:e[`workspace-id`],profile:e.profile}),n=`/workspaces/${t}/services/auth-connections`,r=await pe({profile:e.profile,...e[`workspace-id`]===void 0?{}:{allowMissingProfile:!0}}),i=new URL(n,r).toString(),a=m.jsonMode;m.info(`Opening auth connections page in Tailor Platform Console...`);let o=!0;try{await xa(i)}catch{o=!1}a?m.out({consoleUrl:i,workspaceId:t,opened:o}):o?(m.out(`Console URL: ${i}`),m.out(`Workspace ID: ${t}`)):m.warn(`Failed to open browser automatically. Please open this URL manually:\n${i}`)}}),Xa=I({name:`revoke`,description:`Revoke an auth connection's tokens (keeps the connection; use 'delete' to remove it).`,notes:"Revoke invalidates the connection's active session and tokens but keeps the connection and its stored credentials, so it can be re-authorized later. Use `delete` to remove the connection entirely.",args:J.strictObject({...A,...Ga,...D}),run:async e=>{await L({profile:e.profile});let{client:t,workspaceId:n}=await B({profile:e.profile,workspaceId:e[`workspace-id`]});if(!e.yes&&await P.text({message:`Enter the connection name to confirm revocation ("${e.name}"):`,suggestion:`Pass --yes to skip the confirmation.`})!==e.name)throw _({code:`AUTH_CONNECTION_REVOCATION_CANCELLED`,message:`Auth connection revocation cancelled: the entered name did not match.`,suggestion:`Run the command again and enter the name exactly as shown, or pass --yes to skip the confirmation.`});try{await t.revokeAuthConnection({workspaceId:n,connectionName:e.name})}catch(t){throw t instanceof Q&&t.code===Z.NotFound?_({code:`AUTH_CONNECTION_NOT_FOUND`,message:`Auth connection "${e.name}" not found.`,cause:t}):t}m.success(`Auth connection "${e.name}" revoked.`),N({changed:!0,workspaceId:n,name:e.name})}}),Za=K({name:`authconnection`,description:`Manage auth connections.`,subCommands:{authorize:Ka,list:Ja,open:Ya,revoke:Xa,delete:qa},defaultSubCommand:`list`});function orderAndLimitCrashReports(e,t){let n=e.filter(e=>e.endsWith(Yi)).toSorted(),r=t.order===`asc`?n:n.toReversed();return t.limit&&t.limit>0?r.slice(0,t.limit):r}function formatCrashReportFiles(e,t){return e.map(e=>({file:e,path:q.join(t,e)}))}const Qa=I({name:`list`,description:`List local crash report files.`,args:J.strictObject({...oe()}),run:async e=>{let t=Xi(),n=m.jsonMode;if(!t.localDir){m.info(`Crash report directory not available.`),n&&m.out([]);return}let r;try{r=X.readdirSync(t.localDir)}catch{m.info(`No crash reports found.`),n&&m.out([]);return}let i=await rn(e.limit,async t=>orderAndLimitCrashReports(r,{order:e.order,limit:t})),a=i.items;if(a.length===0)m.info(`No crash reports found.`),n&&m.out([]);else if(n)m.out(formatCrashReportFiles(a,t.localDir)),await M(i,e.limit);else{m.info(`${a.length} crash report(s) in ${t.localDir}:`);for(let e of a)m.log(` ${e}`);await M(i,e.limit)}}}),$a=I({name:`send`,description:`Submit a crash report to help improve the SDK.`,args:J.strictObject({file:G(J.string(),{description:`Path to the crash report file`,required:!0,completion:{type:`file`,extensions:[`log`]}})}),run:async e=>{let t;try{t=X.readFileSync(e.file,`utf-8`)}catch{m.error(`Crash report file not found: ${e.file}`),process.exit(1)}let n=parseCrashLogFile(t);n||(m.error(`Failed to parse crash report file. The file may be corrupted.`),process.exit(1));let r=await Bi();m.info(`Sending crash report...`),await Zi(n,r)?(m.success(`Crash report submitted successfully. Thank you!`),N({changed:!0,id:n.id,file:e.file})):(m.error(`Failed to submit crash report. The server may be unavailable.`),process.exit(1))}});function parseCrashLogFile(e){try{let t=e.replace(/\r\n/g,`
15
+ `),n=`\n${Ji}\n`,r=t.lastIndexOf(n);if(r===-1)return;let i=t.slice(r+n.length).split(`
16
+ `)[0];return i?JSON.parse(i):void 0}catch{return}}const eo=K({name:`crashreport`,description:`Manage crash reports.`,subCommands:{list:Qa,send:$a},defaultSubCommand:`list`});function delay(e){return e>0?new Promise(t=>setTimeout(t,e)):Promise.resolve()}function assertSeedDataDirectory(e){let t;try{t=X.statSync(e)}catch(t){throw t.code===`ENOENT`?_({code:`SEED_DATA_NOT_FOUND`,message:`Seed data directory not found: ${e}.`,suggestion:`Generate seed data before testing migrations.`,cause:t}):t}if(!t.isDirectory())throw _({code:`SEED_DATA_INVALID`,message:`Seed data path is not a directory: ${e}`})}function assertAssertionScript(e){let t=q.resolve(e),n;try{n=X.statSync(t)}catch(e){throw e.code===`ENOENT`?_({code:`MIGRATION_ASSERTION_SCRIPT_NOT_FOUND`,message:`Migration assertion script not found: ${t}`,cause:e}):e}if(!n.isFile())throw _({code:`MIGRATION_ASSERTION_SCRIPT_INVALID`,message:`Migration assertion path is not a file: ${t}`})}function assertCloneTargetRegion(e,t){if(e!==t)throw _({code:`MIGRATION_TEST_REGION_MISMATCH`,message:`Clone mode requires source and target workspaces in the same region (source: ${e}, target: ${t}).`})}function assertTargetWorkspaceDiffers(e,t){if(t?.toLowerCase()===e.toLowerCase())throw _({code:`MIGRATION_TEST_TARGET_INVALID`,message:`The migration test target workspace must differ from the source workspace.`,command:`tailordb migration test`})}function resolveAssertionNamespace(e,t){let n=t??(e.length===1?e[0]:void 0);if(!n)throw _({code:`MIGRATION_TEST_ASSERT_NAMESPACE_REQUIRED`,message:`--assert-namespace is required when pending migrations span multiple namespaces.`,command:`tailordb migration test`});if(!e.includes(n))throw _({code:`MIGRATION_TEST_NO_PENDING_MIGRATIONS`,message:`Assertion namespace "${n}" has no pending migrations.`});return n}async function createMigrationTestBaselineSnapshots(e){let n=new Map([...e.baselines].map(([e,t])=>[e,t.snapshot]));if(e.dataMode!==`clone`)return n;let r=e.inputs.filter(e=>!n.has(e.namespace)),i=await Promise.all(r.map(t=>Kt(e.client,e.workspaceId,t.namespace)));return r.forEach((e,r)=>{n.set(e.namespace,t(i[r],`remote snapshot missing for "${e.namespace}"`))}),n}async function waitForCloneApplicationData(e,t){let n=t.pollInterval??3e3,r=t.timeout??18e5,i=t.errorCodePrefix??`MIGRATION_TEST_CLONE`,a=Date.now()+r,o;for(let s=r;s>0;s=a-Date.now()){let r;try{r=await e.getCloneApplicationDataOperation({sourceWorkspaceId:t.sourceWorkspaceId,targetWorkspaceId:t.targetWorkspaceId,operationId:t.operationId},Number.isFinite(s)?{timeoutMs:s}:void 0)}catch(e){if(e instanceof Q&&e.code===Z.DeadlineExceeded&&Date.now()>=a-100)break;throw e}if(r.status===Ki.COMPLETED)return;if(r.status===Ki.FAILED)throw _({code:`${i}_FAILED`,message:`Application data clone failed: ${r.errorMessage||`unknown platform error`}`});if(r.status!==Ki.PENDING&&r.status!==Ki.PROCESSING)throw u(`Application data clone returned unexpected status ${r.status}.`);r.status!==o&&(o=r.status,t.onStatus?.(r.status)),await delay(Math.min(n,Math.max(a-Date.now(),0)))}throw _({code:`${i}_TIMEOUT`,message:`Application data clone timed out after ${r<1e3?`${r} ms`:`${Math.round(r/1e3)} seconds`}.`,context:{operationId:t.operationId,sourceWorkspaceId:t.sourceWorkspaceId,targetWorkspaceId:t.targetWorkspaceId}})}function loadSnapshotSeedData(e,t,n){let r={};for(let i of t){let t=n?.tables[i],a=q.join(e,`${i}.jsonl`),o;try{o=X.readFileSync(a,`utf8`).trim()}catch(e){if(e.code===`ENOENT`){r[i]=[];continue}throw e}r[i]=o?o.split(`
17
+ `).map((e,n)=>{let r;try{r=JSON.parse(e)}catch(e){throw _({code:`SEED_DATA_INVALID`,message:`Invalid JSON in ${a} at line ${n+1}: ${e instanceof Error?e.message:String(e)}`,cause:e})}if(typeof r!=`object`||!r||Array.isArray(r))throw _({code:`SEED_DATA_INVALID`,message:`Invalid seed row in ${a} at line ${n+1}: expected a JSON object`});let i=r;return t?projectSeedObject(i,t.fields,/* @__PURE__ */ new Set([`id`])):i}):[]}return r}function projectSeedObject(e,t,n=/* @__PURE__ */ new Set){return Object.fromEntries(Object.entries(e).flatMap(([e,r])=>{let i=t[e];return i?[[e,projectSeedValue(r,i)]]:n.has(e)?[[e,r]]:[]}))}function projectSeedValue(e,t){let n=t.fields;return n?t.array?Array.isArray(e)?e.map(e=>isJsonObject(e)?projectSeedObject(e,n):e):e:isJsonObject(e)?projectSeedObject(e,n):e:e}function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function sortSeedTypesForSnapshot(e){let t=Object.keys(e.tables),n=new Set(t),r=/* @__PURE__ */ new Map,i=[];for(let[t,a]of Object.entries(e.tables)){let e=/* @__PURE__ */ new Set;for(let r of Re(a.fields))r===t?i.push(t):n.has(r)&&e.add(r);r.set(t,[...e])}let a=/* @__PURE__ */ new Set,o=[],visit=e=>{if(!a.has(e)){a.add(e);for(let t of r.get(e)??[])visit(t);o.push(e)}};for(let e of t)visit(e);return{order:o,selfRefTypes:i}}function temporaryWorkspaceName(){return`migration-test-${(/* @__PURE__ */ new Date()).toISOString().replace(/[-:T.Z]/g,``).slice(0,14)}-${va(3).toString(`hex`)}`}function stateOrThrow(e){return t(e,`migration test runtime was used before preparation`)}async function resolveTemporaryWorkspaceLocation(e,t,n){if(!n.organizationId&&!n.folderId)return{...t.organizationId?{organizationId:t.organizationId}:{},...t.folderId?{folderId:t.folderId}:{}};let{folderId:r}=n,i=n.organizationId??(t.organizationId||void 0);if(r&&!i)throw _({code:`MIGRATION_TEST_OPTIONS_INVALID`,message:`--folder-id requires --organization-id.`,details:`The source workspace is not in an organization.`,suggestion:`Pass --organization-id together with --folder-id.`});if(r&&i&&!await Oi(async()=>{let{folder:t}=await e.getOrganizationFolder({organizationId:i,folderId:r});return t}))throw _({code:`MIGRATION_TEST_OPTIONS_INVALID`,message:`Folder "${r}" was not found in organization "${i}"${n.organizationId?``:` (the source workspace's organization)`}.`,details:`The folder does not exist there, belongs to a different organization, or is not accessible.`,suggestion:n.organizationId?`Pass a --folder-id that belongs to --organization-id.`:`Pass --organization-id together with --folder-id if the folder is in another organization.`});return{...i?{organizationId:i}:{},...r?{folderId:r}:{}}}function assertTargetMatchesLocation(e,t){let n=[{flag:`--organization-id`,kind:`organization`,wanted:t.organizationId,actual:e.organizationId},{flag:`--folder-id`,kind:`folder`,wanted:t.folderId,actual:e.folderId}];for(let{flag:t,kind:r,wanted:i,actual:a}of n)if(i!==void 0&&i.toLowerCase()!==a?.toLowerCase())throw _({code:`MIGRATION_TEST_OPTIONS_INVALID`,message:`${t} "${i}" does not match the designated target workspace "${e.id}", which ${a?`is in ${r} "${a}"`:`has no ${r}`}.`,suggestion:`Pass the ${r} the target workspace is in, or omit ${t}.`})}function assertSourceMatchesCheckpoints(e,t){let n=e.find(e=>e.hasDrift||e.checkpointMissingLocal);if(n?.checkpointUnset)throw _({code:`MIGRATION_TEST_SOURCE_INVALID`,message:`Source namespace "${n.namespace}" has no migration label and its schema differs from the initial migration snapshot (0000).`,details:hn(n.drifts),suggestion:`Bring the source schema in line with 0000 or set its migration label.`});if(n){let e={...z(t),namespace:n.namespace},r=xr({...e,subcommand:[`status`]}),i=xr({...e,subcommand:[`validate`]});throw _({code:`MIGRATION_TEST_SOURCE_INVALID`,message:`Source namespace "${n.namespace}" does not match its migration checkpoint.`,...n.hasDrift?{details:hn(n.drifts)}:{},suggestion:n.checkpointMissingLocal?`${Ge} Otherwise run ${r} to compare the source workspace's checkpoint and migration history with the local ones.`:`Run ${i} to check the migration history and source schema, or ${r} to inspect the source workspace's checkpoint.`})}let r=e.find(e=>e.checkpointRepair);if(r)throw _({code:`MIGRATION_TEST_SOURCE_REPAIR_PENDING`,message:`Source namespace "${r.namespace}" has a pending migration checkpoint repair.`,suggestion:`Deploy to the source workspace first.`});let i=e.find(e=>e.unfinishedRemovals?.length);if(i)throw _({code:`MIGRATION_TEST_SOURCE_CLEANUP_PENDING`,message:`Source namespace "${i.namespace}" still has tables that migration ${F(i.remoteMigrationNumber)} removed: ${i.unfinishedRemovals?.join(`, `)}.`,suggestion:`Deploy to the source workspace first.`})}function resolveSourceMigrationNumber(e){if(e.skipped===`not_deployed`)throw _({code:`MIGRATION_TEST_SOURCE_CHECKPOINT_MISSING`,message:`Source namespace "${e.namespace}" has not been deployed.`,suggestion:`Deploy to the source workspace before testing.`});return e.remoteMigrationNumber}function findSourceCheck(e,n){return t(e.find(e=>e.namespace===n),`remote schema check result missing for namespace "${n}"`)}async function assertSourceBaselineFresh(e,t,n){let r=e.loaded,i=z({workspaceId:n,profile:e.options.profile,configPath:r.config.path}),a=it(r.config,q.dirname(r.config.path)),o=r.application.tailorDBServices.map(Zn),s=await kt(e.client,n,a,r.config,o),c=s.find(e=>e.hasDrift||e.checkpointMissingLocal||e.checkpointRepair);if(c)throw _({code:`MIGRATION_TEST_SOURCE_CHANGED`,message:`Source namespace "${c.namespace}" changed after migration test preparation.`,suggestion:`Run the migration test again.`});for(let r of a){let a=t.baselines.get(r.namespace);if(!a)continue;let o=await ft(e.client,Kr(n,`tailordb`,r.namespace));tt(o,r.namespace,i);let c=resolveSourceMigrationNumber(findSourceCheck(s,r.namespace));if(c!==a.migrationNumber)throw _({code:`MIGRATION_TEST_SOURCE_CHANGED`,message:`Source namespace "${r.namespace}" moved from migration ${a.migrationNumber} to ${c} after migration test preparation.`,suggestion:`Run the migration test again.`})}let l=o.filter(e=>!t.baselines.has(e.namespace));for(let r of l){let i=t.baselineSnapshots.get(r.namespace);if(!i)continue;let a=await Kt(e.client,n,r.namespace);if(er(i,a).changes.length>0)throw _({code:`MIGRATION_TEST_SOURCE_CHANGED`,message:`Source namespace "${r.namespace}" schema changed after migration test preparation.`,suggestion:`Run the migration test again.`})}}async function deleteExistingUserProfileConfig(e,t){let n=e.loaded.application.authService;if(!n)return;let r=n.config.name;await Oi(()=>e.client.getUserProfileConfig({workspaceId:t,namespaceName:r}))&&await e.client.deleteUserProfileConfig({workspaceId:t,namespaceName:r})}function migrationConfig(e,t){return e.config.db?.[t]?.migration}function authExecutionContext(e,t,n){let r=e.loaded.application.authService;if(!r)throw _({code:`AUTH_CONFIG_REQUIRED`,message:`Auth configuration is required to execute migration test scripts.`});let i=n??en(migrationConfig(e.loaded,t),r.config.machineUsers?Object.keys(r.config.machineUsers):void 0);if(!i)throw _({code:`MACHINE_USER_REQUIRED`,message:`No machine user is available for namespace "${t}".`,suggestion:`Pass --machine-user or configure one in auth or db.${t}.migration.`});return{authNamespace:r.config.name,machineUserName:i}}async function prepareMigrationTest(e){let n=await sn({configPath:e.configPath}),r=q.dirname(n.config.path),i=it(n.config,r);if(i.length===0)throw bt();for(let e of i)Pn(e.migrationsDir,e.namespace,n.config.path);let a;e.data===`seed`&&(a=await Zt({configPath:n.config.path}),assertSeedDataDirectory(q.join(a.distPath,`data`))),e.assertionPath&&assertAssertionScript(e.assertionPath);let o=n.application.tailorDBServices.map(Zn),s=await ue({profile:e.profile}),c=await Ae({profile:e.profile}),l=await Di(s,c),u=await xe({workspaceId:e.workspaceId,profile:e.profile});assertTargetWorkspaceDiffers(u,e.targetWorkspaceId);let[d,f,p]=await Promise.all([l.getWorkspace({workspaceId:u}),l.getApplication({workspaceId:u,applicationName:n.config.name}),e.targetWorkspaceId?l.getWorkspace({workspaceId:e.targetWorkspaceId}):Promise.resolve(void 0)]),m=t(d.workspace,`source workspace "${u}" not found`);t(f.application,`application "${n.config.name}" not found in source workspace`);let h=p?t(p.workspace,`target workspace "${e.targetWorkspaceId}" not found`):void 0;h&&assertTargetMatchesLocation(h,e);let g=await resolveTemporaryWorkspaceLocation(l,m,h?{}:e),v=await kt(l,u,i,n.config,o,{acceptUnfinishedRemovals:!0}),y={workspaceId:u,profile:e.profile,configPath:n.config.path};assertSourceMatchesCheckpoints(v,y);let b=/* @__PURE__ */ new Map,x=/* @__PURE__ */ new Map,S=[];for(let e of i){let t=await ft(l,Kr(u,`tailordb`,e.namespace));tt(t,e.namespace,z(y));let n=resolveSourceMigrationNumber(findSourceCheck(v,e.namespace)),r=Ar(e.migrationsDir);if(n>r)throw _({code:`MIGRATION_TEST_SOURCE_AHEAD`,message:`Source namespace "${e.namespace}" is at migration ${n}, but the local history ends at ${r}.`});let i=V(e.migrationsDir,n);if(!i)throw _({code:`MIGRATION_BASELINE_NOT_FOUND`,message:`No migration baseline snapshot found for namespace "${e.namespace}".`});b.set(e.namespace,{migrationNumber:n,snapshot:i,historyId:i.rebaseline?.historyId??null});let a=V(e.migrationsDir,r);if(!a)throw _({code:`MIGRATION_TEST_SNAPSHOT_NOT_FOUND`,message:`No target migration snapshot found for namespace "${e.namespace}".`});x.set(e.namespace,a),n<r&&S.push(e.namespace)}if(S.length===0)throw _({code:`MIGRATION_TEST_NO_PENDING_MIGRATIONS`,message:`No pending TailorDB migrations found in the source workspace.`});let C=await createMigrationTestBaselineSnapshots({client:l,workspaceId:u,dataMode:e.data,inputs:o,baselines:b}),w={sourceWorkspaceId:u,sourceApplicationName:n.config.name,temporaryWorkspace:{name:temporaryWorkspaceName(),region:m.region,...g},baselines:b,baselineSnapshots:C,targetSnapshots:x,pendingNamespaces:S,...h?{designatedTarget:{id:h.id,region:h.region}}:{}};return{state:{client:l,loaded:n,options:e,...a?{seedContext:a}:{}},prepared:w}}function createMigrationTestDependencies(){let e;return{prepare:async t=>{let{state:n,prepared:r}=await prepareMigrationTest(t);return e=n,r},createWorkspace:async t=>{let n=stateOrThrow(e),r=await Sn(n.client,t.temporaryWorkspace);return m.info(`Created temporary workspace ${r.name} (${r.id}).`),{id:r.id,name:r.name,...r.createdAt?{createdAt:r.createdAt}:{}}},recordWorkspaceExpiry:async(t,n,r=/* @__PURE__ */ new Date)=>{let i=stateOrThrow(e);await Hn(i.client,t,new Date(r.getTime()+jr(n)))},deployBaseline:async({prepared:t,targetWorkspaceId:n})=>{let r=stateOrThrow(e);await deleteExistingUserProfileConfig(r,n),await Fn({configPath:r.loaded.config.path,profile:r.options.profile,workspaceId:n,yes:!0},t.baselines,t.baselineSnapshots);for(let[e,i]of t.baselines)await rt(r.client,n,e,i.migrationNumber,i.historyId??void 0)},seedData:async({prepared:n,targetWorkspaceId:r})=>{let i=stateOrThrow(e),a=t(i.seedContext,`seed context missing after migration test preparation`),o=q.join(a.distPath,`data`);assertSeedDataDirectory(o);let s=new Map(i.loaded.application.tailorDBServices.map(e=>{let t=n.baselines.get(e.namespace),r=Zn(e);return[e.namespace,t?.snapshot??Dt({version:1,namespace:e.namespace,createdAt:(/* @__PURE__ */ new Date()).toISOString(),tables:r.types})]}));for(let[e,t]of s){let{order:n,selfRefTypes:s}=sortSeedTypesForSnapshot(t),c=loadSnapshotSeedData(o,n,t),l=n.filter(e=>(c[e]?.length??0)>0);if(l.length===0)continue;let u=await gn(e,l,q.dirname(i.loaded.config.path),di(i.loaded.config)),d=br({data:c,order:n,codeByteSize:new TextEncoder().encode(u.bundledCode).length}),f=authExecutionContext(i,e,i.options.machineUser??a.machineUserName);for(let t of d){let n=await _t({client:i.client,workspaceId:r,name:`migration-test-seed-${e}.ts`,code:u.bundledCode,arg:{data:t.data,order:t.order,selfRefTypes:s,upsert:!1},invoker:{namespace:f.authNamespace,machineUserName:f.machineUserName}});if(!n.success)throw _({code:`MIGRATION_TEST_SEED_FAILED`,message:n.error??`Seed execution failed for namespace "${e}".`});if(JSON.parse(n.result||`{}`).success!==!0)throw _({code:`MIGRATION_TEST_SEED_FAILED`,message:`Seed execution reported failure for namespace "${e}".`})}}},cloneData:async({prepared:t,sourceWorkspaceId:n,targetWorkspaceId:r,applicationName:i,cloneTimeout:a})=>{let o=stateOrThrow(e);await assertSourceBaselineFresh(o,t,n),m.warn(`Clone mode copies TailorDB records only; IdP users and file blobs are not copied.`);let s;try{s=(await o.client.cloneApplicationData({sourceWorkspaceId:n,sourceApplicationName:i,targetWorkspaceId:r,targetApplicationName:i})).operationId}catch(e){throw e instanceof Q&&e.code===Z.Unimplemented?_({code:`MIGRATION_TEST_CLONE_UNAVAILABLE`,message:`Application data clone is not enabled for this platform.`,suggestion:`Retry with --data seed.`,cause:e}):e}if(!s)throw u(`Application data clone returned no operation ID.`);await waitForCloneApplicationData(o.client,{sourceWorkspaceId:n,targetWorkspaceId:r,operationId:s,timeout:a})},deployMigrations:async({prepared:t,targetWorkspaceId:n,machineUser:r})=>{let i=stateOrThrow(e);await Tr({configPath:i.loaded.config.path,profile:i.options.profile,workspaceId:n,yes:!0},t.targetSnapshots,r)},runAssertion:async({prepared:t,targetWorkspaceId:n,assertionPath:r,assertionNamespace:i,machineUser:a})=>{let o=stateOrThrow(e),s=resolveAssertionNamespace(t.pendingNamespaces,i),c=authExecutionContext(o,s,a),l=await Mr(r,s,0,o.loaded.config.env??{},q.dirname(o.loaded.config.path),xt(o.loaded.plugins,`@tailor-platform/kysely-type`)?.temporal??!1,ui(o.loaded.config)),u=await _t({client:o.client,workspaceId:n,name:`migration-test-assert-${s}.ts`,code:l.bundledCode,invoker:{namespace:c.authNamespace,machineUserName:c.machineUserName}});if(!u.success)throw _({code:`MIGRATION_TEST_ASSERTION_FAILED`,message:u.error??`Migration assertion failed for namespace "${s}".`})},deleteWorkspace:async t=>{await stateOrThrow(e).client.deleteWorkspace({workspaceId:t})}}}const to={from:G(J.string(),{description:`Workspace ID to copy data from`,completion:{type:`none`}}),to:G(J.string(),{description:`Workspace ID to copy data to`,completion:{type:`none`}})};function resumeCommandArgs(e){return[`data`,`operation`,`get`,`--from`,e.sourceWorkspaceId,`--to`,e.targetWorkspaceId,`--operation-id`,e.operationId,`--wait`,...k({profile:e.profile})]}function resumeHint(e){return h({command:`tailor`,args:resumeCommandArgs(e)})}async function hintOnInterrupt(e,t){let onInterrupt=()=>{m.info(`Stopped waiting. The clone keeps running on the platform. To wait for it: ${resumeHint(e)}`)};process.once(`SIGINT`,onInterrupt);try{return await t()}finally{process.off(`SIGINT`,onInterrupt)}}const no={[Ki.PENDING]:`pending`,[Ki.PROCESSING]:`processing`,[Ki.COMPLETED]:`completed`,[Ki.FAILED]:`failed`};function statusName(e){return no[e]??`unknown`}function reportStatus(e){m.info(`status: ${statusName(e)}`,{mode:`stream`})}function formatElapsed(e){let t=Math.floor(e/1e3),n=Math.floor(t/3600),r=Math.floor(t%3600/60),i=t%60;return n>0?`${n}h ${r}m`:r>0?`${r}m ${i}s`:`${i}s`}async function $clone(e){let t=Pe(e.config),n=t?[t]:[];if(e.sourceWorkspaceId===e.targetWorkspaceId)throw _({code:`DATA_CLONE_SAME_WORKSPACE`,message:`The source and target workspaces must be different.`,command:`data clone`});let r=await Di(await ue({profile:e.profile}));try{await r.getApplication({workspaceId:e.targetWorkspaceId,applicationName:e.name})}catch(t){throw t instanceof Q&&t.code===Z.NotFound?_({code:`DATA_CLONE_TARGET_APPLICATION_NOT_FOUND`,message:`Application "${e.name}" was not found in the target workspace "${e.targetWorkspaceId}".`,suggestion:e.nameFromConfig?`Check --to and that you have access to the target workspace, and deploy the application to it first so it has the same namespaces and schema.`:`Check --to and that you have access to the target workspace, and deploy the application "${e.name}" to it first so it has the same namespaces and schema.`,...e.nameFromConfig?{next:{command:`tailor`,args:[`deploy`,...k({workspaceId:e.targetWorkspaceId,profile:e.profile}),...n]}}:{},command:`data clone`,cause:t}):t}if(!e.yes&&!await P.confirm({message:`This will copy the data of application "${e.name}" from workspace "${e.sourceWorkspaceId}" to workspace "${e.targetWorkspaceId}". Continue?`,default:!1}))throw _({code:`DATA_CLONE_CANCELLED`,message:`Data clone cancelled.`});let i;try{i=(await r.cloneApplicationData({sourceWorkspaceId:e.sourceWorkspaceId,sourceApplicationName:e.name,targetWorkspaceId:e.targetWorkspaceId,targetApplicationName:e.name,copyFiles:e.copyFiles,copyIdpUsers:e.copyIdpUsers})).operationId}catch(t){throw t instanceof Q&&t.code===Z.Unimplemented?_({code:`DATA_CLONE_UNAVAILABLE`,message:`Application data clone is not enabled for this platform.`,command:`data clone`,cause:t}):t instanceof Q&&t.code===Z.FailedPrecondition?_({code:`DATA_CLONE_PRECONDITION_FAILED`,message:t.rawMessage,suggestion:`A clone needs both workspaces in the same region with the same namespaces, a matching TailorDB schema (deploy the same version to the target first), and an empty target for every copy type in scope. ${e.nameFromConfig?`To empty the target's TailorDB records, run ${h({command:`tailor`,args:[`tailordb`,`truncate`,`--all`,...k({workspaceId:e.targetWorkspaceId,profile:e.profile}),...n]})}.`:`To empty the target's TailorDB records, run tailor tailordb truncate for the namespaces of this application (see tailor tailordb truncate --help).`} That does not remove IdP users or files: with --copy-idp-users or --copy-files, remove those from the target separately.`,command:`data clone`,cause:t}):t instanceof Q&&t.code===Z.NotFound?_({code:`DATA_CLONE_NOT_FOUND`,message:t.rawMessage,suggestion:`Check that --from and --to are workspace IDs you can access and that the application exists in the source workspace.`,command:`data clone`,cause:t}):t}if(!i)throw u(`Application data clone returned no operation ID.`);m.info(`Clone started (operation: ${i})`);let a={sourceWorkspaceId:e.sourceWorkspaceId,targetWorkspaceId:e.targetWorkspaceId,operationId:i,profile:e.profile};if(e.noWait)return m.info(`The clone keeps running on the platform. To wait for it: ${resumeHint(a)}`),{operationId:i,status:`started`};let o=Date.now();return await hintOnInterrupt(a,()=>waitForCloneApplicationData(r,{sourceWorkspaceId:a.sourceWorkspaceId,targetWorkspaceId:a.targetWorkspaceId,operationId:i,timeout:1/0,errorCodePrefix:`DATA_CLONE`,onStatus:reportStatus})),m.success(`Cloned data of application "${e.name}" from "${e.sourceWorkspaceId}" to "${e.targetWorkspaceId}" in ${formatElapsed(Date.now()-o)}`),{operationId:i,status:`completed`}}const ro=I({name:`clone`,description:`Clone the data of an application (TailorDB namespaces registered in its subgraph) from one workspace to another.`,notes:"\nThe platform rejects the clone with a failed precondition unless all of the following hold:\n- The source and target workspaces are in the same region.\n- The target workspace has the same namespaces as the source.\n- The TailorDB schema of the target matches the source, so deploy the same version to the target first.\n- The target is empty for every namespace and copy type in scope (TailorDB records, plus files and IdP users when `--copy-files` / `--copy-idp-users` are given).\n\nThe command waits until the clone finishes. Pressing Ctrl+C or passing --no-wait does not stop the clone, which keeps running on the platform. Use `tailor data operation get --wait` with the operation ID printed at the start to keep waiting, or without --wait to check the status once.\n\nWith --json, the result carries `status`: `completed` once the clone has finished, or `started` with --no-wait.\n",args:J.strictObject({...D,profile:G(J.string().optional(),{alias:`p`,description:`Workspace profile`,env:`TAILOR_PLATFORM_PROFILE`,completion:{type:`none`}}),...to,name:G(J.string().optional(),{alias:`n`,description:`Application name, the same in the source and the target workspace (default: the name in the config file)`,completion:{type:`none`}}),...te,"copy-files":G(J.boolean().default(!1),{description:`Also copy TailorDB file content`}),"copy-idp-users":G(J.boolean().default(!1),{description:`Also copy IdP users, including their passwords`}),"no-wait":G(J.boolean().default(!1),{description:`Start the clone and exit without waiting for it to finish`})}),run:async e=>{await L({profile:e.profile});let t=e.name??(await R(e.config)).config.name,{operationId:n,status:r}=await $clone({sourceWorkspaceId:e.from,targetWorkspaceId:e.to,name:t,config:e.config,nameFromConfig:e.name===void 0,copyFiles:e[`copy-files`],copyIdpUsers:e[`copy-idp-users`],noWait:e[`no-wait`],profile:e.profile,yes:e.yes});N({changed:!0,sourceWorkspaceId:e.from,targetWorkspaceId:e.to,operationId:n,status:r})}}),io=I({name:`get`,description:`Show the status of a data clone, or wait for it to finish.`,notes:`Without --wait, the command prints the current status once and exits. With --wait, it waits until the clone completes or fails, and exits with an error if it fails. Pressing Ctrl+C stops waiting; the clone keeps running on the platform.`,args:J.strictObject({profile:G(J.string().optional(),{alias:`p`,description:`Workspace profile`,env:`TAILOR_PLATFORM_PROFILE`,completion:{type:`none`}}),...to,"operation-id":G(J.string(),{description:`Operation ID printed when the clone started`,completion:{type:`none`}}),wait:G(J.boolean().default(!1),{description:`Wait until the clone completes or fails`})}),run:async e=>{let t=await Di(await ue({profile:e.profile})),n={sourceWorkspaceId:e.from,targetWorkspaceId:e.to,operationId:e[`operation-id`],profile:e.profile};if(!e.wait){let e=await t.getCloneApplicationDataOperation({sourceWorkspaceId:n.sourceWorkspaceId,targetWorkspaceId:n.targetWorkspaceId,operationId:n.operationId}),r=statusName(e.status);m.info(`Clone operation ${n.operationId}: ${r}`),e.errorMessage&&m.info(`Message: ${e.errorMessage}`),m.out({operationId:n.operationId,status:r,...e.errorMessage?{errorMessage:e.errorMessage}:{}});return}let r=Date.now();await hintOnInterrupt(n,()=>waitForCloneApplicationData(t,{sourceWorkspaceId:n.sourceWorkspaceId,targetWorkspaceId:n.targetWorkspaceId,operationId:n.operationId,timeout:1/0,errorCodePrefix:`DATA_CLONE`,onStatus:reportStatus})),m.success(`Clone operation ${n.operationId} completed (waited ${formatElapsed(Date.now()-r)})`),m.out({operationId:n.operationId,status:`completed`})}}),ao=K({name:`operation`,description:`Inspect asynchronous application data operations.`,subCommands:{get:io}}),oo=K({name:`data`,description:`Manage application data across workspaces.`,subCommands:{clone:ro,operation:ao}}),so=I({name:`deploy`,description:`Deploy your application by applying the Tailor configuration.`,notes:"Every workspace belongs to an organization; when none is given or set as a default, interactive runs ask for one and non-interactive runs fail. Workspace creation uses the selected user's default organization and folder set by `user update` when neither location is given and TAILOR_PLATFORM_TOKEN is not set. Giving --organization-id or --folder-id replaces both defaults. TAILOR_PLATFORM_ORGANIZATION_ID and TAILOR_PLATFORM_FOLDER_ID, including values loaded by --env-file, also replace the defaults; command-line options take precedence, and an empty value of either variable is ignored. With --create-workspace, an existing workspace must match the resolved name, region, organization, and folder to be reused.",args:J.strictObject({...A,...T,...D,"create-workspace":G(J.boolean().optional(),{description:`Create a workspace when the account has none`}),"workspace-name":G(J.string().optional(),{description:`Name for a workspace created during deploy`}),"workspace-region":G(J.string().optional(),{description:`Region for a workspace created during deploy`}),"organization-id":G(J.string().optional(),{description:`Organization ID for a workspace created during deploy`,env:`TAILOR_PLATFORM_ORGANIZATION_ID`}),"folder-id":G(J.string().optional(),{description:`Folder ID for a workspace created during deploy`,env:`TAILOR_PLATFORM_FOLDER_ID`}),"dry-run":G(J.boolean().optional(),{alias:`d`,description:`Run the command without making any changes`}),"no-schema-check":G(J.boolean().optional(),{description:`Skip schema diff check against migration snapshots (beta)`}),"migration-skip-steps":G(J.string().optional(),{description:`Skip steps of a partially applied multi-step migration that already succeeded, as comma-separated namespace/step entries (beta)`}),"no-validate":G(J.boolean().optional(),{description:`Skip client-side validation against platform resource constraints`}),"no-cache":G(J.boolean().optional(),{description:`Disable bundle caching for this run`}),"clean-cache":G(J.boolean().optional(),{description:`Clean the bundle cache before building`})}),run:async e=>{await L({profile:e.profile});let{initTelemetry:t}=await import(`../telemetry-nqOtDWNO.mjs`);await t(),await Le({workspaceId:e[`workspace-id`],profile:e.profile,configPath:e.$source?.(`config`)===`cli`?e.config:me()??`tailor.config.ts`,dryRun:e[`dry-run`],yes:e.yes,createWorkspace:e[`create-workspace`],workspaceName:e[`workspace-name`],workspaceRegion:e[`workspace-region`],...ae(e),noSchemaCheck:e[`no-schema-check`],migrationSkipSteps:vr(e[`migration-skip-steps`]),noValidate:e[`no-validate`],noCache:e[`no-cache`],cleanCache:e[`clean-cache`]},{...ke(process.argv.slice(2)),verbose:e.verbose,json:e.json})}}),co=K({name:`executor`,description:`Manage executors`,subCommands:{trigger:qt,jobs:Qn,list:Ye,get:nn,webhook:Rr},defaultSubCommand:`list`});function scriptNameToRegistryName(e,t){if(t===Gi.JOB)return`workflow--${e}`;let n=/^([^.]+)\.(.+)\.body\.js$/.exec(e);if(n){let[,e,t]=n;return`resolver--${e}--${t}`}let r=/^(.+)\.operation\.js$/.exec(e);if(r){let[,e]=r;return`executor--${e}`}let i=/^([^.]+)\.([^.]+)\.hook\.js$/.exec(e);if(i){let[,e,t]=i;return`auth-hook--${e}--${t}`}return t===Gi.UNSPECIFIED&&!e.includes(`.`)?`workflow--${e}`:null}async function downloadFunctionScript(e){let{client:t,workspaceId:n,name:r,contentHash:i}=e;try{let e=[];for await(let a of t.downloadFunctionRegistryScript({workspaceId:n,name:r,contentHash:i}))a.payload.case===`chunk`&&e.push(a.payload.value);return e.length===0?null:{code:Buffer.concat(e).toString(`utf-8`)}}catch(t){return m.debug(`Failed to download function script "${e.name}": ${t}`),null}}const lo=/^\s+at\s+(?:(.+?)\s+\()?(file:\/\/\/.+?):(\d+):(\d+)\)?$/;function parseStackTrace(e){let n=e.split(`
18
+ `),r=[],i=[];for(let e of n)/^\s+at\s+/.test(e)?i.push(e):i.length===0&&r.push(e);let a=r.join(`
19
+ `);a.startsWith(`rpc error: code = Aborted desc = `)&&(a=a.slice(33));let o=[];for(let e of i){let n=lo.exec(e);n&&o.push({functionName:n[1]||`<anonymous>`,file:t(n[2],`stack frame file missing`),line:Number(t(n[3],`stack frame line missing`)),column:Number(t(n[4],`stack frame column missing`))})}return{errorMessage:a,frames:o}}const uo=/\/\/[#@]\s*sourceMappingURL=data:application\/json[^,]*;base64,(.+)$/m;function extractInlineSourcemap(e){let n=uo.exec(e);if(!n)return null;try{let e=Buffer.from(t(n[1],`sourcemap base64 data missing`),`base64`).toString(`utf-8`),r=JSON.parse(e);return new Da(r)}catch{return null}}function mapStackFrames(e,t){return e.map(e=>{if(!t)return{original:e,mapped:null};try{for(let n=t.sources.length-1;n>=0;n--){let r=t.sources[n];if(r==null)continue;let i=Oa(t,{source:r,line:e.line,column:e.column-1});if(i.line==null)continue;let a=ka(t,{line:i.line,column:i.column});if(a.source===r&&a.line===e.line&&a.column===e.column-1)return{original:e,mapped:{source:r,line:e.line,column:e.column,name:null}}}return{original:e,mapped:null}}catch{return{original:e,mapped:null}}})}function detectEditorScheme(){let e=process.env.VISUAL||process.env.EDITOR||``;return/\bcode\b/.test(e)?`vscode`:null}function osc8Link(e,t){return`\x1b]8;;${e}\x07${t}\x1b]8;;\x07`}function buildSourceLink(e,t,n,r){let i=`${e}:${n}:${r}`;return detectEditorScheme()===`vscode`?osc8Link(`vscode://file${t}:${n}:${r}`,i):osc8Link(`file://${t}`,i)}function buildCodeSnippet(e,t){let n=e.split(`
20
+ `),r=Math.max(0,t-1-2),i=Math.min(n.length,t+2),a=String(i).length,o=[];for(let e=r;e<i;e++){let r=e+1,i=String(r).padStart(a),c=n[e];r===t?o.push(` ${s.error(`>`)} ${s.error(`${i} | ${c}`)}`):o.push(` ${s.dim(`${i} | ${c}`)}`)}return o.join(`
21
+ `)}function readInstalledSource(e){try{let t=X.realpathSync(e);return ii(t)?X.readFileSync(t,`utf-8`):void 0}catch{return}}function formatMappedError(e,t,n,r){let i=[` ${s.error(e)}`];for(let e of t)if(e.mapped){let{source:t,line:a,column:o,name:s}=e.mapped,c=r?q.resolve(r,t):q.resolve(t),l=q.relative(process.cwd(),c),u=l.startsWith(`..`)?l:`./${l}`,d=s??e.original.functionName,f=buildSourceLink(u,c,a,o);if(i.push(`\n at ${d} (${f})`),n){let e=n.sources.indexOf(t),r=(e===-1?void 0:n.sourcesContent?.[e])||readInstalledSource(c);r&&i.push(buildCodeSnippet(r,a))}}else{let t=`${e.original.file.replace(/^file:\/\/\//,``)}:${e.original.line}:${e.original.column}`;i.push(`\n ${s.dim(`at ${e.original.functionName} (${t})`)}`)}return i.join(`
22
+ `)}function formatErrorWithSourcemap(e,t,n){try{let{errorMessage:r,frames:i}=parseStackTrace(e);if(i.length===0)return null;let a=extractInlineSourcemap(t);if(!a)return null;let o=mapStackFrames(i,a);return o.some(e=>e.mapped!==null)?formatMappedError(r,o,a,n):null}catch{return null}}function functionExecutionTypeToString(e){return yn(Gi,e)??`UNSPECIFIED`}function functionErrorKindToString(e){return yn(Ui,e)??`UNSPECIFIED`}function toFunctionExecutionListInfo(e){return{id:e.id,scriptName:e.scriptName,status:zn(e.status),type:functionExecutionTypeToString(e.type),startedAt:e.startedAt?ma(e.startedAt):null,finishedAt:e.finishedAt?ma(e.finishedAt):null,errorKind:functionErrorKindToString(e.errorKind),errorName:e.error?.name||null,errorMessage:e.error?.message||null,hasPlatformLogs:e.hasPlatformLogs}}function toFunctionExecutionDetailInfo(e){return{...toFunctionExecutionListInfo(e),logs:sr(e.logEntries),logEntries:e.logEntries.map(qn),result:e.result,error:e.error?{name:e.error.name,message:e.error.message,stackTrace:e.error.stackTrace}:null}}function composeExecutionErrorString(e){let{name:t,message:n,stackTrace:r}=e,i=t&&n?`${t}: ${n}`:t||n;if(!r)return i;let a=r.split(`
23
23
  `,1)[0]??``;return/^\s+at\s+/.test(a)?`${i}\n${r}`:r}function formatExecutionErrorFallback(e){let[t=``,...n]=composeExecutionErrorString(e).split(`
24
- `);return[` ${w.error(t)}`,...n.map(e=>` ${w.dim(e)}`)].join(`
25
- `)}function deployedBundleDir(){return q.join(process.cwd(),`dist`)}function formatExecutionError(e,t){if(t&&e.stackTrace){let n=formatErrorWithSourcemap(composeExecutionErrorString(e),t,deployedBundleDir());if(n)return n}return formatExecutionErrorFallback(e)}const formatDate=e=>e?e.toISOString():`N/A`;function printFunctionExecutionSummary(e){let t=[[`id`,e.id],[`scriptName`,e.scriptName],[`status`,e.status],[`type`,e.type],[`startedAt`,formatDate(e.startedAt)],[`finishedAt`,formatDate(e.finishedAt)],[`errorKind`,e.errorKind]];y.out(mr(t))}function printFunctionExecutionLogs(e){let t=Mt(e.logEntries);if(t.length!==0){y.log(w.bold(`
26
- Logs:`));for(let e of t)y.log(` ${e}`)}}function printFunctionExecutionOutcome(e){let{detail:t,bundledCode:n}=e;if(t.result){y.log(w.bold(`
27
- Result:`));try{let e=JSON.parse(t.result);y.log(` ${JSON.stringify(e,null,2).split(`
24
+ `);return[` ${s.error(t)}`,...n.map(e=>` ${s.dim(e)}`)].join(`
25
+ `)}function deployedBundleDir(){return q.join(process.cwd(),`dist`)}function formatExecutionError(e,t){if(t&&e.stackTrace){let n=formatErrorWithSourcemap(composeExecutionErrorString(e),t,deployedBundleDir());if(n)return n}return formatExecutionErrorFallback(e)}const formatDate=e=>e?e.toISOString():`N/A`;function printFunctionExecutionSummary(e){let t=[[`id`,e.id],[`scriptName`,e.scriptName],[`status`,e.status],[`type`,e.type],[`startedAt`,formatDate(e.startedAt)],[`finishedAt`,formatDate(e.finishedAt)],[`errorKind`,e.errorKind]];m.out(Dr(t))}function printFunctionExecutionLogs(e){let t=Mn(e.logEntries);if(t.length!==0){m.log(s.bold(`
26
+ Logs:`));for(let e of t)m.log(` ${e}`)}}function printFunctionExecutionOutcome(e){let{detail:t,bundledCode:n}=e;if(t.result){m.log(s.bold(`
27
+ Result:`));try{let e=JSON.parse(t.result);m.log(` ${JSON.stringify(e,null,2).split(`
28
28
  `).join(`
29
- `)}`)}catch{y.log(` ${t.result}`)}}t.error&&(y.log(w.bold(`
30
- Error:`)),y.log(formatExecutionError(t.error,n??null)))}async function fetchFunctionExecution(e){let{execution:t}=await e.client.getFunctionExecution({workspaceId:e.workspaceId,executionId:e.executionId},{signal:e.signal});if(!t)throw S({code:`FUNCTION_EXECUTION_NOT_FOUND`,message:`Function execution '${e.executionId}' not found.`});return t}async function followFunctionExecution(e){let{interval:t,timeout:n,showProgress:r}=e,i=Date.now(),a=0,o,remainingMs=()=>n===void 0?void 0:n-(Date.now()-i),timedOut=()=>{let e=remainingMs();return e!==void 0&&e<=0},timeoutError=()=>{let t=o===void 0?`unknown`:et(o);return S({code:`FUNCTION_EXECUTION_TIMEOUT`,message:`Timed out waiting for function execution '${e.executionId}' to complete. Last status: ${t}.`})},sleep=async()=>{let e=remainingMs();if(e===void 0)await ra(t);else{if(e<=0)throw timeoutError();await ra(Math.min(t,e))}};for(;;){let t=remainingMs();if(t!==void 0&&t<=0)throw timeoutError();let n;try{n=await fetchFunctionExecution({...e,signal:t===void 0?void 0:AbortSignal.timeout(t)})}catch(e){if(timedOut())throw timeoutError();if(!Ne(e))throw e;y.warn(`Retrying function execution poll: ${tr(e)}`,{mode:`stream`}),await sleep();continue}if(r){if(o===void 0&&(printFunctionExecutionSummary(toFunctionExecutionListInfo(n)),ee(n.status)||y.info(`Following log entries until the execution completes (Ctrl+C to stop)`,{mode:`stream`})),n.logEntries.length>a){a===0&&y.log(w.bold(`
31
- Logs:`));for(let e of n.logEntries.slice(a))y.log(` ${kt(dr(e))}`);a=n.logEntries.length}if(o!==void 0&&n.status!==o){let e=jt(et(n.status));y.info(`Status: ${e}`,{mode:`stream`})}}let i=o!==void 0;if(o=n.status,ee(n.status))return{execution:n,printedEntries:a,followed:i};await sleep()}}async function downloadScriptForMapping(e){let{client:t,workspaceId:n,scriptName:r,executionType:i,executionContentHash:a}=e,o=scriptNameToRegistryName(r,i);if(o==null)return y.debug(`Script "${r}" is not a deployed registry script (e.g. function run or seed); skipping sourcemap mapping.`),null;if(a===``)return y.debug(`Function execution "${r}" has no contentHash; skipping sourcemap mapping because the exact bundle cannot be identified.`),null;let s=await downloadFunctionScript({client:t,workspaceId:n,name:o,contentHash:a});return s==null?(y.debug(`Could not download pinned script "${r}" (registry: "${o}", contentHash: "${a}") for stack trace mapping; showing raw stack trace.`),null):s.code}const Wa=z({name:`logs`,description:`List or get function execution logs.`,notes:"Each execution includes `errorKind`, which tells you where a failure came from: `USER_RUNTIME` (your code threw while running, or exceeded its time, memory, or CPU limit), `USER_NON_RUNTIME` (your script failed while loading, before your function was called, such as when its top-level code threw), `PLATFORM` (a failure on the Platform side, or the Platform aborting the run because of its own deadline or cancellation), `NONE` (no error), or `UNSPECIFIED` (not recorded, or a kind this CLI version does not recognize). A workflow job waiting on another job also reports `USER_NON_RUNTIME` when that job fails or is canceled. `errorName` and `errorMessage` hold the error's name and message, or `null` when none was recorded. The list table omits `errorMessage`; use `--json` or the execution details to read it.\n\nEach execution also includes `hasPlatformLogs`, which is `true` when the Platform added log lines of its own to the execution. The flag is best-effort: `false` does not guarantee there are none, so read the `logEntries` of the execution details to be sure. The list table shows a `hasPlatformLogs` column, marking flagged executions with `yes`, only when at least one listed execution is flagged.\n\nExecution details include `logEntries`, the structured log lines (message, severity, timestamp, source) recorded while the function ran. They are available while the execution is still running. `source` is `USER` for your function's own output, `PLATFORM` for a line the Platform added, or `UNSPECIFIED` (not recorded, or a source this CLI version does not recognize); the human-readable output marks Platform lines with `[PLATFORM]`. The `logs` string joins their messages with newlines.\n\nUse `--follow` to keep polling a running execution and print new log entries as they arrive until it completes. Polling continues while the execution is suspended at a wait point, and indefinitely unless `--timeout` is set. With `--json`, `--follow` waits for completion and then emits the final execution details once.\n\nWhen viewing a specific execution that failed, the command displays error details with the stack trace mapped back to your original source files (clickable file links and code snippets, matching `function run` output).\n\nStack traces are mapped only when the execution includes a content hash for the exact build that ran. If the content hash is missing or the build is no longer available, the command falls back to a plain-text error display.",examples:[{cmd:``,desc:`List all function execution logs`},{cmd:`<execution-id>`,desc:`Get execution details with logs`},{cmd:`--json`,desc:`Output as JSON`},{cmd:`<execution-id> --json`,desc:`Get execution details as JSON`},{cmd:`<execution-id> --follow`,desc:`Stream log entries of a running execution until it completes`}],args:J.strictObject({...P,...Ut,"execution-id":G(J.string().optional(),{positional:!0,description:`Execution ID (if provided, shows details with logs)`}),follow:G(J.boolean().default(!1),{alias:`f`,description:`Keep polling a running execution and print new log entries as they arrive (detail mode only)`}),interval:G(In.default(`3s`),{alias:`i`,description:`Polling interval for --follow (e.g., '3s', '500ms', '1m')`}),timeout:G(In.optional(),{alias:`t`,description:`Maximum time to keep following (e.g., '30s', '10m'); unbounded by default`})}),run:async e=>{if(e.follow&&!e.executionId)throw S({code:`FUNCTION_LOGS_OPTIONS_INVALID`,message:`--follow requires an execution ID.`,command:`function logs`});let{client:t,workspaceId:n}=await M({profile:e.profile,workspaceId:e[`workspace-id`]});if(e.executionId){let r=y.jsonMode||e.json,i={client:t,workspaceId:n,executionId:e.executionId},{execution:a,printedEntries:o,followed:s}=e.follow?await followFunctionExecution({...i,interval:ot(e.interval),timeout:e.timeout===void 0?void 0:ot(e.timeout),showProgress:!r}):{execution:await fetchFunctionExecution(i),printedEntries:0,followed:!1},c=toFunctionExecutionDetailInfo(a);if(r){y.out(c);return}(!e.follow||s)&&printFunctionExecutionSummary(c),o===0&&printFunctionExecutionLogs(c),printFunctionExecutionOutcome({detail:c,bundledCode:c.error?await downloadScriptForMapping({client:t,workspaceId:n,scriptName:c.scriptName,executionType:a.type,executionContentHash:a.contentHash}):null})}else{let r=de(e.order),i=await kn(e.limit,e=>$r(async(e,i)=>{let{executions:a,nextPageToken:o}=await t.listFunctionExecutions({workspaceId:n,pageToken:e,pageSize:i,pageDirection:r});return[a,o]},{limit:e})),a=i.items.map(toFunctionExecutionListInfo);if(a.length===0&&!e.json){y.info(`No function execution logs found.`);return}let o=a.some(e=>e.hasPlatformLogs)?e=>e?`yes`:``:null;y.out(a,{display:{errorMessage:null,hasPlatformLogs:o}}),await D(i,e.limit)}}});async function bundleForRun(e){let{detected:t,sourceFile:n,baseDir:r,env:i={},machineUser:a,workspaceId:o,dateDefault:s=`legacy`}=e,c=pi(e.inlineSourcemap),l=di(e.logLevel),u=q.resolve(Qr(),`test-run`);X.mkdirSync(u,{recursive:!0});let d=`test-run--${t.name}`,f=`${d}.js`,p=q.join(u,`${d}.entry.js`),m=generateEntry({detected:t,sourceFile:n,env:i,machineUser:a,workspaceId:o,defaultPermission:e.defaultPermission,dateDefault:s});X.writeFileSync(p,m);let h=await Vr(r),g=Wr({tsconfig:h}),_=await ta.build({plugins:[Ur(p,r),Zr(),Rr(t.type===`resolver`?Br(t.fields,s):{date:!0,temporal:!0},s),Ci()],input:p,write:!1,output:{format:`esm`,sourcemap:!0,minify:!c||{mangle:{keepNames:!0}},comments:Hr,codeSplitting:!1,dir:process.cwd()},tsconfig:h,treeshake:Yr([Gr(l),Xr(e.treeshake)]),...g.options});return g.assertAllResolved(),{bundledCode:Kr({chunk:_.output[0],inlineSourcemap:c,dependencySources:e.inlineSourcemapDependencySources??!1,projectSources:e.inlineSourcemapProjectSources,sourcesDir:process.cwd()}),scriptName:f}}function generateEntry(e){let{detected:t,sourceFile:n,env:r,machineUser:i,workspaceId:a,defaultPermission:o,dateDefault:c}=e,l=q.resolve(n);switch(t.type){case`plain`:return t.namedMain?W`
29
+ `)}`)}catch{m.log(` ${t.result}`)}}t.error&&(m.log(s.bold(`
30
+ Error:`)),m.log(formatExecutionError(t.error,n??null)))}async function fetchFunctionExecution(e){let{execution:t}=await e.client.getFunctionExecution({workspaceId:e.workspaceId,executionId:e.executionId},{signal:e.signal});if(!t)throw _({code:`FUNCTION_EXECUTION_NOT_FOUND`,message:`Function execution '${e.executionId}' not found.`});return t}async function followFunctionExecution(e){let{interval:t,timeout:n,showProgress:r}=e,i=Date.now(),a=0,o,remainingMs=()=>n===void 0?void 0:n-(Date.now()-i),timedOut=()=>{let e=remainingMs();return e!==void 0&&e<=0},timeoutError=()=>{let t=o===void 0?`unknown`:zn(o);return _({code:`FUNCTION_EXECUTION_TIMEOUT`,message:`Timed out waiting for function execution '${e.executionId}' to complete. Last status: ${t}.`})},sleep=async()=>{let e=remainingMs();if(e===void 0)await wa(t);else{if(e<=0)throw timeoutError();await wa(Math.min(t,e))}};for(;;){let t=remainingMs();if(t!==void 0&&t<=0)throw timeoutError();let n;try{n=await fetchFunctionExecution({...e,signal:t===void 0?void 0:AbortSignal.timeout(t)})}catch(e){if(timedOut())throw timeoutError();if(!kn(e))throw e;m.warn(`Retrying function execution poll: ${Cr(e)}`,{mode:`stream`}),await sleep();continue}if(r){if(o===void 0&&(printFunctionExecutionSummary(toFunctionExecutionListInfo(n)),_r(n.status)||m.info(`Following log entries until the execution completes (Ctrl+C to stop)`,{mode:`stream`})),n.logEntries.length>a){a===0&&m.log(s.bold(`
31
+ Logs:`));for(let e of n.logEntries.slice(a))m.log(` ${Or(qn(e))}`);a=n.logEntries.length}if(o!==void 0&&n.status!==o){let e=rr(zn(n.status));m.info(`Status: ${e}`,{mode:`stream`})}}let i=o!==void 0;if(o=n.status,_r(n.status))return{execution:n,printedEntries:a,followed:i};await sleep()}}async function downloadScriptForMapping(e){let{client:t,workspaceId:n,scriptName:r,executionType:i,executionContentHash:a}=e,o=scriptNameToRegistryName(r,i);if(o==null)return m.debug(`Script "${r}" is not a deployed registry script (e.g. function run or seed); skipping sourcemap mapping.`),null;if(a===``)return m.debug(`Function execution "${r}" has no contentHash; skipping sourcemap mapping because the exact bundle cannot be identified.`),null;let s=await downloadFunctionScript({client:t,workspaceId:n,name:o,contentHash:a});return s==null?(m.debug(`Could not download pinned script "${r}" (registry: "${o}", contentHash: "${a}") for stack trace mapping; showing raw stack trace.`),null):s.code}const fo=I({name:`logs`,description:`List or get function execution logs.`,notes:"Each execution includes `errorKind`, which tells you where a failure came from: `USER_RUNTIME` (your code threw while running, or exceeded its time, memory, or CPU limit), `USER_NON_RUNTIME` (your script failed while loading, before your function was called, such as when its top-level code threw), `PLATFORM` (a failure on the Platform side, or the Platform aborting the run because of its own deadline or cancellation), `NONE` (no error), or `UNSPECIFIED` (not recorded, or a kind this CLI version does not recognize). A workflow job waiting on another job also reports `USER_NON_RUNTIME` when that job fails or is canceled. `errorName` and `errorMessage` hold the error's name and message, or `null` when none was recorded. The list table omits `errorMessage`; use `--json` or the execution details to read it.\n\nEach execution also includes `hasPlatformLogs`, which is `true` when the Platform added log lines of its own to the execution. The flag is best-effort: `false` does not guarantee there are none, so read the `logEntries` of the execution details to be sure. The list table shows a `hasPlatformLogs` column, marking flagged executions with `yes`, only when at least one listed execution is flagged.\n\nExecution details include `logEntries`, the structured log lines (message, severity, timestamp, source) recorded while the function ran. They are available while the execution is still running. `source` is `USER` for your function's own output, `PLATFORM` for a line the Platform added, or `UNSPECIFIED` (not recorded, or a source this CLI version does not recognize); the human-readable output marks Platform lines with `[PLATFORM]`. The `logs` string joins their messages with newlines.\n\nUse `--follow` to keep polling a running execution and print new log entries as they arrive until it completes. Polling continues while the execution is suspended at a wait point, and indefinitely unless `--timeout` is set. With `--json`, `--follow` waits for completion and then emits the final execution details once.\n\nWhen viewing a specific execution that failed, the command displays error details with the stack trace mapped back to your original source files (clickable file links and code snippets, matching `function run` output).\n\nStack traces are mapped only when the execution includes a content hash for the exact build that ran. If the content hash is missing or the build is no longer available, the command falls back to a plain-text error display.",examples:[{cmd:``,desc:`List all function execution logs`},{cmd:`<execution-id>`,desc:`Get execution details with logs`},{cmd:`--json`,desc:`Output as JSON`},{cmd:`<execution-id> --json`,desc:`Get execution details as JSON`},{cmd:`<execution-id> --follow`,desc:`Stream log entries of a running execution until it completes`}],args:J.strictObject({...A,...se,"execution-id":G(J.string().optional(),{positional:!0,description:`Execution ID (if provided, shows details with logs)`}),follow:G(J.boolean().default(!1),{alias:`f`,description:`Keep polling a running execution and print new log entries as they arrive (detail mode only)`}),interval:G(E.default(`3s`),{alias:`i`,description:`Polling interval for --follow (e.g., '3s', '500ms', '1m')`}),timeout:G(E.optional(),{alias:`t`,description:`Maximum time to keep following (e.g., '30s', '10m'); unbounded by default`})}),run:async e=>{if(e.follow&&!e.executionId)throw _({code:`FUNCTION_LOGS_OPTIONS_INVALID`,message:`--follow requires an execution ID.`,command:`function logs`});let{client:t,workspaceId:n}=await B({profile:e.profile,workspaceId:e[`workspace-id`]});if(e.executionId){let r=m.jsonMode||e.json,i={client:t,workspaceId:n,executionId:e.executionId},{execution:a,printedEntries:o,followed:s}=e.follow?await followFunctionExecution({...i,interval:ce(e.interval),timeout:e.timeout===void 0?void 0:ce(e.timeout),showProgress:!r}):{execution:await fetchFunctionExecution(i),printedEntries:0,followed:!1},c=toFunctionExecutionDetailInfo(a);if(r){m.out(c);return}(!e.follow||s)&&printFunctionExecutionSummary(c),o===0&&printFunctionExecutionLogs(c),printFunctionExecutionOutcome({detail:c,bundledCode:c.error?await downloadScriptForMapping({client:t,workspaceId:n,scriptName:c.scriptName,executionType:a.type,executionContentHash:a.contentHash}):null})}else{let r=we(e.order),i=await rn(e.limit,e=>Pi(async(e,i)=>{let{executions:a,nextPageToken:o}=await t.listFunctionExecutions({workspaceId:n,pageToken:e,pageSize:i,pageDirection:r});return[a,o]},{limit:e})),a=i.items.map(toFunctionExecutionListInfo);if(a.length===0&&!e.json){m.info(`No function execution logs found.`);return}let o=a.some(e=>e.hasPlatformLogs)?e=>e?`yes`:``:null;m.out(a,{display:{errorMessage:null,hasPlatformLogs:o}}),await M(i,e.limit)}}});async function bundleForRun(e){let{detected:t,sourceFile:n,baseDir:r,env:i={},machineUser:a,workspaceId:o,dateDefault:s=`legacy`}=e,c=mi(e.inlineSourcemap),l=pi(e.logLevel),u=q.resolve(li(),`test-run`);X.mkdirSync(u,{recursive:!0});let d=`test-run--${t.name}`,f=`${d}.js`,p=q.join(u,`${d}.entry.js`),m=generateEntry({detected:t,sourceFile:n,env:i,machineUser:a,workspaceId:o,defaultPermission:e.defaultPermission,dateDefault:s});X.writeFileSync(p,m);let h=await Qr(r),g=ti({tsconfig:h}),_=await Sa.build({plugins:[ei(p,r),ci(),Yr(t.type===`resolver`?Zr(t.fields,s):{date:!0,temporal:!0},s),bi()],input:p,write:!1,output:{format:`esm`,sourcemap:!0,minify:!c||{mangle:{keepNames:!0}},comments:$r,codeSplitting:!1,dir:process.cwd()},tsconfig:h,treeshake:oi([ni(l),si(e.treeshake)]),...g.options});return g.assertAllResolved(),{bundledCode:ri({chunk:_.output[0],inlineSourcemap:c,dependencySources:e.inlineSourcemapDependencySources??!1,projectSources:e.inlineSourcemapProjectSources,sourcesDir:process.cwd()}),scriptName:f}}function generateEntry(e){let{detected:n,sourceFile:r,env:i,machineUser:a,workspaceId:o,defaultPermission:s,dateDefault:c}=e,l=q.resolve(r);switch(n.type){case`plain`:return n.namedMain?H`
32
32
  export { main } from "${l}";
33
- `:W`
33
+ `:H`
34
34
  import _fn from "${l}";
35
35
  export { _fn as main };
36
- `;case`resolver`:{let e=buildMachinePrincipalExpr(i,a),n=Jr({permission:t.permission,defaultPermission:o}),{importStatement:s,resultExpr:u}=yi(t.fields?.output,c);return W`
36
+ `;case`resolver`:{let e=buildMachinePrincipalExpr(a,o),t=ai({permission:n.permission,defaultPermission:s}),{importStatement:r,resultExpr:u}=_i(n.fields?.output,c);return H`
37
37
  import _internalResolver from "${l}";
38
38
  import { t } from "@tailor-platform/sdk";
39
- ${s}
39
+ ${r}
40
40
 
41
41
  const $tailor_resolver_body = async (rawInput) => {
42
42
  const _caller = ${e};
43
- const invoker = (${xi}) ?? _caller;
44
- const context = { input: rawInput, env: ${JSON.stringify(r)}, caller: _caller, invoker };
45
- const input = ${n};
43
+ const invoker = (${vi}) ?? _caller;
44
+ const context = { input: rawInput, env: ${JSON.stringify(i)}, caller: _caller, invoker };
45
+ const input = ${t};
46
46
  const result = await _internalResolver.body({ ...context, input });
47
47
  return ${u};
48
48
  };
49
49
 
50
50
  export { $tailor_resolver_body as main };
51
- `}case`executor`:{let e=buildMachinePrincipalExpr(i,a);return W`
51
+ `}case`executor`:{let e=buildMachinePrincipalExpr(a,o);return H`
52
52
  import _internalExecutor from "${l}";
53
53
 
54
- const _env = ${JSON.stringify(r)};
54
+ const _env = ${JSON.stringify(i)};
55
55
  const _actor = ${e};
56
56
 
57
57
  const __executor_function = async (args) => {
58
- const _invoker = ${xi} ?? _actor;
58
+ const _invoker = ${vi} ?? _actor;
59
59
  return _internalExecutor.operation.body({ ...args, env: _env, actor: _actor, invoker: _invoker });
60
60
  };
61
61
 
62
62
  export { __executor_function as main };
63
- `}case`workflow-job`:{let e=s(t.exportName,`workflow job export name missing`),n=buildMachinePrincipalExpr(i,a);return W`
63
+ `}case`workflow-job`:{let e=t(n.exportName,`workflow job export name missing`),r=buildMachinePrincipalExpr(a,o);return H`
64
64
  import { ${JSON.stringify(e)} as _internalJob } from "${l}";
65
65
 
66
- const env = ${JSON.stringify(r)};
67
- const fallbackInvoker = ${n};
66
+ const env = ${JSON.stringify(i)};
67
+ const fallbackInvoker = ${r};
68
68
 
69
69
  export async function main(input) {
70
- const invoker = ${xi} ?? fallbackInvoker;
70
+ const invoker = ${vi} ?? fallbackInvoker;
71
71
  return await _internalJob.body(input, { env, invoker });
72
72
  }
73
- `}}}function buildMachinePrincipalExpr(e,t){return JSON.stringify({id:e.id,type:`machine_user`,workspaceId:t,attributes:e.attributes??{},attributeList:e.attributeList})}async function detectFunctionType(t){let{filePath:n,jobName:r}=t,i=await f(n),a=Si.safeParse(i.default);if(a.success){let t=i.default.input,n;return t&&(n={parse:n=>e({...n,fields:t})}),{type:`resolver`,name:a.data.name,hasInput:t!=null,inputSchema:n,permission:a.data.permission,fields:{input:a.data.input,output:a.data.output}}}let o=l.safeParse(d(i.default));if(o.success){let{operation:e}=o.data;if(e.kind===`function`||e.kind===`jobFunction`)return{type:`executor`,name:o.data.name}}let s=detectWorkflowJob(i,r);if(s)return s;if(typeof i.default==`function`)return{type:`plain`,name:deriveNameFromPath(n)};if(typeof i.main==`function`)return{type:`plain`,name:deriveNameFromPath(n),namedMain:!0};throw S({code:`FUNCTION_TYPE_UNDETECTED`,message:`Could not detect function type from ${n}.`,details:`The file must have one of:
73
+ `}}}function buildMachinePrincipalExpr(e,t){return JSON.stringify({id:e.id,type:`machine_user`,workspaceId:t,attributes:e.attributes??{},attributeList:e.attributeList})}async function detectFunctionType(t){let{filePath:n,jobName:r}=t,i=await wi(n),a=yi.safeParse(i.default);if(a.success){let t=i.default.input,n;return t&&(n={parse:n=>e({...n,fields:t})}),{type:`resolver`,name:a.data.name,hasInput:t!=null,inputSchema:n,permission:a.data.permission,fields:{input:a.data.input,output:a.data.output}}}let o=Si.safeParse(Ci(i.default));if(o.success){let{operation:e}=o.data;if(e.kind===`function`||e.kind===`jobFunction`)return{type:`executor`,name:o.data.name}}let s=detectWorkflowJob(i,r);if(s)return s;if(typeof i.default==`function`)return{type:`plain`,name:deriveNameFromPath(n)};if(typeof i.main==`function`)return{type:`plain`,name:deriveNameFromPath(n),namedMain:!0};throw _({code:`FUNCTION_TYPE_UNDETECTED`,message:`Could not detect function type from ${n}.`,details:`The file must have one of:
74
74
  - A default-exported resolver (createResolver)
75
75
  - A default-exported executor (createExecutor) with function/jobFunction operation
76
76
  - A named-exported workflow job (createWorkflowJob)
77
77
  - A default-exported function
78
- - A named-exported "main" function`})}function detectWorkflowJob(e,t){let n=[];for(let[t,r]of Object.entries(e)){if(t==="default")continue;let e=oi.safeParse(r);e.success&&n.push({name:e.data.name,exportName:t})}if(n.length===0)return null;if(t){let e=n.find(e=>e.name===t);if(!e){let e=n.map(e=>` - "${e.name}" (export: ${e.exportName})`).join(`
79
- `);throw S({code:`WORKFLOW_JOB_NOT_FOUND`,message:`Workflow job "${t}" not found.`,details:`Available jobs:\n${e}`})}return{type:`workflow-job`,name:e.name,exportName:e.exportName}}if(n.length===1){let[e]=n,t=s(e,`workflow job missing`);return{type:`workflow-job`,name:t.name,exportName:t.exportName}}let r=n.map(e=>` - "${e.name}" (export: ${e.exportName})`).join(`
80
- `);throw S({code:`WORKFLOW_JOB_AMBIGUOUS`,message:`Multiple workflow jobs found.`,details:`Available jobs:\n${r}`,suggestion:`Specify one with --name.`})}function deriveNameFromPath(e){return q.basename(e,q.extname(e))}const Ga=`db.ts`,Ka=`db.snapshot.json`;function generateScriptDbTypes(e,t=!1){let n=Object.values(e.tables).map(e=>Ni(e.name,e.fields,t));return`/**
78
+ - A named-exported "main" function`})}function detectWorkflowJob(e,n){let r=[];for(let[t,n]of Object.entries(e)){if(t==="default")continue;let e=fi.safeParse(n);e.success&&r.push({name:e.data.name,exportName:t})}if(r.length===0)return null;if(n){let e=r.find(e=>e.name===n);if(!e){let e=r.map(e=>` - "${e.name}" (export: ${e.exportName})`).join(`
79
+ `);throw _({code:`WORKFLOW_JOB_NOT_FOUND`,message:`Workflow job "${n}" not found.`,details:`Available jobs:\n${e}`})}return{type:`workflow-job`,name:e.name,exportName:e.exportName}}if(r.length===1){let[e]=r,n=t(e,`workflow job missing`);return{type:`workflow-job`,name:n.name,exportName:n.exportName}}let i=r.map(e=>` - "${e.name}" (export: ${e.exportName})`).join(`
80
+ `);throw _({code:`WORKFLOW_JOB_AMBIGUOUS`,message:`Multiple workflow jobs found.`,details:`Available jobs:\n${i}`,suggestion:`Specify one with --name.`})}function deriveNameFromPath(e){return q.basename(e,q.extname(e))}const po=`db.ts`,mo=`db.snapshot.json`;function generateScriptDbTypes(e,t=!1){let n=Object.values(e.tables).map(e=>ea(e.name,e.fields,t));return`/**
81
81
  * Auto-generated Kysely types for one-off scripts in this directory.
82
82
  * Generated by \`tailor function script\` from the selected TailorDB schema.
83
83
  *
84
84
  * DO NOT EDIT - Re-run \`tailor function script\` to refresh.
85
- */\n\n${Pi([{namespace:e.namespace,types:n}],t)}`}function isGeneratedScriptDbTypes(e){return e.includes("Generated by `tailor function script`")}function assertGeneratedTypeScript(e,t){let{errors:n}=na(q.basename(e),t);if(n.length>0)throw g(`Generated ${e} does not parse as TypeScript: ${n.map(e=>e.message).join(`; `)}`)}function generateScriptSkeleton(e){let{getDBImportPath:t,namespace:n}=e;return[`/**`,` * One-off script. Run it on the platform without deploying:`,` *`,` * tailor function run <this file>`,` *`,` * For large tables, batch updates by primary-key range instead of one`,` * statement over the whole table; see the "Performance and Large Tables"`,` * section in @tailor-platform/sdk's docs/services/tailordb/migration.md.`,` */`,``,`import { getDB } from ${JSON.stringify(t)};`,``,`export default async function main() {`,` const db = getDB(${JSON.stringify(n)});`,``,` // A transaction rolls every change back when any statement fails.`,` await db.transaction().execute(async (trx) => {`,` // e.g. await trx.updateTable("MyTable").set({ ... }).where("id", "=", "...").execute();`,` });`,`}`,``].join(`
86
- `)}function loadScriptSchemaSnapshot(e){let t=q.join(q.dirname(e),Ka);if(!X.existsSync(t))return null;let n;try{n=JSON.parse(X.readFileSync(t,`utf-8`))}catch(e){throw S({code:`SCRIPT_SNAPSHOT_INVALID`,message:`Failed to parse schema snapshot ${t}: ${e instanceof Error?e.message:e}.`,suggestion:"Re-run `tailor function script` to regenerate it.",cause:e})}let r=n;if(typeof r!=`object`||!r||typeof r.namespace!=`string`||typeof r.tables!=`object`||r.tables===null)throw unexpectedSnapshotShapeError(t);let i=r.source??`remote`;if(i!==`local`&&i!==`remote`)throw unexpectedSnapshotShapeError(t);let a={...r};delete a.source;try{return{snapshotPath:t,source:i,snapshot:Pt(a)}}catch{throw unexpectedSnapshotShapeError(t)}}function unexpectedSnapshotShapeError(e){return S({code:`SCRIPT_SNAPSHOT_INVALID`,message:`Schema snapshot ${e} has an unexpected shape.`,suggestion:"Re-run `tailor function script` to regenerate it."})}async function verifyScriptSchemaSnapshot(e){let{client:t,workspaceId:n,config:r,configArgValue:i,sidecar:a}=e,{snapshot:o}=a,s=o.namespace;if(br(r).includes(s)){let{namespaces:t}=await we({configPath:i,namespaces:[s]}),n=t[0];if(n){let t=Object.fromEntries(Object.values(n.tables).map(e=>[e.name,ae(e)])),r=Ln(generatedContractSnapshot(o),generatedContractSnapshot({...o,tables:t}));if(st(r))throw schemaDriftError(`the local table definitions`,r,e)}}let c=await en(t,n,s),l=Ln(a.source===`local`?generatedContractSnapshot(o):Pt(pickTableFields(o)),a.source===`local`?generatedContractSnapshot(c):Pt(pickTableFields(c)));if(st(l))throw schemaDriftError(`the deployed schema`,l,e)}function fieldsOnlySnapshot(e){return Pt(pickTableFields(He(e)))}function generatedContractSnapshot(e){let t=fieldsOnlySnapshot(e),n=Object.fromEntries(Object.entries(t.tables).map(([t,n])=>{let r=e.tables[t],i=Object.fromEntries(Object.entries(n.fields).map(([e,t])=>[e,preserveGeneratedContract(t,r?.fields[e])]));return[t,{...n,fields:i}]}));return Pt({...t,tables:n})}function preserveGeneratedContract(e,t){let n=e.fields?Object.fromEntries(Object.entries(e.fields).map(([e,n])=>[e,preserveGeneratedContract(n,t?.fields?.[e])])):void 0,r=t?.hooks?.create!==void 0||t?.default!==void 0||t?.optionalOnCreate===!0;return{...e,...n===void 0?{}:{fields:n},...r?{optionalOnCreate:!0}:{}}}function pickTableFields(e){let t=Object.fromEntries(Object.entries(e.tables).map(([e,t])=>[e,{name:t.name,pluralForm:t.pluralForm,fields:t.fields}]));return{...e,tables:t}}function schemaDriftError(e,t,n){let r=[...n.configArgValue===`tailor.config.ts`?[]:[`--config=${n.configArgValue}`],`--workspace-id=${n.workspaceId}`,...n.profileArgValue===void 0?[]:[`--profile=${n.profileArgValue}`]],i=b({command:`tailor`,args:[`function`,`script`,n.scriptArgValue,...n.sidecar.source===`remote`?[`--remote`]:[],...r]}),a=b({command:`tailor`,args:[`function`,`run`,n.scriptArgValue,`--allow-schema-drift`,...r]});return S({code:`SCRIPT_SCHEMA_DRIFT`,message:`Schema drift detected: ${Ka} next to the script no longer matches ${e}.`,details:Er(t),suggestion:`Refresh the generated types with ${i}, or run anyway with ${a}.`})}const qa=z({name:`run`,aliases:[`test-run`],description:`Run a function on the Tailor Platform server without deploying.`,args:J.object({...P,file:G(J.string(),{positional:!0,description:`Path to the function file`}),name:G(J.string().optional(),{alias:`n`,description:"Workflow job name to run (matches the `name` field of createWorkflowJob)"}),arg:G(J.string().optional(),{alias:`a`,description:`JSON argument to pass to the function`}),"machine-user":G(J.string().optional(),{alias:`m`,description:`Machine user name for authentication. Falls back to the active profile's default machine user.`,env:`TAILOR_PLATFORM_MACHINE_USER_NAME`}),config:G(J.string().default(`tailor.config.ts`),{alias:`c`,description:`Path to SDK config file`}),"allow-schema-drift":G(J.boolean().default(!1),{description:`Run a scaffolded script even when its schema snapshot no longer matches`})}),notes:"You can pass either a source file (`.ts`) or a pre-bundled file (`.js`).\nWhen a `.js` file is provided, detection and bundling are skipped and the file is executed as-is.\n\nA script scaffolded by `function script` with a generated `db.ts` is checked against its `db.snapshot.json` before execution and refused on schema drift; pass `--allow-schema-drift` to run it anyway. The check compares table and field structure; hook and validator code changes are not detected.\n\n`test-run` is a deprecated alias of this command and will be removed in v3.\n\n> [!WARNING]\n> Workflow job `.start()` calls do not work in this mode.\n> Started jobs are not executed; only the target job's `body` function runs in isolation.",examples:[{cmd:`resolvers/add.ts --arg '{"a":1,"b":2}'`,desc:`Run a resolver with input arguments`},{cmd:`workflows/sample.ts --name validate-order`,desc:`Run a specific workflow job by name`},{cmd:`build/resolvers/add.js --arg '{"a":1,"b":2}'`,desc:`Run a pre-bundled .js file directly`}],run:async e=>{invokedViaTestRunAlias(process.argv)&&y.warn("`tailor function test-run` is deprecated and will be removed in v3. Use `tailor function run` instead.");let t=y.jsonMode,n=q.resolve(e.file);if(!X.existsSync(n))throw S({code:`FILE_NOT_FOUND`,message:`File not found: ${n}`});let{config:r}=await j(e.config),a=resolveAuthNamespace(r.auth),o=await resolveMachineUserName({cliMachineUser:e[`machine-user`],cliMachineUserSource:he(e[`machine-user`]),profile:e.profile,authConfig:r.auth}),{client:s,workspaceId:c}=await M({profile:e.profile,workspaceId:e[`workspace-id`]}),l=await resolveMachineUser({client:s,workspaceId:c,authNamespace:a,machineUserName:o,authConfig:r.auth}),u=q.relative(process.cwd(),n),d=n.endsWith(`.js`);if(!d){if(e[`allow-schema-drift`])X.existsSync(q.join(q.dirname(n),`db.snapshot.json`))&&y.warn(`Skipping the schema snapshot check (--allow-schema-drift).`);else{let t=loadScriptSchemaSnapshot(n);t&&(y.info(`Checking the script's schema snapshot for drift...`),await verifyScriptSchemaSnapshot({client:s,workspaceId:c,config:r,configArgValue:e.config,scriptArgValue:e.file,profileArgValue:e.profile,sidecar:t}))}}let f,p,m,h;if(d)p=q.basename(n),f=X.readFileSync(n,`utf-8`),y.info(`Using pre-bundled script ${w.bold(p)}`);else{y.info(`Detecting function type from ${w.path(u)}`);let t=await detectFunctionType({filePath:n,jobName:e.name});m=t.type,h=t.name,y.info(`Detected: ${w.bold(t.type)} ${w.info(`"${t.name}"`)}`),t.type===`resolver`&&e.arg&&!t.hasInput&&(y.warn(`--arg is ignored because this resolver has no input schema. Define "input" in your resolver to use --arg.`),e.arg=void 0),y.info(`Bundling...`);let i=ii(r),a=q.dirname(r.path);({bundledCode:f,scriptName:p}=await bundleForRun({detected:t,sourceFile:n,baseDir:a,defaultPermission:t.type===`resolver`?vi({config:r.resolver,filePath:n,baseDir:a}):void 0,env:r.env??{},inlineSourcemap:i.inlineSourcemap,inlineSourcemapDependencySources:i.inlineSourcemapDependencySources,inlineSourcemapProjectSources:gi({buildOptions:i,baseDir:a}),logLevel:i.logLevel,treeshake:i.treeshake,dateDefault:ei(r),machineUser:l,workspaceId:c})),y.info(`Bundled as ${w.bold(p)}`)}let g=Wi(i,{namespace:a,machineUserName:l.name});y.info(`Executing on workspace ${w.dim(c)}...`);let _;if(e.arg!==void 0)try{_=JSON.parse(e.arg)}catch(e){throw S({code:`FUNCTION_ARG_INVALID`,message:`Invalid --arg JSON: ${e instanceof Error?e.message:e}`,command:`function run`,cause:e})}let v=await Pe({client:s,workspaceId:c,name:p,code:f,arg:_,invoker:g});if(t)y.out({success:v.success,scriptName:p,functionType:m,functionName:h,logs:v.logs,result:v.result,error:v.error});else{if(v.success?y.success(`Execution succeeded`):y.error(`Execution failed`),v.logs.trim()){y.log(w.bold(`
87
- Logs:`));for(let e of v.logs.split(`
88
- `))y.log(` ${e}`)}if(v.result&&v.success){y.log(w.bold(`
89
- Result:`));try{let e=JSON.parse(v.result);y.log(` ${JSON.stringify(e,null,2).split(`
85
+ */\n\n${ta([{namespace:e.namespace,types:n}],t)}`}function isGeneratedScriptDbTypes(e){return e.includes("Generated by `tailor function script`")}function assertGeneratedTypeScript(e,t){let{errors:n}=Ca(q.basename(e),t);if(n.length>0)throw u(`Generated ${e} does not parse as TypeScript: ${n.map(e=>e.message).join(`; `)}`)}function generateScriptSkeleton(e){let{getDBImportPath:t,namespace:n}=e;return[`/**`,` * One-off script. Run it on the platform without deploying:`,` *`,` * tailor function run <this file>`,` *`,` * For large tables, batch updates by primary-key range instead of one`,` * statement over the whole table; see the "Performance and Large Tables"`,` * section in @tailor-platform/sdk's docs/services/tailordb/migration.md.`,` */`,``,`import { getDB } from ${JSON.stringify(t)};`,``,`export default async function main() {`,` const db = getDB(${JSON.stringify(n)});`,``,` // A transaction rolls every change back when any statement fails.`,` await db.transaction().execute(async (trx) => {`,` // e.g. await trx.updateTable("MyTable").set({ ... }).where("id", "=", "...").execute();`,` });`,`}`,``].join(`
86
+ `)}function loadScriptSchemaSnapshot(e){let t=q.join(q.dirname(e),mo);if(!X.existsSync(t))return null;let n;try{n=JSON.parse(X.readFileSync(t,`utf-8`))}catch(e){throw _({code:`SCRIPT_SNAPSHOT_INVALID`,message:`Failed to parse schema snapshot ${t}: ${e instanceof Error?e.message:e}.`,suggestion:"Re-run `tailor function script` to regenerate it.",cause:e})}let r=n;if(typeof r!=`object`||!r||typeof r.namespace!=`string`||typeof r.tables!=`object`||r.tables===null)throw unexpectedSnapshotShapeError(t);let i=r.source??`remote`;if(i!==`local`&&i!==`remote`)throw unexpectedSnapshotShapeError(t);let a={...r};delete a.source;try{return{snapshotPath:t,source:i,snapshot:Dt(a)}}catch{throw unexpectedSnapshotShapeError(t)}}function unexpectedSnapshotShapeError(e){return _({code:`SCRIPT_SNAPSHOT_INVALID`,message:`Schema snapshot ${e} has an unexpected shape.`,suggestion:"Re-run `tailor function script` to regenerate it."})}async function verifyScriptSchemaSnapshot(e){let{client:t,workspaceId:n,config:r,configArgValue:i,sidecar:a}=e,{snapshot:o}=a,s=o.namespace;if(Nr(r).includes(s)){let{namespaces:t}=await at({configPath:i,namespaces:[s]}),n=t[0];if(n){let t=Object.fromEntries(Object.values(n.tables).map(e=>[e.name,Ie(e)])),r=er(generatedContractSnapshot(o),generatedContractSnapshot({...o,tables:t}));if(Ct(r))throw schemaDriftError(`the local table definitions`,r,e)}}let c=await Kt(t,n,s),l=er(a.source===`local`?generatedContractSnapshot(o):Dt(pickTableFields(o)),a.source===`local`?generatedContractSnapshot(c):Dt(pickTableFields(c)));if(Ct(l))throw schemaDriftError(`the deployed schema`,l,e)}function fieldsOnlySnapshot(e){return Dt(pickTableFields(un(e)))}function generatedContractSnapshot(e){let t=fieldsOnlySnapshot(e),n=Object.fromEntries(Object.entries(t.tables).map(([t,n])=>{let r=e.tables[t],i=Object.fromEntries(Object.entries(n.fields).map(([e,t])=>[e,preserveGeneratedContract(t,r?.fields[e])]));return[t,{...n,fields:i}]}));return Dt({...t,tables:n})}function preserveGeneratedContract(e,t){let n=e.fields?Object.fromEntries(Object.entries(e.fields).map(([e,n])=>[e,preserveGeneratedContract(n,t?.fields?.[e])])):void 0,r=t?.hooks?.create!==void 0||t?.default!==void 0||t?.optionalOnCreate===!0;return{...e,...n===void 0?{}:{fields:n},...r?{optionalOnCreate:!0}:{}}}function pickTableFields(e){let t=Object.fromEntries(Object.entries(e.tables).map(([e,t])=>[e,{name:t.name,pluralForm:t.pluralForm,fields:t.fields}]));return{...e,tables:t}}function schemaDriftError(e,t,n){let r=[...n.configArgValue===`tailor.config.ts`?[]:[`--config=${n.configArgValue}`],`--workspace-id=${n.workspaceId}`,...n.profileArgValue===void 0?[]:[`--profile=${n.profileArgValue}`]],i=h({command:`tailor`,args:[`function`,`script`,n.scriptArgValue,...n.sidecar.source===`remote`?[`--remote`]:[],...r]}),a=h({command:`tailor`,args:[`function`,`run`,n.scriptArgValue,`--allow-schema-drift`,...r]});return _({code:`SCRIPT_SCHEMA_DRIFT`,message:`Schema drift detected: ${mo} next to the script no longer matches ${e}.`,details:dt(t),suggestion:`Refresh the generated types with ${i}, or run anyway with ${a}.`})}const ho=I({name:`run`,aliases:[`test-run`],description:`Run a function on the Tailor Platform server without deploying.`,args:J.object({...A,file:G(J.string(),{positional:!0,description:`Path to the function file`}),name:G(J.string().optional(),{alias:`n`,description:"Workflow job name to run (matches the `name` field of createWorkflowJob)"}),arg:G(J.string().optional(),{alias:`a`,description:`JSON argument to pass to the function`}),"machine-user":G(J.string().optional(),{alias:`m`,description:`Machine user name for authentication. Falls back to the active profile's default machine user.`,env:`TAILOR_PLATFORM_MACHINE_USER_NAME`}),...te,"allow-schema-drift":G(J.boolean().default(!1),{description:`Run a scaffolded script even when its schema snapshot no longer matches`})}),notes:"You can pass either a source file (`.ts`) or a pre-bundled file (`.js`).\nWhen a `.js` file is provided, detection and bundling are skipped and the file is executed as-is.\n\nA script scaffolded by `function script` with a generated `db.ts` is checked against its `db.snapshot.json` before execution and refused on schema drift; pass `--allow-schema-drift` to run it anyway. The check compares table and field structure; hook and validator code changes are not detected.\n\n`test-run` is a deprecated alias of this command and will be removed in v3.\n\n> [!WARNING]\n> Workflow job `.start()` calls do not work in this mode.\n> Started jobs are not executed; only the target job's `body` function runs in isolation.",examples:[{cmd:`resolvers/add.ts --arg '{"a":1,"b":2}'`,desc:`Run a resolver with input arguments`},{cmd:`workflows/sample.ts --name validate-order`,desc:`Run a specific workflow job by name`},{cmd:`build/resolvers/add.js --arg '{"a":1,"b":2}'`,desc:`Run a pre-bundled .js file directly`}],run:async e=>{invokedViaTestRunAlias(process.argv)&&m.warn("`tailor function test-run` is deprecated and will be removed in v3. Use `tailor function run` instead.");let t=m.jsonMode,n=q.resolve(e.file);if(!X.existsSync(n))throw _({code:`FILE_NOT_FOUND`,message:`File not found: ${n}`});let{config:r}=await R(e.config),i=resolveAuthNamespace(r.auth),a=await resolveMachineUserName({cliMachineUser:e[`machine-user`],cliMachineUserSource:de(e[`machine-user`]),profile:e.profile,authConfig:r.auth}),{client:o,workspaceId:c}=await B({profile:e.profile,workspaceId:e[`workspace-id`]}),l=await resolveMachineUser({client:o,workspaceId:c,authNamespace:i,machineUserName:a,authConfig:r.auth}),u=q.relative(process.cwd(),n),d=n.endsWith(`.js`);if(!d){if(e[`allow-schema-drift`])X.existsSync(q.join(q.dirname(n),`db.snapshot.json`))&&m.warn(`Skipping the schema snapshot check (--allow-schema-drift).`);else{let t=loadScriptSchemaSnapshot(n);t&&(m.info(`Checking the script's schema snapshot for drift...`),await verifyScriptSchemaSnapshot({client:o,workspaceId:c,config:r,configArgValue:e.config,scriptArgValue:e.file,profileArgValue:e.profile,sidecar:t}))}}let f,p,h,g;if(d)p=q.basename(n),f=X.readFileSync(n,`utf-8`),m.info(`Using pre-bundled script ${s.bold(p)}`);else{m.info(`Detecting function type from ${s.path(u)}`);let t=await detectFunctionType({filePath:n,jobName:e.name});h=t.type,g=t.name,m.info(`Detected: ${s.bold(t.type)} ${s.info(`"${t.name}"`)}`),t.type===`resolver`&&e.arg&&!t.hasInput&&(m.warn(`--arg is ignored because this resolver has no input schema. Define "input" in your resolver to use --arg.`),e.arg=void 0),m.info(`Bundling...`);let i=di(r),a=q.dirname(r.path);({bundledCode:f,scriptName:p}=await bundleForRun({detected:t,sourceFile:n,baseDir:a,defaultPermission:t.type===`resolver`?gi({config:r.resolver,filePath:n,baseDir:a}):void 0,env:r.env??{},inlineSourcemap:i.inlineSourcemap,inlineSourcemapDependencySources:i.inlineSourcemapDependencySources,inlineSourcemapProjectSources:hi({buildOptions:i,baseDir:a}),logLevel:i.logLevel,treeshake:i.treeshake,dateDefault:ui(r),machineUser:l,workspaceId:c})),m.info(`Bundled as ${s.bold(p)}`)}let v=ua(Wi,{namespace:i,machineUserName:l.name});m.info(`Executing on workspace ${s.dim(c)}...`);let y;if(e.arg!==void 0)try{y=JSON.parse(e.arg)}catch(e){throw _({code:`FUNCTION_ARG_INVALID`,message:`Invalid --arg JSON: ${e instanceof Error?e.message:e}`,command:`function run`,cause:e})}let b=await _t({client:o,workspaceId:c,name:p,code:f,arg:y,invoker:v});if(t)m.out({success:b.success,scriptName:p,functionType:h,functionName:g,logs:b.logs,result:b.result,error:b.error});else{if(b.success?m.success(`Execution succeeded`):m.error(`Execution failed`),b.logs.trim()){m.log(s.bold(`
87
+ Logs:`));for(let e of b.logs.split(`
88
+ `))m.log(` ${e}`)}if(b.result&&b.success){m.log(s.bold(`
89
+ Result:`));try{let e=JSON.parse(b.result);m.log(` ${JSON.stringify(e,null,2).split(`
90
90
  `).join(`
91
- `)}`)}catch{y.log(` ${v.result}`)}}if(v.error&&!v.success){y.log(w.bold(`
92
- Error:`));let e=formatErrorWithSourcemap(v.error,f,process.cwd());e?y.log(e):y.log(` ${w.error(v.error)}`)}}v.success||process.exit(1)}}),Ja=new Set(Ii(J.strictObject(jn)).fields.filter(e=>e.type!==`boolean`).flatMap(e=>[e.cliName,...e.alias??[]].flatMap(toFlagTokens)));function toFlagTokens(e){return e.length===1?[`-${e}`]:[`--${e}`,`--${Ri(e)}`]}function invokedViaTestRunAlias(e){let t=[];for(let n=2;n<e.length&&t.length<2;n++){let r=e[n];if(r===void 0||r===`--`)break;r.startsWith(`-`)?!r.includes(`=`)&&Ja.has(r)&&n++:t.push(r)}return t[0]===`function`&&t[1]===`test-run`}function resolveAuthNamespace(e){if(e?.name)return e.name;throw S({code:`AUTH_CONFIG_REQUIRED`,message:`Auth namespace is required.`,suggestion:`Ensure tailor.config.ts has an auth config.`})}async function resolveMachineUserName(e){let{cliMachineUser:t,cliMachineUserSource:n,profile:r,authConfig:i}=e,a=await Se({machineUser:t,machineUserSource:n,profile:r});if(a)return a;if(i&&!(`external`in i&&i.external)){let e=i.machineUsers;if(e){let t=Object.keys(e);if(t.length>0)return s(t[0],`machine user key missing`)}}throw S({code:`MACHINE_USER_REQUIRED`,message:`Machine user is required.`,suggestion:`Provide --machine-user, set TAILOR_PLATFORM_MACHINE_USER_NAME, set a profile default with 'tailor profile update <profile> --machine-user <name>', or ensure tailor.config.ts has machine users configured.`})}async function resolveMachineUser(e){let{client:t,workspaceId:n,authNamespace:r,machineUserName:i,authConfig:a}=e,o=`00000000-0000-0000-0000-000000000000`;try{let{machineUser:e}=await t.getAuthMachineUser({workspaceId:n,authNamespace:r,name:i});e?.id&&(o=e.id)}catch{y.debug(`Could not fetch machine user "${i}" from server, using nil UUID`)}let s=a?.machineUsers?.[i],c=null,l=[];if(s&&typeof s==`object`){let e=s;c=e.attributes??null,l=e.attributeList??[]}return{name:i,id:o,attributes:c,attributeList:l}}const Ya=z({name:`script`,description:"Scaffold a one-off script to run with `function run`.",args:J.object({...P,...pr,file:G(J.string(),{positional:!0,description:`Path to create the script at (must end with .ts)`}),namespace:G(J.string().optional(),{description:`Target TailorDB namespace (required when the config does not pin one)`}),remote:G(J.boolean().default(!1),{description:`Generate script-scoped DB types from the deployed schema`})}),notes:"The scaffolded script is a plain default-exported function; execute it with `tailor function run <file>`.\n\nBy default, when the project configures `kyselyTypePlugin`, the skeleton imports `getDB()` from the plugin's generated types. Without the plugin, the command uses the namespace's local table definitions to write a script-scoped `db.ts` plus a `db.snapshot.json` next to the script; `function run` refuses to run the script when that snapshot no longer matches the deployed or locally defined table and field structure.\n\nPass `--remote` to generate the script-scoped files from the deployed schema instead, even when `kyselyTypePlugin` is configured. This is required for an external namespace. Re-running the command refreshes `db.ts` and `db.snapshot.json` from the selected source and leaves the script itself untouched.",examples:[{cmd:`scripts/fix-prices.ts`,desc:`Scaffold a one-off script (single-namespace project)`},{cmd:`scripts/fix-prices.ts --namespace tailordb`,desc:`Scaffold a script targeting a specific namespace`},{cmd:`scripts/fix-prices.ts --namespace shared --remote`,desc:`Scaffold from a deployed or external namespace`}],run:async e=>{let t=q.resolve(e.file);if(!t.endsWith(`.ts`))throw S({code:`SCRIPT_PATH_INVALID`,message:`Script path must end with .ts: ${e.file}`,command:`function script`});let n=q.dirname(t),r=X.existsSync(t),i=q.join(n,Ga),a=q.join(n,Ka);if(t===i)throw S({code:`SCRIPT_PATH_INVALID`,message:`${Ga} is reserved for the generated Kysely types written next to the script. Choose a different script file name.`,command:`function script`});let{config:o,plugins:c}=await j(e.config),l=c.find(e=>e.id===Fi),u=X.existsSync(a);if(e.remote&&l!==void 0&&r&&!u)throw S({code:`SCRIPT_EXISTS`,message:`Script already exists: ${q.relative(process.cwd(),t)}.`,suggestion:`Scaffold --remote at a new path so the generated script imports its script-scoped db.ts.`});let d=e.remote||l===void 0||u,f;if(d)try{f=loadScriptSchemaSnapshot(t)?.snapshot.namespace}catch{}let p=resolveNamespace({config:o,explicit:e.namespace,sidecarNamespace:f,remote:e.remote});if(f!==void 0&&f!==p)throw S({code:`SCRIPT_NAMESPACE_MISMATCH`,message:`This directory's generated types target namespace "${f}" (${Ka}).`,suggestion:`Scaffold scripts for namespace "${p}" in a separate directory.`});let m=[],h,g;if(d){let t;if(e.remote){let{client:n,workspaceId:r}=await M({profile:e.profile,workspaceId:e[`workspace-id`]});g=r,y.info(`Fetching deployed schema of namespace ${w.bold(p)}...`),t=await en(n,r,p)}else{y.info(`Loading local definitions of namespace ${w.bold(p)}...`);let{namespaces:n}=await we({configPath:e.config,namespaces:[p]}),r=s(n[0],`namespace ${p}`);t=Lr(r.tables,p)}if(Object.keys(t.tables).length===0){let t=e.remote?`deployed tables in workspace ${s(g,`workspace ID`)}`:`locally defined tables`;throw S({code:`SCRIPT_SCHEMA_NOT_FOUND`,message:`Namespace "${p}" has no ${t}.`})}if(X.existsSync(i)&&!isGeneratedScriptDbTypes(X.readFileSync(i,`utf-8`)))throw S({code:`GENERATED_TYPES_NOT_OWNED`,message:`Refusing to overwrite ${q.relative(process.cwd(),i)}: it was not generated by \`tailor function script\`.`});let r=generateScriptDbTypes(t,Re(c,`@tailor-platform/kysely-type`)?.temporal??!1);assertGeneratedTypeScript(i,r),X.mkdirSync(n,{recursive:!0}),X.writeFileSync(i,r),m.push(i),X.writeFileSync(a,JSON.stringify({...t,source:e.remote?`remote`:`local`},null,2)+`
93
- `),m.push(a),h=`./db`}else{if(r)throw S({code:`SCRIPT_EXISTS`,message:`Script already exists: ${q.relative(process.cwd(),t)}.`,suggestion:`It imports the project's generated Kysely types, so there is nothing to refresh.`});let e=resolveKyselyTypesPath(c);h=toImportSpecifier(q.relative(n,e)),X.existsSync(e)||y.warn(`Generated Kysely types not found at ${w.path(q.relative(process.cwd(),e))}. Run \`tailor generate\` before executing the script.`)}if(!r){let e=generateScriptSkeleton({getDBImportPath:h,namespace:p});assertGeneratedTypeScript(t,e),X.mkdirSync(n,{recursive:!0}),X.writeFileSync(t,e),m.unshift(t)}let _=[`function`,`run`,q.relative(process.cwd(),t)];e.config!==`tailor.config.ts`&&_.push(`--config=${e.config}`);let v=g??e[`workspace-id`];if(v!==void 0&&_.push(`--workspace-id=${v}`),e.profile!==void 0&&_.push(`--profile=${e.profile}`),y.jsonMode)y.out({script:t,created:m,namespace:p,usesGeneratedDbTypes:d});else{r&&y.info(`Script already exists; refreshed generated types only.`);for(let e of m)y.success(`Created ${w.path(q.relative(process.cwd(),e))}`);y.info(`Next: edit the script, then run ${b({command:`tailor`,args:_})}`)}}});function resolveNamespace(e){let{config:t,explicit:n,sidecarNamespace:r,remote:i}=e,a=Lt(t),o=br(t),s=i?a:o;if(n){if(!i&&!o.includes(n))throw S({code:`SCRIPT_NAMESPACE_REQUIRES_REMOTE`,message:`Namespace "${n}" is not owned by the config and requires --remote.`,command:`function script`});return n}if(r!==void 0){if(!i&&!o.includes(r))throw S({code:`SCRIPT_NAMESPACE_REQUIRES_REMOTE`,message:`Namespace "${r}" is not owned by the config and requires --remote.`,command:`function script`});return r}if(s.length===1){let e=s[0];if(e!==void 0)return e}throw s.length>1?S({code:`TAILORDB_NAMESPACE_REQUIRED`,message:`Multiple TailorDB namespaces are defined (${s.join(`, `)}). Specify one with --namespace.`,command:`function script`}):!i&&a.length>0?S({code:`TAILORDB_NAMESPACE_NOT_CONFIGURED`,message:`No owned TailorDB namespace is defined in the config. External namespaces require --remote: ${a.join(`, `)}.`}):S({code:`TAILORDB_NAMESPACE_NOT_CONFIGURED`,message:`No TailorDB namespace is defined in the config.`})}function resolveKyselyTypesPath(e){let t=Re(e,`@tailor-platform/kysely-type`)?.distPath??`./generated/tailordb.ts`;if(t.length===0)throw S({code:`KYSELY_TYPE_PLUGIN_INVALID`,message:`kyselyTypePlugin is configured without a distPath; cannot locate getDB().`});return q.resolve(t)}function toImportSpecifier(e){let t=e.replace(/\.ts$/,``);return t.startsWith(`.`)?t:`./${t}`}const Xa=K({name:`function`,description:`Manage functions`,subCommands:{get:Or,list:Nr,logs:Wa,run:qa,script:Ya},defaultSubCommand:`list`}),Za=z({name:`generate`,description:`Generate files using Tailor configuration.`,args:J.strictObject({config:G(J.string().default(`tailor.config.ts`),{alias:`c`,description:`Path to SDK config file`})}),run:async e=>{let{initTelemetry:t}=await import(`../telemetry-nqOtDWNO.mjs`);await t(),await Bn({configPath:e.config})}}),detectPackageManager=()=>{let e=[`npm`,`yarn`,`pnpm`,`bun`],t=process.env.npm_config_user_agent;if(!t)return;let[n]=t.split(`/`);if(e.includes(n))return n},Qa=z({name:`init`,description:`Initialize a new project using create-sdk.`,args:J.strictObject({name:G(J.string().optional(),{positional:!0,description:`Project name`}),template:G(J.string().optional(),{alias:`t`,description:`Template name`})}),run:async e=>{let t=await wi(),n=t.version&&t.version!==`0.0.0`?t.version:`latest`,r=detectPackageManager();r||=(y.warn(`Could not detect package manager, defaulting to npm`),`npm`);let i=[`create`,`@tailor-platform/sdk@${n}`,...e.name?[e.name]:[],...r===`npm`?[`--`]:[],...e.template?[`--template`,e.template]:[]];y.log(`Running: ${r} ${i.join(` `)}`);let a=aa(r,i,{stdio:`inherit`}),o={command:r,args:i};if(a.error)throw S({code:`INIT_SPAWN_FAILED`,message:`Failed to run ${r}: ${a.error.message}`,suggestion:`Check that ${r} is installed and executable.`,command:`init`,context:o,cause:a.error});if(a.status!==0)throw S({code:`INIT_FAILED`,message:a.signal===null?`${r} create exited with code ${a.status}.`:`${r} create was terminated by ${a.signal}.`,command:`init`,context:{...o,exitCode:a.status??void 0,signal:a.signal??void 0}})}}),$a=8085,eo=`http://localhost:${$a}/callback`;function randomState(){return Xi.randomBytes(32).toString(`base64url`)}function getProfileUserMismatch(e,t,n){if(e.profile&&e.profileUser&&t!==e.profileUser&&n!==e.profileUser)return{profile:e.profile,oldUser:e.profileUser,authenticatedUser:t,loginMode:e.loginMode??`user`}}function quoteCommandArg(e,t=process.platform){return t===`win32`?/^[A-Za-z0-9_./:@+=,-]+$/.test(e)?e:void 0:`'${e.replaceAll(`'`,`'\\''`)}'`}function profileUpdateCommand(e){let t=quoteCommandArg(e.profile),n=quoteCommandArg(e.authenticatedUser);return t&&n?`tailor profile update --user ${n} -- ${t}`:[`tailor profile update --user <authenticated-user> -- <profile>`,`profile = ${JSON.stringify(e.profile)}`,`authenticated user = ${JSON.stringify(e.authenticatedUser)}`].join(`
94
- `)}function retryInstruction(e){if(e.loginMode===`machine-user`)return`Then retry the original machine-user login command.`;let t=quoteCommandArg(e.profile);return t?`Then run:\n tailor login --profile ${t}`:`Then retry the browser login with the same profile value.`}function profileUserMismatchError(e){let t=profileUpdateCommand(e),n=retryInstruction(e);return S({code:`PROFILE_USER_MISMATCH`,message:`Profile "${e.profile}" is configured for "${e.oldUser}", but login authenticated "${e.authenticatedUser}".`,details:`The authenticated user has been saved.`,suggestion:`To use it with this profile, run:\n ${t}\n${n}`,context:{profile:e.profile,configuredUser:e.oldUser,authenticatedUser:e.authenticatedUser}})}function shouldUpdateCurrentUser(e,t){return!e||ri(t)}const startAuthServer=async(e={})=>{let t=ui(e.platformConfig),n=randomState(),r=await Yi(),i=await t.authorizationCode.getAuthorizeUri({redirectUri:eo,state:n,codeVerifier:r}).catch(e=>{throw S({code:`LOGIN_AUTHORIZATION_URL_FAILED`,message:`Failed to prepare the login authorization URL: ${x(e).message}`,cause:e})});return new Promise((a,o)=>{let handleCallback=async(i,l)=>{try{if(!i.url?.startsWith(`/callback`))throw S({code:`LOGIN_CALLBACK_INVALID`,message:`Invalid callback URL`});let o=`http://${i.headers.host}${i.url}`,c=new URL(o).searchParams.get(`code`);c&&y.registerSecret(c);let u=await t.authorizationCode.getTokenFromCodeRedirect(o,{redirectUri:eo,state:n,codeVerifier:r});$e({accessToken:u.accessToken,refreshToken:u.refreshToken??void 0});let d=await mi(u.accessToken,e.platformConfig),f=await F();await rr(f,d.sub,{accessToken:u.accessToken,refreshToken:u.refreshToken??void 0},new Date(s(u.expiresAt,`token response missing expiresAt`)).toISOString(),{platformConfig:e.platformConfig,email:d.email});let p=getProfileUserMismatch(e,d.email,d.sub);if(p)throw I(f),profileUserMismatchError(p);(e.updateCurrentUser??!0)&&(f.current_user=d.sub),await T(f,d.email,d.sub,e.platformConfig),I(f),sendCallbackSuccess(l,`Authentication successful`),a({user:d.sub,email:d.email})}catch(e){sendCallbackFailure(l,401,`Authentication failed`,e),o(x(e))}finally{c.close()}},c=$i.createServer((e,t)=>void handleCallback(e,t)),l=setTimeout(()=>{c.close(),o(S({code:`LOGIN_TIMEOUT`,message:`Login timeout exceeded`}))},3e5);c.on(`close`,()=>{clearTimeout(l)}),c.on(`error`,e=>{o(e)});let openBrowser=async()=>{y.info(`Opening browser for login:\n\n${i}\n`);try{await ea(i)}catch{y.warn(`Failed to open browser automatically. Please open the URL above manually.`)}};c.listen($a,()=>void openBrowser())})},to=`TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET`;async function loginAsMachineUser(e){let t=e.clientSecret??await R.password({message:`Client secret`,suggestion:`Set ${to} or pass --client-secret.`}),n=await li(e.clientId,t,e.platformConfig),r=await F();await rr(r,e.clientId,{accessToken:n.accessToken},new Date(s(n.expiresAt,`token response missing expiresAt`)).toISOString(),{platformConfig:e.platformConfig});let i=getProfileUserMismatch(e,e.clientId);if(i)throw I(r),profileUserMismatchError(i);return(e.updateCurrentUser??!0)&&(r.current_user=e.clientId),I(r),{user:e.clientId,email:null}}const no=z({name:`login`,description:`Login to Tailor Platform.`,args:J.xor([J.strictObject({profile:G(J.string().optional(),{alias:`p`,description:`Workspace profile whose platform settings should be used for login.`,env:`TAILOR_PLATFORM_PROFILE`})}).describe(`User Login`),J.strictObject({"machine-user":G(J.literal(!0),{description:`Login as a platform machine user.`,required:!0}),"client-id":G(J.string(),{description:`Client ID`,env:`TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID`,required:!0}),"client-secret":G(J.string().optional(),{description:`Client secret`,env:to}),profile:G(J.string().optional(),{alias:`p`,description:`Workspace profile whose platform settings should be used for login.`,env:`TAILOR_PLATFORM_PROFILE`})}).describe(`Machine User Login`)]),run:async e=>{try{let t,n;if(`profile`in e&&e.profile){let r=(await F()).profiles[e.profile];if(!r)throw v(e.profile);t=At(r),n=r.user}let r=shouldUpdateCurrentUser(e.profile,t),i;i=`machine-user`in e?await loginAsMachineUser({clientId:e.clientId,clientSecret:e.clientSecret,profile:e.profile,profileUser:n,platformConfig:t,updateCurrentUser:r,loginMode:`machine-user`}):await startAuthServer({profile:e.profile,profileUser:n,platformConfig:t,updateCurrentUser:r,loginMode:`user`}),y.success(`Successfully logged in to Tailor Platform.`),N({changed:!0,...i})}finally{await ni()}}}),ro=z({name:`logout`,description:`Logout from Tailor Platform.`,args:J.strictObject({profile:G(J.string().optional(),{alias:`p`,description:`Workspace profile whose platform settings should be used for logout.`,env:`TAILOR_PLATFORM_PROFILE`})}),run:async e=>{await Sn(()=>logout(e.profile||process.env.TAILOR_PLATFORM_PROFILE))}});async function logout(e){let t=await F(),n=e?t.profiles[e]:void 0;if(e&&!n)throw v(e);let r=n?At(n):void 0,i=n?n.user:t.current_user,a=ri(r),o=e?{allowLegacyUserKey:!0}:void 0;if(!i){y.info(`You are not logged in.`),N({changed:!1,user:null,revoked:!1});return}let hasDefaultUserToken=()=>re(t,i,{platformUrl:hi}),shouldClearCurrentUser=()=>t.current_user===i&&(a||!Fr(t,i))&&!hasDefaultUserToken(),s,c=!1;try{s=await er(t,i,r,o)}catch(e){c=!0,y.warn(`Failed to revoke token: ${e instanceof Error?e.message:e}`)}if(!s&&!c){y.info(`You are not logged in.`);let e=shouldClearCurrentUser();e&&(t.current_user=null),I(t),N({changed:e,user:i,revoked:!1});return}let l=!1;if(s)try{let e=ui(r),t=s.refreshToken?`refresh_token`:`access_token`;await e.revoke({accessToken:s.accessToken,refreshToken:s.refreshToken??null,expiresAt:Date.parse(s.userEntry.token_expires_at)},t),l=!0}catch(e){y.warn(`Failed to revoke token: ${e instanceof Error?e.message:e}`)}await Be(t,i,r,o),shouldClearCurrentUser()&&(t.current_user=null),I(t),y.success(`Successfully logged out from Tailor Platform.`),N({changed:!0,user:i,revoked:l})}const io=K({name:`machineuser`,description:`Manage machine users in your Tailor Platform application.`,subCommands:{list:fn,token:tn},defaultSubCommand:`list`}),ao=K({name:`oauth2client`,description:`Manage OAuth2 clients in your Tailor Platform application.`,subCommands:{list:Xn,get:Zt},defaultSubCommand:`list`}),oo=z({name:`open`,description:`Open Tailor Platform Console.`,args:J.strictObject({...B}),run:async e=>{let t=await Me({workspaceId:e[`workspace-id`],profile:e.profile}),{config:n}=await j(e.config),r=n.name,i=`/workspaces/${t}/services/applications/${encodeURIComponent(r)}`,a=await Ct({profile:e.profile,...e[`workspace-id`]===void 0?{}:{allowMissingProfile:!0}}),o=new URL(i,a).toString(),s=y.jsonMode;y.info(`Opening Tailor Platform Console...`);let c=!0;try{await ea(o)}catch{c=!1}s?y.out({consoleUrl:o,workspaceId:t,applicationName:r,opened:c}):c?(y.out(`Console URL: ${o}`),y.out(`Workspace ID: ${t}`),y.out(`Application Name: ${r}`)):y.warn(`Failed to open browser automatically. Please open this URL manually:\n${o}`)}}),so=K({name:`folder`,description:`Manage organization folders.`,subCommands:{create:Tn,delete:Kn,get:sn,list:Qe,update:Dt}}),co=K({name:`organization`,description:`Manage Tailor Platform organizations.`,subCommands:{folder:so,get:je,list:Fe,tree:xe,update:Te},defaultSubCommand:`list`}),lo=/* @__PURE__ */ `api.auth.authconnection.crashreport.data.deploy.executor.function.generate.init.login.logout.machineuser.oauth2client.open.organization.plugin.profile.query.remove.secret.show.skills.staticwebsite.tailordb.upgrade.user.workflow.workspace`.split(`.`),uo={seed:`@tailor-platform/sdk-plugin-seed`,setup:`@tailor-platform/sdk-plugin-setup`,"tailordb-erd":`@tailor-platform/sdk-plugin-tailordb-erd`},fo=process.platform===`win32`?`;`:`:`;function*ancestorDirs(e){let t=q.resolve(e),n=q.dirname(t);for(;n!==t;)yield t,t=n,n=q.dirname(t);yield t}function windowsExecutableExts(){return(process.env.PATHEXT??`.COM;.EXE;.BAT;.CMD;.PS1`).split(`;`).map(e=>e.trim().toLowerCase()).filter(Boolean)}function isExecutable(e){try{Gi(e,process.platform===`win32`?Ki.F_OK:Ki.X_OK)}catch{return!1}if(process.platform===`win32`){let t=q.extname(e).toLowerCase();return t===``||windowsExecutableExts().includes(t)}return!0}function binaryCandidates(e){return process.platform===`win32`?[e,...windowsExecutableExts().map(t=>`${e}${t}`)]:[e]}function pathDirs(){return(process.env.PATH??``).split(fo).filter(Boolean)}function nodeModulesBinDirs(){let e=[];for(let t of ancestorDirs(process.cwd()))e.push(q.join(t,`node_modules`,`.bin`));return e}function findExecutableIn(e,t){let n=binaryCandidates(t);for(let t of e)for(let e of n){let n=q.join(t,e);if(isExecutable(n))return n}}function resolvePlugin(e,t){if(e.includes(`/`)||e.includes(`\\`)||e.includes(`\0`))return null;let n=`${t}-${e}`,r=findExecutableIn(nodeModulesBinDirs(),n);if(r)return{name:e,path:r,source:`node_modules`};let i=findExecutableIn(pathDirs(),n);return i?{name:e,path:i,source:`path`}:null}function stripBinExt(e){if(process.platform!==`win32`)return e;let t=q.extname(e);return t?e.slice(0,-t.length):e}function listPlugins(e){let t=`${e}-`,n=/* @__PURE__ */ new Map,scan=(e,r)=>{for(let i of e){let e;try{e=qi(i)}catch{continue}for(let a of e){let e=stripBinExt(a);if(!e.startsWith(t)||e.length===t.length)continue;let o=e.slice(t.length);if(n.has(o))continue;let s=q.join(i,a);isExecutable(s)&&n.set(o,{name:o,path:s,source:r})}}};return scan(nodeModulesBinDirs(),`node_modules`),scan(pathDirs(),`path`),[...n.values()]}async function resolveActiveUser(e){let t=await F(),n=e?t.profiles[e]?.user:t.current_user;if(n)return t.users[n]?.email??n}async function buildPluginEnv(e={}){let{profile:t}=e,n={},r=process.argv[1];r&&(n.TAILOR_BIN=r);try{let{version:e}=await wi();e&&(n.TAILOR_VERSION=e)}catch{}let i=mt();if(i&&(n.TAILOR_CONFIG_PATH=i),e.skipPlatformContext)return n;let a;try{a=await Ie({profile:t,allowMissingProfile:!0})}catch{}n.TAILOR_PLATFORM_URL=ti(a),n.TAILOR_PLATFORM_OAUTH2_CLIENT_ID=ai(a);try{n.TAILOR_PLATFORM_WORKSPACE_ID=await Me({profile:t})}catch{}try{let e=await resolveActiveUser(t);e&&(n.TAILOR_PLATFORM_USER=e)}catch{}try{let e=await yt({profile:t});e&&(n.TAILOR_PLATFORM_TOKEN=e)}catch{}return n}function signalToExitCode(e){let t=Qi.constants.signals[e];return typeof t==`number`?128+t:1}function buildSpawnTarget(e,t){if(process.platform!==`win32`)return{command:e,args:[...t],shell:!1};let n=q.extname(e).toLowerCase();return n===`.exe`||n===`.com`?{command:e,args:[...t],shell:!1}:n===`.cmd`||n===`.bat`?{command:e,args:[...t],shell:!0}:n===`.ps1`?{command:findExecutableIn(pathDirs(),`pwsh`)??findExecutableIn(pathDirs(),`powershell`)??`powershell`,args:[`-NoProfile`,`-ExecutionPolicy`,`Bypass`,`-File`,e,...t],shell:!1}:{command:findExecutableIn(pathDirs(),`sh`)??`sh`,args:[`-c`,`command "$@"`,`--`,e,...t],shell:!1}}function hasEnvFileFlag(e){for(let t of e){if(t===`--`)return!1;if(t===`--env-file`||t===`-e`||t===`--env-file-if-exists`||t.startsWith(`--env-file=`)||t.startsWith(`-e=`)||t.startsWith(`--env-file-if-exists=`))return!0}return!1}function explicitProfileFromArgs(e){let t;for(let n=0;n<e.length;n++){let r=e[n];if(r===void 0||r===`--`)break;if(r===`--profile`||r===`-p`){let r=e[n+1];r!==void 0&&!r.startsWith(`-`)&&(t=r,n++)}else r.startsWith(`--profile=`)?t=r.slice(10):r.startsWith(`-p=`)&&(t=r.slice(3))}return t||void 0}function pluginSlug(e,t){return[...e??[],t].join(`-`)}async function dispatchPlugin(e){let t=pluginSlug(e.commandPath,e.name),n=resolvePlugin(t,e.cliName);if(!n)return;let r=explicitProfileFromArgs(e.args)??e.profile,i={...process.env,...await buildPluginEnv({profile:r,skipPlatformContext:hasEnvFileFlag(e.args)})},{command:a,args:o,shell:s}=buildSpawnTarget(n.path,e.args);return await new Promise(n=>{let r=ia(a,o,{stdio:`inherit`,env:i,shell:s});r.on(`error`,r=>{y.error(`Failed to run plugin "${e.cliName}-${t}": ${r.message}`),n(1)}),r.on(`close`,(e,t)=>{n(t?signalToExitCode(t):e??0)})})}async function dispatchPluginWithInstallHint(e){let t=await dispatchPlugin(e);if(t!==void 0)return t;let n=uo[pluginSlug(e.commandPath,e.name)];if(!n)return;let r=[e.cliName,...e.commandPath??[],e.name].join(` `);return y.error(`"${r}" is provided by the ${n} CLI plugin, which is not installed.`),y.info(`Install it with: npm install -D ${n}`),1}const po=z({name:`list`,description:"List discovered plugins (executables named `<cli>-<name>` on PATH or node_modules/.bin).",args:J.strictObject({}),run:async()=>{let e=await wi(),t=Object.keys(e.bin??{})[0]||`tailor`,n=new Set(lo),r=listPlugins(t);if(r.length===0){y.info(W`
91
+ `)}`)}catch{m.log(` ${b.result}`)}}if(b.error&&!b.success){m.log(s.bold(`
92
+ Error:`));let e=formatErrorWithSourcemap(b.error,f,process.cwd());e?m.log(e):m.log(` ${s.error(b.error)}`)}}b.success||process.exit(1)}}),go=new Set(ra(J.strictObject(ye)).fields.filter(e=>e.type!==`boolean`).flatMap(ee));function invokedViaTestRunAlias(e){let t=[];for(let n=2;n<e.length&&t.length<2;n++){let r=e[n];if(r===void 0||r===`--`)break;r.startsWith(`-`)?!r.includes(`=`)&&go.has(r)&&n++:t.push(r)}return t[0]===`function`&&t[1]===`test-run`}function resolveAuthNamespace(e){if(e?.name)return e.name;throw _({code:`AUTH_CONFIG_REQUIRED`,message:`Auth namespace is required.`,suggestion:`Ensure tailor.config.ts has an auth config.`})}async function resolveMachineUserName(e){let{cliMachineUser:n,cliMachineUserSource:r,profile:i,authConfig:a}=e,o=await be({machineUser:n,machineUserSource:r,profile:i});if(o)return o;if(a&&!(`external`in a&&a.external)){let e=a.machineUsers;if(e){let n=Object.keys(e);if(n.length>0)return t(n[0],`machine user key missing`)}}throw _({code:`MACHINE_USER_REQUIRED`,message:`Machine user is required.`,suggestion:`Provide --machine-user, set TAILOR_PLATFORM_MACHINE_USER_NAME, set a profile default with 'tailor profile update <profile> --machine-user <name>', or ensure tailor.config.ts has machine users configured.`})}async function resolveMachineUser(e){let{client:t,workspaceId:n,authNamespace:r,machineUserName:i,authConfig:a}=e,o=`00000000-0000-0000-0000-000000000000`;try{let{machineUser:e}=await t.getAuthMachineUser({workspaceId:n,authNamespace:r,name:i});e?.id&&(o=e.id)}catch{m.debug(`Could not fetch machine user "${i}" from server, using nil UUID`)}let s=a?.machineUsers?.[i],c=null,l=[];if(s&&typeof s==`object`){let e=s;c=e.attributes??null,l=e.attributeList??[]}return{name:i,id:o,attributes:c,attributeList:l}}const _o=I({name:`script`,description:"Scaffold a one-off script to run with `function run`.",args:J.object({...A,...te,file:G(J.string(),{positional:!0,description:`Path to create the script at (must end with .ts)`}),namespace:G(J.string().optional(),{description:`Target TailorDB namespace (required when the config does not pin one)`}),remote:G(J.boolean().default(!1),{description:`Generate script-scoped DB types from the deployed schema`})}),notes:"The scaffolded script is a plain default-exported function; execute it with `tailor function run <file>`.\n\nBy default, when the project configures `kyselyTypePlugin`, the skeleton imports `getDB()` from the plugin's generated types. Without the plugin, the command uses the namespace's local table definitions to write a script-scoped `db.ts` plus a `db.snapshot.json` next to the script; `function run` refuses to run the script when that snapshot no longer matches the deployed or locally defined table and field structure.\n\nPass `--remote` to generate the script-scoped files from the deployed schema instead, even when `kyselyTypePlugin` is configured. This is required for an external namespace. Re-running the command refreshes `db.ts` and `db.snapshot.json` from the selected source and leaves the script itself untouched.",examples:[{cmd:`scripts/fix-prices.ts`,desc:`Scaffold a one-off script (single-namespace project)`},{cmd:`scripts/fix-prices.ts --namespace tailordb`,desc:`Scaffold a script targeting a specific namespace`},{cmd:`scripts/fix-prices.ts --namespace shared --remote`,desc:`Scaffold from a deployed or external namespace`}],run:async e=>{let n=q.resolve(e.file);if(!n.endsWith(`.ts`))throw _({code:`SCRIPT_PATH_INVALID`,message:`Script path must end with .ts: ${e.file}`,command:`function script`});let r=q.dirname(n),i=X.existsSync(n),a=q.join(r,po),o=q.join(r,mo);if(n===a)throw _({code:`SCRIPT_PATH_INVALID`,message:`${po} is reserved for the generated Kysely types written next to the script. Choose a different script file name.`,command:`function script`});let{config:c,plugins:l}=await R(e.config),u=l.find(e=>e.id===na),d=X.existsSync(o);if(e.remote&&u!==void 0&&i&&!d)throw _({code:`SCRIPT_EXISTS`,message:`Script already exists: ${q.relative(process.cwd(),n)}.`,suggestion:`Scaffold --remote at a new path so the generated script imports its script-scoped db.ts.`});let f=e.remote||u===void 0||d,p;if(f)try{p=loadScriptSchemaSnapshot(n)?.snapshot.namespace}catch{}let g=resolveNamespace({config:c,explicit:e.namespace,sidecarNamespace:p,remote:e.remote});if(p!==void 0&&p!==g)throw _({code:`SCRIPT_NAMESPACE_MISMATCH`,message:`This directory's generated types target namespace "${p}" (${mo}).`,suggestion:`Scaffold scripts for namespace "${g}" in a separate directory.`});let v=[],y,b;if(f){let n;if(e.remote){let{client:t,workspaceId:r}=await B({profile:e.profile,workspaceId:e[`workspace-id`]});b=r,m.info(`Fetching deployed schema of namespace ${s.bold(g)}...`),n=await Kt(t,r,g)}else{m.info(`Loading local definitions of namespace ${s.bold(g)}...`);let{namespaces:r}=await at({configPath:e.config,namespaces:[g]}),i=t(r[0],`namespace ${g}`);n=Rt(i.tables,g)}if(Object.keys(n.tables).length===0){let n=e.remote?`deployed tables in workspace ${t(b,`workspace ID`)}`:`locally defined tables`;throw _({code:`SCRIPT_SCHEMA_NOT_FOUND`,message:`Namespace "${g}" has no ${n}.`})}if(X.existsSync(a)&&!isGeneratedScriptDbTypes(X.readFileSync(a,`utf-8`)))throw _({code:`GENERATED_TYPES_NOT_OWNED`,message:`Refusing to overwrite ${q.relative(process.cwd(),a)}: it was not generated by \`tailor function script\`.`});let i=generateScriptDbTypes(n,xt(l,`@tailor-platform/kysely-type`)?.temporal??!1);assertGeneratedTypeScript(a,i),X.mkdirSync(r,{recursive:!0}),X.writeFileSync(a,i),v.push(a),X.writeFileSync(o,JSON.stringify({...n,source:e.remote?`remote`:`local`},null,2)+`
93
+ `),v.push(o),y=`./db`}else{if(i)throw _({code:`SCRIPT_EXISTS`,message:`Script already exists: ${q.relative(process.cwd(),n)}.`,suggestion:`It imports the project's generated Kysely types, so there is nothing to refresh.`});let e=resolveKyselyTypesPath(l);y=toImportSpecifier(q.relative(r,e)),X.existsSync(e)||m.warn(`Generated Kysely types not found at ${s.path(q.relative(process.cwd(),e))}. Run \`tailor generate\` before executing the script.`)}if(!i){let e=generateScriptSkeleton({getDBImportPath:y,namespace:g});assertGeneratedTypeScript(n,e),X.mkdirSync(r,{recursive:!0}),X.writeFileSync(n,e),v.unshift(n)}let x=[`function`,`run`,q.relative(process.cwd(),n)];e.config!==`tailor.config.ts`&&x.push(`--config=${e.config}`);let S=b??e[`workspace-id`];if(S!==void 0&&x.push(`--workspace-id=${S}`),e.profile!==void 0&&x.push(`--profile=${e.profile}`),m.jsonMode)m.out({script:n,created:v,namespace:g,usesGeneratedDbTypes:f});else{i&&m.info(`Script already exists; refreshed generated types only.`);for(let e of v)m.success(`Created ${s.path(q.relative(process.cwd(),e))}`);m.info(`Next: edit the script, then run ${h({command:`tailor`,args:x})}`)}}});function resolveNamespace(e){let{config:t,explicit:n,sidecarNamespace:r,remote:i}=e,a=bn(t),o=Nr(t),s=i?a:o;if(n){if(!i&&!o.includes(n))throw _({code:`SCRIPT_NAMESPACE_REQUIRES_REMOTE`,message:`Namespace "${n}" is not owned by the config and requires --remote.`,command:`function script`});return n}if(r!==void 0){if(!i&&!o.includes(r))throw _({code:`SCRIPT_NAMESPACE_REQUIRES_REMOTE`,message:`Namespace "${r}" is not owned by the config and requires --remote.`,command:`function script`});return r}if(s.length===1){let e=s[0];if(e!==void 0)return e}throw s.length>1?_({code:`TAILORDB_NAMESPACE_REQUIRED`,message:`Multiple TailorDB namespaces are defined (${s.join(`, `)}). Specify one with --namespace.`,command:`function script`}):!i&&a.length>0?_({code:`TAILORDB_NAMESPACE_NOT_CONFIGURED`,message:`No owned TailorDB namespace is defined in the config. External namespaces require --remote: ${a.join(`, `)}.`}):_({code:`TAILORDB_NAMESPACE_NOT_CONFIGURED`,message:`No TailorDB namespace is defined in the config.`})}function resolveKyselyTypesPath(e){let t=xt(e,`@tailor-platform/kysely-type`)?.distPath??`./generated/tailordb.ts`;if(t.length===0)throw _({code:`KYSELY_TYPE_PLUGIN_INVALID`,message:`kyselyTypePlugin is configured without a distPath; cannot locate getDB().`});return q.resolve(t)}function toImportSpecifier(e){let t=e.replace(/\.ts$/,``);return t.startsWith(`.`)?t:`./${t}`}const vo=K({name:`function`,description:`Manage functions`,subCommands:{get:Vr,list:Wr,logs:fo,run:ho,script:_o},defaultSubCommand:`list`}),yo=I({name:`generate`,description:`Generate files using Tailor configuration.`,args:J.strictObject({...te}),run:async e=>{let{initTelemetry:t}=await import(`../telemetry-nqOtDWNO.mjs`);await t(),await cr({configPath:e.config})}}),detectPackageManager=()=>{let e=[`npm`,`yarn`,`pnpm`,`bun`],t=process.env.npm_config_user_agent;if(!t)return;let[n]=t.split(`/`);if(e.includes(n))return n},bo=I({name:`init`,description:`Initialize a new project using create-sdk.`,args:J.strictObject({name:G(J.string().optional(),{positional:!0,description:`Project name`}),template:G(J.string().optional(),{alias:`t`,description:`Template name`})}),run:async e=>{let t=await zi(),n=t.version&&t.version!==`0.0.0`?t.version:`latest`,r=detectPackageManager();r||=(m.warn(`Could not detect package manager, defaulting to npm`),`npm`);let i=[`create`,`@tailor-platform/sdk@${n}`,...e.name?[e.name]:[],...r===`npm`?[`--`]:[],...e.template?[`--template`,e.template]:[]];m.log(`Running: ${r} ${i.join(` `)}`);let a=Ea(r,i,{stdio:`inherit`}),o={command:r,args:i};if(a.error)throw _({code:`INIT_SPAWN_FAILED`,message:`Failed to run ${r}: ${a.error.message}`,suggestion:`Check that ${r} is installed and executable.`,command:`init`,context:o,cause:a.error});if(a.status!==0)throw _({code:`INIT_FAILED`,message:a.signal===null?`${r} create exited with code ${a.status}.`:`${r} create was terminated by ${a.signal}.`,command:`init`,context:{...o,exitCode:a.status??void 0,signal:a.signal??void 0}})}}),xo=8085,So=`http://localhost:${xo}/callback`;function randomState(){return _a.randomBytes(32).toString(`base64url`)}function getProfileUserMismatch(e,t,n){if(e.profile&&e.profileUser&&t!==e.profileUser&&n!==e.profileUser)return{profile:e.profile,oldUser:e.profileUser,authenticatedUser:t,loginMode:e.loginMode??`user`}}function quoteCommandArg(e,t=process.platform){return t===`win32`?/^[A-Za-z0-9_./:@+=,-]+$/.test(e)?e:void 0:`'${e.replaceAll(`'`,`'\\''`)}'`}function profileUpdateCommand(e){let t=quoteCommandArg(e.profile),n=quoteCommandArg(e.authenticatedUser);return t&&n?`tailor profile update --user ${n} -- ${t}`:[`tailor profile update --user <authenticated-user> -- <profile>`,`profile = ${JSON.stringify(e.profile)}`,`authenticated user = ${JSON.stringify(e.authenticatedUser)}`].join(`
94
+ `)}function retryInstruction(e){if(e.loginMode===`machine-user`)return`Then retry the original machine-user login command.`;let t=quoteCommandArg(e.profile);return t?`Then run:\n tailor login --profile ${t}`:`Then retry the browser login with the same profile value.`}function profileUserMismatchError(e){let t=profileUpdateCommand(e),n=retryInstruction(e);return _({code:`PROFILE_USER_MISMATCH`,message:`Profile "${e.profile}" is configured for "${e.oldUser}", but login authenticated "${e.authenticatedUser}".`,details:`The authenticated user has been saved.`,suggestion:`To use it with this profile, run:\n ${t}\n${n}`,context:{profile:e.profile,configuredUser:e.oldUser,authenticatedUser:e.authenticatedUser}})}function shouldUpdateCurrentUser(e,t){return!e||Ei(t)}const startAuthServer=async(e={})=>{let n=ki(e.platformConfig),r=randomState(),i=await ga(),a=await n.authorizationCode.getAuthorizeUri({redirectUri:So,state:r,codeVerifier:i}).catch(e=>{throw _({code:`LOGIN_AUTHORIZATION_URL_FAILED`,message:`Failed to prepare the login authorization URL: ${g(e).message}`,cause:e})});return new Promise((o,s)=>{let handleCallback=async(a,l)=>{try{if(!a.url?.startsWith(`/callback`))throw _({code:`LOGIN_CALLBACK_INVALID`,message:`Invalid callback URL`});let s=`http://${a.headers.host}${a.url}`,c=new URL(s).searchParams.get(`code`);c&&m.registerSecret(c);let u=await n.authorizationCode.getTokenFromCodeRedirect(s,{redirectUri:So,state:r,codeVerifier:i});Ne({accessToken:u.accessToken,refreshToken:u.refreshToken??void 0});let d=await Ai(u.accessToken,e.platformConfig),f=await j();await re(f,d.sub,{accessToken:u.accessToken,refreshToken:u.refreshToken??void 0},new Date(t(u.expiresAt,`token response missing expiresAt`)).toISOString(),{platformConfig:e.platformConfig,email:d.email});let p=getProfileUserMismatch(e,d.email,d.sub);if(p)throw O(f),profileUserMismatchError(p);(e.updateCurrentUser??!0)&&(f.current_user=d.sub),await fe(f,d.email,d.sub,e.platformConfig),O(f),sendCallbackSuccess(l,`Authentication successful`),o({user:d.sub,email:d.email})}catch(e){sendCallbackFailure(l,401,`Authentication failed`,e),s(g(e))}finally{c.close()}},c=ba.createServer((e,t)=>void handleCallback(e,t)),l=setTimeout(()=>{c.close(),s(_({code:`LOGIN_TIMEOUT`,message:`Login timeout exceeded`}))},3e5);c.on(`close`,()=>{clearTimeout(l)}),c.on(`error`,e=>{s(e)});let openBrowser=async()=>{m.info(`Opening browser for login:\n\n${a}\n`);try{await xa(a)}catch{m.warn(`Failed to open browser automatically. Please open the URL above manually.`)}};c.listen(xo,()=>void openBrowser())})},Co=`TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET`;async function loginAsMachineUser(e){let n=e.clientSecret??await P.password({message:`Client secret`,suggestion:`Set ${Co} or pass --client-secret.`}),r=await Ni(e.clientId,n,e.platformConfig),i=await j();await re(i,e.clientId,{accessToken:r.accessToken},new Date(t(r.expiresAt,`token response missing expiresAt`)).toISOString(),{platformConfig:e.platformConfig});let a=getProfileUserMismatch(e,e.clientId);if(a)throw O(i),profileUserMismatchError(a);return(e.updateCurrentUser??!0)&&(i.current_user=e.clientId),O(i),{user:e.clientId,email:null}}const wo=I({name:`login`,description:`Login to Tailor Platform.`,args:J.xor([J.strictObject({profile:G(J.string().optional(),{alias:`p`,description:`Workspace profile whose platform settings should be used for login.`,env:`TAILOR_PLATFORM_PROFILE`})}).describe(`User Login`),J.strictObject({"machine-user":G(J.literal(!0),{description:`Login as a platform machine user.`,required:!0}),"client-id":G(J.string(),{description:`Client ID`,env:`TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID`,required:!0}),"client-secret":G(J.string().optional(),{description:`Client secret`,env:Co}),profile:G(J.string().optional(),{alias:`p`,description:`Workspace profile whose platform settings should be used for login.`,env:`TAILOR_PLATFORM_PROFILE`})}).describe(`Machine User Login`)]),run:async e=>{try{let t,n;if(`profile`in e&&e.profile){let r=(await j()).profiles[e.profile];if(!r)throw p(e.profile);t=ge(r),n=r.user}let r=shouldUpdateCurrentUser(e.profile,t),i;i=`machine-user`in e?await loginAsMachineUser({clientId:e.clientId,clientSecret:e.clientSecret,profile:e.profile,profileUser:n,platformConfig:t,updateCurrentUser:r,loginMode:`machine-user`}):await startAuthServer({profile:e.profile,profileUser:n,platformConfig:t,updateCurrentUser:r,loginMode:`user`}),m.success(`Successfully logged in to Tailor Platform.`),N({changed:!0,...i})}finally{await ji()}}}),To=I({name:`logout`,description:`Logout from Tailor Platform.`,args:J.strictObject({profile:G(J.string().optional(),{alias:`p`,description:`Workspace profile whose platform settings should be used for logout.`,env:`TAILOR_PLATFORM_PROFILE`})}),run:async e=>{await C(()=>logout(e.profile||process.env.TAILOR_PLATFORM_PROFILE))}});async function logout(e){let t=await j(),n=e?t.profiles[e]:void 0;if(e&&!n)throw p(e);let r=n?ge(n):void 0,i=n?n.user:t.current_user,a=Ei(r),o=e?{allowLegacyUserKey:!0}:void 0;if(!i){m.info(`You are not logged in.`),N({changed:!1,user:null,revoked:!1});return}let hasDefaultUserToken=()=>_e(t,i,{platformUrl:Ii}),shouldClearCurrentUser=()=>t.current_user===i&&(a||!Te(t,i))&&!hasDefaultUserToken(),s,c=!1;try{s=await he(t,i,r,o)}catch(e){c=!0,m.warn(`Failed to revoke token: ${e instanceof Error?e.message:e}`)}if(!s&&!c){m.info(`You are not logged in.`);let e=shouldClearCurrentUser();e&&(t.current_user=null),O(t),N({changed:e,user:i,revoked:!1});return}let l=!1;if(s)try{let e=ki(r),t=s.refreshToken?`refresh_token`:`access_token`;await e.revoke({accessToken:s.accessToken,refreshToken:s.refreshToken??null,expiresAt:Date.parse(s.userEntry.token_expires_at)},t),l=!0}catch(e){m.warn(`Failed to revoke token: ${e instanceof Error?e.message:e}`)}await Oe(t,i,r,o),shouldClearCurrentUser()&&(t.current_user=null),O(t),m.success(`Successfully logged out from Tailor Platform.`),N({changed:!0,user:i,revoked:l})}const Eo=K({name:`machineuser`,description:`Manage machine users in your Tailor Platform application.`,subCommands:{list:Bn,token:Nn},defaultSubCommand:`list`});async function createNotificationClient(e){let t=await ue({profile:e});return await Di(t)}function notificationNotFound(e,t){let n=e.map(e=>`"${e}"`).join(`, `);throw _({code:`NOTIFICATION_NOT_FOUND`,message:e.length===1?`Notification ${n} not found.`:`Notifications ${n} not found.`,details:e.length===1?`It is not addressed to you, or it has expired, been revoked, or been dismissed.`:`They are not addressed to you, or they have expired, been revoked, or been dismissed.`,cause:t})}function isNotificationNotFound(e){return e instanceof Q&&e.code===Z.NotFound}function rethrowNotificationError(e,t){throw isNotificationNotFound(t)&&notificationNotFound([e],t),t}const Do=I({name:`dismiss`,description:`Remove a notification from your inbox.`,args:J.strictObject({id:G(J.uuid(),{positional:!0,description:`Notification ID`}),profile:A.profile}),run:async e=>{await L({profile:e.profile});let t=await createNotificationClient(e.profile);try{await t.dismissMyNotification({notificationId:e.id})}catch(t){rethrowNotificationError(e.id,t)}m.success(`Notification "${e.id}" dismissed.`),N({changed:!0,id:e.id})}}),Oo={[W.UNSPECIFIED]:`unknown`,[W.INFO]:`info`,[W.WARNING]:`warning`,[W.CRITICAL]:`critical`},ko={[U.UNSPECIFIED]:`unknown`,[U.ALERT]:`alert`,[U.INCIDENT]:`incident`,[U.MAINTENANCE]:`maintenance`,[U.ANNOUNCEMENT]:`announcement`};function severityLabel(e){return Un(Oo,e,`unknown`)}function categoryLabel(e){return Un(ko,e,`unknown`)}function scopeRefLabel(e){switch(e.ref.case){case`workspaceId`:return`workspace:${e.ref.value}`;case`organizationId`:return`organization:${e.ref.value}`;case`region`:return`region:${y(e.ref.value)}`;default:return}}function transformNotification(e){return{id:e.id,severity:severityLabel(e.severity),category:categoryLabel(e.category),title:y(e.title),scopes:e.scopeRefs.map(scopeRefLabel).filter(e=>e!==void 0),arrivedAt:jn(e.arrivedAt),readAt:jn(e.readAt),expiresAt:jn(e.expiresAt)}}function transformNotificationDetail(e){return{...transformNotification(e),bodyMarkdown:a(e.bodyMarkdown),actions:e.actions.map(e=>({label:y(e.label),url:y(e.url)}))}}const Ao={alert:U.ALERT,incident:U.INCIDENT,maintenance:U.MAINTENANCE,announcement:U.ANNOUNCEMENT},jo={info:W.INFO,warning:W.WARNING,critical:W.CRITICAL},Mo=Object.keys(Ao),No=Object.keys(jo),Po=I({name:`list`,description:`List the notifications in your inbox.`,args:J.strictObject({...se,profile:A.profile,category:G(J.enum(Mo).optional(),{description:`Only this category (${Mo.join(`, `)})`}),severity:G(J.enum(No).optional(),{description:`Only this severity or higher (${No.join(`, `)})`}),unread:G(J.boolean().default(!1),{description:`Only unread notifications`}),"scope-workspace":G(J.uuid().optional(),{description:`Only notifications about this workspace ID`}),"scope-organization":G(J.uuid().optional(),{description:`Only notifications about this organization ID`})}),run:async e=>{let t=m.jsonMode,n=await createNotificationClient(e.profile),r=we(e.order),i=e.category?Ao[e.category]:U.UNSPECIFIED,a=e.severity?jo[e.severity]:W.UNSPECIFIED,o=await rn(e.limit,t=>Pi(async(t,o)=>{let{notifications:s,nextPageToken:c}=await n.listMyNotifications({pageToken:t,pageSize:o,pageDirection:r,category:i,minSeverity:a,unreadOnly:e.unread,scopeWorkspaceId:e[`scope-workspace`]??``,scopeOrganizationId:e[`scope-organization`]??``});return[s,c]},{limit:t}));if(o.items.length===0&&(m.info(`No notifications.`),!t))return;let s=o.items.map(transformNotification);m.out(s,{display:{scopes:null,expiresAt:null,arrivedAt:e=>Rn(e),readAt:e=>e===null?`unread`:Rn(e)}}),await M(o,e.limit)}});function isConsolePath(e){return e.startsWith(`/`)&&!e.startsWith(`//`)}async function resolveActionUrls(e,t){if(!e.some(e=>e.actions.some(e=>isConsolePath(e.url))))return e;let n=await pe({profile:t,allowMissingProfile:!0});return e.map(e=>({...e,actions:e.actions.map(e=>isConsolePath(e.url)?{...e,url:new URL(e.url,n).toString()}:e)}))}function formatDetail(e){let t=[s.bold(e.title),`${s.dim(`id:`)} ${e.id}`,`${s.dim(`severity:`)} ${e.severity} ${s.dim(`category:`)} ${e.category}`,`${s.dim(`arrived:`)} ${Rn(e.arrivedAt)} ${s.dim(`expires:`)} ${e.expiresAt?Rn(e.expiresAt):`never`}`];if(e.scopes.length>0&&t.push(`${s.dim(`about:`)} ${e.scopes.join(`, `)}`),t.push(``,e.bodyMarkdown.trimEnd()),e.actions.length>0){t.push(``,s.dim(`Actions:`));for(let n of e.actions)t.push(`- ${n.label}: ${n.url}`)}return t.join(`
95
+ `)+`
96
+ `}const Fo=I({name:`read`,description:`Show a notification and mark it as read.`,args:J.strictObject({id:G(J.array(J.uuid()).min(1),{positional:!0,description:`Notification ID (repeatable)`}),"no-mark-read":G(J.boolean().default(!1),{description:`Show the notification without marking it as read`}),profile:A.profile}),run:async e=>{let t=await createNotificationClient(e.profile),n=[],r=[];for(let i of new Set(e.id)){let e;try{({notification:e}=await t.getMyNotification({notificationId:i}))}catch(e){if(!isNotificationNotFound(e))throw e}e?n.push(transformNotificationDetail(e)):r.push(i)}n.length===0&&notificationNotFound(r);let i=await resolveActionUrls(n,e.profile),a=/* @__PURE__ */ new Set,print=()=>{m.jsonMode?m.out(i.map(e=>({...e,markedRead:a.has(e.id)}))):m.out(i.map(formatDetail).join(`
97
+ `))};if(!e[`no-mark-read`]){let e=i.map(e=>e.id);try{for(let n=0;n<e.length;n+=100){let r=e.slice(n,n+100);await t.markMyNotificationsRead({notificationIds:r});for(let e of r)a.add(e)}}catch(e){if(!(e instanceof Q&&e.code===Z.PermissionDenied))throw print(),e;m.warn(`Not marked as read: this login is read-only. Pass --no-mark-read to only show notifications.`)}}print(),r.length>0&&notificationNotFound(r)}}),Io=K({name:`notification`,description:`Read the platform notifications sent to you.`,subCommands:{list:Po,read:Fo,dismiss:Do},defaultSubCommand:`list`}),Lo=K({name:`oauth2client`,description:`Manage OAuth2 clients in your Tailor Platform application.`,subCommands:{list:hr,get:An},defaultSubCommand:`list`}),Ro=I({name:`open`,description:`Open Tailor Platform Console.`,args:J.strictObject({...w}),run:async e=>{let t=await xe({workspaceId:e[`workspace-id`],profile:e.profile}),{config:n}=await R(e.config),r=n.name,i=`/workspaces/${t}/services/applications/${encodeURIComponent(r)}`,a=await pe({profile:e.profile,...e[`workspace-id`]===void 0?{}:{allowMissingProfile:!0}}),o=new URL(i,a).toString(),s=m.jsonMode;m.info(`Opening Tailor Platform Console...`);let c=!0;try{await xa(o)}catch{c=!1}s?m.out({consoleUrl:o,workspaceId:t,applicationName:r,opened:c}):c?(m.out(`Console URL: ${o}`),m.out(`Workspace ID: ${t}`),m.out(`Application Name: ${r}`)):m.warn(`Failed to open browser automatically. Please open this URL manually:\n${o}`)}}),zo=K({name:`folder`,description:`Manage organization folders.`,subCommands:{create:Xn,delete:fr,get:In,list:It,update:cn}}),Bo=K({name:`organization`,description:`Manage Tailor Platform organizations.`,subCommands:{folder:zo,get:mt,list:vt,tree:nt,update:ot},defaultSubCommand:`list`}),Vo=/* @__PURE__ */ `api.auth.authconnection.crashreport.data.deploy.executor.function.generate.init.login.logout.machineuser.notification.oauth2client.open.organization.plugin.profile.query.remove.secret.show.skills.staticwebsite.tailordb.upgrade.user.workflow.workspace`.split(`.`),Ho={seed:`@tailor-platform/sdk-plugin-seed`,setup:`@tailor-platform/sdk-plugin-setup`,"tailordb-erd":`@tailor-platform/sdk-plugin-tailordb-erd`},Uo=/* @__PURE__ */ new Map([[`seed`,{verboseAlias:`v`}]]),Wo=process.platform===`win32`?`;`:`:`;function*ancestorDirs(e){let t=q.resolve(e),n=q.dirname(t);for(;n!==t;)yield t,t=n,n=q.dirname(t);yield t}function windowsExecutableExts(){return(process.env.PATHEXT??`.COM;.EXE;.BAT;.CMD;.PS1`).split(`;`).map(e=>e.trim().toLowerCase()).filter(Boolean)}function isExecutable(e){try{da(e,process.platform===`win32`?fa.F_OK:fa.X_OK)}catch{return!1}if(process.platform===`win32`){let t=q.extname(e).toLowerCase();return t===``||windowsExecutableExts().includes(t)}return!0}function binaryCandidates(e){return process.platform===`win32`?[e,...windowsExecutableExts().map(t=>`${e}${t}`)]:[e]}function pathDirs(){return(process.env.PATH??``).split(Wo).filter(Boolean)}function nodeModulesBinDirs(){let e=[];for(let t of ancestorDirs(process.cwd()))e.push(q.join(t,`node_modules`,`.bin`));return e}function findExecutableIn(e,t){let n=binaryCandidates(t);for(let t of e)for(let e of n){let n=q.join(t,e);if(isExecutable(n))return n}}function resolvePlugin(e,t){if(e.includes(`/`)||e.includes(`\\`)||e.includes(`\0`))return null;let n=`${t}-${e}`,r=findExecutableIn(nodeModulesBinDirs(),n);if(r)return{name:e,path:r,source:`node_modules`};let i=findExecutableIn(pathDirs(),n);return i?{name:e,path:i,source:`path`}:null}function stripBinExt(e){if(process.platform!==`win32`)return e;let t=q.extname(e);return t?e.slice(0,-t.length):e}function listPlugins(e){let t=`${e}-`,n=/* @__PURE__ */ new Map,scan=(e,r)=>{for(let i of e){let e;try{e=pa(i)}catch{continue}for(let a of e){let e=stripBinExt(a);if(!e.startsWith(t)||e.length===t.length)continue;let o=e.slice(t.length);if(n.has(o))continue;let s=q.join(i,a);isExecutable(s)&&n.set(o,{name:o,path:s,source:r})}}};return scan(nodeModulesBinDirs(),`node_modules`),scan(pathDirs(),`path`),[...n.values()]}async function resolveActiveUser(e){let t=await j(),n=e?t.profiles[e]?.user:t.current_user;if(n)return t.users[n]?.email??n}async function buildPluginEnv(e={}){let{profile:t}=e,n={},r=process.argv[1];r&&(n.TAILOR_BIN=r);try{let{version:e}=await zi();e&&(n.TAILOR_VERSION=e)}catch{}let i=De();if(i&&(n.TAILOR_CONFIG_PATH=i),e.skipPlatformContext)return n;let a;try{a=await Ae({profile:t,allowMissingProfile:!0})}catch{}n.TAILOR_PLATFORM_URL=Ti(a),n.TAILOR_PLATFORM_OAUTH2_CLIENT_ID=Li(a);try{n.TAILOR_PLATFORM_WORKSPACE_ID=await xe({profile:t})}catch{}try{let e=await resolveActiveUser(t);e&&(n.TAILOR_PLATFORM_USER=e)}catch{}try{let e=await ue({profile:t});e&&(n.TAILOR_PLATFORM_TOKEN=e)}catch{}return n}function signalToExitCode(e){let t=ya.constants.signals[e];return typeof t==`number`?128+t:1}function buildSpawnTarget(e,t){if(process.platform!==`win32`)return{command:e,args:[...t],shell:!1};let n=q.extname(e).toLowerCase();return n===`.exe`||n===`.com`?{command:e,args:[...t],shell:!1}:n===`.cmd`||n===`.bat`?{command:e,args:[...t],shell:!0}:n===`.ps1`?{command:findExecutableIn(pathDirs(),`pwsh`)??findExecutableIn(pathDirs(),`powershell`)??`powershell`,args:[`-NoProfile`,`-ExecutionPolicy`,`Bypass`,`-File`,e,...t],shell:!1}:{command:findExecutableIn(pathDirs(),`sh`)??`sh`,args:[`-c`,`command "$@"`,`--`,e,...t],shell:!1}}function hasEnvFileFlag(e,t){let{envFiles:n,envFilesIfExists:r}=ke(e,t);return n.length>0||r.length>0}function explicitProfileFromArgs(e){let t;for(let n=0;n<e.length;n++){let r=e[n];if(r===void 0||r===`--`)break;if(r===`--profile`||r===`-p`){let r=e[n+1];r!==void 0&&!r.startsWith(`-`)&&(t=r,n++)}else r.startsWith(`--profile=`)?t=r.slice(10):r.startsWith(`-p=`)&&(t=r.slice(3))}return t||void 0}function pluginSlug(e,t){return[...e??[],t].join(`-`)}async function dispatchPlugin(e){let t=pluginSlug(e.commandPath,e.name),n=resolvePlugin(t,e.cliName);if(!n)return;let r=explicitProfileFromArgs(e.args)??e.profile,i=Uo.get(t)??{},a=hasEnvFileFlag(e.args,i);if(a)try{ie(e.args,i)}catch{}let o={...process.env,...await buildPluginEnv({profile:r,skipPlatformContext:a})},{command:s,args:c,shell:l}=buildSpawnTarget(n.path,e.args);return await new Promise(n=>{let r=Ta(s,c,{stdio:`inherit`,env:o,shell:l});r.on(`error`,r=>{m.error(`Failed to run plugin "${e.cliName}-${t}": ${r.message}`),n(1)}),r.on(`close`,(e,t)=>{n(t?signalToExitCode(t):e??0)})})}async function dispatchPluginWithInstallHint(e){let t=await dispatchPlugin(e);if(t!==void 0)return t;let n=Ho[pluginSlug(e.commandPath,e.name)];if(!n)return;let r=[e.cliName,...e.commandPath??[],e.name].join(` `);return m.error(`"${r}" is provided by the ${n} CLI plugin, which is not installed.`),m.info(`Install it with: npm install -D ${n}`),1}const Go=I({name:`list`,description:"List discovered plugins (executables named `<cli>-<name>` on PATH or node_modules/.bin).",args:J.strictObject({}),run:async()=>{let e=await zi(),t=Object.keys(e.bin??{})[0]||`tailor`,n=new Set(Vo),r=listPlugins(t);if(r.length===0){m.info(H`
95
98
  No plugins found.
96
99
  Install an executable named "${t}-<name>" on your PATH or in node_modules/.bin,
97
100
  then run it with "${t} <name>".
98
- `),y.jsonMode&&y.out([]);return}let i=r.map(e=>({name:e.name,source:e.source,path:e.path,shadowed:n.has(e.name)}));y.out(i);for(let e of i)e.shadowed&&y.warn(`Plugin "${t}-${e.name}" is shadowed by the builtin "${t} ${e.name}" command and will not be dispatched.`)}}),mo=K({name:`plugin`,description:`Manage and inspect CLI plugins (beta).`,subCommands:{list:po},defaultSubCommand:`list`});function assertProfileAvailable(e,t){if(e.profiles[t])throw S({code:`PROFILE_EXISTS`,message:`Profile "${t}" already exists.`})}const ho=z({name:`create`,description:`Create a new profile.`,args:J.strictObject({name:G(J.string(),{positional:!0,description:`Profile name`}),user:G(J.string(),{alias:`u`,description:`User email address or machine user client ID`}),"workspace-id":G(J.string(),{alias:`w`,description:`Workspace ID`}),permission:G(J.enum([`write`,`read`]).default(`write`),{description:`Profile permission. 'read' blocks all write commands while the profile is active.`}),"machine-user":G(J.string().optional(),{alias:`m`,description:`Default machine user name for application-data commands (query, workflow start, function run, machineuser token).`}),"machine-user-override":G(J.enum([`allow`,`deny`]).optional(),{description:`Whether the command line or TAILOR_PLATFORM_MACHINE_USER_NAME may override the profile's machine user. 'deny' requires --machine-user.`}),"platform-url":G(J.url().optional(),{description:`Platform API base URL for this profile.`,env:`TAILOR_PLATFORM_URL`}),"oauth2-client-id":G(J.string().optional(),{description:`OAuth2 client ID for logging in to this profile's platform.`,env:`TAILOR_PLATFORM_OAUTH2_CLIENT_ID`}),"console-url":G(J.url().optional(),{description:`Console base URL for this profile.`,env:`TAILOR_PLATFORM_CONSOLE_URL`})}),run:async e=>{if(e[`machine-user-override`]===`deny`&&!e[`machine-user`])throw S({code:`PROFILE_OPTIONS_INVALID`,message:`--machine-user-override deny requires --machine-user.`,command:`profile create`});let t=await F();assertProfileAvailable(t,e.name);let n={...e[`platform-url`]?{platformUrl:e[`platform-url`]}:{},...e[`oauth2-client-id`]?{oauth2ClientId:e[`oauth2-client-id`]}:{},...e[`console-url`]?{consoleUrl:e[`console-url`]}:{}},r=Object.keys(n).length>0?n:void 0,{accessToken:i,user:a}=await tt(t,e.user,r);assertProfileAvailable(t,e.name);let o=await si(i,r);if(!(await ci(async(e,t)=>{let{workspaces:n,nextPageToken:r}=await o.listWorkspaces({pageToken:e,pageSize:t});return[n,r]})).find(t=>t.id===e[`workspace-id`]))throw S({code:`WORKSPACE_NOT_FOUND`,message:`Workspace "${e[`workspace-id`]}" not found.`});t.profiles[e.name]={user:a,workspace_id:e[`workspace-id`],...e.permission===`read`?{readonly:!0}:{},...e[`machine-user`]?{machine_user:e[`machine-user`]}:{},...e[`machine-user-override`]===`deny`?{machine_user_override:`deny`}:{},...e[`platform-url`]?{platform_url:e[`platform-url`]}:{},...e[`oauth2-client-id`]?{oauth2_client_id:e[`oauth2-client-id`]}:{},...e[`console-url`]?{console_url:e[`console-url`]}:{}},I(t),e.json||y.success(`Profile "${e.name}" created successfully.`);let s={name:e.name,user:a,workspaceId:e[`workspace-id`],permission:e.permission,...e[`machine-user`]?{machineUser:e[`machine-user`],machineUserOverride:e[`machine-user-override`]??`allow`}:{},...e[`platform-url`]?{platformUrl:e[`platform-url`]}:{},...e[`oauth2-client-id`]?{oauth2ClientId:e[`oauth2-client-id`]}:{},...e[`console-url`]?{consoleUrl:e[`console-url`]}:{}};y.out(s)}}),go=z({name:`delete`,description:`Delete a profile.`,args:J.strictObject({name:G(J.string(),{positional:!0,description:`Profile name`})}),run:async e=>{let t=await F();if(!t.profiles[e.name])throw v(e.name);delete t.profiles[e.name],I(t),y.success(`Profile "${e.name}" deleted successfully.`),N({changed:!0,name:e.name})}}),_o=z({name:`list`,description:`List all profiles.`,args:J.strictObject({}),run:async()=>{let e=await F(),t=y.jsonMode,n=Object.entries(e.profiles);if(n.length===0){y.info(W`
101
+ `),m.jsonMode&&m.out([]);return}let i=r.map(e=>({name:e.name,source:e.source,path:e.path,shadowed:n.has(e.name)}));m.out(i);for(let e of i)e.shadowed&&m.warn(`Plugin "${t}-${e.name}" is shadowed by the builtin "${t} ${e.name}" command and will not be dispatched.`)}}),Ko=K({name:`plugin`,description:`Manage and inspect CLI plugins (beta).`,subCommands:{list:Go},defaultSubCommand:`list`});function assertProfileAvailable(e,t){if(e.profiles[t])throw _({code:`PROFILE_EXISTS`,message:`Profile "${t}" already exists.`})}const qo=I({name:`create`,description:`Create a new profile.`,args:J.strictObject({name:G(J.string(),{positional:!0,description:`Profile name`}),user:G(J.string(),{alias:`u`,description:`User email address or machine user client ID`}),"workspace-id":G(J.string(),{alias:`w`,description:`Workspace ID`}),permission:G(J.enum([`write`,`read`]).default(`write`),{description:`Profile permission. 'read' blocks all write commands while the profile is active.`}),"machine-user":G(J.string().optional(),{alias:`m`,description:`Default machine user name for application-data commands (query, workflow start, function run, machineuser token).`}),"machine-user-override":G(J.enum([`allow`,`deny`]).optional(),{description:`Whether the command line or TAILOR_PLATFORM_MACHINE_USER_NAME may override the profile's machine user. 'deny' requires --machine-user.`}),"platform-url":G(J.url().optional(),{description:`Platform API base URL for this profile.`,env:`TAILOR_PLATFORM_URL`}),"oauth2-client-id":G(J.string().optional(),{description:`OAuth2 client ID for logging in to this profile's platform.`,env:`TAILOR_PLATFORM_OAUTH2_CLIENT_ID`}),"console-url":G(J.url().optional(),{description:`Console base URL for this profile.`,env:`TAILOR_PLATFORM_CONSOLE_URL`})}),run:async e=>{if(e[`machine-user-override`]===`deny`&&!e[`machine-user`])throw _({code:`PROFILE_OPTIONS_INVALID`,message:`--machine-user-override deny requires --machine-user.`,command:`profile create`});let t=await j();assertProfileAvailable(t,e.name);let n={...e[`platform-url`]?{platformUrl:e[`platform-url`]}:{},...e[`oauth2-client-id`]?{oauth2ClientId:e[`oauth2-client-id`]}:{},...e[`console-url`]?{consoleUrl:e[`console-url`]}:{}},r=Object.keys(n).length>0?n:void 0,{accessToken:i,user:a}=await Se(t,e.user,r);assertProfileAvailable(t,e.name);let o=await Di(i,r);if(!(await Mi(async(e,t)=>{let{workspaces:n,nextPageToken:r}=await o.listWorkspaces({pageToken:e,pageSize:t});return[n,r]})).find(t=>t.id===e[`workspace-id`]))throw _({code:`WORKSPACE_NOT_FOUND`,message:`Workspace "${e[`workspace-id`]}" not found.`});t.profiles[e.name]={user:a,workspace_id:e[`workspace-id`],...e.permission===`read`?{readonly:!0}:{},...e[`machine-user`]?{machine_user:e[`machine-user`]}:{},...e[`machine-user-override`]===`deny`?{machine_user_override:`deny`}:{},...e[`platform-url`]?{platform_url:e[`platform-url`]}:{},...e[`oauth2-client-id`]?{oauth2_client_id:e[`oauth2-client-id`]}:{},...e[`console-url`]?{console_url:e[`console-url`]}:{}},O(t),e.json||m.success(`Profile "${e.name}" created successfully.`);let s={name:e.name,user:a,workspaceId:e[`workspace-id`],permission:e.permission,...e[`machine-user`]?{machineUser:e[`machine-user`],machineUserOverride:e[`machine-user-override`]??`allow`}:{},...e[`platform-url`]?{platformUrl:e[`platform-url`]}:{},...e[`oauth2-client-id`]?{oauth2ClientId:e[`oauth2-client-id`]}:{},...e[`console-url`]?{consoleUrl:e[`console-url`]}:{}};m.out(s)}}),Jo=I({name:`delete`,description:`Delete a profile.`,args:J.strictObject({name:G(J.string(),{positional:!0,description:`Profile name`})}),run:async e=>{let t=await j();if(!t.profiles[e.name])throw p(e.name);delete t.profiles[e.name],O(t),m.success(`Profile "${e.name}" deleted successfully.`),N({changed:!0,name:e.name})}}),Yo=I({name:`list`,description:`List all profiles.`,args:J.strictObject({}),run:async()=>{let e=await j(),n=m.jsonMode,r=Object.entries(e.profiles);if(r.length===0){m.info(H`
99
102
  No profiles found.
100
103
  Please create a profile first using 'tailor profile create' command.
101
- `),t&&y.out([]);return}let r=n.map(([e,t])=>{let n=s(t,`profile entry "${e}" is undefined`);return{name:e,user:n.user,workspaceId:n.workspace_id,permission:n.readonly===!0?`read`:`write`,...n.machine_user?{machineUser:n.machine_user,machineUserOverride:n.machine_user_override??`allow`}:{},...n.platform_url?{platformUrl:n.platform_url}:{},...n.oauth2_client_id?{oauth2ClientId:n.oauth2_client_id}:{},...n.console_url?{consoleUrl:n.console_url}:{}}});y.out(r)}}),vo=z({name:`update`,description:`Update profile properties.`,args:J.strictObject({name:G(J.string(),{positional:!0,description:`Profile name`}),user:G(J.string().optional(),{alias:`u`,description:`New user email address or machine user client ID`}),"workspace-id":G(J.string().optional(),{alias:`w`,description:`New workspace ID`}),permission:G(J.enum([`write`,`read`]).optional(),{description:`Profile permission. 'read' blocks all write commands; 'write' lifts the restriction.`}),"machine-user":G(J.string().optional(),{alias:`m`,description:`Default machine user name for application-data commands (query, workflow start, function run, machineuser token). Pass an empty string to clear.`}),"machine-user-override":G(J.enum([`allow`,`deny`]).optional(),{description:`Whether the command line or TAILOR_PLATFORM_MACHINE_USER_NAME may override the profile's machine user. 'deny' requires --machine-user; 'allow' lifts the restriction.`}),"platform-url":G(J.union([J.url(),J.literal(``)]).optional(),{description:`Platform API base URL for this profile. Pass an empty string to clear.`}),"oauth2-client-id":G(J.string().optional(),{description:`OAuth2 client ID for logging in to this profile's platform. Pass an empty string to clear.`}),"console-url":G(J.union([J.url(),J.literal(``)]).optional(),{description:`Console base URL for this profile. Pass an empty string to clear.`})}),run:async e=>{let t=await F(),n=t.profiles[e.name];if(!n)throw v(e.name);if(!e.user&&!e[`workspace-id`]&&e.permission===void 0&&e[`machine-user`]===void 0&&e[`machine-user-override`]===void 0&&e[`platform-url`]===void 0&&e[`oauth2-client-id`]===void 0&&e[`console-url`]===void 0)throw S({code:`PROFILE_UPDATE_EMPTY`,message:`Please provide at least one property to update.`,command:`profile update`});let r=n.user,i=e.user||r,a=n.workspace_id,o=e[`workspace-id`]||a,s=i,c=e[`machine-user`]===``?void 0:e[`machine-user`]??n.machine_user,l=e[`machine-user-override`]===`allow`?void 0:e[`machine-user-override`]??n.machine_user_override,u=e[`platform-url`]===``?void 0:e[`platform-url`]??n.platform_url,d=e[`oauth2-client-id`]===``?void 0:e[`oauth2-client-id`]??n.oauth2_client_id,f=e[`console-url`]===``?void 0:e[`console-url`]??n.console_url,p={...u?{platformUrl:u}:{},...d?{oauth2ClientId:d}:{},...f?{consoleUrl:f}:{}},m=Object.keys(p).length>0?p:void 0,h=e[`platform-url`]===``?At(n):m;if((e[`machine-user`]!==void 0||e[`machine-user-override`]!==void 0)&&l===`deny`&&!c)throw e[`machine-user-override`]===`deny`?S({code:`PROFILE_OPTIONS_INVALID`,message:`--machine-user-override deny requires --machine-user.`,command:`profile update`}):S({code:`PROFILE_OPTIONS_INVALID`,message:`Cannot clear the machine user while machine-user-override is "deny". Also pass --machine-user-override allow.`,command:`profile update`});if(e.user!==void 0||e[`workspace-id`]!==void 0||e[`platform-url`]!==void 0){let r=await tt(t,i,h,e.name);if(t.profiles[e.name]!==n)throw v(e.name);s=r.user;let a=await si(r.accessToken,m);if(!(await ci(async(e,t)=>{let{workspaces:n,nextPageToken:r}=await a.listWorkspaces({pageToken:e,pageSize:t});return[n,r]})).find(e=>e.id===o))throw S({code:`WORKSPACE_NOT_FOUND`,message:`Workspace "${o}" not found.`})}n.user=s,n.workspace_id=o,e.permission===`read`?n.readonly=!0:e.permission===`write`&&delete n.readonly,e[`machine-user`]!==void 0&&(e[`machine-user`]===``?delete n.machine_user:n.machine_user=e[`machine-user`]),e[`machine-user-override`]===`deny`?n.machine_user_override=`deny`:e[`machine-user-override`]===`allow`&&delete n.machine_user_override,e[`platform-url`]!==void 0&&(e[`platform-url`]===``?delete n.platform_url:n.platform_url=e[`platform-url`]),e[`oauth2-client-id`]!==void 0&&(e[`oauth2-client-id`]===``?delete n.oauth2_client_id:n.oauth2_client_id=e[`oauth2-client-id`]),e[`console-url`]!==void 0&&(e[`console-url`]===``?delete n.console_url:n.console_url=e[`console-url`]),I(t),e.json||y.success(`Profile "${e.name}" updated successfully`);let g={name:e.name,user:s,workspaceId:o,permission:n.readonly===!0?`read`:`write`,...n.machine_user?{machineUser:n.machine_user,machineUserOverride:n.machine_user_override??`allow`}:{},...n.platform_url?{platformUrl:n.platform_url}:{},...n.oauth2_client_id?{oauth2ClientId:n.oauth2_client_id}:{},...n.console_url?{consoleUrl:n.console_url}:{}};y.out(g)}}),yo=K({name:`profile`,description:`Manage workspace profiles (user + workspace combinations).`,subCommands:{create:ho,delete:go,list:_o,update:vo},defaultSubCommand:`list`});async function resolveSecretValue(e,t,n){if(e.value!==void 0)return e.value;let missing=e=>S({code:`SECRET_VALUE_REQUIRED`,message:`No secret value was given: --value is omitted and standard input ${e}.`,suggestion:`Pass --value, or pipe or redirect the value into the command.`,command:n});if(t.isTTY===!0)throw missing(`is a terminal`);let tooLarge=()=>S({code:`SECRET_VALUE_TOO_LARGE`,message:`The secret value read from standard input exceeds 128 KiB.`,command:n}),r=[],i=0;for await(let e of t){let t=typeof e==`string`?Buffer.from(e):e;if(i+=t.length,i>131074)throw tooLarge();r.push(t)}let a;try{a=new TextDecoder(`utf-8`,{fatal:!0,ignoreBOM:!0}).decode(Buffer.concat(r))}catch(e){throw S({code:`SECRET_VALUE_INVALID_UTF8`,message:`The secret value read from standard input is not valid UTF-8.`,command:n,cause:e})}let o=a.replace(/\r?\n$/,``);if(Buffer.byteLength(o)>131072)throw tooLarge();if(o===``)throw missing(`is empty`);return o}const bo={"vault-name":G(J.string(),{alias:`V`,description:`Vault name`})},xo={...bo,name:G(J.string(),{alias:`n`,description:`Secret name`})},So={...xo,value:G(J.string().optional(),{alias:`v`,description:`Secret value (read from standard input when omitted)`})};function secretValueNotes(e){return`Pass the value with \`--value\`, or omit \`--value\` and pipe the value in to keep it out of shell history and process listings, for example \`printf '%s' "$STRIPE_KEY" | tailor secret ${e} --vault-name api-keys --name stripe-secret-key\`. A piped value can be up to 128 KiB, and one trailing newline is removed from it. In a vault managed by \`defineSecretManager()\`, the command asks for confirmation before releasing the vault from the config, which needs an interactive terminal, so pass \`--yes\` when piping the value.`}async function checkVaultManaged(e){let{client:t,workspaceId:n,vaultName:r}=e,i=U(n,`vault`,r),a={isManaged:!1,trn:i,existingLabels:{}},o,s;try{let{metadata:e}=await t.getMetadata({trn:i});s=e?.labels??{},o=s[ge]}catch{return a}return o?(y.warn(`Vault "${r}" is managed by defineSecretManager() in tailor.config.ts (owner: "${o}"). Changes made via CLI may conflict with the config on the next apply.`),{isManaged:!0,trn:i,existingLabels:s}):a}async function releaseVaultOwnership(e){let{client:t,trn:n}=e;await Ke(t,{trn:n,remove:[ge,fe,dt]}),y.info(`Config ownership has been removed from this vault. Remove it from defineSecretManager() in your config to prevent the next apply from re-claiming it.`)}const Co=z({name:`create`,description:`Create a secret in a vault.`,args:J.strictObject({...P,...So,...L}),notes:secretValueNotes(`create`),run:async e=>{let t=await resolveSecretValue(e,process.stdin,`secret create`);y.registerSecret(t),await O({profile:e.profile});let{client:n,workspaceId:r}=await M({profile:e.profile,workspaceId:e[`workspace-id`]}),i=await checkVaultManaged({client:n,workspaceId:r,vaultName:e[`vault-name`]});if(i.isManaged&&!e.yes&&!await R.confirm({message:`Do you want to proceed?`,default:!1}))throw S({code:`SECRET_CREATION_CANCELLED`,message:`Secret creation cancelled. The vault is still managed by the config.`});try{await n.createSecretManagerSecret({workspaceId:r,secretmanagerVaultName:e[`vault-name`],secretmanagerSecretName:e.name,secretmanagerSecretValue:t})}catch(t){if(t instanceof Q){if(t.code===Z.NotFound)throw S({code:`VAULT_NOT_FOUND`,message:`Vault "${e[`vault-name`]}" not found.`,cause:t});if(t.code===Z.AlreadyExists)throw S({code:`SECRET_EXISTS`,message:`Secret "${e.name}" already exists.`,cause:t})}throw t}i.isManaged&&await releaseVaultOwnership({client:n,...i}),y.success(`Secret: ${e.name} created in vault: ${e[`vault-name`]}`),N({changed:!0,workspaceId:r,vaultName:e[`vault-name`],name:e.name,vaultOwnershipReleased:i.isManaged})}}),wo=z({name:`delete`,description:`Delete a secret in a vault.`,args:J.strictObject({...P,...xo,...L}),run:async e=>{await O({profile:e.profile});let{client:t,workspaceId:n}=await M({profile:e.profile,workspaceId:e[`workspace-id`]}),r=await checkVaultManaged({client:t,workspaceId:n,vaultName:e[`vault-name`]});if(!e.yes&&await R.text({message:`Enter the secret name to confirm deletion ("${e.name}"):`,suggestion:`Pass --yes to skip the confirmation.`})!==e.name)throw S({code:`SECRET_DELETION_CANCELLED`,message:`Secret deletion cancelled: the entered name did not match.`,suggestion:`Run the command again and enter the name exactly as shown, or pass --yes to skip the confirmation.`});try{await t.deleteSecretManagerSecret({workspaceId:n,secretmanagerVaultName:e[`vault-name`],secretmanagerSecretName:e.name})}catch(t){throw t instanceof Q&&t.code===Z.NotFound?S({code:`SECRET_NOT_FOUND`,message:`Secret "${e.name}" not found in vault "${e[`vault-name`]}".`,cause:t}):t}r.isManaged&&await releaseVaultOwnership({client:t,...r}),y.success(`Secret: ${e.name} deleted from vault: ${e[`vault-name`]}`),N({changed:!0,workspaceId:n,vaultName:e[`vault-name`],name:e.name,vaultOwnershipReleased:r.isManaged})}});function secretInfo(e){return{name:e.name,createdAt:e.createTime?Ji(e.createTime):null,updatedAt:e.updateTime?Ji(e.updateTime):null}}async function secretList(e){let{client:t,workspaceId:n}=await M({profile:e.profile,workspaceId:e.workspaceId}),r=de(e.order);return(await $r(async(i,a)=>{let{secrets:o,nextPageToken:s}=await t.listSecretManagerSecrets({workspaceId:n,secretmanagerVaultName:e.vaultName,pageToken:i,pageSize:a,pageDirection:r});return[o,s]},{limit:e.limit})).map(secretInfo)}const To=z({name:`list`,description:`List all secrets in a vault.`,args:J.strictObject({...P,...bo,...Tr()}),run:async e=>{try{let t=await kn(e.limit,t=>secretList({workspaceId:e[`workspace-id`],profile:e.profile,vaultName:e[`vault-name`],order:e.order,limit:t})),n=t.items;y.out(n),await D(t,e.limit)}catch(t){throw t instanceof Q&&t.code===Z.NotFound?S({code:`VAULT_NOT_FOUND`,message:`Vault "${e[`vault-name`]}" not found.`,cause:t}):t}}}),Eo=z({name:`update`,description:`Update a secret in a vault.`,args:J.strictObject({...P,...So,...L}),notes:secretValueNotes(`update`),run:async e=>{let t=await resolveSecretValue(e,process.stdin,`secret update`);y.registerSecret(t),await O({profile:e.profile});let{client:n,workspaceId:r}=await M({profile:e.profile,workspaceId:e[`workspace-id`]}),i=await checkVaultManaged({client:n,workspaceId:r,vaultName:e[`vault-name`]});if(i.isManaged&&!e.yes&&!await R.confirm({message:`Do you want to proceed?`,default:!1}))throw S({code:`SECRET_UPDATE_CANCELLED`,message:`Secret update cancelled. The vault is still managed by the config.`});try{await n.updateSecretManagerSecret({workspaceId:r,secretmanagerVaultName:e[`vault-name`],secretmanagerSecretName:e.name,secretmanagerSecretValue:t})}catch(t){throw t instanceof Q&&t.code===Z.NotFound?S({code:`SECRET_NOT_FOUND`,message:`Secret "${e.name}" not found in vault "${e[`vault-name`]}".`,cause:t}):t}i.isManaged&&await releaseVaultOwnership({client:n,...i}),y.success(`Secret: ${e.name} updated in vault: ${e[`vault-name`]}`),N({changed:!0,workspaceId:r,vaultName:e[`vault-name`],name:e.name,vaultOwnershipReleased:i.isManaged})}}),Do={name:G(J.string(),{positional:{named:!0},description:`Vault name`})},Oo=z({name:`create`,description:`Create a new Secret Manager vault.`,args:J.strictObject({...P,...Do}),run:async e=>{await O({profile:e.profile});let{client:t,workspaceId:n}=await M({profile:e.profile,workspaceId:e[`workspace-id`]});try{await t.createSecretManagerVault({workspaceId:n,secretmanagerVaultName:e.name})}catch(t){throw t instanceof Q&&t.code===Z.AlreadyExists?S({code:`VAULT_EXISTS`,message:`Vault "${e.name}" already exists.`,cause:t}):t}y.success(`Vault: ${e.name} created`),N({changed:!0,workspaceId:n,name:e.name})}}),ko=z({name:`delete`,description:`Delete a Secret Manager vault.`,args:J.strictObject({...P,...Do,...L}),run:async e=>{await O({profile:e.profile});let{client:t,workspaceId:n}=await M({profile:e.profile,workspaceId:e[`workspace-id`]}),r=await checkVaultManaged({client:t,workspaceId:n,vaultName:e.name});if(!e.yes&&await R.text({message:`Enter the vault name to confirm deletion ("${e.name}"):`,suggestion:`Pass --yes to skip the confirmation.`})!==e.name)throw S({code:`VAULT_DELETION_CANCELLED`,message:`Vault deletion cancelled: the entered name did not match.`,suggestion:`Run the command again and enter the name exactly as shown, or pass --yes to skip the confirmation.`});try{await t.deleteSecretManagerVault({workspaceId:n,secretmanagerVaultName:e.name})}catch(t){throw t instanceof Q&&t.code===Z.NotFound?S({code:`VAULT_NOT_FOUND`,message:`Vault "${e.name}" not found.`,cause:t}):t}r.isManaged&&y.info(`Remove this vault from defineSecretManager() in your config to prevent the next apply from re-creating it.`),y.success(`Vault: ${e.name} deleted`),N({changed:!0,workspaceId:n,name:e.name,managed:r.isManaged})}});function vaultInfo(e){return{name:e.name,createdAt:e.createTime?Ji(e.createTime):null,updatedAt:e.updateTime?Ji(e.updateTime):null}}async function vaultList(e){let{client:t,workspaceId:n}=await M({profile:e?.profile,workspaceId:e?.workspaceId}),r=de(e?.order);return(await $r(async(e,i)=>{let{vaults:a,nextPageToken:o}=await t.listSecretManagerVaults({workspaceId:n,pageToken:e,pageSize:i,pageDirection:r});return[a,o]},{limit:e?.limit})).map(vaultInfo)}const Ao=z({name:`list`,description:`List all Secret Manager vaults in the workspace.`,args:J.strictObject({...P,...Tr()}),run:async e=>{let t=await kn(e.limit,t=>vaultList({workspaceId:e[`workspace-id`],profile:e.profile,order:e.order,limit:t})),n=t.items;y.out(n),await D(t,e.limit)}}),jo=K({name:`vault`,description:`Manage Secret Manager vaults.`,subCommands:{create:Oo,delete:ko,list:Ao},defaultSubCommand:`list`}),Mo=K({name:`secret`,description:`Manage Secret Manager vaults and secrets.`,subCommands:{vault:jo,create:Co,update:Eo,list:To,delete:wo},defaultSubCommand:`vault`}),No={[n.UNSPECIFIED]:`unspecified`,[n.PENDING]:`pending`,[n.VERIFYING]:`verifying`,[n.CERT_ISSUED]:`cert_issued`,[n.ACTIVE]:`active`,[n.FAILED]:`failed`,[n.REMOVING]:`removing`},Po=z({name:`get`,description:`Get details of a custom domain.`,args:J.strictObject({...P,domain:G(J.string(),{positional:!0,description:`Custom domain name`})}),run:async e=>{let{client:t,workspaceId:n}=await M({profile:e.profile,workspaceId:e[`workspace-id`]}),r=`Custom domain "${e.domain}" not found.`;try{let{customDomain:i}=await t.getCustomDomain({workspaceId:n,domain:e.domain});if(!i)throw S({code:`STATIC_WEBSITE_DOMAIN_NOT_FOUND`,message:r});let a={domain:i.domain,status:No[i.status]??`unknown`,trafficCnameTarget:i.trafficCnameTarget,certificateCnameTarget:i.certificateCnameTarget,errorMessage:i.errorMessage||void 0};y.out(a)}catch(e){throw e instanceof Q&&e.code===Z.NotFound?S({code:`STATIC_WEBSITE_DOMAIN_NOT_FOUND`,message:r,cause:e}):e}}}),Fo=z({name:`list`,description:`List custom domains for a static website.`,args:J.strictObject({...P,name:G(J.string(),{positional:!0,description:`Static website name`})}),run:async e=>{let{client:t,workspaceId:n}=await M({profile:e.profile,workspaceId:e[`workspace-id`]});try{let{customDomains:r}=await t.listCustomDomains({workspaceId:n,staticWebsiteName:e.name});if(r.length===0){y.info(`No custom domains found.`),y.jsonMode&&y.out([]);return}let i=r.map(e=>({domain:e.domain,status:No[e.status]??`unknown`,trafficCnameTarget:e.trafficCnameTarget,certificateCnameTarget:e.certificateCnameTarget}));y.out(i)}catch(t){throw t instanceof Q&&t.code===Z.NotFound?S({code:`STATIC_WEBSITE_NOT_FOUND`,message:`Static website "${e.name}" not found.`,cause:t}):t}}}),Io=K({name:`domain`,description:`Manage custom domains for static websites.`,subCommands:{list:Fo,get:Po}}),Lo=z({name:`get`,description:`Get details of a specific static website.`,args:J.strictObject({...P,name:G(J.string(),{positional:!0,description:`Static website name`})}),run:async e=>{let{client:t,workspaceId:n}=await M({profile:e.profile,workspaceId:e[`workspace-id`]}),r=`Static website "${e.name}" not found.`;try{let{staticwebsite:i}=await t.getStaticWebsite({workspaceId:n,name:e.name});if(!i)throw S({code:`STATIC_WEBSITE_NOT_FOUND`,message:r});let a={workspaceId:n,name:i.name,description:i.description,url:i.url,allowedIpAddresses:e.json?i.allowedIpAddresses:i.allowedIpAddresses.join(`
102
- `)};y.out(a)}catch(e){throw e instanceof Q&&e.code===Z.NotFound?S({code:`STATIC_WEBSITE_NOT_FOUND`,message:r,cause:e}):e}}});async function listStaticWebsites(e){let{client:t,workspaceId:n}=await M({profile:e?.profile,workspaceId:e?.workspaceId}),r=de(e?.order);return(await $r(async(e,i)=>{let{staticwebsites:a,nextPageToken:o}=await t.listStaticWebsites({workspaceId:n,pageToken:e,pageSize:i,pageDirection:r});return[a,o]},{limit:e?.limit})).map(e=>({workspaceId:n,name:e.name,description:e.description,url:e.url,allowedIpAddresses:e.allowedIpAddresses}))}const Ro=z({name:`list`,description:`List all static websites in a workspace.`,args:J.strictObject({...P,...Tr()}),run:async e=>{let t=y.jsonMode,n=await kn(e.limit,t=>listStaticWebsites({workspaceId:e[`workspace-id`],profile:e.profile,order:e.order,limit:t})),r=n.items,i=t?r:r.map(({allowedIpAddresses:e,...t})=>{if(e.length===0)return{...t,allowedIpAddresses:`No allowed IP addresses`};let n=e.length,r=n===1?`1 IP address`:`${n} IP addresses`;return{...t,allowedIpAddresses:r}});y.out(i),await D(n,e.limit)}}),zo=K({name:`staticwebsite`,description:`Manage static websites in your workspace.`,subCommands:{deploy:ye,domain:Io,list:Ro,get:Lo},defaultSubCommand:`list`}),Bo=new Set(Object.values(E));async function activateBaseline(e,t,n,r){let i=await $.realpath(e),a=q.dirname(i),o=q.basename(i),s=await $.mkdtemp(q.join(a,`.${o}-rebaseline-`)),c=`${s}-previous`,l=!1,u=!1;try{await $.cp(i,s,{recursive:!0});for(let e of await $.readdir(s,{withFileTypes:!0})){if(!e.isDirectory()||!rn.test(e.name))continue;let t=q.join(s,e.name);(await $.readdir(t)).some(e=>Bo.has(e))&&await $.rm(t,{recursive:!0,force:!0})}let e={...t,namespace:n,version:8,createdAt:(/* @__PURE__ */ new Date()).toISOString(),rebaseline:r},a=await Oe(e,s,0);Mn(a.filePath),await $.rename(i,c),l=!0;try{await $.rename(s,i),u=!0}catch(e){throw await $.rename(c,i),l=!1,e}try{await $.rm(c,{recursive:!0,force:!0})}catch(e){y.warn(`The previous migration directory remains at ${c}: ${e instanceof Error?e.message:String(e)}`)}l=!1}finally{X.existsSync(s)&&await $.rm(s,{recursive:!0,force:!0}),!u&&l&&X.existsSync(c)&&await $.rename(c,i)}}async function rebaseline(e){ze(`tailordb migration`);let{config:t,plugins:n}=await j(e.configPath),r=q.dirname(t.path),i=Xe(We(t,r),e.namespace),a=`First run ${b({command:`tailor`,args:[`tailordb`,`migration`,`generate`,`--config`,t.path]})}.`;xt(i.migrationsDir,i.namespace,t.path);let o=A(i.migrationsDir);if(!o)throw S({code:`MIGRATION_HISTORY_NOT_FOUND`,message:`No migration history found for namespace "${i.namespace}".`,suggestion:a});let s=ir(i.migrationsDir),l=A(i.migrationsDir,0)?.rebaseline?.historyId??null,u=ke([i])[i.namespace],d=n.length>0?new Mi(n):void 0,{defineApplication:f}=await import(`../application-83WVdH85.mjs`),p=f({config:t,pluginManager:d});for(let e of p.tailorDBServices)await e.loadTypes(),await e.processNamespacePlugins();let m=p.tailorDBServices.find(e=>e.namespace===i.namespace);if(!m)throw S({code:`TAILORDB_NAMESPACE_NOT_FOUND`,message:`No TailorDB service found for namespace "${i.namespace}"`});let assertLocalTypesReady=()=>{let e=Lr(m.types,i.namespace),t=Zn(o,e.tables,i.namespace);if(st(t))throw y.error(`Migration history does not reproduce the current local schema for namespace ${w.bold(i.namespace)}:`),y.log(Er(t)),S({code:`MIGRATION_HISTORY_MISMATCH`,message:`Refusing to re-baseline: the migration history must reproduce the current local schema.`,suggestion:a})},localSourceFiles=()=>[t.path,...c(m.config,r)];assertLocalTypesReady();let h=be(localSourceFiles()),{client:g,workspaceId:_}=await M({profile:e.profile,workspaceId:e.workspaceId}),v=k({configPath:t.path,workspaceId:_,profile:e.profile}),x=[`--config`,t.path,...v.contextArgs??[]],migrationHint=e=>Tt({...v,subcommand:e,namespace:i.namespace}),C=`Run ${migrationHint([`set`,`0`,`--force`])}`,T=V(s),ee=`run ${migrationHint([`set`,T,`--force`])}, then run this command again.`,E=`Run the command again.`,te=`after resolving the connection error, deploy with schema checks enabled by running ${b({command:`tailor`,args:[`deploy`,...x]})}.`,assertConnectedWorkspaceReady=async(e,n)=>{let r=await _e(g,U(_,`tailordb`,i.namespace));Cr(r,i.namespace,v);let a=r.number;if(a!==s){let e=a===null?`<unset>`:V(a);throw S({code:`REBASELINE_CHECKPOINT_BEHIND`,message:`The connected workspace must be at the latest migration ${V(s)} before re-baselining; current checkpoint is ${e}.`})}if(r.historyIdInvalid)throw S({code:`REBASELINE_REMOTE_HISTORY_INVALID`,message:`Refusing to re-baseline: the connected workspace has an invalid migration history marker.`,suggestion:n===`confirmation`?E:`To replace the marker with the local migration history, ${ee}`});if(r.historyId!==e)throw n===`confirmation`?S({code:`REBASELINE_STATE_CHANGED`,message:`The connected workspace migration history changed while waiting for confirmation.`,suggestion:E}):En({state:r,localHistoryId:e,namespace:i.namespace,code:`REBASELINE_REMOTE_HISTORY_MISMATCH`,suggestion:`Run this command from a checkout of the migration history that was deployed to the workspace. To replace that history with the local one on purpose, ${ee}`});let o=await Mr(g,_,[i],t,[It(m)]),c=o[0];if(!c||c.remoteMigrationNumber!==s||c.hasDrift||c.checkpointMissingLocal)throw c?.hasDrift&&(y.error(`Remote schema drift detected:`),y.log(dn(o))),S({code:`REBASELINE_REMOTE_SCHEMA_MISMATCH`,message:`Refusing to re-baseline: the connected workspace remote schema must match the latest migration.`,suggestion:n===`confirmation`?E:`Run ${migrationHint([`status`])} to compare the workspace with the local migration history. To rewrite the workspace's tables to the latest migration, run ${migrationHint([`sync`,T])}, which deletes the tables and fields that migration does not have together with their data, then run this command again.`})};if(await assertConnectedWorkspaceReady(l,`initial`),y.newline(),y.warn(`This will replace the migration history for ${w.bold(i.namespace)}.`),y.log(` Latest migration: ${V(s)}`),y.log(` New history: 0000/schema.json only`),y.log(` migrate.ts and db.ts files will disappear from the working tree.`),y.log(` Committed migration files will remain in Git history. Preserve any uncommitted files before continuing.`),y.log(` Every other environment must already be at the latest migration.`),y.log(` The connected workspace checkpoint will be reset to 0000.`),y.newline(),!e.yes&&!await R.confirm({message:`Re-baseline this migration history and reset the connected workspace checkpoint?`,default:!1}))throw S({code:`REBASELINE_CANCELLED`,message:`Migration re-baseline cancelled.`});if(xt(i.migrationsDir,i.namespace,t.path),ke([i])[i.namespace]!==u)throw S({code:`REBASELINE_STATE_CHANGED`,message:`Migration files changed while waiting for confirmation.`,suggestion:E});if(be(localSourceFiles())!==h)throw S({code:`REBASELINE_STATE_CHANGED`,message:`Local TailorDB table or config files changed.`,suggestion:E});assertLocalTypesReady(),await assertConnectedWorkspaceReady(l,`confirmation`);let D={historyId:Qt(),replacedHistoryId:l,replacedLatestMigration:s};await activateBaseline(i.migrationsDir,o,i.namespace,D);try{await bt(g,_,i.namespace,0,D.historyId)}catch(e){throw S({code:`REBASELINE_CHECKPOINT_UPDATE_FAILED`,message:`The local migration history was re-baselined, but the connected workspace checkpoint could not be updated.`,suggestion:`${C}, or ${te}`,cause:e})}return y.success(`Re-baselined ${w.bold(i.namespace)} and reset the connected workspace checkpoint to 0000.`),{changed:!0,workspaceId:_,namespace:i.namespace,...D,schemaPath:zt(i.migrationsDir,0,`schema`)}}const Vo=z({name:`rebaseline`,description:`Collapse the full migration history into a new 0000 baseline.`,notes:`Re-baselining removes migrations after 0000 from the working tree, records a new migration history ID, and resets the connected workspace checkpoint without changing its schema or data. Every environment must already have applied the latest migration before you run this command.`,args:J.strictObject({...B,...L,namespace:G(J.string().optional(),{alias:`n`,description:`Target TailorDB namespace (required if multiple namespaces exist)`})}),run:async e=>{await O({profile:e.profile});let t=await rebaseline({configPath:e.config,namespace:e.namespace,yes:e.yes,workspaceId:e[`workspace-id`],profile:e.profile});N(t)}});async function fetchRemoteGqlPermissions(e){let{client:t,workspaceId:n,namespace:r}=e;return fi(async(e,i)=>{let{permissions:a,nextPageToken:o}=await t.listTailorDBGQLPermissions({workspaceId:n,namespaceName:r,pageToken:e,pageSize:i});return[a,o]})}async function fetchRemoteTypes(e){let{client:t,workspaceId:n,namespace:r}=e;return ci(async(e,i)=>{try{let{tailordbTypes:a,nextPageToken:o}=await t.listTailorDBTypes({workspaceId:n,namespaceName:r,pageToken:e,pageSize:i});return[a,o]}catch(e){throw e instanceof Q&&e.code===Z.NotFound?S({code:`MIGRATION_NAMESPACE_NOT_DEPLOYED`,message:`Cannot apply the snapshot: TailorDB namespace "${r}" has not been deployed yet.`,suggestion:`Deploy the namespace first.`,cause:e}):e}})}async function planSnapshotApply(e){let{snapshot:t,...n}=e,r=await fetchRemoteTypes(n),i=new Set(r.map(e=>e.name)),{creates:a,updates:o,deletes:s}=Kt(t,i),c=await fetchRemoteGqlPermissions(n),l=new Set(c.map(e=>e.typeName)),u=Object.entries(t.tables).flatMap(([e,t])=>t.permissions?.gql?[{typeName:e,permission:ct(t.permissions.gql)}]:[]),d=new Set(u.map(e=>e.typeName));return{creates:a,updates:o,deletes:s,desiredGqlPermissions:u,gqlPermissionDeletes:c.filter(e=>!d.has(e.typeName)),remoteGqlPermissionTypes:l}}async function applySnapshotPlan(e){let{client:t,workspaceId:n,namespace:r,snapshot:i,manifestOptions:a,plan:o}=e,{creates:s,updates:c,deletes:l,desiredGqlPermissions:u,gqlPermissionDeletes:d}=o,f=Dr(i,a),manifestFor=e=>{let t=f.get(e);if(!t)throw g(`Internal error: no manifest generated for table "${e}". No changes were applied.`);return t},p=s.map(e=>manifestFor(e)),m=c.map(e=>manifestFor(e));await Promise.all([...p.map(e=>t.createTailorDBType({workspaceId:n,namespaceName:r,tailordbType:e})),...m.map(e=>t.updateTailorDBType({workspaceId:n,namespaceName:r,tailordbType:e}))]),await Promise.all(u.map(({typeName:e,permission:i})=>{let a={workspaceId:n,namespaceName:r,typeName:e,permission:i};return o.remoteGqlPermissionTypes.has(e)?t.updateTailorDBGQLPermission(a):t.createTailorDBGQLPermission(a)})),await Promise.all(d.map(e=>t.deleteTailorDBGQLPermission({workspaceId:n,namespaceName:r,typeName:e.typeName}))),await Promise.all(l.map(e=>t.deleteTailorDBType({workspaceId:n,namespaceName:r,tailordbTypeName:e})))}async function assertMigrationsReproduceLocalTypes(e,t){let{config:n,plugins:r}=e,i=r.length>0?new Mi(r):void 0,{defineApplication:a,generatePluginFilesIfNeeded:o}=await import(`../application-83WVdH85.mjs`),s=a({config:n,pluginManager:i}),c=s.tailorDBServices.find(e=>e.namespace===t.namespace);if(!c)throw S({code:`TAILORDB_NAMESPACE_NOT_FOUND`,message:`No TailorDB service found for namespace "${t.namespace}"`});for(let e of s.tailorDBServices)await e.loadTypes(),await e.processNamespacePlugins();let l=o(i,s.tailorDBServices,n.path),u=s.executorService??(l.length>0?(await import(`../service-WhSyhaho.mjs`)).createExecutorService({config:{files:[]},baseDir:q.dirname(n.path)}):void 0);await u?.loadExecutors(),l.length>0&&await u?.loadPluginExecutorFiles([...l]);let d=/* @__PURE__ */ new Set;for(let e of Object.values(u?.executors??{}))se(e)&&e.trigger.kind===`tailordb`&&d.add(e.trigger.tableName);let f={executorUsedTables:d,namespaceGqlOperations:c.config.gqlOperations},p=A(t.migrationsDir);if(!p)return f;let m=Lr(c.types,t.namespace),h=Zn(p,m.tables,t.namespace);if(!st(h))return f;throw y.error(`Migration history does not reproduce the current local schema for namespace ${w.bold(t.namespace)}:`),y.log(Er(h)),y.newline(),y.info(`This usually means one of the following:`),y.info(` - Migration files were edited and replaying them no longer matches the table definitions — fix the migration files.`,{mode:`plain`}),y.info(` - Table definitions changed without a new migration — run 'tailor tailordb migration generate' first.`,{mode:`plain`}),y.newline(),S({code:`MIGRATION_HISTORY_MISMATCH`,message:`Refusing to continue: the migration history must reproduce the current local schema before it can be applied to the remote.`,suggestion:`Generate a migration for the pending schema changes first.`})}async function sync(e){ze(`tailordb migration`);let t=Ar(e.number),n=await j(e.configPath),{config:r}=n,i=q.dirname(r.path),a=We(r,i),o=Xe(a,e.namespace);xt(o.migrationsDir,o.namespace,r.path);let s=Un(o.migrationsDir,t),c=A(o.migrationsDir,t);if(!c)throw S({code:`MIGRATION_BASELINE_NOT_FOUND`,message:`No initial schema snapshot found in ${o.migrationsDir}. Expected 0000/schema.json.`,suggestion:`Create the initial schema snapshot first.`});let l=await assertMigrationsReproduceLocalTypes(n,o),{client:u,workspaceId:d}=await M({profile:e.profile,workspaceId:e.workspaceId}),f=U(d,`tailordb`,o.namespace),p=await _e(u,f);Cr(p,o.namespace,k({configPath:e.configPath,workspaceId:d,profile:e.profile}));let m=c.rebaseline?.historyId,h=le({state:p,localHistoryId:m??null,namespace:o.namespace,code:`MIGRATION_SYNC_HISTORY_MISMATCH`,force:e.force}),g=p.number,_=await planSnapshotApply({client:u,workspaceId:d,namespace:o.namespace,snapshot:c}),{creates:v,updates:b,deletes:x,desiredGqlPermissions:C,gqlPermissionDeletes:T}=_;y.newline(),y.info(`Namespace: ${w.bold(o.namespace)}`),y.log(` Current migration: ${g===null?`<unset>`:w.bold(V(g))}`),y.log(` Target migration: ${w.bold(V(t))}`),y.log(` Tables to create: ${w.bold(String(v.length))}`),y.log(` Tables to update: ${w.bold(String(b.length))}`),y.log(` Tables to delete: ${w.bold(String(x.length))}`),y.log(` GQL permissions to set: ${w.bold(String(C.length))}`),y.log(` GQL permissions to delete: ${w.bold(String(T.length))}`),y.newline(),h&&(y.warn(h),y.newline());let ee=v.length+b.length+x.length+C.length+T.length;if(ee===0?y.info(`No tables to apply; only the migration label will be updated.`):(y.warn(`This operation will overwrite remote TailorDB tables to match the selected snapshot.`),x.length>0&&y.warn(`Existing data in deleted tables will be lost.`),y.newline()),y.warn(`Sync never runs migrate.ts scripts; it only applies the schema snapshot and moves the migration label.`),y.newline(),g!==null&&t<g?(y.warn(`Migrations ${V(t+1)}–${V(g)} will become pending again and re-execute on the next deploy, including their migrate.ts scripts. Make sure those scripts are idempotent (safe to re-run).`),y.newline()):g!==null&&t>g&&(y.warn(`Moving the migration label forwards (${V(g)} → ${V(t)}): migrate.ts scripts for migrations ${V(g+1)}–${V(t)} will not run on the next deploy.`),y.newline()),!e.yes){if(!await R.confirm({message:`Continue and set migration label to ${V(t)}?`,default:!1}))throw S({code:`MIGRATION_SYNC_CANCELLED`,message:`Migration sync cancelled.`});y.newline()}try{await applySnapshotPlan({client:u,workspaceId:d,namespace:o.namespace,snapshot:c,manifestOptions:l,plan:_})}catch(e){ln(e,[`The target snapshot marks a field as required, but existing remote records have no value for it.`,`Populate those records first (e.g. with a migration script applied via 'tailor deploy'), then re-run the sync.`])}let E=await bt(u,d,o.namespace,t,m);return y.success(`Synced namespace ${w.bold(o.namespace)} to migration ${w.bold(V(t))}.`),t<s&&(y.newline(),y.info(`Run 'tailor deploy' to apply migrations ${V(t+1)}–${V(s)} from the working tree.`)),{changed:ee>0||E,workspaceId:d,namespace:o.namespace,previousMigrationNumber:g,migrationNumber:t,historyId:m??null,tables:{created:v,updated:b,deleted:x},gqlPermissions:{set:C.map(({typeName:e})=>e),deleted:T.map(({typeName:e})=>e)}}}const Ho=z({name:`sync`,description:`Sync remote TailorDB schema and checkpoint to a local migration snapshot to recover from schema drift or a checkpoint outside the local history.`,notes:"The command refuses to run when the namespace records a migration history ID other than the local one, or one that cannot be read, unless the namespace has neither a checkpoint nor a history ID yet. `--force` overwrites the tables and that history ID with those of the local history, and still asks for confirmation unless `--yes` is given.",args:J.strictObject({...B,...L,number:G(J.string(),{positional:!0,description:`Migration number to sync to (e.g., 0001 or 1; 0 targets the baseline snapshot)`}),namespace:G(J.string().optional(),{alias:`n`,description:`Target TailorDB namespace (required if multiple namespaces exist)`}),force:G(J.boolean().default(!1),{description:`Proceed even when the namespace records a migration history ID other than the local one`})}),run:async e=>{await O({profile:e.profile});let t=await sync({configPath:e.config,number:e.number,namespace:e.namespace,yes:e.yes,force:e.force,workspaceId:e[`workspace-id`],profile:e.profile});N(t)}});async function assertMigrationStateUnchanged(e){let{client:t,workspaceId:n,namespace:r,before:i}=e,a=await _e(t,U(n,`tailordb`,r));if(a.number!==i.number||a.historyId!==i.historyId||a.inProgress?.number!==i.inProgress?.number||a.inProgress?.executionId!==i.inProgress?.executionId||a.inProgress?.kind!==i.inProgress?.kind)throw S({code:`MIGRATION_RESOLVE_STATE_CHANGED`,message:`The migration state of namespace "${r}" changed while the command was running.`,suggestion:`Run the command again.`})}function warnMainRunResolution(e){let{namespace:t,migrationNumber:n,resolution:r,runStatus:i,commandContext:a}=e,o=V(n),s=Le(i);r===`rollback`?(y.warn(`Rolling back does not undo what the script of migration ${o} changed in existing fields, and deletes the tables and fields the migration introduced together with their data. When migration ${o} is deployed again, its script runs again, so make sure it is safe to run twice.`),s===`complete`&&y.warn(`The run of migration ${o} succeeded. To keep what its script wrote, run the command with --complete instead.`)):(y.warn(`Completing applies the schema of migration ${o} without running its migrate.ts again; do this only after the data it needs is in place.`),s===`rollback`&&y.warn(`The run of migration ${o} did not succeed, so the data it migrates may not be in place. To run the script again on the next deploy, run the command with --rollback instead.`)),i===`unknown`&&y.warn(`Whether the run of migration ${o} succeeded could not be confirmed. Check it with ${ht(t,n,a)} before you continue.`)}async function resolve$1(e){ze(`tailordb migration`);let t=await j(e.configPath),n=q.dirname(t.config.path),r=Xe(We(t.config,n),e.namespace),{namespace:i}=r;xt(r.migrationsDir,i,t.config.path);let{client:a,workspaceId:o}=await M({profile:e.profile,workspaceId:e.workspaceId}),s=k({configPath:e.configPath,workspaceId:o,profile:e.profile}),c=Tt({...s,subcommand:[`status`],namespace:i}),l=await _e(a,U(o,`tailordb`,i));if(l.inProgressInvalid)throw S({code:`MIGRATION_RESOLVE_RECORD_UNREADABLE`,message:`Namespace "${i}" records a partially applied migration that cannot be read.`,suggestion:`Run ${c} to inspect the migration state.`});if(!l.inProgress||An(l))throw S({code:`MIGRATION_RESOLVE_NO_IN_PROGRESS`,message:`No migration is in progress for namespace "${i}".`,suggestion:`Run ${c} to check the migration state.`});let u=l.number??0,d=u+1;if(l.inProgress.number!==d)throw S({code:`MIGRATION_RESOLVE_RECORD_INVALID`,message:`Namespace "${i}" records migration ${V(l.inProgress.number)} as in progress, but its checkpoint is ${V(u)}; the next migration to run would be ${V(d)}.`,details:`The checkpoint or the in-progress record changed after the deploy that started the migration wrote it.`,suggestion:`Run ${c} to compare the checkpoint with the in-progress migration, and restore the changed label before resolving.`});let f=A(r.migrationsDir,0)?.rebaseline?.historyId??null;if(!ne(l,f))throw En({state:l,localHistoryId:f,namespace:i,code:`MIGRATION_RESOLVE_HISTORY_MISMATCH`,suggestion:`Run the command from a checkout of the migration history that was deployed to the workspace.`});let p=l.inProgress.number,m=V(p),h=l.inProgress.kind===`main`?await wt(a,o,i,l.inProgress):void 0;if(h===`running`)throw Ce(`The run of migration ${i}/${m} is still running.`,l.inProgress.executionId);let g=e.resolution===`rollback`?p-1:p;Un(r.migrationsDir,g);let _=A(r.migrationsDir,g);if(!_)throw S({code:`MIGRATION_BASELINE_NOT_FOUND`,message:`No initial schema snapshot found in ${r.migrationsDir}. Expected 0000/schema.json.`,suggestion:`Create the initial schema snapshot first.`});let v=await assertMigrationsReproduceLocalTypes(t,r),b=await planSnapshotApply({client:a,workspaceId:o,namespace:i,snapshot:_});if(y.newline(),y.info(`Namespace: ${w.bold(i)}`),y.log(` In progress: ${w.bold(m)}`),h&&y.log(` Run: ${w.bold(h)}`),y.log(` Resolution: ${w.bold(e.resolution)} (schema of migration ${w.bold(V(g))})`),y.log(` Tables to create: ${w.bold(String(b.creates.length))}`),y.log(` Tables to update: ${w.bold(String(b.updates.length))}`),y.log(` Tables to delete: ${w.bold(String(b.deletes.length))}`),y.newline(),b.deletes.length>0&&y.warn(`Existing data in deleted tables will be lost.`),h?warnMainRunResolution({namespace:i,migrationNumber:p,resolution:e.resolution,runStatus:h,commandContext:s}):e.resolution===`rollback`?y.warn(`Rolling back does not undo the data changes made by steps of migration ${m} that already completed. When migration ${m} is deployed again, its steps run again from the first step, so make sure every step is safe to run twice.`):y.warn(`Completing applies the schema of migration ${m} without running its migrate.ts again; do this only after the data it needs is in place.`),y.newline(),!e.yes){if(!await R.confirm({message:`Continue and ${e.resolution} migration ${V(p)}?`,default:!1}))throw S({code:`MIGRATION_RESOLVE_CANCELLED`,message:`Migration resolve cancelled.`});y.newline()}await assertMigrationStateUnchanged({client:a,workspaceId:o,namespace:i,before:l}),await De(a,o,i,p);try{await applySnapshotPlan({client:a,workspaceId:o,namespace:i,snapshot:_,manifestOptions:v,plan:b})}catch(e){ln(e,[`The schema of migration ${m} marks a field as required, but records still have no value for it.`,`Fill in those records first (for example with 'tailor query'), then run the command again; the migration stays in progress until the update goes through.`])}l.maintenanceModeCheckpoint!==null&&await nt(a,o,i);let x=await bt(a,o,i,g,_.rebaseline?.historyId);await ie(a,o,i,p),y.success(`Resolved migration ${w.bold(V(p))} of namespace ${w.bold(i)} (${e.resolution}); the checkpoint is ${w.bold(V(g))}.`);let{creates:C,updates:T,deletes:ee,desiredGqlPermissions:E,gqlPermissionDeletes:te}=b;return{changed:C.length+T.length+ee.length+E.length+te.length>0||x,workspaceId:o,namespace:i,resolution:e.resolution,migrationNumber:p,checkpoint:g,...h?{runStatus:h}:{},tables:{created:C,updated:T,deleted:ee},gqlPermissions:{set:E.map(({typeName:e})=>e),deleted:te.map(({typeName:e})=>e)}}}const Uo=z({name:`resolve`,description:`Settle a migration that a failed deploy left partially applied, or whose run a deploy could not confirm.`,notes:"Use this after a deploy failed partway through a migration whose `migrate.ts` exports `steps`, or after a deploy could not confirm whether the script of a migration ran (`MIGRATION_OUTCOME_UNKNOWN`). The migration stays in progress: when `maintenanceMode` is on in your config, the tables of its namespace stay in maintenance mode, and the other migration commands that move the checkpoint are refused. A deploy stops before changing anything while a run it could not confirm is not settled.\n\n- `--rollback` sends the schema of the migration before the failed one. The next deploy runs the failed migration again, from its first step for a script that exports `steps`. Data changes the script already made are not undone.\n- `--complete` sends the schema of the failed migration itself and records it as completed, without running its `migrate.ts` again. Fix the data first (for example with `tailor query`), and make sure no record lacks a value for a field that becomes required.\n\nFor a run that a deploy could not confirm, the command reads how the run ended and shows it before asking for confirmation: use `--complete` when it succeeded, and `--rollback` when it failed, was canceled, or did not start. It refuses while the run is still running, and warns when the option you chose does not fit how the run ended.\n\nBoth options remove the in-progress record, take the tables out of maintenance mode, and remove the temporary resources of the failed run, so `deploy` and the other migration commands work again. As with `tailordb migration sync`, the local migration history must reproduce the current table definitions. If sending the schema stops partway, run the command again.",args:J.strictObject({...B,...L,rollback:G(J.boolean().default(!1),{description:`Return the namespace to the schema before the in-progress migration`}),complete:G(J.boolean().default(!1),{description:`Apply the schema of the in-progress migration and mark it as completed`}),namespace:G(J.string().optional(),{alias:`n`,description:`Target TailorDB namespace (required if multiple namespaces exist)`})}),run:async e=>{if(e.rollback===e.complete)throw S({code:`MIGRATION_RESOLVE_DIRECTION_REQUIRED`,message:`Specify exactly one of --rollback or --complete.`});await O({profile:e.profile});let t=await resolve$1({configPath:e.config,resolution:e.rollback?`rollback`:`complete`,namespace:e.namespace,yes:e.yes,workspaceId:e[`workspace-id`],profile:e.profile});N(t)}});async function set(e){ze(`tailordb migration`);let t=Ar(e.number),{config:n}=await j(e.configPath),r=q.dirname(n.path),i=We(n,r),a=Xe(i,e.namespace),o=a.namespace;xt(a.migrationsDir,o,n.path),Un(a.migrationsDir,t);let s=A(a.migrationsDir,0)?.rebaseline?.historyId,{client:c,workspaceId:l}=await M({profile:e.profile,workspaceId:e.workspaceId}),u=U(l,`tailordb`,o),d=await _e(c,u);Cr(d,o,k({configPath:e.configPath,workspaceId:l,profile:e.profile}));let f=le({state:d,localHistoryId:s??null,namespace:o,code:`MIGRATION_SET_HISTORY_MISMATCH`,force:e.force}),p=d.number,m=p??0,h=ft(d),g=s??`<unset>`;if(y.newline(),y.warn(`This operation will change TailorDB migration state metadata.`),y.log(`Namespace: ${w.bold(o)}`),y.log(`Current migration: ${p===null?`<unset>`:w.bold(V(p))}`),y.log(`New migration: ${w.bold(V(t))}`),y.log(`Current migration history ID: ${w.bold(h)}`),y.log(`New migration history ID: ${w.bold(g)}`),y.newline(),f&&(y.warn(f),y.newline()),t<m?(y.warn(`Setting migration number backwards (${V(m)} → ${V(t)}) will cause previous migrations to be re-executed on next apply.`),y.newline()):t>m&&(y.warn(`Setting migration number forwards (${V(m)} → ${V(t)}) will skip migrations ${V(m+1)} to ${V(t)}.`),y.newline()),!e.yes){if(!await R.confirm({message:`Continue with migration checkpoint and history ID update?`,default:!1}))throw S({code:`MIGRATION_SET_CANCELLED`,message:`Migration checkpoint update cancelled.`});y.newline()}let _=await bt(c,l,o,t,s);return y.success(`Migration checkpoint set to ${w.bold(V(t))} for namespace ${w.bold(o)}`),{changed:_,workspaceId:l,namespace:o,previousMigrationNumber:p,migrationNumber:t,historyId:s??null}}const Wo=z({name:`set`,description:`Set migration checkpoint to a specific number.`,notes:"The migration number must be a 4-digit value (e.g. `0001`) or a bare integer (e.g. `1`) within 0–9999, and must exist in the local migration history; `0` is always accepted as the baseline, provided the local history passes validation. A gapped history is rejected.\n\nThe command refuses to run when the namespace records a migration history ID other than the local one, or one that cannot be read, unless the namespace has neither a checkpoint nor a history ID yet. `--force` replaces that history ID with the local one, or removes it when the local history has none, and still asks for confirmation unless `--yes` is given.\n\nMetadata lookup failures (authentication, permission, or network errors) are reported as errors; only a not-yet-deployed namespace is treated as having no checkpoint.",args:J.strictObject({...B,...L,number:G(J.string(),{positional:!0,description:`Migration number to set (e.g., 0001 or 1)`}),namespace:G(J.string().optional(),{alias:`n`,description:`Target TailorDB namespace (required if multiple namespaces exist)`}),force:G(J.boolean().default(!1),{description:`Proceed even when the namespace records a migration history ID other than the local one`})}),run:async e=>{await O({profile:e.profile});let t=await set({configPath:e.config,number:e.number,namespace:e.namespace,yes:e.yes,force:e.force,workspaceId:e[`workspace-id`],profile:e.profile});N(t)}});function isStatusFailure(e){return e.status===`error`}function formatCheckpointRecovery(e,t,n){return e.kind===`outside`?gn([{namespace:t,remoteMigrationNumber:e.number,localLatestMigration:e.localLatestMigration,historyIdMismatch:e.historyIdMismatch,...e.rebaselinePending?{rebaselinePending:e.rebaselinePending}:{}}],n).map(e=>`\n${e}`).join(``):``}async function collectMigrationStatuses(e){let{config:t}=await j(e.configPath),n=q.dirname(t.path),r=We(t,n);if(r.length===0)throw Ge();let i=e.namespace?r.filter(t=>t.namespace===e.namespace):r;if(i.length===0)throw S({code:`TAILORDB_NAMESPACE_NOT_FOUND`,message:`Namespace "${e.namespace}" not found or does not have migrations configured`});let a=/* @__PURE__ */ new Map,o=/* @__PURE__ */ new Map;for(let{namespace:e,migrationsDir:n}of i)try{xt(n,e,t.path);let r=Jn(n),i=/* @__PURE__ */ new Map,o;for(let e of r)if(e.type===`schema`){let t=Mn(e.path);e.number===0&&(o=t.rebaseline)}else try{let t=Jt(e.path);t.description&&i.set(e.number,t.description)}catch(e){if(m(e)&&e.code===`MIGRATION_FILE_VERSION_UNSUPPORTED`)throw e}a.set(e,{migrationFiles:r,descriptions:i,rebaseline:o})}catch(t){o.set(e,_(t))}if(a.size===0)return i.map(({namespace:e})=>({status:`error`,namespace:e,error:o.get(e)??`Failed to read local migration history.`}));let{client:s,workspaceId:c}=await M({profile:e.profile,workspaceId:e.workspaceId}),l=k({configPath:e.configPath,workspaceId:c,profile:e.profile}),u=[];for(let{namespace:e,migrationsDir:t}of i){if(o.has(e)){u.push({status:`error`,namespace:e,error:o.get(e)??`Failed to read local migration history.`});continue}let n=a.get(e);if(!n){u.push({status:`error`,namespace:e,error:`Failed to read local migration history.`});continue}let{migrationFiles:r,descriptions:i,rebaseline:d}=n,f=d?.historyId??null,p=U(c,`tailordb`,e),m;try{m=await _e(s,p)}catch(t){u.push({status:`error`,namespace:e,error:t instanceof Error?t.message:String(t)});continue}let h=m.number??0,g=formatCheckpointRecovery($n(m,t,d),e,l);if(m.historyIdInvalid){u.push({status:`error`,namespace:e,error:`Remote migration history ID is invalid.`+g});continue}if(m.inProgressInvalid){u.push({status:`error`,namespace:e,error:`Remote in-progress migration record is invalid.`});continue}if(!ne(m,f)){u.push({status:`error`,namespace:e,error:`Remote migration history ID ${m.historyId??`<unset>`} does not match local migration history ID ${f??`<unset>`}.`+g});continue}let _=r.map(e=>e.number).filter((e,t,n)=>n.indexOf(e)===t).toSorted((e,t)=>e-t),v=_.at(-1)??0;if(h>v){u.push({status:`error`,namespace:e,error:`Remote migration checkpoint ${V(h)} is ahead of the latest local migration ${V(v)}.`+g});continue}let y=_.filter(e=>e>h).map(e=>({number:e,label:V(e),...i.has(e)?{description:i.get(e)}:{}})),b=An(m)?null:m.inProgress;u.push({status:`ok`,namespace:e,currentMigration:h,currentMigrationLabel:V(h),pendingMigrations:y,...b?{inProgressMigration:b.number,inProgressMigrationLabel:V(b.number),inProgressMigrationRun:b.kind,inProgressMigrationActions:qe({...l,state:m,namespace:e})}:{}})}return u}function printMigrationStatuses(e){for(let t of e)if(y.newline(),y.info(`Namespace: ${w.bold(t.namespace)}`),isStatusFailure(t))y.error(` Migration status error: ${t.error}`);else{if(y.log(` Current migration: ${w.bold(t.currentMigrationLabel)}`),t.inProgressMigrationLabel){y.log(t.inProgressMigrationRun===`main`?` In progress: ${w.bold(t.inProgressMigrationLabel)} (the outcome of its run is not settled)`:` In progress: ${w.bold(t.inProgressMigrationLabel)} (partially applied)`);for(let e of t.inProgressMigrationActions??[])y.log(` ${pe(e)}`)}if(t.pendingMigrations.length>0){y.log(` Pending migrations:`);for(let e of t.pendingMigrations)e.description?y.log(` - ${e.label}: ${e.description}`):y.log(` - ${e.label}`)}else y.log(` Pending migrations: (none)`)}y.newline()}async function status(e){ze(`tailordb migration`);let t=await collectMigrationStatuses(e);e.json?y.out(t):printMigrationStatuses(t);let n=t.filter(isStatusFailure);if(n.length>0){let e=n.map(e=>e.namespace).join(`, `);throw S({code:`MIGRATION_STATUS_FAILED`,message:`Migration status check failed for ${n.length} namespace${n.length===1?``:`s`}: ${e}`})}}const Go=z({name:`status`,description:`Show the current migration status for TailorDB namespaces, including applied and pending migrations.`,notes:`Local migration files are checked for a valid layout (numbering and required files in each migration directory) and a compatible format version, and deployed migration history IDs must match the local baseline. Invalid or incompatible files, history mismatches, a remote checkpoint ahead of the latest local migration, and metadata lookup failures are reported per namespace and make the command exit non-zero; only a not-yet-deployed namespace is treated as having no applied migrations.`,args:J.strictObject({...B,namespace:G(J.string().optional(),{alias:`n`,description:`Target TailorDB namespace (shows all namespaces if not specified)`})}),run:async e=>{await status({configPath:e.config,namespace:e.namespace,workspaceId:e[`workspace-id`],profile:e.profile,json:y.jsonMode})}});async function runMigrationTest(e,t=createMigrationTestDependencies()){if(e.targetWorkspaceId&&!e.yes)throw S({code:`MIGRATION_TEST_OPTIONS_INVALID`,message:`--target-workspace-id requires --yes because the target may be overwritten.`,command:`tailordb migration test`});if(e.keep&&e.targetWorkspaceId)throw S({code:`MIGRATION_TEST_OPTIONS_INVALID`,message:`--keep applies only to automatically created workspaces; a designated target is always retained.`,command:`tailordb migration test`});if(e.keepTtl!==void 0&&!e.keep)throw S({code:`MIGRATION_TEST_OPTIONS_INVALID`,message:`--keep-ttl was given without --keep.`,suggestion:`Pass --keep together with --keep-ttl, or remove --keep-ttl.`,command:`tailordb migration test`});if(e.cloneTimeout!==void 0&&e.data!==`clone`)throw S({code:`MIGRATION_TEST_OPTIONS_INVALID`,message:`--clone-timeout was given without --data clone.`,suggestion:`Pass --data clone, or remove --clone-timeout.`,command:`tailordb migration test`});if(e.assertionNamespace&&!e.assertionPath)throw S({code:`MIGRATION_TEST_OPTIONS_INVALID`,message:`--assert is required when --assert-namespace is provided.`,command:`tailordb migration test`});let n=await t.prepare(e);if(assertTargetWorkspaceDiffers(n.sourceWorkspaceId,e.targetWorkspaceId),e.assertionPath&&resolveAssertionNamespace(n.pendingNamespaces,e.assertionNamespace),e.data===`clone`&&e.targetWorkspaceId){let e=s(n.designatedTarget,`designated clone target was not loaded during preparation`);assertCloneTargetRegion(n.temporaryWorkspace.region,e.region)}let r=e.targetWorkspaceId===void 0,i=r?await t.createWorkspace(n):{id:s(e.targetWorkspaceId,`designated target workspace missing`),name:void 0,createdAt:void 0},a=e.keepTtl??(e.keep?void 0:`24h`),o=!1;if(r&&a!==void 0)try{await t.recordWorkspaceExpiry(i.id,a,i.createdAt),o=!0}catch(t){y.warn(`Failed to record an expiry on temporary workspace ${i.id}: ${t instanceof Error?t.message:String(t)}. Record one with ${b({command:`tailor`,args:[`workspace`,`ttl`,`set`,`--ttl`,a,`--workspace-id=${i.id}`,...e.profile?[`--profile=${e.profile}`]:[]]})}.`)}let c,l=!1,u=!1;try{let r={prepared:n,targetWorkspaceId:i.id};await t.deployBaseline(r);let a={...r,sourceWorkspaceId:n.sourceWorkspaceId,applicationName:n.sourceApplicationName,cloneTimeout:e.cloneTimeout};e.data===`clone`?await t.cloneData(a):await t.seedData(a);let o={...r,machineUser:e.machineUser};await t.deployMigrations(o),e.assertionPath&&await t.runAssertion({...o,assertionPath:e.assertionPath,assertionNamespace:e.assertionNamespace})}catch(e){c=e,l=!0}if(r&&e.keep)y.info(`Keeping temporary workspace ${i.name??i.id}${o?`; it can be pruned after ${a}`:``}.`);else if(r)try{await t.deleteWorkspace(i.id),u=!0}catch(t){if(!l)throw S({code:`MIGRATION_TEST_WORKSPACE_CLEANUP_FAILED`,message:`Failed to delete temporary workspace ${i.id}: ${t instanceof Error?t.message:String(t)}`,suggestion:e.profile?`Delete the temporary workspace manually with TAILOR_PLATFORM_PROFILE=${e.profile}.`:`Delete the temporary workspace manually.`,next:{command:`tailor`,args:[`workspace`,`delete`,`--workspace-id`,i.id]},cause:t});y.warn(`Failed to delete temporary workspace ${i.id}: ${t instanceof Error?t.message:String(t)}`)}if(l)throw c;return{success:!0,workspaceId:i.id,...i.name?{workspaceName:i.name}:{},temporary:r,deleted:u,data:e.data,pendingNamespaces:n.pendingNamespaces}}async function migrationTest(e){ze(`tailordb migration`);let t=await runMigrationTest(e);e.json?y.out(t):y.success(`Pending migrations completed in workspace ${t.workspaceName??t.workspaceId}.`)}const Ko=z({name:`test`,description:`Test pending migrations with seed fixtures or cloned data in a temporary workspace.`,notes:`The source workspace is read-only. Without --target-workspace-id, the command creates a workspace in the source workspace's region and deletes it after success or failure; pass --keep to retain it for inspection. Right after creating the workspace it records a 24h expiry (unless --keep is given without --keep-ttl), so if the run is interrupted before the command can delete the workspace, workspace prune --expired removes it later. A designated target is retained and requires --yes. Clone mode copies TailorDB records only; it does not copy IdP users or file blobs. With --keep-ttl, the kept workspace records an expiry; it is not deleted automatically, but workspace prune --expired removes it once the expiry has passed. Organization and folder IDs loaded by --env-file are used the same way as the options; command-line options take precedence, and empty env-file values are ignored.`,args:J.strictObject({...B,yes:G(J.boolean().default(!1),{alias:`y`,description:`Acknowledge that a designated target workspace may be overwritten`}),data:G(J.enum([`seed`,`clone`]).default(`seed`),{description:`Data source for the migration test (seed or clone)`}),"target-workspace-id":G(J.uuid().optional(),{description:`Existing throwaway workspace to retain after the test (requires --yes)`}),keep:G(J.boolean().default(!1),{description:`Keep the automatically created workspace after the test`}),"organization-id":G(J.uuid().optional(),{description:`Organization to create the temporary workspace in, at its root unless --folder-id is given (default: the source workspace's organization and folder). With --target-workspace-id, must match the target's organization`,env:`TAILOR_PLATFORM_ORGANIZATION_ID`}),"folder-id":G(J.uuid().optional(),{description:`Folder to create the temporary workspace in (default: the source workspace's folder). Requires --organization-id when the source workspace is not in an organization. With --target-workspace-id, must match the target's folder`,env:`TAILOR_PLATFORM_FOLDER_ID`}),assert:G(J.string().optional(),{description:`Path to a TypeScript assertion script to run after migrations`,completion:{type:`file`,extensions:[`ts`]}}),"assert-namespace":G(J.string().optional(),{description:`TailorDB namespace exposed to the assertion script`}),"keep-ttl":G(jr.optional(),{description:`Record an expiry on the kept workspace, e.g. 24h or 7d (${Gt}), so workspace prune --expired can delete it (requires --keep)`,completion:{type:`none`}}),"clone-timeout":G(In.optional(),{description:`How long to wait for the clone to finish with --data clone, e.g. 30s or 10m (default: 30m)`,completion:{type:`none`}}),"machine-user":G(J.string().optional(),{description:`Machine user for seed, migration, and assertion script execution`})}),run:async e=>{await O({profile:e.profile}),await migrationTest({configPath:e.config,workspaceId:e[`workspace-id`],profile:e.profile,data:e.data,targetWorkspaceId:e[`target-workspace-id`],keep:e.keep,keepTtl:e[`keep-ttl`],..._r(e),assertionPath:e.assert,assertionNamespace:e[`assert-namespace`],machineUser:e[`machine-user`],cloneTimeout:e[`clone-timeout`]===void 0?void 0:ot(e[`clone-timeout`]),yes:e.yes,json:y.jsonMode})}});function assertMigrationScriptsReady(e,t,n){let r=[],i=[],a=[],o=[],s=[];for(let t of Jn(e)){if(t.type!==`diff`)continue;let n=Jt(t.path),c=zt(e,t.number,`migrate`),l=X.existsSync(c);l&&s.push([t.number,c]),n.requiresMigrationScript&&!n.scriptSkipped&&!l&&r.push(t.number),n.scriptSkipped&&l&&i.push(t.number),l&&sr(c)>0&&a.push(t.number),n.hasWarnings&&!n.scriptSkipped&&!l&&o.push({migrationNumber:t.number,warnings:n.warnings})}if(r.length>0)throw S({code:`MIGRATION_SCRIPT_REQUIRED`,message:`Migration(s) ${r.map(V).join(`, `)} in namespace "${t}" require a migration script but have no migrate.ts.`,suggestion:`Add one with 'tailor tailordb migration script <number>', or record that no script is needed with 'tailor tailordb migration script <number> --no-script --reason "..."'.`});if(i.length>0){let e=i.map(e=>` ${gt({migrationNumber:e,namespace:t,configPath:n})}`).join(`
103
- `);throw S({code:`MIGRATION_SCRIPT_SKIP_CONFLICT`,message:`Migration(s) ${i.map(V).join(`, `)} in namespace "${t}" have both a --no-script skip acknowledgment and migrate.ts.`,suggestion:`Clear the stale acknowledgment(s):\n${e}\nOr delete migrate.ts to keep the skip.`})}if(a.length>0)throw S({code:`MIGRATION_SCRIPT_REVIEW_REQUIRED`,message:`Migration(s) ${a.map(V).join(`, `)} in namespace "${t}" still have a TODO() call or review marker in migrate.ts, where the generated script leaves a value or logic for you to decide.`,suggestion:Vt});for(let[e,n]of s){let r=Yn(n);r.kind===`main`&&r.ignoredSteps&&y.warn(Xt(`${t}/${V(e)}`))}return o}function buildValidationReports(e){let{targetNamespaces:t,migrationFileErrors:n,localResults:r,remoteResults:i,unacknowledgedWarnings:a}=e;return t.map(e=>{let t=n.get(e.namespace);if(t!==void 0)return{namespace:e.namespace,valid:!1,migrationFiles:{valid:!1,error:t}};let o=s(r.find(t=>t.namespace===e.namespace),`local schema check result missing for namespace "${e.namespace}"`),c={hasDiff:o.hasDiff,...o.diff?{diff:o.diff}:{}};if(i===void 0)return{namespace:e.namespace,valid:!1,migrationFiles:{valid:!0},localSchema:c,remoteSchema:{skipped:`check_failed`}};let l=s(i.find(t=>t.namespace===e.namespace),`remote schema check result missing for namespace "${e.namespace}"`),u=l.checkpointMissingLocal===!0,d={remoteMigrationNumber:l.remoteMigrationNumber,hasDrift:l.hasDrift,drifts:l.drifts,...l.skipped?{skipped:l.skipped}:{},...l.checkpointUnset?{checkpointUnset:!0}:{},...u?{checkpointMissingLocal:!0}:{},...l.rebaselinePending?{rebaselinePending:l.rebaselinePending}:{},...l.localLatestMigration===void 0?{}:{localLatestMigration:l.localLatestMigration},...l.historyIdMismatch===void 0?{}:{historyIdMismatch:l.historyIdMismatch},...l.checkpointRepair?{checkpointRepair:l.checkpointRepair}:{}},f=a?.get(e.namespace),p;if(f!==void 0){let e=f.filter(e=>e.migrationNumber>l.remoteMigrationNumber);p={valid:e.length===0,missing:e}}return{namespace:e.namespace,valid:!c.hasDiff&&!d.hasDrift&&!u&&p?.valid!==!1,migrationFiles:{valid:!0},localSchema:c,remoteSchema:d,...p?{warningAcknowledgments:p}:{}}})}async function collectValidationReports(e){let{config:t,plugins:n}=await j(e.configPath),r=q.dirname(t.path),i=We(t,r);if(i.length===0)throw Ge();let a=e.namespace?i.filter(t=>t.namespace===e.namespace):i;if(a.length===0)throw S({code:`TAILORDB_NAMESPACE_NOT_FOUND`,message:`Namespace "${e.namespace}" not found or does not have migrations configured`});let o=n.length>0?new Mi(n):void 0,{defineApplication:s}=await import(`../application-83WVdH85.mjs`),c=s({config:t,pluginManager:o});for(let e of c.tailorDBServices)await e.loadTypes(),await e.processNamespacePlugins();zr({tailorDBServices:c.tailorDBServices});for(let{namespace:e}of a)if(!c.tailorDBServices.some(t=>t.namespace===e))throw S({code:`TAILORDB_NAMESPACE_NOT_FOUND`,message:`No TailorDB service found for namespace "${e}"`});let l=c.tailorDBServices.map(It),u=new Map(l.map(e=>[e.namespace,e.types])),d=/* @__PURE__ */ new Map,f=[],p=e.strict?/* @__PURE__ */ new Map:void 0;for(let n of a)try{xt(n.migrationsDir,n.namespace,t.path),A(n.migrationsDir);let r=assertMigrationScriptsReady(n.migrationsDir,n.namespace,e.configPath);p?.set(n.namespace,r),f.push(n)}catch(e){d.set(n.namespace,_(e))}let m={targetNamespaces:a,migrationFileErrors:d,localResults:await hr(u,f),...p?{unacknowledgedWarnings:p}:{}};if(f.length===0)return{reports:buildValidationReports(m)};let h,g;try{let n=await M({profile:e.profile,workspaceId:e.workspaceId});g=n.workspaceId,h=await Mr(n.client,g,f,t,l)}catch(e){return{reports:buildValidationReports(m),remoteError:e}}return{reports:buildValidationReports({...m,remoteResults:h}),workspaceId:g}}function printValidationReports(e){for(let t of e){if(y.newline(),y.info(`Namespace: ${w.bold(t.namespace)}`),!t.migrationFiles.valid){y.log(` Migration files: ${w.error(`invalid`)}`),y.log(` ${t.migrationFiles.error}`);continue}y.log(` Migration files: ${w.success(`OK`)}`);let e=t.localSchema;e?.hasDiff?e.diff?(y.log(` Local schema: ${w.error(`changes not in migration files`)}`),y.log(` ${Wt(e.diff)}`),y.log(Er(e.diff))):y.log(` Local schema: ${w.error(`no migration snapshot found`)}`):y.log(` Local schema: ${w.success(`OK`)}`);let n=t.remoteSchema;n?.skipped===`check_failed`?y.log(` Remote schema: ${w.error(`not checked`)}`):n?.checkpointRepair?y.log(` Remote schema: ${w.success(`OK`)} (next deploy will reset the checkpoint to 0000 from ${V(n.checkpointRepair.from)})`):n?.checkpointMissingLocal?(y.log(` Remote schema: ${w.error(`remote migration ${V(n.remoteMigrationNumber)} is not in the local migration history`)}`),n.rebaselinePending&&y.log(` Fell behind before 'migration rebaseline' ran; must reach ${V(n.rebaselinePending.replacedLatestMigration)} first.`)):n?.hasDrift?(y.log(` Remote schema: ${w.error(`drift detected`)} (${n.checkpointUnset?`no checkpoint yet; compared with 0000`:`remote migration: ${V(n.remoteMigrationNumber)}`})`),y.log(rt(n.drifts))):n?.skipped===`not_deployed`?y.log(` Remote schema: ${w.dim(`skipped (namespace not deployed)`)}`):n?.skipped===`no_snapshot`?y.log(` Remote schema: ${w.dim(`skipped (no local snapshot for remote migration ${V(n.remoteMigrationNumber)})`)}`):n?.checkpointUnset?y.log(` Remote schema: ${w.success(`OK`)} (no checkpoint yet; tables match 0000)`):n&&y.log(` Remote schema: ${w.success(`OK`)} (remote migration: ${V(n.remoteMigrationNumber)})`);let r=t.warningAcknowledgments;if(r){if(r.valid)y.log(` Warning acknowledgments: ${w.success(`OK`)}`);else{y.log(` Warning acknowledgments: ${w.error(`missing for pending migration(s) with possible data loss`)}`);for(let e of r.missing){let t=V(e.migrationNumber);for(let n of e.warnings){let e=n.fieldName?`.${n.fieldName}`:``;y.log(` ${t}: ${n.tableName}${e}: ${n.reason}`)}}}}}y.newline()}function hasMissingCheckpoint(e){return e.remoteSchema?.checkpointMissingLocal===!0}function remoteDrifts(e){return e.map(e=>({namespace:e.namespace,hasDrift:e.remoteSchema?.hasDrift??!1,drifts:e.remoteSchema?.drifts??[],...e.remoteSchema?.checkpointUnset?{checkpointUnset:!0}:{}}))}function printResolutionHints(e,t){e.some(e=>e.localSchema?.hasDiff&&!e.localSchema.diff)&&y.info(`Run 'tailor tailordb migration generate' to create the initial snapshot.`),e.some(e=>e.localSchema?.diff)&&y.info(`Run 'tailor tailordb migration generate' to create migration files.`),zn(e.filter(hasMissingCheckpoint).map(e=>({namespace:e.namespace,remoteMigrationNumber:e.remoteSchema.remoteMigrationNumber,...e.remoteSchema.rebaselinePending?{rebaselinePending:e.remoteSchema.rebaselinePending}:{}}))),e.some(e=>e.remoteSchema?.hasDrift)&&xn(t,remoteDrifts(e));let n=e.filter(e=>e.warningAcknowledgments&&!e.warningAcknowledgments.valid);if(n.length>0){y.info(`For each migration listed, either add a data migration script with 'tailor tailordb migration script <number>' or record why none is needed:`);for(let e of n)for(let n of e.warningAcknowledgments?.missing??[])y.info(` ${gt({migrationNumber:n.migrationNumber,namespace:e.namespace,configPath:t.configPath,noScript:!0})}`,{mode:`plain`})}}async function validate(e){ze(`tailordb migration`);let t=await collectValidationReports(e),{reports:n}=t,r=n.filter(e=>!e.valid).length,i=k({configPath:e.configPath,workspaceId:t.workspaceId,profile:e.profile});if(e.json?y.out(n):(printValidationReports(n),r===0&&!(`remoteError`in t)?y.success(`All migration validation checks passed.`):printResolutionHints(n,i)),`remoteError`in t)throw t.remoteError;if(r>0)throw S({code:`MIGRATION_VALIDATION_FAILED`,message:`Migration validation failed for ${r} namespace(s)`,suggestion:[...gn(n.filter(hasMissingCheckpoint).map(e=>({namespace:e.namespace,...e.remoteSchema,localLatestMigration:e.remoteSchema.localLatestMigration??null,historyIdMismatch:e.remoteSchema.historyIdMismatch??!1})),i),...yr(remoteDrifts(n),i)].join(`
104
- `)||void 0})}const qo=z({name:`validate`,description:`Validate the full migration history, unreviewed generated migration scripts, and schema drift (local tables vs. migration snapshot, remote schema vs. migration checkpoint) without deploying. This includes the migration and schema-drift checks used by 'deploy' and exits with a non-zero code when issues are found.`,args:J.strictObject({...B,namespace:G(J.string().optional(),{alias:`n`,description:`Target TailorDB namespace (validates all namespaces if not specified)`}),strict:G(J.boolean().default(!1),{description:`Also fail when a pending migration can drop data without an acknowledgment`})}),run:async e=>{await validate({configPath:e.config,namespace:e.namespace,workspaceId:e[`workspace-id`],profile:e.profile,json:y.jsonMode,strict:e.strict})}}),Jo=K({name:`migration`,description:`Manage TailorDB schema migrations (beta).`,subCommands:{generate:Je,rebaseline:Vo,resolve:Uo,script:ve,set:Wo,status:Go,sync:Ho,test:Ko,validate:qo}}),Yo=K({name:`tailordb`,description:`Manage TailorDB tables and data.`,notes:"The `tailordb erd` commands are provided by the @tailor-platform/sdk-plugin-tailordb-erd CLI plugin.",subCommands:{truncate:Ue,migration:Jo}}),Xo=z({name:`upgrade`,description:`Run codemods to upgrade your project to a newer SDK version.`,args:J.strictObject({from:G(J.string(),{description:`SDK version before the upgrade (e.g., 1.33.0)`}),"dry-run":G(J.boolean().default(!1),{alias:`d`,description:`Preview changes without modifying files`}),path:G(J.string().default(`.`),{description:`Project directory to upgrade`,completion:{type:`directory`}})}),run:async e=>{let{initTelemetry:t}=await import(`../telemetry-nqOtDWNO.mjs`);await t();let{upgrade:n}=await import(`../service-DDrbdyd-.mjs`);await n({from:e.from,dryRun:e[`dry-run`],path:q.resolve(e.path)})}}),Zo=z({name:`current`,description:`Show current user.`,args:J.strictObject({profile:P.profile}),run:async e=>{let t=await F(),n=e.profile||process.env.TAILOR_PLATFORM_PROFILE,r=n?t.profiles[n]:void 0;if(n&&!r)throw v(n);let i=r?At(r):void 0,a=n?r?.user??null:t.current_user,o=y.jsonMode;if(!a)throw S({code:`USER_NOT_SET`,message:`Current user not set.`,suggestion:`Log in first to register a user.`,next:{command:`tailor`,args:[`login`,...H({profile:n})]}});if(!re(t,a,i))throw S({code:`USER_NOT_FOUND`,message:`Current user '${a}' not found in registered users.`,suggestion:`Log in again to register the user.`,next:{command:`tailor`,args:[`login`,...H({profile:n})]}});o?y.out({user:a}):y.out(a)}});function activeCurrentUserKey(e,t){if(!t)return e.current_user?Hn(e,e.current_user):null;let n=e.profiles[t];if(!n)throw v(t);return Hn(e,n.user,At(n))}function toUserListInfo(e,t){let n=e.indexOf(`|`),r=n===-1?null:e.slice(0,n);return{user:n===-1?e:e.slice(n+1),platformUrl:r,current:t===e}}function formatUserListInfo(e){return`${e.user}${e.platformUrl?` [${e.platformUrl}]`:``}${e.current?` (current)`:``}`}const Qo=z({name:`list`,description:`List all users.`,args:J.strictObject({profile:P.profile}),run:async e=>{let t=await F(),n=y.jsonMode,r=activeCurrentUserKey(t,e.profile||process.env.TAILOR_PLATFORM_PROFILE),i=Object.keys(t.users);if(i.length===0){y.info(W`
104
+ `),n&&m.out([]);return}let i=r.map(([e,n])=>{let r=t(n,`profile entry "${e}" is undefined`);return{name:e,user:r.user,workspaceId:r.workspace_id,permission:r.readonly===!0?`read`:`write`,...r.machine_user?{machineUser:r.machine_user,machineUserOverride:r.machine_user_override??`allow`}:{},...r.platform_url?{platformUrl:r.platform_url}:{},...r.oauth2_client_id?{oauth2ClientId:r.oauth2_client_id}:{},...r.console_url?{consoleUrl:r.console_url}:{}}});m.out(i)}}),Xo=I({name:`update`,description:`Update profile properties.`,args:J.strictObject({name:G(J.string(),{positional:!0,description:`Profile name`}),user:G(J.string().optional(),{alias:`u`,description:`New user email address or machine user client ID`}),"workspace-id":G(J.string().optional(),{alias:`w`,description:`New workspace ID`}),permission:G(J.enum([`write`,`read`]).optional(),{description:`Profile permission. 'read' blocks all write commands; 'write' lifts the restriction.`}),"machine-user":G(J.string().optional(),{alias:`m`,description:`Default machine user name for application-data commands (query, workflow start, function run, machineuser token). Pass an empty string to clear.`}),"machine-user-override":G(J.enum([`allow`,`deny`]).optional(),{description:`Whether the command line or TAILOR_PLATFORM_MACHINE_USER_NAME may override the profile's machine user. 'deny' requires --machine-user; 'allow' lifts the restriction.`}),"platform-url":G(J.union([J.url(),J.literal(``)]).optional(),{description:`Platform API base URL for this profile. Pass an empty string to clear.`}),"oauth2-client-id":G(J.string().optional(),{description:`OAuth2 client ID for logging in to this profile's platform. Pass an empty string to clear.`}),"console-url":G(J.union([J.url(),J.literal(``)]).optional(),{description:`Console base URL for this profile. Pass an empty string to clear.`})}),run:async e=>{let t=await j(),n=t.profiles[e.name];if(!n)throw p(e.name);if(!e.user&&!e[`workspace-id`]&&e.permission===void 0&&e[`machine-user`]===void 0&&e[`machine-user-override`]===void 0&&e[`platform-url`]===void 0&&e[`oauth2-client-id`]===void 0&&e[`console-url`]===void 0)throw _({code:`PROFILE_UPDATE_EMPTY`,message:`Please provide at least one property to update.`,command:`profile update`});let r=n.user,i=e.user||r,a=n.workspace_id,o=e[`workspace-id`]||a,s=i,c=e[`machine-user`]===``?void 0:e[`machine-user`]??n.machine_user,l=e[`machine-user-override`]===`allow`?void 0:e[`machine-user-override`]??n.machine_user_override,u=e[`platform-url`]===``?void 0:e[`platform-url`]??n.platform_url,d=e[`oauth2-client-id`]===``?void 0:e[`oauth2-client-id`]??n.oauth2_client_id,f=e[`console-url`]===``?void 0:e[`console-url`]??n.console_url,h={...u?{platformUrl:u}:{},...d?{oauth2ClientId:d}:{},...f?{consoleUrl:f}:{}},g=Object.keys(h).length>0?h:void 0,v=e[`platform-url`]===``?ge(n):g;if((e[`machine-user`]!==void 0||e[`machine-user-override`]!==void 0)&&l===`deny`&&!c)throw e[`machine-user-override`]===`deny`?_({code:`PROFILE_OPTIONS_INVALID`,message:`--machine-user-override deny requires --machine-user.`,command:`profile update`}):_({code:`PROFILE_OPTIONS_INVALID`,message:`Cannot clear the machine user while machine-user-override is "deny". Also pass --machine-user-override allow.`,command:`profile update`});if(e.user!==void 0||e[`workspace-id`]!==void 0||e[`platform-url`]!==void 0){let r=await Se(t,i,v,e.name);if(t.profiles[e.name]!==n)throw p(e.name);s=r.user;let a=await Di(r.accessToken,g);if(!(await Mi(async(e,t)=>{let{workspaces:n,nextPageToken:r}=await a.listWorkspaces({pageToken:e,pageSize:t});return[n,r]})).find(e=>e.id===o))throw _({code:`WORKSPACE_NOT_FOUND`,message:`Workspace "${o}" not found.`})}n.user=s,n.workspace_id=o,e.permission===`read`?n.readonly=!0:e.permission===`write`&&delete n.readonly,e[`machine-user`]!==void 0&&(e[`machine-user`]===``?delete n.machine_user:n.machine_user=e[`machine-user`]),e[`machine-user-override`]===`deny`?n.machine_user_override=`deny`:e[`machine-user-override`]===`allow`&&delete n.machine_user_override,e[`platform-url`]!==void 0&&(e[`platform-url`]===``?delete n.platform_url:n.platform_url=e[`platform-url`]),e[`oauth2-client-id`]!==void 0&&(e[`oauth2-client-id`]===``?delete n.oauth2_client_id:n.oauth2_client_id=e[`oauth2-client-id`]),e[`console-url`]!==void 0&&(e[`console-url`]===``?delete n.console_url:n.console_url=e[`console-url`]),O(t),e.json||m.success(`Profile "${e.name}" updated successfully`);let y={name:e.name,user:s,workspaceId:o,permission:n.readonly===!0?`read`:`write`,...n.machine_user?{machineUser:n.machine_user,machineUserOverride:n.machine_user_override??`allow`}:{},...n.platform_url?{platformUrl:n.platform_url}:{},...n.oauth2_client_id?{oauth2ClientId:n.oauth2_client_id}:{},...n.console_url?{consoleUrl:n.console_url}:{}};m.out(y)}}),Zo=K({name:`profile`,description:`Manage workspace profiles (user + workspace combinations).`,subCommands:{create:qo,delete:Jo,list:Yo,update:Xo},defaultSubCommand:`list`});async function resolveSecretValue(e,t,n){if(e.value!==void 0)return e.value;let missing=e=>_({code:`SECRET_VALUE_REQUIRED`,message:`No secret value was given: --value is omitted and standard input ${e}.`,suggestion:`Pass --value, or pipe or redirect the value into the command.`,command:n});if(t.isTTY===!0)throw missing(`is a terminal`);let tooLarge=()=>_({code:`SECRET_VALUE_TOO_LARGE`,message:`The secret value read from standard input exceeds 128 KiB.`,command:n}),r=[],i=0;for await(let e of t){let t=typeof e==`string`?Buffer.from(e):e;if(i+=t.length,i>131074)throw tooLarge();r.push(t)}let a;try{a=new TextDecoder(`utf-8`,{fatal:!0,ignoreBOM:!0}).decode(Buffer.concat(r))}catch(e){throw _({code:`SECRET_VALUE_INVALID_UTF8`,message:`The secret value read from standard input is not valid UTF-8.`,command:n,cause:e})}let o=a.replace(/\r?\n$/,``);if(Buffer.byteLength(o)>131072)throw tooLarge();if(o===``)throw missing(`is empty`);return o}const Qo={"vault-name":G(J.string(),{alias:`V`,description:`Vault name`})},$o={...Qo,name:G(J.string(),{alias:`n`,description:`Secret name`})},es={...$o,value:G(J.string().optional(),{alias:`v`,description:`Secret value (read from standard input when omitted)`})};function secretValueNotes(e){return`Pass the value with \`--value\`, or omit \`--value\` and pipe the value in to keep it out of shell history and process listings, for example \`printf '%s' "$STRIPE_KEY" | tailor secret ${e} --vault-name api-keys --name stripe-secret-key\`. A piped value can be up to 128 KiB, and one trailing newline is removed from it. In a vault managed by \`defineSecretManager()\`, the command asks for confirmation before releasing the vault from the config, which needs an interactive terminal, so pass \`--yes\` when piping the value.`}async function checkVaultManaged(e){let{client:t,workspaceId:n,vaultName:r}=e,i=Kr(n,`vault`,r),a={isManaged:!1,trn:i,existingLabels:{}},o,s;try{let{metadata:e}=await t.getMetadata({trn:i});s=e?.labels??{},o=s[$t]}catch{return a}return o?(m.warn(`Vault "${r}" is managed by defineSecretManager() in tailor.config.ts (owner: "${o}"). Changes made via CLI may conflict with the config on the next apply.`),{isManaged:!0,trn:i,existingLabels:s}):a}async function releaseVaultOwnership(e){let{client:t,trn:n}=e;await Jt(t,{trn:n,remove:[$t,st,Be]}),m.info(`Config ownership has been removed from this vault. Remove it from defineSecretManager() in your config to prevent the next apply from re-claiming it.`)}const ts=I({name:`create`,description:`Create a secret in a vault.`,args:J.strictObject({...A,...es,...D}),notes:secretValueNotes(`create`),run:async e=>{let t=await resolveSecretValue(e,process.stdin,`secret create`);m.registerSecret(t),await L({profile:e.profile});let{client:n,workspaceId:r}=await B({profile:e.profile,workspaceId:e[`workspace-id`]}),i=await checkVaultManaged({client:n,workspaceId:r,vaultName:e[`vault-name`]});if(i.isManaged&&!e.yes&&!await P.confirm({message:`Do you want to proceed?`,default:!1}))throw _({code:`SECRET_CREATION_CANCELLED`,message:`Secret creation cancelled. The vault is still managed by the config.`});try{await n.createSecretManagerSecret({workspaceId:r,secretmanagerVaultName:e[`vault-name`],secretmanagerSecretName:e.name,secretmanagerSecretValue:t})}catch(t){if(t instanceof Q){if(t.code===Z.NotFound)throw _({code:`VAULT_NOT_FOUND`,message:`Vault "${e[`vault-name`]}" not found.`,cause:t});if(t.code===Z.AlreadyExists)throw _({code:`SECRET_EXISTS`,message:`Secret "${e.name}" already exists.`,cause:t})}throw t}i.isManaged&&await releaseVaultOwnership({client:n,...i}),m.success(`Secret: ${e.name} created in vault: ${e[`vault-name`]}`),N({changed:!0,workspaceId:r,vaultName:e[`vault-name`],name:e.name,vaultOwnershipReleased:i.isManaged})}}),ns=I({name:`delete`,description:`Delete a secret in a vault.`,args:J.strictObject({...A,...$o,...D}),run:async e=>{await L({profile:e.profile});let{client:t,workspaceId:n}=await B({profile:e.profile,workspaceId:e[`workspace-id`]}),r=await checkVaultManaged({client:t,workspaceId:n,vaultName:e[`vault-name`]});if(!e.yes&&await P.text({message:`Enter the secret name to confirm deletion ("${e.name}"):`,suggestion:`Pass --yes to skip the confirmation.`})!==e.name)throw _({code:`SECRET_DELETION_CANCELLED`,message:`Secret deletion cancelled: the entered name did not match.`,suggestion:`Run the command again and enter the name exactly as shown, or pass --yes to skip the confirmation.`});try{await t.deleteSecretManagerSecret({workspaceId:n,secretmanagerVaultName:e[`vault-name`],secretmanagerSecretName:e.name})}catch(t){throw t instanceof Q&&t.code===Z.NotFound?_({code:`SECRET_NOT_FOUND`,message:`Secret "${e.name}" not found in vault "${e[`vault-name`]}".`,cause:t}):t}r.isManaged&&await releaseVaultOwnership({client:t,...r}),m.success(`Secret: ${e.name} deleted from vault: ${e[`vault-name`]}`),N({changed:!0,workspaceId:n,vaultName:e[`vault-name`],name:e.name,vaultOwnershipReleased:r.isManaged})}});function secretInfo(e){return{name:e.name,createdAt:e.createTime?ma(e.createTime):null,updatedAt:e.updateTime?ma(e.updateTime):null}}async function secretList(e){let{client:t,workspaceId:n}=await B({profile:e.profile,workspaceId:e.workspaceId}),r=we(e.order);return(await Pi(async(i,a)=>{let{secrets:o,nextPageToken:s}=await t.listSecretManagerSecrets({workspaceId:n,secretmanagerVaultName:e.vaultName,pageToken:i,pageSize:a,pageDirection:r});return[o,s]},{limit:e.limit})).map(secretInfo)}const rs=I({name:`list`,description:`List all secrets in a vault.`,args:J.strictObject({...A,...Qo,...oe()}),run:async e=>{try{let t=await rn(e.limit,t=>secretList({workspaceId:e[`workspace-id`],profile:e.profile,vaultName:e[`vault-name`],order:e.order,limit:t})),n=t.items;m.out(n),await M(t,e.limit)}catch(t){throw t instanceof Q&&t.code===Z.NotFound?_({code:`VAULT_NOT_FOUND`,message:`Vault "${e[`vault-name`]}" not found.`,cause:t}):t}}}),is=I({name:`update`,description:`Update a secret in a vault.`,args:J.strictObject({...A,...es,...D}),notes:secretValueNotes(`update`),run:async e=>{let t=await resolveSecretValue(e,process.stdin,`secret update`);m.registerSecret(t),await L({profile:e.profile});let{client:n,workspaceId:r}=await B({profile:e.profile,workspaceId:e[`workspace-id`]}),i=await checkVaultManaged({client:n,workspaceId:r,vaultName:e[`vault-name`]});if(i.isManaged&&!e.yes&&!await P.confirm({message:`Do you want to proceed?`,default:!1}))throw _({code:`SECRET_UPDATE_CANCELLED`,message:`Secret update cancelled. The vault is still managed by the config.`});try{await n.updateSecretManagerSecret({workspaceId:r,secretmanagerVaultName:e[`vault-name`],secretmanagerSecretName:e.name,secretmanagerSecretValue:t})}catch(t){throw t instanceof Q&&t.code===Z.NotFound?_({code:`SECRET_NOT_FOUND`,message:`Secret "${e.name}" not found in vault "${e[`vault-name`]}".`,cause:t}):t}i.isManaged&&await releaseVaultOwnership({client:n,...i}),m.success(`Secret: ${e.name} updated in vault: ${e[`vault-name`]}`),N({changed:!0,workspaceId:r,vaultName:e[`vault-name`],name:e.name,vaultOwnershipReleased:i.isManaged})}}),as={name:G(J.string(),{positional:{named:!0},description:`Vault name`})},os=I({name:`create`,description:`Create a new Secret Manager vault.`,args:J.strictObject({...A,...as}),run:async e=>{await L({profile:e.profile});let{client:t,workspaceId:n}=await B({profile:e.profile,workspaceId:e[`workspace-id`]});try{await t.createSecretManagerVault({workspaceId:n,secretmanagerVaultName:e.name})}catch(t){throw t instanceof Q&&t.code===Z.AlreadyExists?_({code:`VAULT_EXISTS`,message:`Vault "${e.name}" already exists.`,cause:t}):t}m.success(`Vault: ${e.name} created`),N({changed:!0,workspaceId:n,name:e.name})}}),ss=I({name:`delete`,description:`Delete a Secret Manager vault.`,args:J.strictObject({...A,...as,...D}),run:async e=>{await L({profile:e.profile});let{client:t,workspaceId:n}=await B({profile:e.profile,workspaceId:e[`workspace-id`]}),r=await checkVaultManaged({client:t,workspaceId:n,vaultName:e.name});if(!e.yes&&await P.text({message:`Enter the vault name to confirm deletion ("${e.name}"):`,suggestion:`Pass --yes to skip the confirmation.`})!==e.name)throw _({code:`VAULT_DELETION_CANCELLED`,message:`Vault deletion cancelled: the entered name did not match.`,suggestion:`Run the command again and enter the name exactly as shown, or pass --yes to skip the confirmation.`});try{await t.deleteSecretManagerVault({workspaceId:n,secretmanagerVaultName:e.name})}catch(t){throw t instanceof Q&&t.code===Z.NotFound?_({code:`VAULT_NOT_FOUND`,message:`Vault "${e.name}" not found.`,cause:t}):t}r.isManaged&&m.info(`Remove this vault from defineSecretManager() in your config to prevent the next apply from re-creating it.`),m.success(`Vault: ${e.name} deleted`),N({changed:!0,workspaceId:n,name:e.name,managed:r.isManaged})}});function vaultInfo(e){return{name:e.name,createdAt:e.createTime?ma(e.createTime):null,updatedAt:e.updateTime?ma(e.updateTime):null}}async function vaultList(e){let{client:t,workspaceId:n}=await B({profile:e?.profile,workspaceId:e?.workspaceId}),r=we(e?.order);return(await Pi(async(e,i)=>{let{vaults:a,nextPageToken:o}=await t.listSecretManagerVaults({workspaceId:n,pageToken:e,pageSize:i,pageDirection:r});return[a,o]},{limit:e?.limit})).map(vaultInfo)}const cs=I({name:`list`,description:`List all Secret Manager vaults in the workspace.`,args:J.strictObject({...A,...oe()}),run:async e=>{let t=await rn(e.limit,t=>vaultList({workspaceId:e[`workspace-id`],profile:e.profile,order:e.order,limit:t})),n=t.items;m.out(n),await M(t,e.limit)}}),ls=K({name:`vault`,description:`Manage Secret Manager vaults.`,subCommands:{create:os,delete:ss,list:cs},defaultSubCommand:`list`}),us=K({name:`secret`,description:`Manage Secret Manager vaults and secrets.`,subCommands:{vault:ls,create:ts,update:is,list:rs,delete:ns},defaultSubCommand:`vault`}),ds={[Hi.UNSPECIFIED]:`unspecified`,[Hi.PENDING]:`pending`,[Hi.VERIFYING]:`verifying`,[Hi.CERT_ISSUED]:`cert_issued`,[Hi.ACTIVE]:`active`,[Hi.FAILED]:`failed`,[Hi.REMOVING]:`removing`},fs=I({name:`get`,description:`Get details of a custom domain.`,args:J.strictObject({...A,domain:G(J.string(),{positional:!0,description:`Custom domain name`})}),run:async e=>{let{client:t,workspaceId:n}=await B({profile:e.profile,workspaceId:e[`workspace-id`]}),r=`Custom domain "${e.domain}" not found.`;try{let{customDomain:i}=await t.getCustomDomain({workspaceId:n,domain:e.domain});if(!i)throw _({code:`STATIC_WEBSITE_DOMAIN_NOT_FOUND`,message:r});let a={domain:i.domain,status:ds[i.status]??`unknown`,trafficCnameTarget:i.trafficCnameTarget,certificateCnameTarget:i.certificateCnameTarget,errorMessage:i.errorMessage||void 0};m.out(a)}catch(e){throw e instanceof Q&&e.code===Z.NotFound?_({code:`STATIC_WEBSITE_DOMAIN_NOT_FOUND`,message:r,cause:e}):e}}}),ps=I({name:`list`,description:`List custom domains for a static website.`,args:J.strictObject({...A,name:G(J.string(),{positional:!0,description:`Static website name`})}),run:async e=>{let{client:t,workspaceId:n}=await B({profile:e.profile,workspaceId:e[`workspace-id`]});try{let{customDomains:r}=await t.listCustomDomains({workspaceId:n,staticWebsiteName:e.name});if(r.length===0){m.info(`No custom domains found.`),m.jsonMode&&m.out([]);return}let i=r.map(e=>({domain:e.domain,status:ds[e.status]??`unknown`,trafficCnameTarget:e.trafficCnameTarget,certificateCnameTarget:e.certificateCnameTarget}));m.out(i)}catch(t){throw t instanceof Q&&t.code===Z.NotFound?_({code:`STATIC_WEBSITE_NOT_FOUND`,message:`Static website "${e.name}" not found.`,cause:t}):t}}}),ms=K({name:`domain`,description:`Manage custom domains for static websites.`,subCommands:{list:ps,get:fs}}),hs=I({name:`get`,description:`Get details of a specific static website.`,args:J.strictObject({...A,name:G(J.string(),{positional:!0,description:`Static website name`})}),run:async e=>{let{client:t,workspaceId:n}=await B({profile:e.profile,workspaceId:e[`workspace-id`]}),r=`Static website "${e.name}" not found.`;try{let{staticwebsite:i}=await t.getStaticWebsite({workspaceId:n,name:e.name});if(!i)throw _({code:`STATIC_WEBSITE_NOT_FOUND`,message:r});let a={workspaceId:n,name:i.name,description:i.description,url:i.url,allowedIpAddresses:e.json?i.allowedIpAddresses:i.allowedIpAddresses.join(`
105
+ `)};m.out(a)}catch(e){throw e instanceof Q&&e.code===Z.NotFound?_({code:`STATIC_WEBSITE_NOT_FOUND`,message:r,cause:e}):e}}});async function listStaticWebsites(e){let{client:t,workspaceId:n}=await B({profile:e?.profile,workspaceId:e?.workspaceId}),r=we(e?.order);return(await Pi(async(e,i)=>{let{staticwebsites:a,nextPageToken:o}=await t.listStaticWebsites({workspaceId:n,pageToken:e,pageSize:i,pageDirection:r});return[a,o]},{limit:e?.limit})).map(e=>({workspaceId:n,name:e.name,description:e.description,url:e.url,allowedIpAddresses:e.allowedIpAddresses}))}const gs=I({name:`list`,description:`List all static websites in a workspace.`,args:J.strictObject({...A,...oe()}),run:async e=>{let t=m.jsonMode,n=await rn(e.limit,t=>listStaticWebsites({workspaceId:e[`workspace-id`],profile:e.profile,order:e.order,limit:t})),r=n.items,i=t?r:r.map(({allowedIpAddresses:e,...t})=>{if(e.length===0)return{...t,allowedIpAddresses:`No allowed IP addresses`};let n=e.length,r=n===1?`1 IP address`:`${n} IP addresses`;return{...t,allowedIpAddresses:r}});m.out(i),await M(n,e.limit)}}),_s=K({name:`staticwebsite`,description:`Manage static websites in your workspace.`,subCommands:{deploy:et,domain:ms,list:gs,get:hs},defaultSubCommand:`list`}),vs=new Set(Object.values(ar));async function activateBaseline(e,t,n,r){let i=await $.realpath(e),a=q.dirname(i),o=q.basename(i),s=await $.mkdtemp(q.join(a,`.${o}-rebaseline-`)),c=`${s}-previous`,l=!1,u=!1;try{await $.cp(i,s,{recursive:!0});for(let e of await $.readdir(s,{withFileTypes:!0})){if(!e.isDirectory()||!Gn.test(e.name))continue;let t=q.join(s,e.name);(await $.readdir(t)).some(e=>vs.has(e))&&await $.rm(t,{recursive:!0,force:!0})}let e={...t,namespace:n,version:8,createdAt:(/* @__PURE__ */ new Date()).toISOString(),rebaseline:r},a=await ut(e,s,0);Fr(a.filePath),await $.rename(i,c),l=!0;try{await $.rename(s,i),u=!0}catch(e){throw await $.rename(c,i),l=!1,e}try{await $.rm(c,{recursive:!0,force:!0})}catch(e){m.warn(`The previous migration directory remains at ${c}: ${e instanceof Error?e.message:String(e)}`)}l=!1}finally{X.existsSync(s)&&await $.rm(s,{recursive:!0,force:!0}),!u&&l&&X.existsSync(c)&&await $.rename(c,i)}}async function rebaseline(e){St(`tailordb migration`);let{config:t,plugins:n}=await R(e.configPath),r=q.dirname(t.path),i=yr(it(t,r),e.namespace),a=`First run ${h({command:`tailor`,args:Jn([`generate`],{configPath:t.path})})}.`;Pn(i.migrationsDir,i.namespace,t.path);let o=V(i.migrationsDir);if(!o)throw _({code:`MIGRATION_HISTORY_NOT_FOUND`,message:`No migration history found for namespace "${i.namespace}".`,suggestion:a});let c=Ar(i.migrationsDir),l=V(i.migrationsDir,0)?.rebaseline?.historyId??null,u=pn([i])[i.namespace],d=n.length>0?new $i(n):void 0,{defineApplication:f}=await import(`../application-OeNMQzOC.mjs`),p=f({config:t,pluginManager:d});for(let e of p.tailorDBServices)await e.loadTypes(),await e.processNamespacePlugins();let g=p.tailorDBServices.find(e=>e.namespace===i.namespace);if(!g)throw _({code:`TAILORDB_NAMESPACE_NOT_FOUND`,message:`No TailorDB service found for namespace "${i.namespace}"`});let assertLocalTypesReady=()=>{let e=Rt(g.types,i.namespace),t=At(o,e.tables,i.namespace);if(Ct(t))throw m.error(`Migration history does not reproduce the current local schema for namespace ${s.bold(i.namespace)}:`),m.log(dt(t)),_({code:`MIGRATION_HISTORY_MISMATCH`,message:`Refusing to re-baseline: the migration history must reproduce the current local schema.`,suggestion:a})},localSourceFiles=()=>[t.path,...xi(g.config,r)];assertLocalTypesReady();let v=gt(localSourceFiles()),{client:y,workspaceId:b}=await B({profile:e.profile,workspaceId:e.workspaceId}),x=z({configPath:t.path,workspaceId:b,profile:e.profile}),migrationHint=e=>xr({...x,subcommand:e,namespace:i.namespace}),S=`Run ${migrationHint([`sync`,F(0),`--force`])}`,C=F(c),w=`run ${migrationHint([`sync`,C,`--force`])}, which removes the fields that migration does not have and deletes the tables it does not have together with their data, then run this command again.`,T=`Run the command again.`,E=`after resolving the connection error, deploy with schema checks enabled by running ${h({command:`tailor`,args:[`deploy`,...mr(x)]})}.`,assertConnectedWorkspaceReady=async(e,n)=>{let r=await ft(y,Kr(b,`tailordb`,i.namespace));tt(r,i.namespace,x);let a=r.number;if(a!==c){let e=a===null?`<unset>`:F(a);throw _({code:`REBASELINE_CHECKPOINT_BEHIND`,message:`The connected workspace must be at the latest migration ${F(c)} before re-baselining; current checkpoint is ${e}.`})}if(r.historyIdInvalid)throw _({code:`REBASELINE_REMOTE_HISTORY_INVALID`,message:`Refusing to re-baseline: the connected workspace has an invalid migration history marker.`,suggestion:n===`confirmation`?T:`To replace the marker with the local migration history, ${w}`});if(r.historyId!==e)throw n===`confirmation`?_({code:`REBASELINE_STATE_CHANGED`,message:`The connected workspace migration history changed while waiting for confirmation.`,suggestion:T}):tn({state:r,localHistoryId:e,namespace:i.namespace,code:`REBASELINE_REMOTE_HISTORY_MISMATCH`,suggestion:`Run this command from a checkout of the migration history that was deployed to the workspace. To replace that history with the local one on purpose, ${w}`});let o=await kt(y,b,[i],t,[Zn(g)]),s=o[0];if(!s||s.remoteMigrationNumber!==c||s.hasDrift||s.checkpointMissingLocal)throw s?.hasDrift&&(m.error(`Remote schema drift detected:`),m.log(Ze(o))),_({code:`REBASELINE_REMOTE_SCHEMA_MISMATCH`,message:`Refusing to re-baseline: the connected workspace remote schema must match the latest migration.`,suggestion:n===`confirmation`?T:`Run ${migrationHint([`status`])} to compare the workspace with the local migration history. To rewrite the workspace's tables to the latest migration, run ${migrationHint([`sync`,C])}, which deletes the tables and fields that migration does not have together with their data, then run this command again.`})};if(await assertConnectedWorkspaceReady(l,`initial`),m.newline(),m.warn(`This will replace the migration history for ${s.bold(i.namespace)}.`),m.log(` Latest migration: ${F(c)}`),m.log(` New history: 0000/schema.json only`),m.log(` migrate.ts and db.ts files will disappear from the working tree.`),m.log(` Committed migration files will remain in Git history. Preserve any uncommitted files before continuing.`),m.log(` Every other environment must already be at the latest migration.`),m.log(` The connected workspace checkpoint will be reset to 0000.`),m.newline(),!e.yes&&!await P.confirm({message:`Re-baseline this migration history and reset the connected workspace checkpoint?`,default:!1}))throw _({code:`REBASELINE_CANCELLED`,message:`Migration re-baseline cancelled.`});if(Pn(i.migrationsDir,i.namespace,t.path),pn([i])[i.namespace]!==u)throw _({code:`REBASELINE_STATE_CHANGED`,message:`Migration files changed while waiting for confirmation.`,suggestion:T});if(gt(localSourceFiles())!==v)throw _({code:`REBASELINE_STATE_CHANGED`,message:`Local TailorDB table or config files changed.`,suggestion:T});assertLocalTypesReady(),await assertConnectedWorkspaceReady(l,`confirmation`);let ee={historyId:Xe(),replacedHistoryId:l,replacedLatestMigration:c};await activateBaseline(i.migrationsDir,o,i.namespace,ee);try{await rt(y,b,i.namespace,0,ee.historyId)}catch(e){throw _({code:`REBASELINE_CHECKPOINT_UPDATE_FAILED`,message:`The local migration history was re-baselined, but the connected workspace checkpoint could not be updated.`,suggestion:`${S}, or ${E}`,cause:e})}return m.success(`Re-baselined ${s.bold(i.namespace)} and reset the connected workspace checkpoint to 0000.`),{changed:!0,workspaceId:b,namespace:i.namespace,...ee,schemaPath:wn(i.migrationsDir,0,`schema`)}}const ys=I({name:`rebaseline`,description:`Collapse the full migration history into a new 0000 baseline.`,notes:`Re-baselining removes migrations after 0000 from the working tree, records a new migration history ID, and resets the connected workspace checkpoint without changing its schema or data. Every environment must already have applied the latest migration before you run this command.`,args:J.strictObject({...w,...D,namespace:G(J.string().optional(),{alias:`n`,description:`Target TailorDB namespace (required if multiple namespaces exist)`})}),run:async e=>{await L({profile:e.profile});let t=await rebaseline({configPath:e.config,namespace:e.namespace,yes:e.yes,workspaceId:e[`workspace-id`],profile:e.profile});N(t)}});async function fetchRemoteGqlPermissions(e){let{client:t,workspaceId:n,namespace:r}=e;return Fi(async(e,i)=>{let{permissions:a,nextPageToken:o}=await t.listTailorDBGQLPermissions({workspaceId:n,namespaceName:r,pageToken:e,pageSize:i});return[a,o]})}async function fetchRemoteTypes(e){let{client:t,workspaceId:n,namespace:r}=e;return Mi(async(e,i)=>{try{let{tailordbTypes:a,nextPageToken:o}=await t.listTailorDBTypes({workspaceId:n,namespaceName:r,pageToken:e,pageSize:i});return[a,o]}catch(e){throw e instanceof Q&&e.code===Z.NotFound?_({code:`MIGRATION_NAMESPACE_NOT_DEPLOYED`,message:`Cannot apply the snapshot: TailorDB namespace "${r}" has not been deployed yet.`,suggestion:`Deploy the namespace first.`,cause:e}):e}})}async function planSnapshotApply(e){let{snapshot:t,...n}=e,r=await fetchRemoteTypes(n),i=new Set(r.map(e=>e.name)),{creates:a,updates:o,deletes:s}=lt(t,i),c=await fetchRemoteGqlPermissions(n),l=new Set(c.map(e=>e.typeName)),u=Object.entries(t.tables).flatMap(([e,t])=>t.permissions?.gql?[{typeName:e,permission:on(t.permissions.gql)}]:[]),d=new Set(u.map(e=>e.typeName));return{creates:a,updates:o,deletes:s,desiredGqlPermissions:u,gqlPermissionDeletes:c.filter(e=>!d.has(e.typeName)),remoteGqlPermissionTypes:l}}async function applySnapshotPlan(e){let{client:t,workspaceId:n,namespace:r,snapshot:i,manifestOptions:a,plan:o}=e,{creates:s,updates:c,deletes:l,desiredGqlPermissions:d,gqlPermissionDeletes:f}=o,p=Xt(i,a),manifestFor=e=>{let t=p.get(e);if(!t)throw u(`Internal error: no manifest generated for table "${e}". No changes were applied.`);return t},m=s.map(e=>manifestFor(e)),h=c.map(e=>manifestFor(e));await Promise.all([...m.map(e=>t.createTailorDBType({workspaceId:n,namespaceName:r,tailordbType:e})),...h.map(e=>t.updateTailorDBType({workspaceId:n,namespaceName:r,tailordbType:e}))]),await Promise.all(d.map(({typeName:e,permission:i})=>{let a={workspaceId:n,namespaceName:r,typeName:e,permission:i};return o.remoteGqlPermissionTypes.has(e)?t.updateTailorDBGQLPermission(a):t.createTailorDBGQLPermission(a)})),await Promise.all(f.map(e=>t.deleteTailorDBGQLPermission({workspaceId:n,namespaceName:r,typeName:e.typeName}))),await Promise.all(l.map(e=>t.deleteTailorDBType({workspaceId:n,namespaceName:r,tailordbTypeName:e})))}async function assertMigrationsReproduceLocalTypes(e,t){let{config:n,plugins:r}=e,i=r.length>0?new $i(r):void 0,{defineApplication:a,generatePluginFilesIfNeeded:o}=await import(`../application-OeNMQzOC.mjs`),c=a({config:n,pluginManager:i}),l=c.tailorDBServices.find(e=>e.namespace===t.namespace);if(!l)throw _({code:`TAILORDB_NAMESPACE_NOT_FOUND`,message:`No TailorDB service found for namespace "${t.namespace}"`});for(let e of c.tailorDBServices)await e.loadTypes(),await e.processNamespacePlugins();let u=o(i,c.tailorDBServices,n.path),d=c.executorService??(u.length>0?(await import(`../service-Dffd4how.mjs`)).createExecutorService({config:{files:[]},baseDir:q.dirname(n.path)}):void 0);await d?.loadExecutors(),u.length>0&&await d?.loadPluginExecutorFiles([...u]);let f=/* @__PURE__ */ new Set;for(let e of Object.values(d?.executors??{}))zt(e)&&e.trigger.kind===`tailordb`&&f.add(e.trigger.tableName);let p={executorUsedTables:f,namespaceGqlOperations:l.config.gqlOperations},h=V(t.migrationsDir);if(!h)return p;let g=Rt(l.types,t.namespace),v=At(h,g.tables,t.namespace);if(!Ct(v))return p;throw m.error(`Migration history does not reproduce the current local schema for namespace ${s.bold(t.namespace)}:`),m.log(dt(v)),m.newline(),m.info(`This usually means one of the following:`),m.info(` - Migration files were edited and replaying them no longer matches the table definitions — fix the migration files.`,{mode:`plain`}),m.info(` - Table definitions changed without a new migration — run 'tailor tailordb migration generate' first.`,{mode:`plain`}),m.newline(),_({code:`MIGRATION_HISTORY_MISMATCH`,message:`Refusing to continue: the migration history must reproduce the current local schema before it can be applied to the remote.`,suggestion:`Generate a migration for the pending schema changes first.`})}async function sync(e){St(`tailordb migration`);let t=Nt(e.number),n=await R(e.configPath),{config:r}=n,i=q.dirname(r.path),a=it(r,i),o=yr(a,e.namespace);Pn(o.migrationsDir,o.namespace,r.path);let c=_n(o.migrationsDir,t),l=V(o.migrationsDir,t);if(!l)throw _({code:`MIGRATION_BASELINE_NOT_FOUND`,message:`No initial schema snapshot found in ${o.migrationsDir}. Expected 0000/schema.json.`,suggestion:`Create the initial schema snapshot first.`});let u=await assertMigrationsReproduceLocalTypes(n,o),{client:d,workspaceId:f}=await B({profile:e.profile,workspaceId:e.workspaceId}),p=Kr(f,`tailordb`,o.namespace),h=await ft(d,p);tt(h,o.namespace,z({configPath:e.configPath,workspaceId:f,profile:e.profile}));let g=l.rebaseline?.historyId,v=Pt({state:h,localHistoryId:g??null,namespace:o.namespace,code:`MIGRATION_SYNC_HISTORY_MISMATCH`,force:e.force}),y=h.number,b=await planSnapshotApply({client:d,workspaceId:f,namespace:o.namespace,snapshot:l}),{creates:x,updates:S,deletes:C,desiredGqlPermissions:w,gqlPermissionDeletes:T}=b;m.newline(),m.info(`Namespace: ${s.bold(o.namespace)}`),m.log(` Current migration: ${y===null?`<unset>`:s.bold(F(y))}`),m.log(` Target migration: ${s.bold(F(t))}`),m.log(` Tables to create: ${s.bold(String(x.length))}`),m.log(` Tables to update: ${s.bold(String(S.length))}`),m.log(` Tables to delete: ${s.bold(String(C.length))}`),m.log(` GQL permissions to set: ${s.bold(String(w.length))}`),m.log(` GQL permissions to delete: ${s.bold(String(T.length))}`),m.newline(),v&&(m.warn(v),m.newline());let E=x.length+S.length+C.length+w.length+T.length;if(E===0?m.info(`No tables to apply; only the migration label will be updated.`):(m.warn(`This operation will overwrite remote TailorDB tables to match the selected snapshot.`),C.length>0&&m.warn(`Existing data in deleted tables will be lost.`),m.newline()),m.warn(`Sync never runs migrate.ts scripts; it only applies the schema snapshot and moves the migration label.`),m.newline(),y!==null&&t<y?(m.warn(`Migrations ${F(t+1)}–${F(y)} will become pending again and re-execute on the next deploy, including their migrate.ts scripts. Make sure those scripts are idempotent (safe to re-run).`),m.newline()):y!==null&&t>y&&(m.warn(`Moving the migration label forwards (${F(y)} → ${F(t)}): migrate.ts scripts for migrations ${F(y+1)}–${F(t)} will not run on the next deploy.`),m.newline()),!e.yes){if(!await P.confirm({message:`Continue and set migration label to ${F(t)}?`,default:!1}))throw _({code:`MIGRATION_SYNC_CANCELLED`,message:`Migration sync cancelled.`});m.newline()}try{await applySnapshotPlan({client:d,workspaceId:f,namespace:o.namespace,snapshot:l,manifestOptions:u,plan:b})}catch(e){qe(e,[`The target snapshot marks a field as required, but existing remote records have no value for it.`,`Populate those records first (e.g. with a migration script applied via 'tailor deploy'), then re-run the sync.`])}let ee=await rt(d,f,o.namespace,t,g);return m.success(`Synced namespace ${s.bold(o.namespace)} to migration ${s.bold(F(t))}.`),t<c&&(m.newline(),m.info(`Run 'tailor deploy' to apply migrations ${F(t+1)}–${F(c)} from the working tree.`)),{changed:E>0||ee,workspaceId:f,namespace:o.namespace,previousMigrationNumber:y,migrationNumber:t,historyId:g??null,tables:{created:x,updated:S,deleted:C},gqlPermissions:{set:w.map(({typeName:e})=>e),deleted:T.map(({typeName:e})=>e)}}}const bs=I({name:`sync`,description:`Sync remote TailorDB schema and checkpoint to a local migration snapshot to recover from schema drift or a checkpoint outside the local history.`,notes:"The command refuses to run when the namespace records a migration history ID other than the local one, or one that cannot be read, unless the namespace has neither a checkpoint nor a history ID yet. `--force` overwrites the tables and that history ID with those of the local history, and still asks for confirmation unless `--yes` is given.",args:J.strictObject({...w,...D,number:G(J.string(),{positional:!0,description:`Migration number to sync to (e.g., 0001 or 1; 0 targets the baseline snapshot)`}),namespace:G(J.string().optional(),{alias:`n`,description:`Target TailorDB namespace (required if multiple namespaces exist)`}),force:G(J.boolean().default(!1),{description:`Proceed even when the namespace records a migration history ID other than the local one`})}),run:async e=>{await L({profile:e.profile});let t=await sync({configPath:e.config,number:e.number,namespace:e.namespace,yes:e.yes,force:e.force,workspaceId:e[`workspace-id`],profile:e.profile});N(t)}});async function assertMigrationStateUnchanged(e){let{client:t,workspaceId:n,namespace:r,before:i}=e,a=await ft(t,Kr(n,`tailordb`,r));if(a.number!==i.number||a.historyId!==i.historyId||a.inProgress?.number!==i.inProgress?.number||a.inProgress?.executionId!==i.inProgress?.executionId||a.inProgress?.kind!==i.inProgress?.kind)throw _({code:`MIGRATION_RESOLVE_STATE_CHANGED`,message:`The migration state of namespace "${r}" changed while the command was running.`,suggestion:`Run the command again.`})}function warnMainRunResolution(e){let{namespace:t,migrationNumber:n,resolution:r,runStatus:i,commandContext:a}=e,o=F(n),s=Fe(i);r===`rollback`?(m.warn(`Rolling back does not undo what the script of migration ${o} changed in existing fields, and deletes the tables and fields the migration introduced together with their data. When migration ${o} is deployed again, its script runs again, so make sure it is safe to run twice.`),s===`complete`&&m.warn(`The run of migration ${o} succeeded. To keep what its script wrote, run the command with --complete instead.`)):(m.warn(`Completing applies the schema of migration ${o} without running its migrate.ts again; do this only after the data it needs is in place.`),s===`rollback`&&m.warn(`The run of migration ${o} did not succeed, so the data it migrates may not be in place. To run the script again on the next deploy, run the command with --rollback instead.`)),i===`unknown`&&m.warn(`Whether the run of migration ${o} succeeded could not be confirmed. Check it with ${ln(t,n,a)} before you continue.`)}async function resolve$1(e){St(`tailordb migration`);let t=await R(e.configPath),n=q.dirname(t.config.path),r=yr(it(t.config,n),e.namespace),{namespace:i}=r;Pn(r.migrationsDir,i,t.config.path);let{client:a,workspaceId:o}=await B({profile:e.profile,workspaceId:e.workspaceId}),c=z({configPath:e.configPath,workspaceId:o,profile:e.profile}),l=xr({...c,subcommand:[`status`],namespace:i}),u=await ft(a,Kr(o,`tailordb`,i));if(u.inProgressInvalid)throw _({code:`MIGRATION_RESOLVE_RECORD_UNREADABLE`,message:`Namespace "${i}" records a partially applied migration that cannot be read.`,suggestion:`Run ${l} to inspect the migration state.`});let d=u.number??0,f=d+1,p=Jr(u)?u.inProgress:null,h=p?null:u.inProgress,g=!h&&e.resolution===`rollback`?(await kt(a,o,[r],t.config,[],{acceptInterruptedMigration:!0}))[0]:void 0,v=g!==void 0&&(g.interruptedMigration===f||g.leftInMaintenanceMode&&!g.hasDrift&&Ar(r.migrationsDir)>=f);if(!h&&!v)throw _({code:`MIGRATION_RESOLVE_NO_IN_PROGRESS`,message:`No migration is in progress for namespace "${i}".`,suggestion:`Run ${l} to check the migration state.`});if(h&&h.number!==f)throw _({code:`MIGRATION_RESOLVE_RECORD_INVALID`,message:`Namespace "${i}" records migration ${F(h.number)} as in progress, but its checkpoint is ${F(d)}; the next migration to run would be ${F(f)}.`,details:`The checkpoint or the in-progress record changed after the deploy that started the migration wrote it.`,suggestion:`Run ${l} to compare the checkpoint with the in-progress migration, and restore the changed label before resolving.`});let y=V(r.migrationsDir,0)?.rebaseline?.historyId??null;if(!He(u,y))throw tn({state:u,localHistoryId:y,namespace:i,code:`MIGRATION_RESOLVE_HISTORY_MISMATCH`,suggestion:`Run the command from a checkout of the migration history that was deployed to the workspace.`});let b=f,x=F(b),S=h?.kind===`main`?await mn(a,o,i,h):void 0;if(S===`running`)throw Lt(`The run of migration ${i}/${x} is still running.`,h?.executionId);let C=e.resolution===`rollback`?b-1:b;_n(r.migrationsDir,C);let w=V(r.migrationsDir,C);if(!w)throw _({code:`MIGRATION_BASELINE_NOT_FOUND`,message:`No initial schema snapshot found in ${r.migrationsDir}. Expected 0000/schema.json.`,suggestion:`Create the initial schema snapshot first.`});let T=await assertMigrationsReproduceLocalTypes(t,r),E=await planSnapshotApply({client:a,workspaceId:o,namespace:i,snapshot:w});if(m.newline(),m.info(`Namespace: ${s.bold(i)}`),m.log(v?` Interrupted: ${s.bold(x)} (not recorded as in progress)`:` In progress: ${s.bold(x)}`),S&&m.log(` Run: ${s.bold(S)}`),m.log(` Resolution: ${s.bold(e.resolution)} (schema of migration ${s.bold(F(C))})`),m.log(` Tables to create: ${s.bold(String(E.creates.length))}`),m.log(` Tables to update: ${s.bold(String(E.updates.length))}`),m.log(` Tables to delete: ${s.bold(String(E.deletes.length))}`),m.newline(),E.deletes.length>0&&m.warn(`Existing data in deleted tables will be lost.`),S?warnMainRunResolution({namespace:i,migrationNumber:b,resolution:e.resolution,runStatus:S,commandContext:c}):v?(m.warn(`No deploy recorded migration ${x} as in progress, but its pre-migration schema or maintenance mode is still in place. A deploy that is still running looks the same until it records the migration, so make sure no deploy to this workspace is running.`),m.warn(`Rolling back does not undo data changes a script of migration ${x} may already have made. When migration ${x} is deployed again, it runs again from the start.`)):e.resolution===`rollback`?m.warn(`Rolling back does not undo the data changes made by steps of migration ${x} that already completed. When migration ${x} is deployed again, its steps run again from the first step, so make sure every step is safe to run twice.`):m.warn(`Completing applies the schema of migration ${x} without running its migrate.ts again; do this only after the data it needs is in place.`),m.newline(),!e.yes){if(!await P.confirm({message:`Continue and ${e.resolution} migration ${F(b)}?`,default:!1}))throw _({code:`MIGRATION_RESOLVE_CANCELLED`,message:`Migration resolve cancelled.`});m.newline()}await assertMigrationStateUnchanged({client:a,workspaceId:o,namespace:i,before:u}),await fn(a,o,i,b);try{await applySnapshotPlan({client:a,workspaceId:o,namespace:i,snapshot:w,manifestOptions:T,plan:E})}catch(e){qe(e,[`The schema of migration ${x} marks a field as required, but records still have no value for it.`,`Fill in those records first (for example with 'tailor query'), then run the command again${v?`.`:`; the migration stays in progress until the update goes through.`}`])}u.maintenanceModeCheckpoint!==null&&await Ve(a,o,i);let ee=await rt(a,o,i,C,w.rebaseline?.historyId);await an(a,o,i,b),p&&await an(a,o,i,p.number),m.success(`Resolved migration ${s.bold(F(b))} of namespace ${s.bold(i)} (${e.resolution}); the checkpoint is ${s.bold(F(C))}.`);let{creates:te,updates:D,deletes:O,desiredGqlPermissions:ne,gqlPermissionDeletes:re}=E;return{changed:te.length+D.length+O.length+ne.length+re.length>0||ee,workspaceId:o,namespace:i,resolution:e.resolution,migrationNumber:b,checkpoint:C,...v?{interrupted:v}:{},...S?{runStatus:S}:{},tables:{created:te,updated:D,deleted:O},gqlPermissions:{set:ne.map(({typeName:e})=>e),deleted:re.map(({typeName:e})=>e)}}}const xs=I({name:`resolve`,description:`Settle a migration that a failed deploy left partially applied, or whose run a deploy could not confirm.`,notes:'Use this after a deploy failed partway through a migration whose `migrate.ts` exports `steps`, or after a deploy could not confirm whether the script of a migration ran (`MIGRATION_OUTCOME_UNKNOWN`). The migration stays in progress: when `maintenanceMode` is on in your config, the tables of its namespace stay in maintenance mode, and the other migration commands that move the checkpoint are refused. A deploy stops before changing anything while a run it could not confirm is not settled.\n\n- `--rollback` sends the schema of the migration before the failed one. The next deploy runs the failed migration again, from its first step for a script that exports `steps`. Data changes the script already made are not undone.\n- `--complete` sends the schema of the failed migration itself and records it as completed, without running its `migrate.ts` again. Fix the data first (for example with `tailor query`), and make sure no record lacks a value for a field that becomes required.\n\nFor a run that a deploy could not confirm, the command reads how the run ended and shows it before asking for confirmation: use `--complete` when it succeeded, and `--rollback` when it failed, was canceled, or did not start. It refuses while the run is still running, and warns when the option you chose does not fit how the run ended.\n\n`--rollback` also settles a migration that no deploy recorded as in progress, but whose pre-migration schema or maintenance mode a deploy left in place, for example because the deploy stopped before recording it. See "Settling a migration that stays in progress" in the TailorDB Migrations guide for when it runs.\n\nBoth options remove the in-progress record, take the tables out of maintenance mode, and remove the temporary resources of the failed run, so `deploy` and the other migration commands work again. As with `tailordb migration sync`, the local migration history must reproduce the current table definitions. If sending the schema stops partway, run the command again.',args:J.strictObject({...w,...D,rollback:G(J.boolean().default(!1),{description:`Return the namespace to the schema before the in-progress migration`}),complete:G(J.boolean().default(!1),{description:`Apply the schema of the in-progress migration and mark it as completed`}),namespace:G(J.string().optional(),{alias:`n`,description:`Target TailorDB namespace (required if multiple namespaces exist)`})}),run:async e=>{if(e.rollback===e.complete)throw _({code:`MIGRATION_RESOLVE_DIRECTION_REQUIRED`,message:`Specify exactly one of --rollback or --complete.`});await L({profile:e.profile});let t=await resolve$1({configPath:e.config,resolution:e.rollback?`rollback`:`complete`,namespace:e.namespace,yes:e.yes,workspaceId:e[`workspace-id`],profile:e.profile});N(t)}});function isStatusFailure(e){return e.status===`error`}function formatCheckpointRecovery(e,t,n){return e.kind===`outside`?ze([{namespace:t,remoteMigrationNumber:e.number,localLatestMigration:e.localLatestMigration,historyIdMismatch:e.historyIdMismatch,...e.rebaselinePending?{rebaselinePending:e.rebaselinePending}:{}}],n).map(e=>`\n${e}`).join(``):``}async function collectMigrationStatuses(e){let{config:t}=await R(e.configPath),n=q.dirname(t.path),r=it(t,n);if(r.length===0)throw bt();let i=e.namespace?r.filter(t=>t.namespace===e.namespace):r;if(i.length===0)throw _({code:`TAILORDB_NAMESPACE_NOT_FOUND`,message:`Namespace "${e.namespace}" not found or does not have migrations configured`});let a=/* @__PURE__ */ new Map,s=/* @__PURE__ */ new Map;for(let{namespace:e,migrationsDir:n}of i)try{Pn(n,e,t.path);let r=zr(n),i=/* @__PURE__ */ new Map,s;for(let e of r)if(e.type===`schema`){let t=Fr(e.path);e.number===0&&(s=t.rebaseline)}else try{let t=Ue(e.path);t.description&&i.set(e.number,t.description)}catch(e){if(o(e)&&e.code===`MIGRATION_FILE_VERSION_UNSUPPORTED`)throw e}a.set(e,{migrationFiles:r,descriptions:i,rebaseline:s})}catch(t){s.set(e,f(t))}if(a.size===0)return i.map(({namespace:e})=>({status:`error`,namespace:e,error:s.get(e)??`Failed to read local migration history.`}));let{client:c,workspaceId:l}=await B({profile:e.profile,workspaceId:e.workspaceId}),u=z({configPath:e.configPath,workspaceId:l,profile:e.profile}),d=[];for(let{namespace:e,migrationsDir:t}of i){if(s.has(e)){d.push({status:`error`,namespace:e,error:s.get(e)??`Failed to read local migration history.`});continue}let n=a.get(e);if(!n){d.push({status:`error`,namespace:e,error:`Failed to read local migration history.`});continue}let{migrationFiles:r,descriptions:i,rebaseline:o}=n,f=o?.historyId??null,p=Kr(l,`tailordb`,e),m;try{m=await ft(c,p)}catch(t){d.push({status:`error`,namespace:e,error:t instanceof Error?t.message:String(t)});continue}let h=m.number??0,g=formatCheckpointRecovery(Je(m,t,o),e,u);if(m.historyIdInvalid){d.push({status:`error`,namespace:e,error:`Remote migration history ID is invalid.`+g});continue}if(m.inProgressInvalid){d.push({status:`error`,namespace:e,error:`Remote in-progress migration record is invalid.`});continue}if(!He(m,f)){d.push({status:`error`,namespace:e,error:`Remote migration history ID ${m.historyId??`<unset>`} does not match local migration history ID ${f??`<unset>`}.`+g});continue}let _=r.map(e=>e.number).filter((e,t,n)=>n.indexOf(e)===t).toSorted((e,t)=>e-t),v=_.at(-1)??0;if(h>v){d.push({status:`error`,namespace:e,error:`Remote migration checkpoint ${F(h)} is ahead of the latest local migration ${F(v)}.`+g});continue}let y=_.filter(e=>e>h).map(e=>({number:e,label:F(e),...i.has(e)?{description:i.get(e)}:{}})),b=Jr(m)?null:m.inProgress;d.push({status:`ok`,namespace:e,currentMigration:h,currentMigrationLabel:F(h),pendingMigrations:y,...b?{inProgressMigration:b.number,inProgressMigrationLabel:F(b.number),inProgressMigrationRun:b.kind,inProgressMigrationActions:Vt({...u,state:m,namespace:e})}:{}})}return d}function printMigrationStatuses(e){for(let t of e)if(m.newline(),m.info(`Namespace: ${s.bold(t.namespace)}`),isStatusFailure(t))m.error(` Migration status error: ${t.error}`);else{if(m.log(` Current migration: ${s.bold(t.currentMigrationLabel)}`),t.inProgressMigrationLabel){m.log(t.inProgressMigrationRun===`main`?` In progress: ${s.bold(t.inProgressMigrationLabel)} (the outcome of its run is not settled)`:` In progress: ${s.bold(t.inProgressMigrationLabel)} (partially applied)`);for(let e of t.inProgressMigrationActions??[])m.log(` ${Tt(e)}`)}if(t.pendingMigrations.length>0){m.log(` Pending migrations:`);for(let e of t.pendingMigrations)e.description?m.log(` - ${e.label}: ${e.description}`):m.log(` - ${e.label}`)}else m.log(` Pending migrations: (none)`)}m.newline()}async function status(e){St(`tailordb migration`);let t=await collectMigrationStatuses(e);e.json?m.out(t):printMigrationStatuses(t);let n=t.filter(isStatusFailure);if(n.length>0){let e=n.map(e=>e.namespace).join(`, `);throw _({code:`MIGRATION_STATUS_FAILED`,message:`Migration status check failed for ${n.length} namespace${n.length===1?``:`s`}: ${e}`})}}const Ss=I({name:`status`,description:`Show the current migration status for TailorDB namespaces, including applied and pending migrations.`,notes:`Local migration files are checked for a valid layout (numbering and required files in each migration directory) and a compatible format version, and deployed migration history IDs must match the local baseline. Invalid or incompatible files, history mismatches, a remote checkpoint ahead of the latest local migration, and metadata lookup failures are reported per namespace and make the command exit non-zero; only a not-yet-deployed namespace is treated as having no applied migrations.`,args:J.strictObject({...w,namespace:G(J.string().optional(),{alias:`n`,description:`Target TailorDB namespace (shows all namespaces if not specified)`})}),run:async e=>{await status({configPath:e.config,namespace:e.namespace,workspaceId:e[`workspace-id`],profile:e.profile,json:m.jsonMode})}});async function runMigrationTest(e,n=createMigrationTestDependencies()){if(e.targetWorkspaceId&&!e.yes)throw _({code:`MIGRATION_TEST_OPTIONS_INVALID`,message:`--target-workspace-id requires --yes because the target may be overwritten.`,command:`tailordb migration test`});if(e.keep&&e.targetWorkspaceId)throw _({code:`MIGRATION_TEST_OPTIONS_INVALID`,message:`--keep applies only to automatically created workspaces; a designated target is always retained.`,command:`tailordb migration test`});if(e.keepTtl!==void 0&&!e.keep)throw _({code:`MIGRATION_TEST_OPTIONS_INVALID`,message:`--keep-ttl was given without --keep.`,suggestion:`Pass --keep together with --keep-ttl, or remove --keep-ttl.`,command:`tailordb migration test`});if(e.cloneTimeout!==void 0&&e.data!==`clone`)throw _({code:`MIGRATION_TEST_OPTIONS_INVALID`,message:`--clone-timeout was given without --data clone.`,suggestion:`Pass --data clone, or remove --clone-timeout.`,command:`tailordb migration test`});if(e.assertionNamespace&&!e.assertionPath)throw _({code:`MIGRATION_TEST_OPTIONS_INVALID`,message:`--assert is required when --assert-namespace is provided.`,command:`tailordb migration test`});let r=await n.prepare(e);if(assertTargetWorkspaceDiffers(r.sourceWorkspaceId,e.targetWorkspaceId),e.assertionPath&&resolveAssertionNamespace(r.pendingNamespaces,e.assertionNamespace),e.data===`clone`&&e.targetWorkspaceId){let e=t(r.designatedTarget,`designated clone target was not loaded during preparation`);assertCloneTargetRegion(r.temporaryWorkspace.region,e.region)}let i=e.targetWorkspaceId===void 0,a=i?await n.createWorkspace(r):{id:t(e.targetWorkspaceId,`designated target workspace missing`),name:void 0,createdAt:void 0},o=e.keepTtl??(e.keep?void 0:`24h`),s=!1;if(i&&o!==void 0)try{await n.recordWorkspaceExpiry(a.id,o,a.createdAt),s=!0}catch(t){m.warn(`Failed to record an expiry on temporary workspace ${a.id}: ${t instanceof Error?t.message:String(t)}. Record one with ${h({command:`tailor`,args:[`workspace`,`ttl`,`set`,`--ttl`,o,`--workspace-id=${a.id}`,...e.profile?[`--profile=${e.profile}`]:[]]})}.`)}let c,l=!1,u=!1;try{let t={prepared:r,targetWorkspaceId:a.id};await n.deployBaseline(t);let i={...t,sourceWorkspaceId:r.sourceWorkspaceId,applicationName:r.sourceApplicationName,cloneTimeout:e.cloneTimeout};e.data===`clone`?await n.cloneData(i):await n.seedData(i);let o={...t,machineUser:e.machineUser};await n.deployMigrations(o),e.assertionPath&&await n.runAssertion({...o,assertionPath:e.assertionPath,assertionNamespace:e.assertionNamespace})}catch(e){c=e,l=!0}if(i&&e.keep)m.info(`Keeping temporary workspace ${a.name??a.id}${s?`; it can be pruned after ${o}`:``}.`);else if(i)try{await n.deleteWorkspace(a.id),u=!0}catch(t){if(!l)throw _({code:`MIGRATION_TEST_WORKSPACE_CLEANUP_FAILED`,message:`Failed to delete temporary workspace ${a.id}: ${t instanceof Error?t.message:String(t)}`,suggestion:e.profile?`Delete the temporary workspace manually with TAILOR_PLATFORM_PROFILE=${e.profile}.`:`Delete the temporary workspace manually.`,next:{command:`tailor`,args:[`workspace`,`delete`,`--workspace-id`,a.id]},cause:t});m.warn(`Failed to delete temporary workspace ${a.id}: ${t instanceof Error?t.message:String(t)}`)}if(l)throw c;return{success:!0,workspaceId:a.id,...a.name?{workspaceName:a.name}:{},temporary:i,deleted:u,data:e.data,pendingNamespaces:r.pendingNamespaces}}async function migrationTest(e){St(`tailordb migration`);let t=await runMigrationTest(e);e.json?m.out(t):m.success(`Pending migrations completed in workspace ${t.workspaceName??t.workspaceId}.`)}const Cs=J.strictObject({organizationId:J.uuid({message:`organization-id must be a valid UUID`}).optional(),folderId:J.uuid({message:`folder-id must be a valid UUID`}).optional()}),ws=I({name:`test`,description:`Test pending migrations with seed fixtures or cloned data in a temporary workspace.`,notes:`The source workspace is read-only. Without --target-workspace-id, the command creates a workspace in the source workspace's region and deletes it after success or failure; pass --keep to retain it for inspection. Right after creating the workspace it records a 24h expiry (unless --keep is given without --keep-ttl), so if the run is interrupted before the command can delete the workspace, workspace prune --expired removes it later. A designated target is retained and requires --yes. Clone mode copies TailorDB records only; it does not copy IdP users or file blobs. With --keep-ttl, the kept workspace records an expiry; it is not deleted automatically, but workspace prune --expired removes it once the expiry has passed. Command-line options take precedence over TAILOR_PLATFORM_ORGANIZATION_ID and TAILOR_PLATFORM_FOLDER_ID, including values loaded by --env-file, and an empty value of either variable is ignored.`,args:J.strictObject({...w,yes:G(J.boolean().default(!1),{alias:`y`,description:`Acknowledge that a designated target workspace may be overwritten`}),data:G(J.enum([`seed`,`clone`]).default(`seed`),{description:`Data source for the migration test (seed or clone)`}),"target-workspace-id":G(J.uuid().optional(),{description:`Existing throwaway workspace to retain after the test (requires --yes)`}),keep:G(J.boolean().default(!1),{description:`Keep the automatically created workspace after the test`}),"organization-id":G(J.string().optional(),{description:`Organization to create the temporary workspace in, at its root unless --folder-id is given (default: the source workspace's organization and folder). With --target-workspace-id, must match the target's organization`,env:`TAILOR_PLATFORM_ORGANIZATION_ID`}),"folder-id":G(J.string().optional(),{description:`Folder to create the temporary workspace in (default: the source workspace's folder). Requires --organization-id when the source workspace is not in an organization. With --target-workspace-id, must match the target's folder`,env:`TAILOR_PLATFORM_FOLDER_ID`}),assert:G(J.string().optional(),{description:`Path to a TypeScript assertion script to run after migrations`,completion:{type:`file`,extensions:[`ts`]}}),"assert-namespace":G(J.string().optional(),{description:`TailorDB namespace exposed to the assertion script`}),"keep-ttl":G(Hr.optional(),{description:`Record an expiry on the kept workspace, e.g. 24h or 7d (${Tn}), so workspace prune --expired can delete it (requires --keep)`,completion:{type:`none`}}),"clone-timeout":G(E.optional(),{description:`How long to wait for the clone to finish with --data clone, e.g. 30s or 10m (default: 30m)`,completion:{type:`none`}}),"machine-user":G(J.string().optional(),{description:`Machine user for seed, migration, and assertion script execution`})}),run:async e=>{await L({profile:e.profile}),await migrationTest({configPath:e.config,workspaceId:e[`workspace-id`],profile:e.profile,data:e.data,targetWorkspaceId:e[`target-workspace-id`],keep:e.keep,keepTtl:e[`keep-ttl`],...Ir(Cs,ae(e)),assertionPath:e.assert,assertionNamespace:e[`assert-namespace`],machineUser:e[`machine-user`],cloneTimeout:e[`clone-timeout`]===void 0?void 0:ce(e[`clone-timeout`]),yes:e.yes,json:m.jsonMode})}});function sectionError(e){return JSON.parse(Wn(e)).error}function assertMigrationScriptsReady(e,t,n){let r=[],i=[],a=[],o=[],s=[];for(let t of zr(e)){if(t.type!==`diff`)continue;let n=Ue(t.path),c=wn(e,t.number,`migrate`),l=X.existsSync(c);l&&s.push([t.number,c]),n.requiresMigrationScript&&!n.scriptSkipped&&!l&&r.push(t.number),n.scriptSkipped&&l&&i.push(t.number),l&&Br(c)>0&&a.push(t.number),n.hasWarnings&&!n.scriptSkipped&&!l&&o.push({migrationNumber:t.number,warnings:n.warnings})}if(r.length>0)throw _({code:`MIGRATION_SCRIPT_REQUIRED`,message:`Migration(s) ${r.map(F).join(`, `)} in namespace "${t}" require a migration script but have no migrate.ts.`,suggestion:`Add one with 'tailor tailordb migration script <number>', or record that no script is needed with 'tailor tailordb migration script <number> --no-script --reason "..."'.`});if(i.length>0){let e=i.map(e=>` ${ur({migrationNumber:e,namespace:t,configPath:n})}`).join(`
106
+ `);throw _({code:`MIGRATION_SCRIPT_SKIP_CONFLICT`,message:`Migration(s) ${i.map(F).join(`, `)} in namespace "${t}" have both a --no-script skip acknowledgment and migrate.ts.`,suggestion:`Clear the stale acknowledgment(s):\n${e}\nOr delete migrate.ts to keep the skip.`})}if(a.length>0)throw _({code:`MIGRATION_SCRIPT_REVIEW_REQUIRED`,message:`Migration(s) ${a.map(F).join(`, `)} in namespace "${t}" still have a TODO() call or review marker in migrate.ts, where the generated script leaves a value or logic for you to decide.`,suggestion:Ur});for(let[e,n]of s){let r=En(n);r.kind===`main`&&r.ignoredSteps&&m.warn(Wt(`${t}/${F(e)}`))}return o}function assertSkipStepsCheckable(e,t,n,r){for(let[i,a]of e){if(!t.has(i)){let e=[...t];throw _({code:`MIGRATION_SKIP_STEPS_INVALID`,message:`Cannot check the steps to skip in namespace '${i}': the config defines no TailorDB namespace with that name.`,suggestion:e.length>0?`Use one of the config's TailorDB namespaces: ${e.join(`, `)}. To check a namespace of another config, run the command with that config.`:`The config defines no TailorDB namespace. Remove --migration-skip-steps.`,context:{namespace:i,requested:[...a],namespaces:e}})}if(!n.has(i))throw yt(i,a);if(r!==void 0&&i!==r)throw _({code:`MIGRATION_VALIDATE_OPTIONS_CONFLICT`,message:`Cannot check the steps to skip in namespace '${i}': --namespace limits validation to '${r}'.`,suggestion:`Remove --namespace, or remove the --migration-skip-steps entries of other namespaces.`,context:{namespace:i,requested:[...a]}})}}async function checkNamespaceInProgress(e){let{checks:t,namespace:n,state:r,pending:i,checkpointRepaired:a}=e,{client:o,workspaceId:s,commandContext:c}=t;if(a&&(r.inProgress||r.inProgressInvalid))throw Bt(n);return await wt({client:o,workspaceId:s,namespace:n,state:r,next:i[0],commandContext:c})}async function reportNamespaceInProgress(e){let{state:t}=e;if(!t.inProgress&&!t.inProgressInvalid)return{};let n=t.inProgress&&!Jr(t)?{migrationNumber:t.inProgress.number}:{};try{let t=await checkNamespaceInProgress(e);return t.kind===`resume`?{report:{valid:!0,migrationNumber:t.inProgress.number},resumed:t.inProgress}:{}}catch(e){if(!o(e))throw e;return{report:{valid:!1,...n,error:sectionError(e)}}}}async function reportPendingScripts(e){let{checks:n,namespace:r,pending:i,resumed:a}=e,s=n.skipSteps.get(r),c=i.filter(e=>e.hasScript).map(e=>e.number);if(c.length===0&&!s)return{};let l;try{l=await qr({client:n.client,workspaceId:n.workspaceId,requested:ht(n.skipSteps,[r]),pendingMigrations:i,inProgressByNamespace:a?{[r]:a}:{},source:{application:n.application,config:n.config}})}catch(e){return!o(e)&&!ct(e)?{report:{valid:!1,migrationNumbers:c,skipped:`check_failed`},error:e}:{report:{valid:!1,migrationNumbers:c,error:sectionError(e)}}}return{report:{valid:!0,migrationNumbers:c,machineUser:t(l?.byNamespace.get(r),`a namespace whose pending scripts can run has a machine user to run them`)}}}async function checkPendingMigrations(e){let n=/* @__PURE__ */ new Map,r=/* @__PURE__ */ new Map,i;for(let{namespace:a,migrationsDir:o}of e.namespaces){let s=e.remoteResults.find(e=>e.namespace===a),c=t(e.remoteStates.get(a),`remote migration state missing for namespace "${a}"`);if(s?.checkpointMissingLocal)continue;let l=s?.checkpointRepair!==void 0,u=Yt(a,o,s?.checkpointRepair?.to??c.number??0),d=await reportNamespaceInProgress({checks:e,namespace:a,state:c,pending:u,checkpointRepaired:l});if(d.report&&n.set(a,d.report),d.report?.valid===!1)continue;let f=await reportPendingScripts({checks:e,namespace:a,pending:u,resumed:d.resumed});f.report&&r.set(a,f.report),i??=f.error}return{inProgressReports:n,scriptReports:r,...i===void 0?{}:{error:i}}}function buildValidationReports(e){let{targetNamespaces:n,migrationFileErrors:r,localResults:i,remoteResults:a,inProgressReports:o,scriptReports:s,unacknowledgedWarnings:c}=e;return n.map(e=>{let n=r.get(e.namespace);if(n!==void 0)return{namespace:e.namespace,valid:!1,migrationFiles:{valid:!1,error:n}};let l=t(i.find(t=>t.namespace===e.namespace),`local schema check result missing for namespace "${e.namespace}"`),u={hasDiff:l.hasDiff,...l.diff?{diff:l.diff}:{}};if(a===void 0)return{namespace:e.namespace,valid:!1,migrationFiles:{valid:!0},localSchema:u,remoteSchema:{skipped:`check_failed`}};let d=t(a.find(t=>t.namespace===e.namespace),`remote schema check result missing for namespace "${e.namespace}"`),f=d.checkpointMissingLocal===!0,p={remoteMigrationNumber:d.remoteMigrationNumber,hasDrift:d.hasDrift,drifts:d.drifts,...d.skipped?{skipped:d.skipped}:{},...d.checkpointUnset?{checkpointUnset:!0}:{},...f?{checkpointMissingLocal:!0}:{},...d.rebaselinePending?{rebaselinePending:d.rebaselinePending}:{},...d.localLatestMigration===void 0?{}:{localLatestMigration:d.localLatestMigration},...d.historyIdMismatch===void 0?{}:{historyIdMismatch:d.historyIdMismatch},...d.checkpointRepair?{checkpointRepair:d.checkpointRepair}:{},...d.unfinishedRemovals?.length?{unfinishedRemovals:d.unfinishedRemovals}:{},...d.interruptedMigration===void 0?{}:{interruptedMigration:d.interruptedMigration}},m=c?.get(e.namespace),h;if(m!==void 0){let e=m.filter(e=>e.migrationNumber>d.remoteMigrationNumber);h={valid:e.length===0,missing:e}}let g=o?.get(e.namespace),_=s?.get(e.namespace);return{namespace:e.namespace,valid:!u.hasDiff&&!p.hasDrift&&!f&&g?.valid!==!1&&_?.valid!==!1&&h?.valid!==!1,migrationFiles:{valid:!0},localSchema:u,remoteSchema:p,...g?{migrationInProgress:g}:{},..._?{pendingMigrationScripts:_}:{},...h?{warningAcknowledgments:h}:{}}})}async function collectValidationReports(e){let{config:t,plugins:n}=await R(e.configPath),r=q.dirname(t.path),i=it(t,r);if(i.length===0)throw bt();let a=e.namespace?i.filter(t=>t.namespace===e.namespace):i;if(a.length===0)throw _({code:`TAILORDB_NAMESPACE_NOT_FOUND`,message:`Namespace "${e.namespace}" not found or does not have migrations configured`});let o=n.length>0?new $i(n):void 0,{defineApplication:s}=await import(`../application-OeNMQzOC.mjs`),c=s({config:t,pluginManager:o});for(let e of c.tailorDBServices)await e.loadTypes(),await e.processNamespacePlugins();Xr({tailorDBServices:c.tailorDBServices});for(let{namespace:e}of a)if(!c.tailorDBServices.some(t=>t.namespace===e))throw _({code:`TAILORDB_NAMESPACE_NOT_FOUND`,message:`No TailorDB service found for namespace "${e}"`});let l=e.migrationSkipSteps??/* @__PURE__ */ new Map;assertSkipStepsCheckable(l,new Set(c.tailorDBServices.map(e=>e.namespace)),new Set(i.map(e=>e.namespace)),e.namespace);let u=c.tailorDBServices.map(Zn),d=new Map(u.map(e=>[e.namespace,e.types])),p=/* @__PURE__ */ new Map,m=[],h=e.strict?/* @__PURE__ */ new Map:void 0;for(let n of a)try{Pn(n.migrationsDir,n.namespace,t.path),V(n.migrationsDir);let r=assertMigrationScriptsReady(n.migrationsDir,n.namespace,e.configPath);h?.set(n.namespace,r),m.push(n)}catch(e){p.set(n.namespace,f(e))}let g={targetNamespaces:a,migrationFileErrors:p,localResults:await Lr(d,m),...h?{unacknowledgedWarnings:h}:{}};if(m.length===0)return{reports:buildValidationReports(g)};let v,y,b,x=/* @__PURE__ */ new Map;try{let n=await B({profile:e.profile,workspaceId:e.workspaceId});y=n.workspaceId,b=n.client,v=await kt(b,y,m,t,u,{acceptUnfinishedRemovals:!0,acceptInterruptedMigration:!0,remoteStates:x})}catch(e){return{reports:buildValidationReports(g),remoteError:e}}let S=await checkPendingMigrations({client:b,workspaceId:y,application:c,config:t,namespaces:m,remoteResults:v,remoteStates:x,skipSteps:l,commandContext:z({configPath:e.configPath,workspaceId:y,profile:e.profile})});return{reports:buildValidationReports({...g,remoteResults:v,inProgressReports:S.inProgressReports,scriptReports:S.scriptReports}),workspaceId:y,...`error`in S?{remoteError:S.error}:{}}}function printSectionError(e,t){let[n,...r]=String(t.message).split(`
107
+ `);m.log(` ${e}: ${s.error(n??``)}`);let i=typeof t.suggestion==`string`?t.suggestion.split(`
108
+ `):[];for(let e of[...r,...i])m.log(e?` ${e}`:``)}function printValidationReports(e){for(let t of e){if(m.newline(),m.info(`Namespace: ${s.bold(t.namespace)}`),!t.migrationFiles.valid){m.log(` Migration files: ${s.error(`invalid`)}`),m.log(` ${t.migrationFiles.error}`);continue}m.log(` Migration files: ${s.success(`OK`)}`);let e=t.localSchema;e?.hasDiff?e.diff?(m.log(` Local schema: ${s.error(`changes not in migration files`)}`),m.log(` ${$e(e.diff)}`),m.log(dt(e.diff))):m.log(` Local schema: ${s.error(`no migration snapshot found`)}`):m.log(` Local schema: ${s.success(`OK`)}`);let n=t.remoteSchema;n?.skipped===`check_failed`?m.log(` Remote schema: ${s.error(`not checked`)}`):n?.checkpointRepair?m.log(` Remote schema: ${s.success(`OK`)} (next deploy will reset the checkpoint to 0000 from ${F(n.checkpointRepair.from)})`):n?.interruptedMigration===void 0?n?.checkpointMissingLocal?(m.log(` Remote schema: ${s.error(`remote migration ${F(n.remoteMigrationNumber)} is not in the local migration history`)}`),n.rebaselinePending&&m.log(` Fell behind before 'migration rebaseline' ran; must reach ${F(n.rebaselinePending.replacedLatestMigration)} first.`)):n?.hasDrift?(m.log(` Remote schema: ${s.error(`drift detected`)} (${n.checkpointUnset?`no checkpoint yet; compared with 0000`:`remote migration: ${F(n.remoteMigrationNumber)}`})`),m.log(hn(n.drifts))):n?.skipped===`not_deployed`?m.log(` Remote schema: ${s.dim(`skipped (namespace not deployed)`)}`):n?.skipped===`no_snapshot`?m.log(` Remote schema: ${s.dim(`skipped (no local snapshot for remote migration ${F(n.remoteMigrationNumber)})`)}`):n?.checkpointUnset?m.log(` Remote schema: ${s.success(`OK`)} (no checkpoint yet; tables match 0000)`):n&&m.log(` Remote schema: ${s.success(`OK`)} (remote migration: ${F(n.remoteMigrationNumber)})`):m.log(` Remote schema: ${s.success(`OK`)} (an earlier deploy left migration ${F(n.interruptedMigration)} without recording it as in progress; the next deploy runs it again from the start)`),n?.unfinishedRemovals&&m.log(` The next deploy deletes ${n.unfinishedRemovals.join(`, `)}, which migration ${F(n.remoteMigrationNumber)} removed.`);let r=t.migrationInProgress;r?.error?printSectionError(`Migration in progress`,r.error):r?.migrationNumber!==void 0&&m.log(` Migration in progress: ${s.success(`OK`)} (the next deploy resumes ${F(r.migrationNumber)})`);let i=t.pendingMigrationScripts;if(i?.skipped===`check_failed`)m.log(` Pending migration scripts: ${s.error(`not checked`)}`);else if(i?.error)printSectionError(`Pending migration scripts`,i.error);else if(i){let e=i.migrationNumbers.map(F).join(`, `);m.log(` Pending migration scripts: ${s.success(`OK`)} (${e} ${i.migrationNumbers.length===1?`runs`:`run`} as '${i.machineUser}')`)}let a=t.warningAcknowledgments;if(a){if(a.valid)m.log(` Warning acknowledgments: ${s.success(`OK`)}`);else{m.log(` Warning acknowledgments: ${s.error(`missing for pending migration(s) with possible data loss`)}`);for(let e of a.missing){let t=F(e.migrationNumber);for(let n of e.warnings){let e=n.fieldName?`.${n.fieldName}`:``;m.log(` ${t}: ${n.tableName}${e}: ${n.reason}`)}}}}}m.newline()}function hasMissingCheckpoint(e){return e.remoteSchema?.checkpointMissingLocal===!0}function remoteDrifts(e){return e.map(e=>({namespace:e.namespace,hasDrift:e.remoteSchema?.hasDrift??!1,drifts:e.remoteSchema?.drifts??[],...e.remoteSchema?.checkpointUnset?{checkpointUnset:!0}:{}}))}function printResolutionHints(e,t){e.some(e=>e.localSchema?.hasDiff&&!e.localSchema.diff)&&m.info(`Run 'tailor tailordb migration generate' to create the initial snapshot.`),e.some(e=>e.localSchema?.diff)&&m.info(`Run 'tailor tailordb migration generate' to create migration files.`),jt(e.filter(hasMissingCheckpoint).map(e=>({namespace:e.namespace,remoteMigrationNumber:e.remoteSchema.remoteMigrationNumber,...e.remoteSchema.rebaselinePending?{rebaselinePending:e.remoteSchema.rebaselinePending}:{}}))),e.some(e=>e.remoteSchema?.hasDrift)&&tr(t,remoteDrifts(e));let n=e.filter(e=>e.warningAcknowledgments&&!e.warningAcknowledgments.valid);if(n.length>0){m.info(`For each migration listed, either add a data migration script with 'tailor tailordb migration script <number>' or record why none is needed:`);for(let e of n)for(let n of e.warningAcknowledgments?.missing??[])m.info(` ${ur({migrationNumber:n.migrationNumber,namespace:e.namespace,configPath:t.configPath,noScript:!0})}`,{mode:`plain`})}}async function validate(e){St(`tailordb migration`);let t=await collectValidationReports(e),{reports:n}=t,r=n.filter(e=>!e.valid).length,i=z({configPath:e.configPath,workspaceId:t.workspaceId,profile:e.profile});if(e.json?m.out(n):(printValidationReports(n),r===0&&!(`remoteError`in t)?m.success(`All migration validation checks passed.`):printResolutionHints(n,i)),`remoteError`in t)throw t.remoteError;if(r>0)throw _({code:`MIGRATION_VALIDATION_FAILED`,message:`Migration validation failed for ${r} namespace(s)`,suggestion:[...ze(n.filter(hasMissingCheckpoint).map(e=>({namespace:e.namespace,...e.remoteSchema,localLatestMigration:e.remoteSchema.localLatestMigration??null,historyIdMismatch:e.remoteSchema.historyIdMismatch??!1})),i),...Ot(remoteDrifts(n),i)].join(`
109
+ `)||void 0})}const Ts=I({name:`validate`,description:`Run the migration and schema-drift checks that 'deploy' runs before changing anything, without deploying, and exit with a non-zero code when issues are found.`,notes:"Migration scripts are checked across the full migration history, not only the pending migrations that `deploy` checks. Like `deploy`, the command bundles only the pending scripts and checks the machine user that runs them.",args:J.strictObject({...w,namespace:G(J.string().optional(),{alias:`n`,description:`Target TailorDB namespace (validates all namespaces if not specified)`}),strict:G(J.boolean().default(!1),{description:`Also fail when a pending migration can drop data without an acknowledgment`}),"migration-skip-steps":G(J.string().optional(),{description:`Also check that 'deploy --migration-skip-steps' can skip these steps of a partially applied multi-step migration, as comma-separated namespace/step entries`})}),run:async e=>{await validate({configPath:e.config,namespace:e.namespace,workspaceId:e[`workspace-id`],profile:e.profile,json:m.jsonMode,strict:e.strict,migrationSkipSteps:vr(e[`migration-skip-steps`])})}}),Es=K({name:`migration`,description:`Manage TailorDB schema migrations (beta).`,subCommands:{generate:Mt,rebaseline:ys,resolve:xs,script:Qe,status:Ss,sync:bs,test:ws,validate:Ts}}),Ds=K({name:`tailordb`,description:`Manage TailorDB tables and data.`,notes:"The `tailordb erd` commands are provided by the @tailor-platform/sdk-plugin-tailordb-erd CLI plugin.",subCommands:{truncate:Et,migration:Es}}),Os=I({name:`upgrade`,description:`Run codemods to upgrade your project to a newer SDK version.`,args:J.strictObject({from:G(J.string(),{description:`SDK version before the upgrade (e.g., 1.33.0)`}),"dry-run":G(J.boolean().default(!1),{alias:`d`,description:`Preview changes without modifying files`}),path:G(J.string().default(`.`),{description:`Project directory to upgrade`,completion:{type:`directory`}})}),run:async e=>{let{initTelemetry:t}=await import(`../telemetry-nqOtDWNO.mjs`);await t();let{upgrade:n}=await import(`../service-B2vx6CGM.mjs`);await n({from:e.from,dryRun:e[`dry-run`],path:q.resolve(e.path)})}}),ks=I({name:`current`,description:`Show current user.`,args:J.strictObject({profile:A.profile}),run:async e=>{let t=await j(),n=e.profile||process.env.TAILOR_PLATFORM_PROFILE,r=n?t.profiles[n]:void 0;if(n&&!r)throw p(n);let i=r?ge(r):void 0,a=n?r?.user??null:t.current_user,o=m.jsonMode;if(!a)throw _({code:`USER_NOT_SET`,message:`Current user not set.`,suggestion:`Log in first to register a user.`,next:{command:`tailor`,args:[`login`,...k({profile:n})]}});if(!_e(t,a,i))throw _({code:`USER_NOT_FOUND`,message:`Current user '${a}' not found in registered users.`,suggestion:`Log in again to register the user.`,next:{command:`tailor`,args:[`login`,...k({profile:n})]}});o?m.out({user:a}):m.out(a)}});function activeCurrentUserKey(e,t){if(!t)return e.current_user?je(e,e.current_user):null;let n=e.profiles[t];if(!n)throw p(t);return je(e,n.user,ge(n))}function toUserListInfo(e,t){let n=e.indexOf(`|`),r=n===-1?null:e.slice(0,n);return{user:n===-1?e:e.slice(n+1),platformUrl:r,current:t===e}}function formatUserListInfo(e){return`${e.user}${e.platformUrl?` [${e.platformUrl}]`:``}${e.current?` (current)`:``}`}const As=I({name:`list`,description:`List all users.`,args:J.strictObject({profile:A.profile}),run:async e=>{let t=await j(),n=m.jsonMode,r=activeCurrentUserKey(t,e.profile||process.env.TAILOR_PLATFORM_PROFILE),i=Object.keys(t.users);if(i.length===0){m.info(H`
105
110
  No users found.
106
111
  Please login first using 'tailor login' command to register a user.
107
- `),n&&y.out([]);return}let a=i.map(e=>toUserListInfo(e,r));n?y.out([...new Set(a.map(e=>e.user))]):a.forEach(e=>{e.current?y.success(formatUserListInfo(e),{mode:`plain`}):y.log(formatUserListInfo(e))})}}),$o={[t.PAT_SCOPE_UNSPECIFIED]:`unknown`,[t.PAT_SCOPE_READ]:`read`,[t.PAT_SCOPE_WRITE]:`write`};function patScopeToString(e){return Gn($o,e,`unknown`)}function transformPersonalAccessToken(e){return{name:e.name,scopes:e.scopes.map(patScopeToString),createdAt:$t(e.createdAt),lastUsedAt:$t(e.lastUsedAt)}}function getScopesFromWriteFlag(e){return e?[t.PAT_SCOPE_READ,t.PAT_SCOPE_WRITE]:[t.PAT_SCOPE_READ]}function getScopeStringsFromWriteFlag(e){return e?[`read`,`write`]:[`read`]}function printCreatedToken(e,t,n,r){let i=getScopeStringsFromWriteFlag(n);y.jsonMode?y.out({name:e,scopes:i,token:t}):y.out(W`
112
+ `),n&&m.out([]);return}let a=i.map(e=>toUserListInfo(e,r));n?m.out([...new Set(a.map(e=>e.user))]):a.forEach(e=>{e.current?m.success(formatUserListInfo(e),{mode:`plain`}):m.log(formatUserListInfo(e))})}}),js={[Vi.PAT_SCOPE_UNSPECIFIED]:`unknown`,[Vi.PAT_SCOPE_READ]:`read`,[Vi.PAT_SCOPE_WRITE]:`write`};function patScopeToString(e){return Un(js,e,`unknown`)}function transformPersonalAccessToken(e){return{name:e.name,scopes:e.scopes.map(patScopeToString),createdAt:jn(e.createdAt),lastUsedAt:jn(e.lastUsedAt)}}function getScopesFromWriteFlag(e){return e?[Vi.PAT_SCOPE_READ,Vi.PAT_SCOPE_WRITE]:[Vi.PAT_SCOPE_READ]}function getScopeStringsFromWriteFlag(e){return e?[`read`,`write`]:[`read`]}function printCreatedToken(e,t,n,r){let i=getScopeStringsFromWriteFlag(n);m.jsonMode?m.out({name:e,scopes:i,token:t}):m.out(H`
108
113
  Personal access token ${r} successfully.
109
114
 
110
115
  name: ${e}
@@ -112,21 +117,21 @@ Error:`));let e=formatErrorWithSourcemap(v.error,f,process.cwd());e?y.log(e):y.l
112
117
  token: ${t}
113
118
 
114
119
  Please save this token in a secure location. You won't be able to see it again.
115
- `)}async function createPatOperatorClient(e){let t=await yt({profile:e});return await si(t)}const es=z({name:`create`,description:`Create a new personal access token.`,args:J.strictObject({name:G(J.string(),{positional:!0,description:`Token name`}),write:G(J.boolean().default(!1),{alias:`W`,description:`Grant write permission (default: read-only)`}),profile:P.profile}),run:async e=>{await O({profile:e.profile});let t=await createPatOperatorClient(e.profile),n=getScopesFromWriteFlag(e.write),r=await t.createPersonalAccessToken({name:e.name,scopes:n});if(!r.accessToken)throw g(`Failed to create personal access token`);y.registerSecret(r.accessToken),printCreatedToken(e.name,r.accessToken,e.write,`created`)}}),ts=z({name:`delete`,description:`Delete a personal access token.`,args:J.strictObject({name:G(J.string(),{positional:!0,description:`Token name`}),profile:P.profile}),run:async e=>{await O({profile:e.profile}),await(await createPatOperatorClient(e.profile)).deletePersonalAccessToken({name:e.name}),y.success(`Personal access token "${e.name}" deleted successfully.`),N({changed:!0,name:e.name})}}),ns=z({name:`list`,description:`List all personal access tokens.`,args:J.strictObject({...Tr(),profile:P.profile}),run:async e=>{let t=y.jsonMode,n=await createPatOperatorClient(e.profile),r=de(e.order),i=await kn(e.limit,e=>$r(async(e,t)=>{let{personalAccessTokens:i,nextPageToken:a}=await n.listPersonalAccessTokens({pageToken:e,pageSize:t,pageDirection:r});return[i,a]},{limit:e})),a=i.items;if(a.length===0&&(y.info(W`
120
+ `)}async function createPatOperatorClient(e){let t=await ue({profile:e});return await Di(t)}const Ms=I({name:`create`,description:`Create a new personal access token.`,args:J.strictObject({name:G(J.string(),{positional:!0,description:`Token name`}),write:G(J.boolean().default(!1),{alias:`W`,description:`Grant write permission (default: read-only)`}),profile:A.profile}),run:async e=>{await L({profile:e.profile});let t=await createPatOperatorClient(e.profile),n=getScopesFromWriteFlag(e.write),r=await t.createPersonalAccessToken({name:e.name,scopes:n});if(!r.accessToken)throw u(`Failed to create personal access token`);m.registerSecret(r.accessToken),printCreatedToken(e.name,r.accessToken,e.write,`created`)}}),Ns=I({name:`delete`,description:`Delete a personal access token.`,args:J.strictObject({name:G(J.string(),{positional:!0,description:`Token name`}),profile:A.profile}),run:async e=>{await L({profile:e.profile}),await(await createPatOperatorClient(e.profile)).deletePersonalAccessToken({name:e.name}),m.success(`Personal access token "${e.name}" deleted successfully.`),N({changed:!0,name:e.name})}}),Ps=I({name:`list`,description:`List all personal access tokens.`,args:J.strictObject({...oe(),profile:A.profile}),run:async e=>{let t=m.jsonMode,n=await createPatOperatorClient(e.profile),r=we(e.order),i=await rn(e.limit,e=>Pi(async(e,t)=>{let{personalAccessTokens:i,nextPageToken:a}=await n.listPersonalAccessTokens({pageToken:e,pageSize:t,pageDirection:r});return[i,a]},{limit:e})),a=i.items;if(a.length===0&&(m.info(H`
116
121
  No personal access tokens found.
117
122
  Please create a token using 'tailor user pat create' command.
118
- `),!t))return;let o=a.map(transformPersonalAccessToken);y.out(o,{display:{scopes:e=>e.join(`/`),lastUsedAt:e=>e===null?`never`:un(e)}}),await D(i,e.limit)}}),rs=z({name:`update`,description:`Update a personal access token (delete and recreate).`,args:J.strictObject({name:G(J.string(),{positional:!0,description:`Token name`}),write:G(J.boolean().default(!1),{alias:`W`,description:`Grant write permission (if not specified, keeps read-only)`}),profile:P.profile}),run:async e=>{await O({profile:e.profile});let t=await createPatOperatorClient(e.profile);await t.deletePersonalAccessToken({name:e.name});let n=getScopesFromWriteFlag(e.write),r=await t.createPersonalAccessToken({name:e.name,scopes:n});if(!r.accessToken)throw g(`Failed to create personal access token`);y.registerSecret(r.accessToken),printCreatedToken(e.name,r.accessToken,e.write,`updated`)}}),is=K({name:`pat`,description:`Manage personal access tokens.`,subCommands:{list:ns,create:es,delete:ts,update:rs},defaultSubCommand:`list`}),as=z({name:`switch`,description:`Set current user.`,args:J.strictObject({user:G(J.string(),{positional:!0,description:`User email address or machine user client ID`}),profile:P.profile}),run:async e=>{let t=await F(),n=e.profile||process.env.TAILOR_PLATFORM_PROFILE,r=n?t.profiles[n]:void 0;if(n&&!r)throw v(n);let i=r?At(r):void 0;if(e.user.includes(`|`))throw S({code:`USER_NAME_INVALID`,message:`User "${e.user}" looks like a platform-scoped token key. Pass the user name without the platform URL and select the platform with TAILOR_PLATFORM_URL or a profile.`,command:`user switch`});let a=nn(t,e.user,i);if(!a)throw S({code:`USER_NOT_FOUND`,message:`User "${e.user}" not found.`,suggestion:`Log in first to register this user.`,next:{command:`tailor`,args:[`login`,...H({profile:n})]}});let o=r?r.user:t.current_user;r?r.user=a:t.current_user=a,I(t),y.success(`Current user set to "${a}" successfully.`),N({changed:o!==a,user:a,profile:n||null})}}),os=J.union([J.uuid(),J.literal(``)]),ss=z({name:`update`,description:`Set the current user's default organization and folder for new workspaces.`,notes:W`
123
+ `),!t))return;let o=a.map(transformPersonalAccessToken);m.out(o,{display:{scopes:e=>e.join(`/`),lastUsedAt:e=>e===null?`never`:Rn(e)}}),await M(i,e.limit)}}),Fs=I({name:`update`,description:`Update a personal access token (delete and recreate).`,args:J.strictObject({name:G(J.string(),{positional:!0,description:`Token name`}),write:G(J.boolean().default(!1),{alias:`W`,description:`Grant write permission (if not specified, keeps read-only)`}),profile:A.profile}),run:async e=>{await L({profile:e.profile});let t=await createPatOperatorClient(e.profile);await t.deletePersonalAccessToken({name:e.name});let n=getScopesFromWriteFlag(e.write),r=await t.createPersonalAccessToken({name:e.name,scopes:n});if(!r.accessToken)throw u(`Failed to create personal access token`);m.registerSecret(r.accessToken),printCreatedToken(e.name,r.accessToken,e.write,`updated`)}}),Is=K({name:`pat`,description:`Manage personal access tokens.`,subCommands:{list:Ps,create:Ms,delete:Ns,update:Fs},defaultSubCommand:`list`}),Ls=I({name:`switch`,description:`Set current user.`,args:J.strictObject({user:G(J.string(),{positional:!0,description:`User email address or machine user client ID`}),profile:A.profile}),run:async e=>{let t=await j(),n=e.profile||process.env.TAILOR_PLATFORM_PROFILE,r=n?t.profiles[n]:void 0;if(n&&!r)throw p(n);let i=r?ge(r):void 0;if(e.user.includes(`|`))throw _({code:`USER_NAME_INVALID`,message:`User "${e.user}" looks like a platform-scoped token key. Pass the user name without the platform URL and select the platform with TAILOR_PLATFORM_URL or a profile.`,command:`user switch`});let a=Me(t,e.user,i);if(!a)throw _({code:`USER_NOT_FOUND`,message:`User "${e.user}" not found.`,suggestion:`Log in first to register this user.`,next:{command:`tailor`,args:[`login`,...k({profile:n})]}});let o=r?r.user:t.current_user;r?r.user=a:t.current_user=a,O(t),m.success(`Current user set to "${a}" successfully.`),N({changed:o!==a,user:a,profile:n||null})}}),Rs=J.union([J.uuid(),J.literal(``)]),zs=I({name:`update`,description:`Set the current user's default organization and folder for new workspaces.`,notes:H`
119
124
  \`workspace create\`, workspace creation during \`deploy\`, and the programmatic \`createWorkspace()\` use the default folder, or directly use the default organization when no folder is set. Every workspace belongs to an organization, so creation fails when neither the command nor these defaults give one. Giving either an organization or a folder replaces both defaults for that run. For the CLI, use --organization-id or --folder-id, or TAILOR_PLATFORM_ORGANIZATION_ID / TAILOR_PLATFORM_FOLDER_ID. The defaults are not used while TAILOR_PLATFORM_TOKEN is set, because that token does not belong to a user logged in here.
120
125
 
121
126
  Each run replaces both defaults: --default-organization-id alone clears the default folder, --default-folder-id is accepted only together with --default-organization-id, and --default-organization-id "" clears both. The IDs are not checked against the Platform here; \`workspace create\` and \`deploy\` point back to them when the Platform cannot find them or denies access to them.
122
127
 
123
128
  The defaults belong to this user's login on the selected platform, so \`logout\` removes them, and older SDK versions drop them when they rewrite the CLI config file.
124
- `,args:J.strictObject({"default-organization-id":G(os.optional(),{alias:`o`,description:"Organization that `workspace create` uses when no location is given. Pass an empty string to clear the defaults."}),"default-folder-id":G(os.optional(),{alias:`f`,description:"Folder in the default organization that `workspace create` uses (requires --default-organization-id)"}),profile:P.profile}),run:async e=>{let t=e[`default-organization-id`],n=e[`default-folder-id`];if(t===void 0&&n===void 0)throw S({code:`USER_UPDATE_EMPTY`,message:`Please provide at least one property to update.`,command:`user update`});if(t===void 0||t===``&&n)throw S({code:`USER_DEFAULT_FOLDER_WITHOUT_ORGANIZATION`,message:`--default-folder-id requires a --default-organization-id.`,suggestion:`Pass the organization that owns the folder with --default-organization-id.`,command:`user update`});let r=await F(),i=lr(r,{profile:e.profile});if(!i){let t=e.profile||process.env.TAILOR_PLATFORM_PROFILE;throw v(s(t,`Only a named profile can be missing`))}let{profile:a,user:o,userEntry:c}=i,l={command:`tailor`,args:[`login`,...H({profile:a})]};if(!o)throw S({code:`USER_NOT_SET`,message:`Current user not set.`,suggestion:`Log in first to register a user.`,next:l});if(!c)throw S({code:`USER_NOT_FOUND`,message:`User "${o}" has no login of its own on the selected platform.`,suggestion:`Log in on that platform to store the defaults with that login.`,next:l});let u=c.default_organization_id??null,d=c.default_folder_id??null;delete c.default_organization_id,delete c.default_folder_id,t&&(c.default_organization_id=t,n&&(c.default_folder_id=n)),I(r);let f=c.default_organization_id??null,p=c.default_folder_id??null;y.success(f?`Default organization for new workspaces set to ${f} ${p?`with folder ${p}`:`with no default folder`}.`:`Default organization and folder for new workspaces cleared.`),f&&Ot()&&y.warn("`workspace create` does not use these defaults while TAILOR_PLATFORM_TOKEN is set."),N({changed:u!==f||d!==p,user:o,profile:a||null,defaultOrganizationId:f,defaultFolderId:p})}}),cs=K({name:`user`,description:`Manage Tailor Platform users.`,subCommands:{current:Zo,list:Qo,switch:as,update:ss,pat:is},defaultSubCommand:`list`}),ls=K({name:`workflow`,description:`Manage workflows and workflow executions.`,subCommands:{list:On,get:Ae,start:Ze,wait:lt,executions:it,resume:ue},defaultSubCommand:`list`}),us=K({name:`app`,description:`Manage workspace applications`,subCommands:{health:xr,list:at},defaultSubCommand:`list`}),locationIdsArg=()=>J.array(J.union([J.literal(``),J.uuid()])).optional(),ds=J.preprocess(e=>typeof e==`string`&&e.trim()===``?NaN:e,J.coerce.number().int().nonnegative());function matchesName(e,t){return t.nameRegexes.length===0||t.nameRegexes.some(t=>t.test(e.name))}function hasLocation(e){return e.organizationRoots.length>0||e.folderIds.length>0||e.personal}function matchesScope(e,t){return hasLocation(t)?e.folderId?t.folderIds.includes(e.folderId):e.organizationId?t.organizationRoots.includes(e.organizationId):t.personal:!0}function staleCandidateReason(e,t){if(e.deleteProtection)return`delete protection was turned on`;if(!matchesScope(e,t))return`it moved outside the requested scope`;if(!matchesName(e,t))return`it no longer matches the name filter`;if(t.exclude.has(e.name))return`it is now excluded by --exclude`}function selectPruneCandidates(e,t,n){let r={candidates:[],excluded:[],protectedSkipped:[],missingCreateTime:[],tooYoung:[]};for(let i of e)if(matchesScope(i,t)&&matchesName(i,t)){if(t.exclude.has(i.name))r.excluded.push(i);else if(i.deleteProtection)r.protectedSkipped.push(i);else{if(t.olderThanMs!==void 0){let e=$t(i.createTime);if(!e){r.missingCreateTime.push(i);continue}if(e.getTime()>n.getTime()-t.olderThanMs){r.tooYoung.push(i);continue}}r.candidates.push(i)}}return r}async function partitionByExpiry(e,t,n){let r=bi(),i=await Promise.all(t.map(async t=>({workspace:t,result:await r(()=>Rn(e,t.id,n))}))),a={expired:[],pending:[],unset:[],unreadable:[]};for(let{workspace:e,result:t}of i)`error`in t?a.unreadable.push({workspace:e,reason:t.error.message}):recordExpiryState(a,e,t.expiry);return a}function recordExpiryState(e,t,n){switch(n.state){case`expired`:e.expired.push(t);return;case`pending`:e.pending.push(t);return;case`unset`:e.unset.push(t);return;case`invalid`:e.unreadable.push({workspace:t,reason:`recorded expiry "${n.value}" is not a value this CLI wrote`})}}async function fetchAllWorkspaces(e){return $r(async(t,n)=>{let{workspaces:r,nextPageToken:i}=await e.listWorkspaces({pageToken:t,pageSize:n});return[r,i]})}function compileNameRegex(e){try{return new RegExp(e),RegExp(`^(?:${e})$`)}catch(t){throw S({code:`INVALID_NAME_PATTERN`,message:`Invalid --name "${e}".`,details:t instanceof Error?t.message:String(t)})}}const fs=[{key:`excluded`,selection:`excluded`,reason:`excluded by --exclude`},{key:`deleteProtection`,selection:`protectedSkipped`,reason:`delete protection is on`},{key:`unknownAge`,selection:`missingCreateTime`,reason:`creation time is unknown`}],ps="Specify --organization-root, --folder-id, or --personal on the command line. The default organization/folder set by `tailor user update` is not used by prune.",ms=z({name:`prune`,description:`Delete stale temporary workspaces, by name and age or by the expiry each recorded at creation.`,notes:W`
129
+ `,args:J.strictObject({"default-organization-id":G(Rs.optional(),{alias:`o`,description:"Organization that `workspace create` uses when no location is given. Pass an empty string to clear the defaults."}),"default-folder-id":G(Rs.optional(),{alias:`f`,description:"Folder in the default organization that `workspace create` uses (requires --default-organization-id)"}),profile:A.profile}),run:async e=>{let n=e[`default-organization-id`],r=e[`default-folder-id`];if(n===void 0&&r===void 0)throw _({code:`USER_UPDATE_EMPTY`,message:`Please provide at least one property to update.`,command:`user update`});if(n===void 0||n===``&&r)throw _({code:`USER_DEFAULT_FOLDER_WITHOUT_ORGANIZATION`,message:`--default-folder-id requires a --default-organization-id.`,suggestion:`Pass the organization that owns the folder with --default-organization-id.`,command:`user update`});let i=await j(),a=ne(i,{profile:e.profile});if(!a){let n=e.profile||process.env.TAILOR_PLATFORM_PROFILE;throw p(t(n,`Only a named profile can be missing`))}let{profile:o,user:s,userEntry:c}=a,l={command:`tailor`,args:[`login`,...k({profile:o})]};if(!s)throw _({code:`USER_NOT_SET`,message:`Current user not set.`,suggestion:`Log in first to register a user.`,next:l});if(!c)throw _({code:`USER_NOT_FOUND`,message:`User "${s}" has no login of its own on the selected platform.`,suggestion:`Log in on that platform to store the defaults with that login.`,next:l});let u=c.default_organization_id??null,d=c.default_folder_id??null;delete c.default_organization_id,delete c.default_folder_id,n&&(c.default_organization_id=n,r&&(c.default_folder_id=r)),O(i);let f=c.default_organization_id??null,h=c.default_folder_id??null;m.success(f?`Default organization for new workspaces set to ${f} ${h?`with folder ${h}`:`with no default folder`}.`:`Default organization and folder for new workspaces cleared.`),f&&le()&&m.warn("`workspace create` does not use these defaults while TAILOR_PLATFORM_TOKEN is set."),N({changed:u!==f||d!==h,user:s,profile:o||null,defaultOrganizationId:f,defaultFolderId:h})}}),Bs=K({name:`user`,description:`Manage Tailor Platform users.`,subCommands:{current:ks,list:As,switch:Ls,update:zs,pat:Is},defaultSubCommand:`list`}),Vs=K({name:`workflow`,description:`Manage workflows and workflow executions.`,subCommands:{list:$n,get:pt,start:Ft,wait:Gt,executions:Ht,resume:Ke},defaultSubCommand:`list`}),Hs=K({name:`app`,description:`Manage workspace applications`,subCommands:{health:Pr,list:Ut},defaultSubCommand:`list`}),locationIdsArg=()=>J.array(J.union([J.literal(``),J.uuid()])).optional(),Us=J.preprocess(e=>typeof e==`string`&&e.trim()===``?NaN:e,J.coerce.number().int().nonnegative());function matchesName(e,t){return t.nameRegexes.length===0||t.nameRegexes.some(t=>t.test(e.name))}function hasLocation(e){return e.organizationRoots.length>0||e.folderIds.length>0}function matchesScope(e,t){return hasLocation(t)?e.folderId?t.folderIds.includes(e.folderId):t.organizationRoots.includes(e.organizationId):!0}function staleCandidateReason(e,t){if(e.deleteProtection)return`delete protection was turned on`;if(!matchesScope(e,t))return`it moved outside the requested scope`;if(!matchesName(e,t))return`it no longer matches the name filter`;if(t.exclude.has(e.name))return`it is now excluded by --exclude`}function selectPruneCandidates(e,t,n){let r={candidates:[],excluded:[],protectedSkipped:[],missingCreateTime:[],tooYoung:[]};for(let i of e)if(matchesScope(i,t)&&matchesName(i,t)){if(t.exclude.has(i.name))r.excluded.push(i);else if(i.deleteProtection)r.protectedSkipped.push(i);else{if(t.olderThanMs!==void 0){let e=jn(i.createTime);if(!e){r.missingCreateTime.push(i);continue}if(e.getTime()>n.getTime()-t.olderThanMs){r.tooYoung.push(i);continue}}r.candidates.push(i)}}return r}async function partitionByExpiry(e,t,n){let r=Ri(),i=await Promise.all(t.map(async t=>({workspace:t,result:await r(()=>or(e,t.id,n))}))),a={expired:[],pending:[],unset:[],unreadable:[]};for(let{workspace:e,result:t}of i)`error`in t?a.unreadable.push({workspace:e,reason:t.error.message}):recordExpiryState(a,e,t.expiry);return a}function recordExpiryState(e,t,n){switch(n.state){case`expired`:e.expired.push(t);return;case`pending`:e.pending.push(t);return;case`unset`:e.unset.push(t);return;case`invalid`:e.unreadable.push({workspace:t,reason:`recorded expiry "${n.value}" is not a value this CLI wrote`})}}async function fetchAllWorkspaces(e){return Pi(async(t,n)=>{let{workspaces:r,nextPageToken:i}=await e.listWorkspaces({pageToken:t,pageSize:n});return[r,i]})}function compileNameRegex(e){try{return new RegExp(e),RegExp(`^(?:${e})$`)}catch(t){throw _({code:`INVALID_NAME_PATTERN`,message:`Invalid --name "${e}".`,details:t instanceof Error?t.message:String(t)})}}const Ws=[{key:`excluded`,selection:`excluded`,reason:`excluded by --exclude`},{key:`deleteProtection`,selection:`protectedSkipped`,reason:`delete protection is on`},{key:`unknownAge`,selection:`missingCreateTime`,reason:`creation time is unknown`}],Gs="Specify --organization-root or --folder-id on the command line. The default organization/folder set by `tailor user update` is not used by prune.",Ks=I({name:`prune`,description:`Delete stale temporary workspaces, by name and age or by the expiry each recorded at creation.`,notes:H`
125
130
  Use this to reclaim workspaces left behind by CI runs, preview deployments, or interrupted local test runs. A workspace is deleted only when its whole name matches a --name pattern, it was created at least --older-than ago, and it is not excluded, delete-protected, or outside the requested locations. Run with --dry-run first to see what would be deleted.
126
131
 
127
132
  With --expired the workspaces select themselves instead: each one is deleted only once the --ttl expiry it recorded at creation has passed, so callers need no --name or --older-than. A workspace that records no expiry is never deleted this way, and neither is one whose recorded expiry cannot be read. Because that expiry is recorded on the workspace rather than derived from its name, anything able to write the workspace's metadata can bring its deletion forward -- and writing a workspace's metadata is a lesser permission than deleting it. --expired therefore requires at least one location, and --name still applies on top.
128
133
 
129
- Every workspace lives in exactly one location, and the location options name them explicitly: --organization-root selects the workspaces directly under an organization and none inside its folders, --folder-id selects the workspaces in one folder, and --personal selects the workspaces belonging to no organization and no folder. Each option can be given more than once, they combine as a union, and none of them is read from the environment or from the default organization/folder set by \`user update\` -- a sweep covers exactly the locations spelled out on the command line. Selecting --personal is a deliberate choice to accept, for every organization-less workspace visible to this login, the expiry that anyone able to write a workspace's metadata may have recorded. Without any location option, a --name / --older-than sweep considers every visible workspace.
134
+ Every workspace lives in exactly one location, and the location options name them explicitly: --organization-root selects the workspaces directly under an organization and none inside its folders, and --folder-id selects the workspaces in one folder. Each option can be given more than once, they combine as a union, and none of them is read from the environment or from the default organization/folder set by \`user update\` -- a sweep covers exactly the locations spelled out on the command line. Without any location option, a --name / --older-than sweep considers every visible workspace.
130
135
 
131
136
  Without a location option, prune warns before listing workspaces that every workspace visible to this login is a candidate for the name and age filters, even with --yes or --dry-run. The default organization/folder set by \`tailor user update\` is not used.
132
137
 
@@ -135,14 +140,15 @@ Error:`));let e=formatErrorWithSourcemap(v.error,f,process.cwd());e?y.log(e):y.l
135
140
  Safety guards: the command aborts without deleting anything when more workspaces match than --limit allows (--dry-run still lists them all), both --expired and --older-than 0s (no age check) are only accepted together with at least one location option, and a location option that resolves to an empty value (an unset CI secret) is rejected instead of silently widening the sweep -- even when another location is given alongside it. Each workspace is re-read immediately before it is deleted and skipped when it no longer matches the name, location, exclusion, or delete-protection criteria that selected it. Unlike \`workspace delete\`, a single confirmation covers every listed candidate; pass --yes to skip it in CI. Deleted workspaces can be restored with \`workspace restore\` for a limited time.
136
141
 
137
142
  Only workspaces visible to the current login (or the machine user in CI) are considered.
138
- `,args:J.strictObject({name:G(J.array(J.string().min(1)).optional(),{description:`Select workspaces whose whole name matches this regular expression (repeatable)`}),"older-than":G(Ft.optional(),{description:`Minimum age since creation, such as 30m, 24h, or 7d. 0s disables the age check and requires a location. Required unless --expired is given`}),expired:G(J.boolean().default(!1),{description:`Select workspaces whose own --ttl expiry has passed, instead of by name and age. Requires --organization-root, --folder-id, or --personal`}),"organization-root":G(locationIdsArg(),{placeholder:`ORGANIZATION_ID`,description:`Consider the workspaces directly under this organization, excluding those in its folders (repeatable)`}),"folder-id":G(locationIdsArg(),{description:`Consider the workspaces in this folder (repeatable)`}),personal:G(J.boolean().default(!1),{description:`Consider the workspaces belonging to no organization and no folder`}),exclude:G(J.array(J.string().min(1)).optional(),{description:`Keep a workspace with this exact name even when it matches (repeatable)`}),limit:G(ds.default(20),{description:`Abort when more workspaces match than this, without deleting anything. 0 removes the cap`}),"dry-run":G(J.boolean().default(!1),{description:`List the workspaces that would be deleted without deleting them`}),profile:G(ce.optional(),{description:`Workspace profile used for authentication and Platform selection`,env:`TAILOR_PLATFORM_PROFILE`}),...L}),run:async e=>{let t=e.name??[],n=e[`older-than`];if(e.expired&&n!==void 0)throw S({code:`CONFLICTING_AGE_FILTER`,message:`--expired and --older-than cannot be combined.`,details:`--expired defers to the expiry each workspace recorded at creation, which --older-than would override.`});if(!e.expired&&n===void 0)throw S({code:`MISSING_AGE_FILTER`,message:`Specify --older-than, or --expired to use each workspace's recorded expiry.`});if(!e.expired&&t.length===0)throw S({code:`MISSING_NAME_FILTER`,message:`Specify at least one --name.`,details:`Only workspaces whose name matches the filter are considered for deletion.`});let r=e[`organization-root`]??[],i=e[`folder-id`]??[],a=[[`--organization-root`,r],[`--folder-id`,i]].filter(([,e])=>e.includes(``)).map(([e])=>e);if(a.length>0)throw S({code:`EMPTY_SCOPE`,message:`${a.join(` and `)} resolved to an empty value.`,details:`An empty location is indistinguishable from an omitted one, so the sweep would not cover what the caller meant. This usually means an unset CI secret.`,suggestion:`Set the id, or drop the option on purpose.`});let o=n===void 0?void 0:vr(n),s={nameRegexes:t.map(compileNameRegex),...o===void 0?{}:{olderThanMs:o},organizationRoots:r,folderIds:i,personal:e.personal,exclude:new Set(e.exclude??[])};if(e.expired&&!hasLocation(s))throw S({code:`UNSCOPED_EXPIRED`,message:`--expired requires --organization-root, --folder-id, or --personal.`,suggestion:ps,details:`The expiry lives on the workspace, and writing a workspace's metadata is a lesser permission than deleting it, so an unscoped sweep would delete on behalf of anyone able to write that metadata.`});if(o===0&&!hasLocation(s))throw S({code:`UNSCOPED_ZERO_AGE`,message:`--older-than 0s requires --organization-root, --folder-id, or --personal.`,suggestion:ps,details:`Without an age check the name filter is the only guard, so the sweep must name the organization roots, folders, or personal workspaces it covers.`});await O({profile:e.profile}),hasLocation(s)||y.warn(`No location was specified. Every workspace visible to this login is a candidate for the name and age filters. ${ps}`);let c=await yt({profile:e.profile}),l=await Ie({profile:e.profile}),u=await si(c,l),d=/* @__PURE__ */ new Date,f=selectPruneCandidates(await fetchAllWorkspaces(u),s,d),p={dryRun:e[`dry-run`],candidates:[],deleted:[],failed:[],skipped:{excluded:[],deleteProtection:[],unknownAge:[],notExpired:[],noExpiry:[],unreadableExpiry:[],expiryChanged:[],changed:[]}};if(e.expired){let e=await partitionByExpiry(u,f.candidates,d);f.candidates=e.expired;for(let t of e.pending)p.skipped.notExpired.push(t.name);for(let t of e.unset)p.skipped.noExpiry.push(t.name);for(let{workspace:t,reason:n}of e.unreadable)p.skipped.unreadableExpiry.push(t.name),y.warn(`Keeping ${t.name} (${t.id}): ${n}.`);y.info(`${e.pending.length} workspace(s) have not expired and ${e.unset.length} record no expiry; both were kept.`)}for(let{key:e,selection:t,reason:n}of fs)for(let r of f[t])p.skipped[e].push(r.name),y.warn(`Keeping ${r.name} (${r.id}): ${n}.`);if(f.tooYoung.length>0&&y.info(`${f.tooYoung.length} matching workspace(s) are younger than ${e[`older-than`]} and were kept.`),f.candidates.length===0){y.info(`No stale workspaces matched.`),y.jsonMode&&y.out(p);return}let m=e.limit>0&&f.candidates.length>e.limit;if(m&&!e[`dry-run`])throw S({code:`PRUNE_LIMIT_EXCEEDED`,message:`${f.candidates.length} workspaces matched, but --limit is ${e.limit}. Nothing was deleted.`,details:`A match count this high usually means the name filter is broader than intended.`,suggestion:`Check the filter with --dry-run, then raise --limit (or pass --limit 0) if every match should be deleted.`});if(p.candidates=await Yt(u,f.candidates),y.jsonMode||y.out(p.candidates,{display:{name:Nn,folderName:null,organizationId:null,folderId:null,updatedAt:null}}),e[`dry-run`]){m&&y.warn(`${p.candidates.length} workspaces matched, but --limit is ${e.limit}: a real run would abort without deleting anything.`),y.info(`Dry run: ${p.candidates.length} workspace(s) would be deleted.`),y.jsonMode&&y.out(p);return}if(!e.yes&&!await R.confirm({message:`Delete these ${p.candidates.length} workspace(s)? They can be restored with "tailor workspace restore" for a limited time.`,default:!1}))throw S({code:`PRUNE_CANCELLED`,message:`Prune cancelled. No workspaces were deleted.`});let h=/* @__PURE__ */ new Set;for(let t of p.candidates){let n=or(t);try{let{workspace:r}=await u.getWorkspace({workspaceId:t.id}),i=r?staleCandidateReason(r,s):void 0;if(i){p.skipped.changed.push(t.name),y.warn(`Keeping ${n} (${t.id}): ${i}.`);continue}if(e.expired){let e=await Rn(u,t.id,/* @__PURE__ */ new Date);if(`error`in e&&e.error instanceof Q&&e.error.code===Z.NotFound)throw e.error;if((`error`in e?`unreadable`:e.expiry.state)!==`expired`){p.skipped.expiryChanged.push(n),y.info(`Skipped ${n} (${t.id}): its recorded expiry no longer selects it.`);continue}}h.add(t.id),await u.deleteWorkspace({workspaceId:t.id}),p.deleted.push(t),y.success(`Deleted ${n} (${t.id}).`)}catch(e){if(e instanceof Q&&e.code===Z.NotFound){h.add(t.id),p.deleted.push(t),y.info(`${n} (${t.id}) was already deleted.`);continue}let r=e instanceof Error?e.message:String(e);p.failed.push({workspace:t,error:r}),y.error(`Failed to delete ${n} (${t.id}): ${r}`)}}let g=await Ht(h);if(g.length>0&&y.info(`Removed ${g.length} local profile(s) that pointed at deleted workspaces: ${g.join(`, `)}.`),y.jsonMode&&y.out(p),y.success(`Deleted ${p.deleted.length} workspace(s).`),p.failed.length>0)throw S({code:`PRUNE_INCOMPLETE`,message:`Failed to delete ${p.failed.length} workspace(s).`,suggestion:`Fix the reported errors and run the command again; deleted workspaces are not retried.`})}}),hs=J.object({workspaceId:J.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:J.string().optional()});async function clearWorkspaceTtl(e){let t=Sr(hs,e),{client:n,workspaceId:r}=await M({profile:t.profile,workspaceId:t.workspaceId});return{workspaceId:r,changed:await Qn(n,r)}}const gs=z({name:`clear`,description:`Drop a workspace's recorded prune expiry.`,notes:`
143
+ `,args:J.strictObject({name:G(J.array(J.string().min(1)).optional(),{description:`Select workspaces whose whole name matches this regular expression (repeatable)`}),"older-than":G(vn.optional(),{description:`Minimum age since creation, such as 30m, 24h, or 7d. 0s disables the age check and requires a location. Required unless --expired is given`}),expired:G(J.boolean().default(!1),{description:`Select workspaces whose own --ttl expiry has passed, instead of by name and age. Requires --organization-root or --folder-id`}),"organization-root":G(locationIdsArg(),{placeholder:`ORGANIZATION_ID`,description:`Consider the workspaces directly under this organization, excluding those in its folders (repeatable)`}),"folder-id":G(locationIdsArg(),{description:`Consider the workspaces in this folder (repeatable)`}),exclude:G(J.array(J.string().min(1)).optional(),{description:`Keep a workspace with this exact name even when it matches (repeatable)`}),limit:G(Us.default(20),{description:`Abort when more workspaces match than this, without deleting anything. 0 removes the cap`}),"dry-run":G(J.boolean().default(!1),{description:`List the workspaces that would be deleted without deleting them`}),profile:G(We.optional(),{description:`Workspace profile used for authentication and Platform selection`,env:`TAILOR_PLATFORM_PROFILE`}),...D}),run:async e=>{let t=e.name??[],n=e[`older-than`];if(e.expired&&n!==void 0)throw _({code:`CONFLICTING_AGE_FILTER`,message:`--expired and --older-than cannot be combined.`,details:`--expired defers to the expiry each workspace recorded at creation, which --older-than would override.`});if(!e.expired&&n===void 0)throw _({code:`MISSING_AGE_FILTER`,message:`Specify --older-than, or --expired to use each workspace's recorded expiry.`});if(!e.expired&&t.length===0)throw _({code:`MISSING_NAME_FILTER`,message:`Specify at least one --name.`,details:`Only workspaces whose name matches the filter are considered for deletion.`});let r=e[`organization-root`]??[],i=e[`folder-id`]??[],a=[[`--organization-root`,r],[`--folder-id`,i]].filter(([,e])=>e.includes(``)).map(([e])=>e);if(a.length>0)throw _({code:`EMPTY_SCOPE`,message:`${a.join(` and `)} resolved to an empty value.`,details:`An empty location is indistinguishable from an omitted one, so the sweep would not cover what the caller meant. This usually means an unset CI secret.`,suggestion:`Set the id, or drop the option on purpose.`});let o=n===void 0?void 0:jr(n),s={nameRegexes:t.map(compileNameRegex),...o===void 0?{}:{olderThanMs:o},organizationRoots:r,folderIds:i,exclude:new Set(e.exclude??[])};if(e.expired&&!hasLocation(s))throw _({code:`UNSCOPED_EXPIRED`,message:`--expired requires --organization-root or --folder-id.`,suggestion:Gs,details:`The expiry lives on the workspace, and writing a workspace's metadata is a lesser permission than deleting it, so an unscoped sweep would delete on behalf of anyone able to write that metadata.`});if(o===0&&!hasLocation(s))throw _({code:`UNSCOPED_ZERO_AGE`,message:`--older-than 0s requires --organization-root or --folder-id.`,suggestion:Gs,details:`Without an age check the name filter is the only guard, so the sweep must name the organization roots or folders it covers.`});await L({profile:e.profile}),hasLocation(s)||m.warn(`No location was specified. Every workspace visible to this login is a candidate for the name and age filters. ${Gs}`);let c=await ue({profile:e.profile}),l=await Ae({profile:e.profile}),u=await Di(c,l),d=/* @__PURE__ */ new Date,f=selectPruneCandidates(await fetchAllWorkspaces(u),s,d),p={dryRun:e[`dry-run`],candidates:[],deleted:[],failed:[],skipped:{excluded:[],deleteProtection:[],unknownAge:[],notExpired:[],noExpiry:[],unreadableExpiry:[],expiryChanged:[],changed:[]}};if(e.expired){let e=await partitionByExpiry(u,f.candidates,d);f.candidates=e.expired;for(let t of e.pending)p.skipped.notExpired.push(t.name);for(let t of e.unset)p.skipped.noExpiry.push(t.name);for(let{workspace:t,reason:n}of e.unreadable)p.skipped.unreadableExpiry.push(t.name),m.warn(`Keeping ${t.name} (${t.id}): ${n}.`);m.info(`${e.pending.length} workspace(s) have not expired and ${e.unset.length} record no expiry; both were kept.`)}for(let{key:e,selection:t,reason:n}of Ws)for(let r of f[t])p.skipped[e].push(r.name),m.warn(`Keeping ${r.name} (${r.id}): ${n}.`);if(f.tooYoung.length>0&&m.info(`${f.tooYoung.length} matching workspace(s) are younger than ${e[`older-than`]} and were kept.`),f.candidates.length===0){m.info(`No stale workspaces matched.`),m.jsonMode&&m.out(p);return}let h=e.limit>0&&f.candidates.length>e.limit;if(h&&!e[`dry-run`])throw _({code:`PRUNE_LIMIT_EXCEEDED`,message:`${f.candidates.length} workspaces matched, but --limit is ${e.limit}. Nothing was deleted.`,details:`A match count this high usually means the name filter is broader than intended.`,suggestion:`Check the filter with --dry-run, then raise --limit (or pass --limit 0) if every match should be deleted.`});if(p.candidates=await On(u,f.candidates),m.jsonMode||m.out(p.candidates,{display:{name:nr,folderName:null,organizationId:null,folderId:null,updatedAt:null}}),e[`dry-run`]){h&&m.warn(`${p.candidates.length} workspaces matched, but --limit is ${e.limit}: a real run would abort without deleting anything.`),m.info(`Dry run: ${p.candidates.length} workspace(s) would be deleted.`),m.jsonMode&&m.out(p);return}if(!e.yes&&!await P.confirm({message:`Delete these ${p.candidates.length} workspace(s)? They can be restored with "tailor workspace restore" for a limited time.`,default:!1}))throw _({code:`PRUNE_CANCELLED`,message:`Prune cancelled. No workspaces were deleted.`});let g=/* @__PURE__ */ new Set;for(let t of p.candidates){let n=Sr(t);try{let{workspace:r}=await u.getWorkspace({workspaceId:t.id}),i=r?staleCandidateReason(r,s):void 0;if(i){p.skipped.changed.push(t.name),m.warn(`Keeping ${n} (${t.id}): ${i}.`);continue}if(e.expired){let e=await or(u,t.id,/* @__PURE__ */ new Date);if(`error`in e&&e.error instanceof Q&&e.error.code===Z.NotFound)throw e.error;if((`error`in e?`unreadable`:e.expiry.state)!==`expired`){p.skipped.expiryChanged.push(n),m.info(`Skipped ${n} (${t.id}): its recorded expiry no longer selects it.`);continue}}g.add(t.id),await u.deleteWorkspace({workspaceId:t.id}),p.deleted.push(t),m.success(`Deleted ${n} (${t.id}).`)}catch(e){if(e instanceof Q&&e.code===Z.NotFound){g.add(t.id),p.deleted.push(t),m.info(`${n} (${t.id}) was already deleted.`);continue}let r=e instanceof Error?e.message:String(e);p.failed.push({workspace:t,error:r}),m.error(`Failed to delete ${n} (${t.id}): ${r}`)}}let v=await Cn(g);if(v.length>0&&m.info(`Removed ${v.length} local profile(s) that pointed at deleted workspaces: ${v.join(`, `)}.`),m.jsonMode&&m.out(p),m.success(`Deleted ${p.deleted.length} workspace(s).`),p.failed.length>0)throw _({code:`PRUNE_INCOMPLETE`,message:`Failed to delete ${p.failed.length} workspace(s).`,suggestion:`Fix the reported errors and run the command again; deleted workspaces are not retried.`})}}),qs=J.object({workspaceId:J.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:J.string().optional()});async function clearWorkspaceTtl(e){let t=Ir(qs,e),{client:n,workspaceId:r}=await B({profile:t.profile,workspaceId:t.workspaceId});return{workspaceId:r,changed:await gr(n,r)}}const Js=I({name:`clear`,description:`Drop a workspace's recorded prune expiry.`,notes:`
139
144
  A workspace recording no expiry is never deleted by \`workspace prune --expired\`. Clearing an expiry the workspace does not record succeeds without changing anything.
140
- `,args:J.strictObject({...P}),run:async e=>{await O({profile:e.profile});let{workspaceId:t,changed:n}=await clearWorkspaceTtl({workspaceId:e[`workspace-id`],profile:e.profile});y.success(`Workspace records no prune expiry.`),N({changed:n,workspaceId:t,expiresAt:null})}}),_s=J.object({workspaceId:J.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:J.string().optional(),ttl:jr});async function setWorkspaceTtl(e){let t=Sr(_s,e),{client:n,workspaceId:r}=await M({profile:t.profile,workspaceId:t.workspaceId}),i=bn(new Date(Date.now()+vr(t.ttl)));return{workspaceId:r,expiresAt:i,changed:await hn(n,r,i)}}const vs=z({name:`set`,description:`Record when a workspace becomes prunable, replacing any expiry it already records.`,notes:"\n The expiry runs from now, not from when the workspace was created, so `--ttl 24h` always leaves a full day regardless of the workspace's age. Use this to give a restored workspace a new expiry, or to record one after `workspace create --ttl` failed to.\n\n This is not an auto-delete timer: it only makes the workspace eligible for `workspace prune --expired`, which still honors delete protection and its own filters.\n ",args:J.strictObject({...P,ttl:G(jr,{description:`Time from now until the workspace becomes prunable, such as 30m, 24h, or 7d (${Gt})`})}),run:async e=>{await O({profile:e.profile});let{workspaceId:t,expiresAt:n,changed:r}=await setWorkspaceTtl({workspaceId:e[`workspace-id`],profile:e.profile,ttl:e.ttl});y.success(`Workspace becomes prunable at ${n.toISOString()}.`),N({changed:r,workspaceId:t,expiresAt:n.toISOString()})}}),ys=K({name:`ttl`,description:`Manage when a workspace becomes prunable.`,subCommands:{set:vs,clear:gs}}),bs=K({name:`user`,description:`Manage workspace users`,subCommands:{invite:cn,list:fr,remove:qt,update:qn},defaultSubCommand:`list`}),xs=K({name:`workspace`,description:`Manage Tailor Platform workspaces.`,subCommands:{app:us,create:Cn,delete:gr,get:pn,list:Wn,prune:ms,restore:Fn,ttl:ys,user:bs},defaultSubCommand:`list`});await cr(new URL(`./ts-hook.mjs`,import.meta.url)),ji();const Ss=await wi(),Cs=Object.keys(Ss.bin??{})[0]||`tailor`,ws=Ss.name??`@tailor-platform/sdk`,Ts=await Ui(import.meta.url),Es=Hi(Vi(Ts),`agent-skills`),Ds=Hi(Vi(Ts),`docs`,`cli-reference.md`),Os=`AI coding agent detected:
145
+ `,args:J.strictObject({...A}),run:async e=>{await L({profile:e.profile});let{workspaceId:t,changed:n}=await clearWorkspaceTtl({workspaceId:e[`workspace-id`],profile:e.profile});m.success(`Workspace records no prune expiry.`),N({changed:n,workspaceId:t,expiresAt:null})}}),Ys=J.object({workspaceId:J.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:J.string().optional(),ttl:Hr});async function setWorkspaceTtl(e){let t=Ir(Ys,e),{client:n,workspaceId:r}=await B({profile:t.profile,workspaceId:t.workspaceId}),i=Kn(new Date(Date.now()+jr(t.ttl)));return{workspaceId:r,expiresAt:i,changed:await Hn(n,r,i)}}const Xs=I({name:`set`,description:`Record when a workspace becomes prunable, replacing any expiry it already records.`,notes:"\n The expiry runs from now, not from when the workspace was created, so `--ttl 24h` always leaves a full day regardless of the workspace's age. Use this to give a restored workspace a new expiry, or to record one after `workspace create --ttl` failed to.\n\n This is not an auto-delete timer: it only makes the workspace eligible for `workspace prune --expired`, which still honors delete protection and its own filters.\n ",args:J.strictObject({...A,ttl:G(Hr,{description:`Time from now until the workspace becomes prunable, such as 30m, 24h, or 7d (${Tn})`})}),run:async e=>{await L({profile:e.profile});let{workspaceId:t,expiresAt:n,changed:r}=await setWorkspaceTtl({workspaceId:e[`workspace-id`],profile:e.profile,ttl:e.ttl});m.success(`Workspace becomes prunable at ${n.toISOString()}.`),N({changed:r,workspaceId:t,expiresAt:n.toISOString()})}}),Zs=K({name:`ttl`,description:`Manage when a workspace becomes prunable.`,subCommands:{set:Xs,clear:Js}}),Qs=K({name:`user`,description:`Manage workspace users`,subCommands:{invite:Ln,list:Er,remove:Dn,update:pr},defaultSubCommand:`list`}),$s=K({name:`workspace`,description:`Manage Tailor Platform workspaces.`,subCommands:{app:Hs,create:Yn,delete:kr,get:Vn,list:dr,prune:Ks,restore:ir,ttl:Zs,user:Qs},defaultSubCommand:`list`}),ec=J.looseObject({version:J.literal(1),failedAt:J.iso.datetime().optional()});function getBannerStatePath(e){if(e)return q.join(e,`tailor-platform`,`notification-banner.json`)}function readBannerState(e){let t;try{t=X.readFileSync(e,`utf8`)}catch{return}let n;try{n=JSON.parse(t)}catch{return}let r=ec.safeParse(n);if(!r.success)return;let{version:i,failedAt:a}=r.data;return{version:i,...a===void 0?{}:{failedAt:a}}}function writeBannerState(e,t){X.mkdirSync(q.dirname(e),{recursive:!0});let n=`${e}.${process.pid}.tmp`;X.writeFileSync(n,JSON.stringify(t)+`
146
+ `),X.renameSync(n,e)}function inFailureBackoff(e,t){if(e?.failedAt===void 0)return!1;let n=t-Date.parse(e.failedAt);return n>=0&&n<3e5}const tc=/* @__PURE__ */ new Set([`notification`,`login`,`logout`,`auth`,`api`,`query`,`init`,`generate`,`show`,`plugin`,`skills`,`completion`,`crashreport`,`upgrade`,`profile`,`open`]),nc=/* @__PURE__ */ new Map([[`user`,/* @__PURE__ */ new Set([`pat`])]]),rc=/* @__PURE__ */ new Set([`--profile`,`-p`,`--workspace-id`,`-w`,`--env-file`,`-e`,`--env-file-if-exists`]),ic=/* @__PURE__ */ new Set([`--help`,`-h`,`--help-all`,`-H`,`--help-json`,`--version`,`-v`]);function commandPathFromArgv(e){let t=[],n=!1;for(let r of e)if(n)n=!1;else{if(r===`--`)break;if(r.startsWith(`-`))n=!r.includes(`=`)&&rc.has(r);else if(t.push(r),t.length===2)break}return t}function tokensBeforeSeparator(e){let t=e.indexOf(`--`);return t===-1?e:e.slice(0,t)}function lookupSkipReason(e,t){if(i(t.TAILOR_NOTIFICATION_BANNER)===!1)return`disabled`;if(tokensBeforeSeparator(e).some(e=>ic.has(e)))return`help`;let[n,r]=commandPathFromArgv(e);if(n===void 0)return`no-command`;if(n.startsWith(`__`)||tc.has(n))return`excluded-command`;let a=nc.get(n);if(a&&(r===void 0||!a.has(r)))return`excluded-command`}const ac=`NOTIFICATION_ID`;function severityRank(e){return e===W.CRITICAL?0:1}function severityCell(e){return e===W.CRITICAL?`${b.error} ${s.bold(`CRITICAL`)}`:`${b.warning} ${s.bold(`WARNING `)}`}const oc=new Intl.Segmenter(void 0,{granularity:`grapheme`});function truncate(e,t){if(r(e)<=t)return e;let n=``,i=0;for(let{segment:a}of oc.segment(e)){let e=r(a);if(i+e>t-1)break;n+=a,i+=e}return n+`…`}function formatNotificationBanner(e,t,n={}){let r=Math.max(t,e.length),i=r===1?`1 unread notification needs your attention`:`${r} unread notifications need your attention`,a=n.columns??(process.stderr.columns||80),o=Math.max(a-14,20),c=e.toSorted((e,t)=>severityRank(e.severity)-severityRank(t.severity)),l=c.slice(0,3),u=l.map(e=>` ${severityCell(e.severity)} ${truncate(y(e.title),o)}`),d=r-l.length;if(d>0){let t=e.length>=r?c.slice(3).filter(e=>e.severity===W.CRITICAL).length:0,n=t>0?` (${t} CRITICAL)`:``;u.push(s.dim(` …and ${d} more${n}.`))}let f=n.profile?[`--profile`,n.profile]:[],p=h({command:`tailor`,args:[`notification`,`list`,...f]}),m=h({command:`tailor`,args:[`notification`,`read`,ac,...f]}).replaceAll(` read ${ac}`,` read <id>`);return u.push(s.dim(` Run ${p} for details.`)),u.push(s.dim(` Run ${m} to clear a notification.`)),{header:i,lines:u}}const sc=[`TAILOR_NOTIFICATION_BANNER`,`TAILOR_PLATFORM_PROFILE`,`TAILOR_PLATFORM_TOKEN`,`TAILOR_TOKEN`,`TAILOR_PLATFORM_URL`,`PLATFORM_URL`];function lookupEnv(){return JSON.stringify(sc.map(e=>process.env[e]??null))}let cc;function startNotificationLookup(e,t={}){cc=void 0;try{if(lookupSkipReason(e,process.env)!==void 0||!l()||Ee(e)!==void 0)return;let n=getBannerStatePath(`configDir`in t?t.configDir:ha);if(n&&inFailureBackoff(readBannerState(n),Date.now()))return;let r=new AbortController,i={controller:r,promise:Promise.resolve(),dispatched:!1,finished:!1,abandoned:!1,stateFile:n,env:lookupEnv()},a=setTimeout(()=>r.abort(),3e3);a.unref(),i.promise=runLookup(e,r.signal,()=>{i.dispatched=!0}).then(e=>{i.finished=!0,i.settled=e},()=>{i.finished=!0,i.settled=void 0,i.dispatched&&!i.abandoned&&recordFailure(i.stateFile)}).finally(()=>clearTimeout(a)),cc=i}catch{cc=void 0}}async function runLookup(e,t,n){await new Promise(e=>setImmediate(e));let r=await import(`../context-CYBcQZyO.mjs`),i=r.readEnvironmentToken();if(i===void 0&&!r.platformConfigExists())return;let a=explicitProfileFromArgs(e),o=a??process.env.TAILOR_PLATFORM_PROFILE,s,c;if(i===void 0){let e=await r.loadStoredAccessTokenWithoutRefresh({profile:o});if(!e)return;({accessToken:s,platformConfig:c}=e)}else s=i,c=await r.loadPlatformClientConfig({profile:o,allowMissingProfile:!0});let[{initOperatorClient:l},{NotificationSeverity:u}]=await Promise.all([import(`../client-DO2_Xz_z.mjs`),import(`../notification_resource_pb-BZ0hCA01.mjs`)]),d=await l(s,c,{renewToken:!1});n();let f=await d.listMyNotifications({pageSize:20,minSeverity:u.WARNING,unreadOnly:!0},{signal:t});return{explicitProfile:a,totalCount:Number(f.totalCount),notifications:f.notifications.map(e=>({severity:e.severity,title:e.title}))}}function suppressedByError(e){return e instanceof d||e instanceof Q&&e.code===Z.Unauthenticated||o(e)&&typeof e.code==`string`&&e.code.startsWith(`AUTH_`)}function recordFailure(e){if(e)try{writeBannerState(e,{version:1,failedAt:new Date(Date.now()).toISOString()})}catch{}}async function waitAtMost(e,t){let n;await Promise.race([e,new Promise(e=>n=setTimeout(e,t))]),clearTimeout(n)}async function printNotificationBanner(e){let t=cc;if(cc=void 0,t)try{let n=lookupEnv()===t.env&&!suppressedByError(e.error)&&!m.jsonMode&&l();n&&!t.finished&&await waitAtMost(t.promise,150),t.abandoned=!0,t.controller.abort();let r=t.settled;if(!n||!r||r.notifications.length===0)return;let i=formatNotificationBanner(r.notifications,r.totalCount,{profile:r.explicitProfile});m.newline(),m.warn(i.header);for(let e of i.lines)m.log(e)}catch{}}await wr(new URL(`./ts-hook.mjs`,import.meta.url)),Qi();const lc=await zi(),uc=Object.keys(lc.bin??{})[0]||`tailor`,dc=lc.name??`@tailor-platform/sdk`,fc=await la(import.meta.url),pc=ca(sa(fc),`agent-skills`),mc=ca(sa(fc),`docs`,`cli-reference.md`),hc=`AI coding agent detected:
141
147
 
142
- - Unless \`--json=false\` or \`${C}=false\` is set, commands that return structured results print JSON to stdout. Parse it instead of the table output, which is formatted for humans and may change.
143
- - CLI plugin commands keep the table unless you pass \`--json\` or set \`${C}=true\`.
148
+ - Unless \`--json=false\` or \`${v}=false\` is set, commands that return structured results print JSON to stdout. Parse it instead of the table output, which is formatted for humans and may change.
149
+ - CLI plugin commands keep the table unless you pass \`--json\` or set \`${v}=true\`.
144
150
  - Pass \`--help-json\` to a command for machine-readable help.
145
- - Full command reference: \`${Ds}\``;function defaultSkillsRunToAdd(e){let{run:t,...n}=e;return{...n,defaultSubCommand:`add`}}const ks=Bi(K({name:Cs,description:Ss.description||`Tailor CLI for managing Tailor Platform SDK applications`,notes:`CLI plugins (beta): an unknown subcommand is dispatched to an external plugin executable named \`${Cs}-<name>\` (found on your PATH or in node_modules/.bin), similar to \`gh\` extensions.
146
- Run \`${Cs} plugin list\` to see which plugins are installed and where they resolve from.
147
- The \`setup\` commands are provided by the @tailor-platform/sdk-plugin-setup CLI plugin.`,subCommands:{api:ga,auth:ya,authconnection:Aa,crashreport:Na,data:za,deploy:Ba,executor:Va,function:Xa,generate:Za,init:Qa,login:no,logout:ro,machineuser:io,oauth2client:ao,open:oo,organization:co,plugin:mo,profile:yo,query:Rt,remove:vt,secret:Mo,show:Pr,staticwebsite:zo,tailordb:Yo,upgrade:Xo,user:cs,workflow:ls,workspace:xs}}),{sourceDir:Es,package:ws,mode:`copy`,descriptionAppend:!1,globalArgs:J.strictObject(jn),commandMap:{add:[`add`],remove:[`remove`]},unknownKeys:`strict`,descriptions:{skills:`Manage Tailor SDK agent skills.`,add:`Install Tailor SDK agent skills.`,list:`List Tailor SDK agent skills.`,remove:`Remove installed Tailor SDK agent skills.`,sync:`Remove and reinstall Tailor SDK agent skills.`}}),As=zi({...ks,subCommands:{...ks.subCommands,skills:defaultSkillsRunToAdd(ks.subCommands.skills)}});Li(As,{version:Ss.version,globalArgs:J.strictObject(jn),displayErrors:!1,agentHelp:Os,setup:({agent:e})=>{p(e?.id)},onUnknownSubcommand:({commandPath:e,name:t,args:n,precedingArgs:r})=>dispatchPluginWithInstallHint({commandPath:e,name:t,args:[...r,...n],cliName:Cs,profile:process.env.TAILOR_PLATFORM_PROFILE}),cleanup:async({error:e})=>{if(e){mn()||ut(e,process.argv.slice(2));let t;if(y.jsonMode?y.log(_n(e,{includeStack:y.verbose})):m(e)?(y.log(e.format()),y.verbose&&e.stack&&y.debug(`\nStack trace:\n${e.stack}`)):e instanceof Error?(y.error(e.message),t=u(e).suggestion??h(e),t&&y.log(` ${w.info(`Suggestion:`)} ${t}`),y.verbose&&e.stack&&y.debug(`\nStack trace:\n${e.stack}`)):y.error(`Unknown error: ${e}`),Vn(e,{jsonMode:y.jsonMode,suggestion:t}),!m(e)&&(!(e instanceof Error)||e instanceof TypeError||e instanceof RangeError)){let{reportCrash:t}=await import(`../crashreport-C2AcQNTe.mjs`);await t(e,`handledError`)}}let{shutdownTelemetry:t}=await import(`../telemetry-nqOtDWNO.mjs`);await t()}});export{As as mainCommand};
151
+ - Full command reference: \`${mc}\``;function defaultSkillsRunToAdd(e){let{run:t,...n}=e;return{...n,defaultSubCommand:`add`}}const gc=oa(K({name:uc,description:lc.description||`Tailor CLI for managing Tailor Platform SDK applications`,notes:`CLI plugins (beta): an unknown subcommand is dispatched to an external plugin executable named \`${uc}-<name>\` (found on your PATH or in node_modules/.bin), similar to \`gh\` extensions.
152
+ Run \`${uc} plugin list\` to see which plugins are installed and where they resolve from.
153
+ The \`setup\` commands are provided by the @tailor-platform/sdk-plugin-setup CLI plugin.`,subCommands:{api:La,auth:Ba,authconnection:Za,crashreport:eo,data:oo,deploy:so,executor:co,function:vo,generate:yo,init:bo,login:wo,logout:To,machineuser:Eo,notification:Io,oauth2client:Lo,open:Ro,organization:Bo,plugin:Ko,profile:Zo,query:xn,remove:Qt,secret:us,show:Gr,staticwebsite:_s,tailordb:Ds,upgrade:Os,user:Bs,workflow:Vs,workspace:$s}}),{sourceDir:pc,package:dc,mode:`copy`,descriptionAppend:!1,globalArgs:J.strictObject(ye),commandMap:{add:[`add`],remove:[`remove`]},unknownKeys:`strict`,descriptions:{skills:`Manage Tailor SDK agent skills.`,add:`Install Tailor SDK agent skills.`,list:`List Tailor SDK agent skills.`,remove:`Remove installed Tailor SDK agent skills.`,sync:`Remove and reinstall Tailor SDK agent skills.`}}),_c=aa({...gc,subCommands:{...gc.subCommands,skills:defaultSkillsRunToAdd(gc.subCommands.skills)}});ia(_c,{version:lc.version,globalArgs:J.strictObject(ye),displayErrors:!1,agentHelp:hc,setup:({agent:e})=>{x(e?.id),ie(process.argv.slice(2)),startNotificationLookup(process.argv.slice(2))},onUnknownSubcommand:({commandPath:e,name:t,args:n,precedingArgs:r})=>dispatchPluginWithInstallHint({commandPath:e,name:t,args:[...r,...n],cliName:uc,profile:process.env.TAILOR_PLATFORM_PROFILE}),cleanup:async({error:e})=>{if(e){S()||ve(e,process.argv.slice(2));let t;if(m.jsonMode?m.log(Wn(e,{includeStack:m.verbose})):o(e)?(m.log(e.format()),m.verbose&&e.stack&&m.debug(`\nStack trace:\n${e.stack}`)):e instanceof Error?(m.error(e.message),t=n(e).suggestion??c(e),t&&m.log(` ${s.info(`Suggestion:`)} ${t}`),m.verbose&&e.stack&&m.debug(`\nStack trace:\n${e.stack}`)):m.error(`Unknown error: ${e}`),lr(e,{jsonMode:m.jsonMode,suggestion:t}),!o(e)&&(!(e instanceof Error)||e instanceof TypeError||e instanceof RangeError)){let{reportCrash:t}=await import(`../crashreport-GRnWyDnF.mjs`);await t(e,`handledError`)}}await printNotificationBanner({error:e});let{shutdownTelemetry:t}=await import(`../telemetry-nqOtDWNO.mjs`);await t()}});export{_c as mainCommand};
148
154
  //# sourceMappingURL=main.mjs.map