@tailor-platform/sdk 2.38.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.
- package/CHANGELOG.md +64 -0
- package/dist/{application-Bz80INH4.mjs → application-OeNMQzOC.mjs} +1 -1
- package/dist/{application-CeqD1OK-.mjs → application-mNOJx9Y2.mjs} +4 -4
- package/dist/{application-CeqD1OK-.mjs.map → application-mNOJx9Y2.mjs.map} +1 -1
- package/dist/cli/commands/executor/trigger.d.mts +1 -0
- package/dist/cli/commands/generate/seed/bundler.d.mts +7 -5
- package/dist/cli/commands/workspace/transform.d.mts +1 -2
- package/dist/cli/lib.d.mts +4 -2
- package/dist/cli/lib.mjs +1 -1
- package/dist/cli/lib.mjs.map +1 -1
- package/dist/cli/main.mjs +30 -30
- package/dist/cli/main.mjs.map +1 -1
- package/dist/cli/shared/build-options.d.mts +13 -0
- package/dist/cli/shared/client.d.mts +1 -0
- package/dist/cli/shared/script-workflow.d.mts +65 -0
- package/dist/cli/shared/seed-chunker.d.mts +3 -3
- package/dist/{client-DOQv-BP8.mjs → client-CqiPQgMG.mjs} +2 -2
- package/dist/client-CqiPQgMG.mjs.map +1 -0
- package/dist/client-DO2_Xz_z.mjs +1 -0
- package/dist/completion/zsh-worker.zsh +61 -6
- package/dist/configure/index.mjs +1 -1
- package/dist/configure/index.mjs.map +1 -1
- package/dist/configure/services/auth/types.d.mts +20 -3
- package/dist/configure/services/executor/trigger/webhook.d.mts +8 -1
- package/dist/{context-OOASEQLA.mjs → context-CYBcQZyO.mjs} +1 -1
- package/dist/{context-DSi5kfqr.mjs → context-aAgFGDBD.mjs} +4 -4
- package/dist/{context-DSi5kfqr.mjs.map → context-aAgFGDBD.mjs.map} +1 -1
- package/dist/{register-ts-hook-CXYYYgCl.mjs → register-ts-hook-CORbtrSN.mjs} +82 -71
- package/dist/register-ts-hook-CORbtrSN.mjs.map +1 -0
- package/dist/{service-DB-RHn25.mjs → service-Bkz_TB5v.mjs} +2 -2
- package/dist/{service-DB-RHn25.mjs.map → service-Bkz_TB5v.mjs.map} +1 -1
- package/dist/service-Dffd4how.mjs +1 -0
- package/dist/syntax-diagnostic-BQgOV8Fz.mjs +2 -0
- package/dist/syntax-diagnostic-BQgOV8Fz.mjs.map +1 -0
- package/dist/validation-errors-ChvCG6wT.mjs +3 -0
- package/dist/validation-errors-ChvCG6wT.mjs.map +1 -0
- package/dist/vitest/index.mjs +1 -1
- package/dist/vitest/index.mjs.map +1 -1
- package/docs/cli/application.md +3 -3
- package/docs/cli/executor.md +13 -17
- package/docs/cli/function.md +1 -1
- package/docs/cli/workspace.md +2 -3
- package/docs/configuration.md +28 -0
- package/docs/github-actions.md +82 -15
- package/docs/migration/v2.md +5 -3
- package/docs/services/auth.md +5 -0
- package/docs/services/executor.md +2 -0
- package/docs/services/tailordb/migration.md +3 -3
- package/package.json +12 -12
- package/dist/client-CHXix4LD.mjs +0 -1
- package/dist/client-DOQv-BP8.mjs.map +0 -1
- package/dist/register-ts-hook-CXYYYgCl.mjs.map +0 -1
- package/dist/service-DsAWXbVX.mjs +0 -1
- package/dist/validation-errors-DqCeUW4L.mjs +0 -3
- package/dist/validation-errors-DqCeUW4L.mjs.map +0 -1
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import{t as e}from"./wait-point-registry-B-ESkTZX.mjs";import{i as t,n,r,t as i}from"./resource_pb-elY668ZB.mjs";import{t as a}from"./assert-WeXvmG4j.mjs";import{a as o,c as s,i as c,l,o as u,s as d,t as f}from"./validation-errors-
|
|
1
|
+
import{t as e}from"./wait-point-registry-B-ESkTZX.mjs";import{i as t,n,r,t as i}from"./resource_pb-elY668ZB.mjs";import{t as a}from"./assert-WeXvmG4j.mjs";import{a as o,c as s,i as c,l,o as u,s as d,t as f}from"./validation-errors-ChvCG6wT.mjs";import{S as p,a as m,b as h,c as g,d as _,g as v,h as y,i as b,l as x,m as S,p as C,r as w,s as T,t as E,w as ee,x as D}from"./errors-9OOL3xOM.mjs";import{$ as te,A as ne,E as re,F as O,I as ie,J as k,K as ae,M as oe,N as se,O as ce,Q as le,R as ue,V as de,W as fe,X as pe,Y as me,Z as he,_ as ge,a as A,at as _e,et as ve,g as ye,l as be,m as xe,nt as Se,ot as Ce,p as we,q as Te,s as Ee,st as j,u as De,v as Oe,x as ke,z as Ae}from"./context-aAgFGDBD.mjs";import{$ as je,A as Me,B as Ne,C as Pe,D as Fe,F as Ie,G as Le,H as Re,I as ze,J as Be,L as Ve,M as He,N as Ue,O as We,P as Ge,Q as Ke,S as qe,V as Je,X as Ye,Y as Xe,Z as Ze,_ as Qe,a as $e,b as et,c as tt,d as nt,et as rt,f as it,g as at,h as ot,i as st,j as ct,k as lt,n as ut,o as dt,p as ft,r as pt,s as mt,t as ht}from"./application-mNOJx9Y2.mjs";import{C as gt,S as _t,_ as vt,b as yt,d as bt,l as xt,t as St,v as Ct,y as wt}from"./service-Bkz_TB5v.mjs";import{t as M}from"./multiline-EyzjEwn9.mjs";import{A as Tt,C as Et,D as Dt,E as N,F as Ot,L as kt,O as At,P as jt,R as Mt,S as P,f as Nt,h as Pt,k as Ft,m as It,p as F,t as Lt,w as Rt,x as zt,z as Bt}from"./client-CqiPQgMG.mjs";import{t as Vt}from"./package-json-C690ceex.mjs";import{t as Ht}from"./user-agent-vdHYF3QL.mjs";import{n as Ut,r as Wt,t as Gt}from"./migration-steps-C6F3zNdQ.mjs";import{$t as Kt,A as qt,At as Jt,B as Yt,C as Xt,Ct as Zt,D as Qt,Et as $t,F as en,Ft as tn,G as nn,H as rn,Ht as an,I as on,It as sn,Jt as cn,K as ln,Lt as un,Mt as dn,N as fn,Nt as pn,O as mn,Ot as hn,P as gn,Pt as _n,Q as vn,Qt as yn,R as bn,Rt as xn,S as Sn,St as Cn,T as wn,Tt as Tn,U as En,Ut as Dn,Vt as On,Wt as kn,Xt as An,Y as jn,Yt as Mn,Z as Nn,_ as Pn,_t as Fn,a as In,at as I,b as Ln,bt as Rn,ct as zn,d as Bn,dt as Vn,en as Hn,et as Un,f as Wn,ft as Gn,g as Kn,gt as qn,h as L,ht as Jn,i as Yn,it as Xn,j as Zn,jt as Qn,k as $n,kt as er,l as R,lt as tr,mt as nr,o as rr,ot as ir,p as ar,pt as or,q as sr,r as cr,rt as lr,s as ur,st as dr,t as fr,tn as pr,tt as mr,u as z,ut as hr,v as gr,vt as _r,w as vr,wt as yr,x as br,xt as xr,y as Sr,yt as Cr,z as wr,zt as Tr}from"./workspace_resource_pb-Cow7mrJY.mjs";import{r as B}from"./telemetry-DfT2UfI4.mjs";import{t as Er}from"./manager-B813m43t.mjs";import{a as Dr,i as Or,o as kr,r as Ar,s as jr,t as Mr}from"./seed-Cn-3JApy.mjs";import{c as Nr,l as Pr,o as Fr,s as Ir,u as Lr}from"./kysely-type-DhAZqdQg.mjs";import*as Rr from"node:module";import{arg as V,createDefineCommand as zr,defineCommand as Br}from"@politty/zod";import*as H from"pathe";import{basename as Vr,dirname as Hr,isAbsolute as Ur,join as Wr,relative as Gr,resolve as Kr,sep as qr}from"pathe";import{resolveTSConfig as Jr}from"pkg-types";import{z as U}from"zod";import{create as Yr,createRegistry as Xr,fromJson as Zr,toJson as Qr}from"@bufbuild/protobuf";import*as W from"node:fs";import{mkdirSync as $r,readFileSync as ei,realpathSync as ti,renameSync as ni,rmSync as ri,statSync as ii,utimesSync as ai,writeFileSync as oi}from"node:fs";import{isDeepStrictEqual as si}from"node:util";import{ValueSchema as ci,timestampDate as G}from"@bufbuild/protobuf/wkt";import{Code as K,ConnectError as q}from"@connectrpc/connect";import{formatDistanceToNowStrict as li}from"date-fns";import{isCI as ui}from"std-env";import{pathToFileURL as di}from"node:url";import{findUpSync as fi}from"find-up-simple";import{xdgConfig as pi}from"xdg-basedir";import mi from"p-limit";import*as hi from"node:crypto";import{createHash as gi,randomUUID as _i}from"node:crypto";import{tmpdir as vi}from"node:os";import{ExitPromptError as yi}from"@inquirer/core";import{confirm as bi,input as xi,password as Si,select as Ci}from"@inquirer/prompts";import*as wi from"rolldown";import{Visitor as Ti,parseSync as Ei}from"oxc-parser";import*as Di from"inflection";import{parse as Oi}from"@0no-co/graphql.web";import*as J from"node:fs/promises";import{mkdir as ki,readFile as Ai,rename as ji,rm as Mi,stat as Ni,writeFile as Pi}from"node:fs/promises";import{setTimeout as Fi}from"node:timers/promises";import*as Ii from"fs";import{lookup as Li}from"mime-types";import{spawn as Ri}from"node:child_process";import{pathToString as zi,usedTypes as Bi}from"@bufbuild/protobuf/reflect";import{createValidator as Vi}from"@bufbuild/protovalidate";import{setTimeout as Hi}from"timers/promises";import{createPrompt as Ui}from"@toiroakr/read-multiline";import{astVisitor as Wi,parse as Gi}from"pgsql-ast-parser";const Y=zr(),Ki=U.union([U.string(),U.number(),U.boolean()]),qi=U.union([U.string(),U.number()]),Ji=U.union([Ki,U.strictObject({value:qi,allowSecretReason:U.string().min(1,{message:`'allowSecretReason' must state why the value is safe to keep in 'env'.`})})]),Yi=U.enum(je),Xi=/^[a-z][a-z0-9_-]{0,62}$/,Zi=/^$|^[a-z][a-z0-9_-]{0,62}$/,Qi=`sdk-`,$i=U.string().regex(Zi,{message:`'metadata' values must match ${Zi.source}.`}),ea=U.record(U.string(),$i).superRefine((e,t)=>{let n=Object.keys(e);n.length>17&&t.addIssue({code:`custom`,message:`'metadata' can hold at most 17 entries.`});for(let e of n)Xi.test(e)?e.startsWith(Qi)&&t.addIssue({code:`custom`,path:[e],message:`'metadata' keys starting with '${Qi}' are reserved for the SDK.`}):t.addIssue({code:`custom`,path:[e],message:`'metadata' keys must match ${Xi.source}.`})}),ta=U.string().refine(e=>Yi.safeParse(e.trim().toUpperCase()).success,{message:`'logLevel' must be one of: ${je.join(`, `)}.`}),na=U.string().refine(rt,{error:e=>`'allowedRuntimeGlobals' lists '${String(e.input)}', which is not a Node-only global the Tailor Platform runtime lacks.`}),ra=U.record(U.string().min(1),U.union([U.literal(!0),U.array(na)])),ia=U.strictObject({moduleSideEffects:U.boolean().optional(),annotations:U.boolean().optional(),unknownGlobalSideEffects:U.boolean().optional(),propertyReadSideEffects:U.boolean().optional()}),aa=U.strictObject({inlineSourcemap:U.boolean().optional(),inlineSourcemapDependencySources:U.union([U.boolean(),U.array(U.string())]).optional(),inlineSourcemapProjectSources:U.strictObject({include:U.array(U.string()).optional(),exclude:U.array(U.string()).optional()}).optional(),logLevel:ta.optional(),allowedRuntimeGlobals:ra.optional(),treeshake:ia.optional()}),oa=[`inlineSourcemap`,`logLevel`],sa=U.strictObject({id:U.uuid({message:`'id' must be a UUID.`}).optional(),name:U.string().min(1,{message:`'name' must be a non-empty string.`}),env:U.record(U.string(),Ji).optional(),cors:U.array(U.string()).optional(),allowedIpAddresses:U.array(U.string()).optional(),disableIntrospection:U.boolean().optional(),inlineSourcemap:U.boolean().optional(),logLevel:ta.optional(),buildOptions:aa.optional(),defaultDateRepresentation:U.enum([`temporal`,`date`],{message:`'defaultDateRepresentation' must be "temporal" or "date".`}).optional(),maintenanceMode:U.union([U.literal(!1),U.enum([`migration`,`deploy`])],{message:`'maintenanceMode' must be false, "migration", or "deploy".`}).optional(),metadata:ea.optional(),db:U.unknown().optional(),resolver:U.unknown().optional(),idp:U.unknown().optional(),auth:U.unknown().optional(),executor:U.unknown().optional(),workflow:U.unknown().optional(),httpAdapter:U.unknown().optional(),staticWebsites:U.unknown().optional(),aiGateways:U.unknown().optional(),secrets:U.unknown().optional()}).superRefine((e,t)=>{for(let n of oa)e[n]!==void 0&&e.buildOptions?.[n]!==void 0&&t.addIssue({code:`custom`,path:[n],message:`'${n}' is set both at the top level and in 'buildOptions.${n}'. Keep only 'buildOptions.${n}'.`})}),ca=U.looseObject({id:U.string(),description:U.string(),importPath:U.string().optional(),pluginConfig:U.unknown().optional(),tableConfigRequired:U.union([U.boolean(),_t]).optional(),onTableLoaded:_t.optional(),onNamespaceLoaded:_t.optional(),onTailorDBReady:_t.optional(),onResolverReady:_t.optional(),onExecutorReady:_t.optional(),onDeployed:_t.optional()}).refine(e=>!(e.onTableLoaded||e.onNamespaceLoaded)||!!e.importPath,{message:`importPath is required when plugin has definition-time hooks (onTableLoaded/onNamespaceLoaded)`}).transform(e=>e),la=/^[A-Za-z0-9+/=_.-]+$/,ua=/* @__PURE__ */ new Map;function resolveEnvValue(e){return isAllowedSecret(e)?e.value:e}async function scanEnvForSecrets(e){let t=Object.entries(e.env??{}).filter(([,e])=>!isAllowedSecret(e)).map(([e,t])=>[e,resolveEnvValue(t)]);if(t.length===0)return[];let n=await scanWithProviderRules(t),r=new Set(n.map(e=>e.key));for(let[e,i]of t)r.has(e)||typeof i!=`string`||looksRandomlyGenerated(i)&&n.push({key:e,detector:`high-entropy`,severity:`warning`});return n}async function assertEnvHasNoSecrets(e){let t=gi(`sha256`).update(JSON.stringify([e.configPath??``,e.env??{}])).digest(`hex`),n=ua.get(t);if(n)return n;let r=reportEnvSecrets(e);return ua.set(t,r),r}async function reportEnvSecrets(e){let t=await scanEnvForSecrets(e);for(let e of t)e.severity===`warning`&&C.warn(`env.${e.key} looks like a randomly generated credential. If it is one, move it to Secret Manager; otherwise allow it with ${h.bold(`allowSecretReason`)}.`);let n=t.filter(e=>e.severity===`error`);if(n.length===0)return;let r=e.configPath?` in ${e.configPath}`:``,i=n.map(e=>{let t=e.rule?`${e.detector}: ${e.rule}`:e.detector,n=e.docsUrl?`\n ${e.docsUrl}`:``;return` - env.${e.key} (matched ${t})${n}`}).join(`
|
|
2
2
|
`),a=n[0]?.key??`KEY`;throw Error(`Secret detected in 'env'${r}:\n${i}\n'env' values are deployed as plaintext and are readable by anyone who can read the application's configuration. Define these with defineSecretManager() instead, and read them through Secret Manager at runtime.
|
|
3
|
-
If a value is genuinely safe to keep in 'env', allow it where it is defined: ${a}: { value: ..., allowSecretReason: "<why this is safe>" }`)}async function scanWithProviderRules(e){let[{lintSource:t},{rules:n}]=await Promise.all([import(`@secretlint/core`),import(`@secretlint/secretlint-rule-preset-recommend`)]),r=[],i=``;for(let[t,n]of e){let e=`${t}=${String(n)}`;r.push({key:t,start:i.length,end:i.length+e.length}),i+=`${e}\n`}let a=await t({source:{filePath:`/tailor-config-env`,content:i,contentType:`text`},options:{maskSecrets:!0,noPhysicFilePath:!0,config:{rules:n.filter(e=>e.meta.id!==`@secretlint/secretlint-rule-filter-comments`).map(e=>({id:e.meta.id,rule:e,...e.meta.id===`@secretlint/secretlint-rule-aws`?{options:{enableIDScanRule:!0}}:{}}))}}}),o=[],s=/* @__PURE__ */ new Set;for(let e of a.messages){let t=r.find(t=>e.range[0]>=t.start&&e.range[0]<t.end);if(!t)continue;let n=e.ruleId.startsWith(`@secretlint/secretlint-rule-`)?e.ruleId.slice(28):e.ruleId,i=JSON.stringify([t.key,n,e.messageId]);s.has(i)||(s.add(i),o.push({key:t.key,detector:n,rule:e.messageId,...e.docsUrl?{docsUrl:e.docsUrl}:{},severity:`error`}))}return o}function isAllowedSecret(e){return typeof e==`object`}function looksRandomlyGenerated(e){return e.length<20||!oa.test(e)?!1:shannonEntropyPerChar(e)>=4.2}function shannonEntropyPerChar(e){let t=/* @__PURE__ */ new Map;for(let n of e)t.set(n,(t.get(n)??0)+1);let n=0;for(let r of t.values()){let t=r/e.length;n-=t*Math.log2(t)}return n}function installCliTailordbStub(){Vt()}async function loadConfig(e,t={}){installCliTailordbStub();let n=Ee(e);if(!n)throw Error(`Configuration file not found: tailor.config.ts not found in current or parent directories`);let r=H.resolve(process.cwd(),n);if(!W.existsSync(r))throw Error(`Configuration file not found: ${e}`);let i=ci(r),a=t.importNonce??_t();a&&i.searchParams.set(xt,a);let o;try{o=await import(i.href)}catch(e){throw atConfigSource(e,r)}if(typeof o!=`object`||!o||!(`default`in o)||!o.default)throw atConfigFile(/* @__PURE__ */ Error(`Invalid Tailor config module: default export not found`),r);let s=ia.safeParse(o.default);if(!s.success)throw f({file:r,exportName:`default`,subject:`Tailor config`,error:s.error});let c=o.default;try{await assertEnvHasNoSecrets({env:c.env,configPath:r})}catch(e){throw e instanceof Error?atConfigFile(e,r):e}let l=c.env?Object.fromEntries(Object.entries(c.env).map(([e,t])=>[e,resolveEnvValue(t)])):void 0,u=[];if(Object.hasOwn(o,`plugins`)){let e=o.plugins;if(!Array.isArray(e))throw atConfigFile(/* @__PURE__ */ Error(`Invalid \`plugins\` export in ${r}: expected an array returned by definePlugins(), got ${typeof e}`),r);let t=/* @__PURE__ */ new Set;for(let[n,i]of e.entries()){let e=aa.safeParse(i);if(!e.success)throw f({file:r,exportName:`plugins`,subject:"`plugins` export",error:e.error,pathPrefix:[n]});if(t.has(e.data.id))throw atConfigFile(/* @__PURE__ */ Error(`Duplicate plugin ID "${e.data.id}" detected in ${r}. Each plugin must have a unique ID.`),r);t.add(e.data.id),u.push(i)}}return{config:{...c,...l?{env:l}:{},path:r},plugins:u}}function atConfigFile(e,t){return l(e,{location:{file:t}})}function atConfigSource(e,t){return o(e)||(e instanceof Error?s(e).location?e:atConfigFile(e,t):e)}async function assertWritable(e){let t=e?.profile||process.env.TAILOR_PLATFORM_PROFILE;if(!t)return;let n=(await Oe()).profiles[t];if(n&&n.readonly===!0)throw E({code:`PROFILE_READONLY`,message:`Profile "${t}" is read-only.`,details:`This profile blocks platform-state mutations (apply, create/update/delete, deploy, etc.). Application-data operations remain available because their permissions are governed by the machine user.`,suggestion:`Use a different profile, unset TAILOR_PLATFORM_PROFILE, or run ${w({command:`tailor`,args:ee(t,[`--permission`,`write`])})}.`})}function hasEnvAccessToken(){return!!(process.env.TAILOR_PLATFORM_TOKEN??process.env.TAILOR_TOKEN)}async function apiCall(e){let t=await A({profile:e.profile}),n;try{n=await De({profile:e.profile})}catch(e){if(!hasEnvAccessToken())throw e}let r;r=e.endpoint.includes(`/`)?e.endpoint:`tailor.v1.OperatorService/${e.endpoint}`;let i=new URL(r,Ct(n)),a=await fetch(i.toString(),{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${t}`,"User-Agent":await zt()},body:e.body??`{}`}),o=await a.json();if(!a.ok)throw E({code:`API_REQUEST_FAILED`,message:`API call failed (${a.status}): ${JSON.stringify(o)}`,context:{status:a.status}});return{status:a.status,data:o}}function printMutationResult(e){C.jsonMode&&C.out(e)}async function loadOperatorWorkspaceContext(e){let t=await A({profile:e.profile});return{client:await N(t),workspaceId:await xe({profile:e.profile,workspaceId:e.workspaceId})}}function canPrompt(){return _()&&!C.jsonMode}function withGuard(e,t){return async n=>{let{suggestion:r,...i}=n;if(!canPrompt()){let e=new x(t);throw r===void 0?e:l(e,{suggestion:r})}try{return await e(i)}catch(e){throw e instanceof gi&&process.exit(130),e}}}const X={confirm:withGuard(_i,`Interactive confirmations are not available in this environment. Use --yes to skip confirmation prompts, or provide the required options explicitly.`),text:withGuard(vi),password:withGuard(yi),select:e=>withGuard(bi)(e)};async function fetchWithinLimit(e,t){if(!e)return{items:await t(e),truncated:!1};let n=await t(Math.min(e+1,2**53-1));return n.length<=e?{items:n,truncated:!1}:{items:n.slice(0,e),truncated:!0}}async function reportTruncation(e,t){e.truncated&&(process.stdout.writableLength>0&&await new Promise(e=>process.stdout.write(``,()=>e())),C.info(`More results exist beyond --limit ${t}. Raise --limit to see more.`))}const ca=`forced by SDK version`;function forcedBySdkVersionSuffix(e){return e.forcedBySdkVersion?` ${h.dim(`[${ca}]`)}`:``}function createChangeSet(e){let t=[],n=[],r=[],i=[],a=[],isEmpty=()=>t.length===0&&n.length===0&&r.length===0&&i.length===0;return{title:e,creates:t,updates:n,deletes:r,replaces:i,unchanged:a,isEmpty,lines:()=>{if(isEmpty())return[];let itemLines=e=>t=>[` ${e} ${t.name}${forcedBySdkVersionSuffix(t)}`,...(t.details??[]).map(e=>` ${e}`)];return[h.bold(`${e}:`),...t.flatMap(itemLines(O.create)),...r.flatMap(itemLines(O.delete)),...n.flatMap(itemLines(O.update)),...i.flatMap(itemLines(O.replace))]}}}function summarizeChangeSets(e){let t={create:0,update:0,delete:0,replace:0,forcedBySdkVersion:0};for(let n of e)t.create+=n.creates.length,t.update+=n.updates.length,t.delete+=n.deletes.length,t.replace+=n.replaces.length,t.forcedBySdkVersion+=n.updates.filter(e=>e.forcedBySdkVersion).length;return t}function formatPlanSummary(e){let t=[`${e.create} to create`,e.forcedBySdkVersion>0?`${e.update} to update (${e.forcedBySdkVersion} ${ca})`:`${e.update} to update`,`${e.delete} to delete`];return e.replace>0&&t.push(`${e.replace} to replace`),`Plan: ${t.join(`, `)}`}function toComparableProtoJson(e,t){return Yr(e,Kr(e,t))}function stableStringify$1(e){return Array.isArray(e)?`[${e.map(e=>e===void 0?`null`:stableStringify$1(e)).join(`,`)}]`:e&&typeof e==`object`?`{${Object.entries(e).filter(([e,t])=>e!==`$typeName`&&t!==void 0).toSorted(([e],[t])=>e.localeCompare(t)).map(([e,t])=>`${JSON.stringify(e)}:${stableStringify$1(t)}`).join(`,`)}}`:JSON.stringify(typeof e==`bigint`?e.toString():e)}function normalizeProtoConfig(e){return e==null?e:JSON.parse(stableStringify$1(e))}function normalizeStringArray(e){return(e??[]).toSorted()}function areNormalizedEqual(e,t){return stableStringify$1(normalizeProtoConfig(e))===stableStringify$1(normalizeProtoConfig(t))}function trnPrefix(e){return`trn:v1:workspace:${e}`}function resourceTrn(e,t,n){return`${trnPrefix(e)}:${t}:${n}`}function nestedResourceTrn(e,t,n){return`${trnPrefix(e)}:${t[0]}:${t[1]}:${n[0]}:${n[1]}`}function tailorDBTypeTrn(e,t,n){return nestedResourceTrn(e,[`tailordb`,t],[`type`,n])}function resolverTrn(e,t,n){return nestedResourceTrn(e,[`pipeline`,t],[`resolver`,n])}const la=`sdk-name`,ua=`sdk-version`,da=`sdk-app-id`;function sdkAppIdLabelValue(e){return`app-${e}`}function hasMatchingSdkVersion(e,t){return e?.[ua]===t?.[ua]}function isOwnedByApp(e,t,n){if(!e)return!1;let r=e[da];return r?n!==void 0&&r===sdkAppIdLabelValue(n):e[la]===t}function prefixFor(e){return e===`jobs`?`sdk-job-depended-by-app-`:`sdk-depended-by-app-`}const fa=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;function dependedByAppLabelKey(e,t=`resource`){return fa.test(e)?`${prefixFor(t)}${e}`:void 0}function recordedDependencies(e,t=`resource`){if(!e)return[];let n=prefixFor(t);return Object.entries(e).toSorted(([e],[t])=>e<t?-1:+(e>t)).flatMap(([e,t])=>{if(!e.startsWith(n))return[];let r=e.slice(n.length);return fa.test(r)?[{appId:r,reason:t}]:[]})}const Z={tailorDBType:(e,t)=>`tailordb:${e}:type:${t}`,resolver:(e,t)=>`pipeline:${e}:resolver:${t}`,idp:e=>`idp:${e}`,workflow:e=>`workflow:${e}`,workflowJobs:e=>`workflow:${e}:jobs`};function dependencyLabelWrite(e){let{existingLabels:t,dependentApps:n,runAppIds:r,pinned:i,scope:a=`resource`}=e;if(i)return{labels:{},remove:recordedDependencies(t,a).flatMap(({appId:e})=>dependedByAppLabelKey(e,a)??[])};let o=n??/* @__PURE__ */ new Map,s=r??/* @__PURE__ */ new Set,c={};for(let[e,t]of o){let n=dependedByAppLabelKey(e,a);if(!n)throw E({code:`APP_ID_INVALID`,message:`Application id "${e}" cannot be recorded as a dependency of this deploy.`,suggestion:`Ids are written by deploy as lowercase UUIDs; restore the generated value in the config's "id".`});c[n]=t}return{labels:c,remove:recordedDependencies(t,a).flatMap(({appId:e})=>{if(!s.has(e)||o.has(e))return[];let t=dependedByAppLabelKey(e,a);return t?[t]:[]})}}async function buildMetaRequest(e){let{trn:t,appName:n,appId:r,metadata:i}=e,a=await Rt(),o=a.version?`v${a.version.replace(/\./g,`-`)}`:`unknown`;return{trn:t,labels:{...i,[la]:n,[ua]:o,...r?{[da]:sdkAppIdLabelValue(r)}:{}},remove:r?void 0:[da]}}function addDependencyRecords(e,t){let{key:n,dependentApps:r,runAppIds:i,pinned:a,scope:o}=t;return e.dependencies=[...e.dependencies??[],{dependentApps:r?.get(n),runAppIds:i,pinned:a,scope:o}],e}const pa=Symbol(`metadataWriteBatch`);var MetadataWriteBatch=class{#e;#t=/* @__PURE__ */ new Map;#n;constructor(e){this.#e=e}async enqueue(e){if(this.#n){await this.#n.catch(()=>void 0),await writeMetadataLabelsDirect(this.#e,e);return}let t=this.#t.get(e.trn)??[];t.push(e),this.#t.set(e.trn,t)}flush(){return this.#n??=this.#r(),this.#n}async#r(){let e=[...this.#t].toSorted(([e],[t])=>e<t?-1:+(e>t)),readRequest=async([e,t])=>{let n=(await P(()=>this.#e.getMetadata({trn:e})))?.metadata?.labels??{},r=t.reduce(applyMetadataLabelWrite,n);return areSameLabels(n,r)?void 0:{trn:e,labels:r}},t=[],n=0;for(;n<e.length||t.length>0;){let r=t.length===0?[]:void 0;for(;n<e.length&&t.length<100;){t.length>0&&(r=void 0);let i=e.slice(n,n+100);n+=i.length;let a=await Promise.all(i.map(async e=>{let t=await readRequest(e);return t?{entry:e,request:t}:void 0}));for(let e of a)e&&(t.push(e.entry),r?.push(e.request))}let i=t.splice(0,100),a=r??(await Promise.all(i.map(e=>readRequest(e)))).filter(e=>e!==void 0);a.length>0&&await this.#e.bulkSetMetadata({requests:a})}}};function hasMetadataLabelChange(e){return!!(Object.keys(e.labels??{}).length||e.remove?.length||e.dependencies?.length)}function applyMetadataLabelWrite(e,t){let{labels:n,remove:r,dependencies:i}=t,a=(i??[]).map(t=>dependencyLabelWrite({...t,existingLabels:e})),o={...e,...n,...Object.assign({},...a.map(e=>e.labels))};for(let e of[...r??[],...a.flatMap(e=>e.remove)])delete o[e];return o}function metadataRecoveryError(e,t){let describeCause=e=>m(e)?S(e.format()):T(e).message;return l(AggregateError([e,t],`Resource apply failed: ${describeCause(e)}\nQueued metadata recovery failed: ${describeCause(t)}`,{cause:t}),{code:`DEPLOY_METADATA_RECOVERY_FAILED`,suggestion:`Some resources may already have changed and deployment metadata could not be saved. Inspect the current resources and resolve both failures before deploying again.`,causes:{apply:e,recovery:t}})}async function withMetadataWriteBatch(e,t){let n=new MetadataWriteBatch(e),r=new Proxy(e,{get(e,t,r){return t===pa?n:Reflect.get(e,t,r)}}),i;try{i=await t(r)}catch(e){try{await n.flush()}catch(t){throw metadataRecoveryError(e,t)}throw e}return await n.flush(),i}async function writeMetadataLabels(e,t){if(!hasMetadataLabelChange(t))return;let n=e[pa];n?await n.enqueue(t):await writeMetadataLabelsDirect(e,t)}async function writeMetadataLabelsDirect(e,t){if(!hasMetadataLabelChange(t))return!1;let{trn:n}=t,r=(await P(()=>e.getMetadata({trn:n})))?.metadata?.labels??{},i=applyMetadataLabelWrite(r,t);return!areSameLabels(r,i)&&(await e.setMetadata({trn:n,labels:i}),!0)}function areSameLabels(e,t){let n=Object.keys(e);return n.length===Object.keys(t).length&&n.every(n=>e[n]===t[n])}async function fetchExistingResourcesWithLabels(e){let{client:t,fetchPage:n,getName:r,getTrn:i}=e,a=await F(n),o={};return await Promise.all(a.map(async e=>{let n=r(e);if(!n)return;let{metadata:a}=await t.getMetadata({trn:i(n)});o[n]={resource:e,allLabels:a?.labels}})),o}function createOwnershipTracker(e,t){let n={conflicts:[],unmanaged:[],resourceOwners:/* @__PURE__ */ new Set};return{result:n,ownsDesired(r,i){if(isOwnedByApp(r,e,t))return!0;let a=r?.[la];return a?n.conflicts.push({...i,currentOwner:a}):n.unmanaged.push(i),!1},ownsRemaining(r){if(isOwnedByApp(r,e,t))return!0;let i=r?.[la];return i&&n.resourceOwners.add(i),!1}}}async function applyStaticWebsite(e,t,n=`create-update`){let{changeSet:r,customDomainChangeSet:i,customDomainTransferChangeSet:a}=t;n===`create-update`?(await Promise.all([...r.creates.map(async t=>{await e.createStaticWebsite(t.request),await writeMetadataLabels(e,t.metaRequest)}),...r.updates.map(async t=>{await e.updateStaticWebsite(t.request),await writeMetadataLabels(e,t.metaRequest)})]),await Promise.all([...i.creates.map(async t=>{let{transfer:n}=await e.addCustomDomain(t.request);await writeMetadataLabels(e,t.metaRequest),n&&C.info(`Custom domain "${t.name}" was transferred from workspace ${n.sourceWorkspaceId}.`)}),...i.updates.map(t=>writeMetadataLabels(e,t.metaRequest))]),await Promise.all(i.deletes.map(t=>e.removeCustomDomain(t.request))),await Promise.all(a.deletes.map(t=>e.cancelCustomDomainTransfer(t.request))),await Promise.all(a.creates.map(t=>e.requestCustomDomainTransfer(t.request)))):await Promise.all(r.deletes.map(t=>e.deleteStaticWebsite(t.request)))}function customDomainTrn(e,t,n){return`trn:v1:workspace:${e}:staticwebsite:${t}:custom_domain:${n}`}const ma={[dn.COMPLETED]:`completed`,[dn.CANCELLED]:`was cancelled`,[dn.EXPIRED]:`expired`};function describePreviousTransfer(e){let t=ma[e.status]??`ended`;return`a previous transfer to workspace ${e.targetWorkspaceId} ${t}`}function assertStaticWebsiteDeletesNotOffered(e){let t=[...e.customDomainLiveOffers.values()];for(let n of e.changeSet.deletes){let e=t.find(e=>e.sourceStaticWebsiteName===n.name);if(e)throw E({code:`STATIC_WEBSITE_TRANSFER_IN_FLIGHT`,message:`Static website "${n.name}" cannot be deleted: its custom domain "${e.domain}" is offered to workspace ${e.targetWorkspaceId}.`,suggestion:`Cancel the pending transfer before deleting the static website.`,details:`The platform refuses to delete a static website while one of its custom domains is still offered. Changing the entry back to a plain string and deploying cancels the offer.`,context:{resourceType:`staticwebsite`,staticWebsiteName:n.name,domain:e.domain,targetWorkspaceId:e.targetWorkspaceId}})}}function normalizeComparableStaticWebsiteShape(e){return{description:e.description,allowedIpAddresses:e.allowedIpAddresses.toSorted()}}function normalizeComparableStaticWebsite(e){return normalizeComparableStaticWebsiteShape({description:e.description||``,allowedIpAddresses:[...e.allowedIpAddresses||[]]})}function areStaticWebsitesEqual(e,t){return areNormalizedEqual(normalizeComparableStaticWebsite(e),normalizeComparableStaticWebsite(t))}function expectedLocalStaticWebsiteNames(e){return e.expectedLocalStaticWebsiteNames??new Set(e.application.staticWebsiteServices.map(e=>e.name))}async function planStaticWebsite(e){let{client:t,workspaceId:n,application:r,forRemoval:i}=e,a=createChangeSet(`StaticWebsites`),o=createChangeSet(`CustomDomains`),s=createChangeSet(`CustomDomainTransfers`),c=[],l=createOwnershipTracker(r.name,r.id),u=await fetchExistingResourcesWithLabels({client:t,fetchPage:async(e,r)=>{let{staticwebsites:i,nextPageToken:a}=await t.listStaticWebsites({workspaceId:n,pageToken:e,pageSize:r});return[i,a]},getName:e=>e.name,getTrn:e=>resourceTrn(n,`staticwebsite`,e)}),d=/* @__PURE__ */ new Set,f=i?[]:r.staticWebsiteServices;for(let e of f){let t=e,i=e.name,o=u[i],s=await buildMetaRequest({trn:resourceTrn(n,`staticwebsite`,i),appName:r.name,appId:r.id}),c=normalizeComparableStaticWebsite(t),f={workspaceId:n,staticwebsite:{name:i,description:t.description||``,allowedIpAddresses:t.allowedIpAddresses||[]}};if(o){let e=l.ownsDesired(o.allLabels,{resourceType:`staticwebsite`,resourceLabel:`StaticWebsite`,resourceName:i}),t=e&&areStaticWebsitesEqual(o.resource,c);t&&hasMatchingSdkVersion(o.allLabels,s.labels)?a.unchanged.push({name:i}):a.updates.push({name:i,request:f,metaRequest:s,...t&&{forcedBySdkVersion:!0}}),e&&d.add(i),delete u[i]}else a.creates.push({name:i,request:f,metaRequest:s}),d.add(i)}Object.entries(u).forEach(([e])=>{let t=u[e];l.ownsRemaining(t?.allLabels)&&a.deletes.push({name:e,request:{workspaceId:n,name:e}})});let p=/* @__PURE__ */ new Map;for(let e of f)e.customDomains!==void 0&&d.has(e.name)&&p.set(e.name,new Map(e.customDomains.map(e=>{let t=typeof e==`string`?{domain:e}:{domain:e.domain,transferToWorkspaceId:e.transferTo.workspaceId};return[t.domain,t]})));let m=/* @__PURE__ */ new Map,h=[...d].filter(e=>!a.creates.some(t=>t.name===e)),g=Promise.all(h.map(async e=>{let r=await P(async()=>{let{customDomains:r}=await t.listCustomDomains({workspaceId:n,staticWebsiteName:e});return r});if(!r)return;let i=await Promise.all(r.map(async r=>{let{metadata:i}=await t.getMetadata({trn:customDomainTrn(n,e,r.domain)});return{domain:r.domain,status:r.status,allLabels:i?.labels}}));m.set(e,i)})),_=p.size>0||a.deletes.length>0?F(async(e,r)=>{let{transfers:i,nextPageToken:a}=await t.listCustomDomainTransfers({workspaceId:n,status:dn.PENDING,pageToken:e,pageSize:r});return[i,a]}):Promise.resolve([]),[,v]=await Promise.all([g,_]),y=v.filter(e=>e.sourceWorkspaceId===n),b=new Map(y.map(e=>[e.domain,e])),x=/* @__PURE__ */ new Set;for(let e of p.values())for(let t of e.values())t.transferToWorkspaceId!==void 0&&!b.has(t.domain)&&x.add(t.domain);let S=/* @__PURE__ */ new Map;await Promise.all([...x].map(async e=>{let r=await P(()=>t.getCustomDomainTransfer({workspaceId:n,domain:e}));r?.transfer&&S.set(e,r.transfer)}));for(let e of d){let t=p.get(e)??/* @__PURE__ */ new Map,i=m.get(e)??[],a=new Map(i.map(e=>[e.domain,e])),u=new Set(i.filter(e=>isOwnedByApp(e.allLabels,r.name,r.id)).map(e=>e.domain));for(let[i,s]of t){let t=a.get(i);if(t?.status===Yt.REMOVING)throw E({code:`CUSTOM_DOMAIN_REMOVING`,message:`Custom domain "${i}" on static website "${e}" is being removed.`,suggestion:`Delete this entry, or wait for the removal to finish and deploy again to re-add it.`,details:`A domain reaches this state when it is removed outside the SDK. The platform refuses to re-add, offer or accept it until the removal completes.`,context:{resourceType:`staticwebsite.custom_domain`,staticWebsiteName:e,domain:i}});if(t)l.ownsDesired(t.allLabels,{resourceType:`staticwebsite.custom_domain`,resourceLabel:`StaticWebsite custom domain`,resourceName:i})?o.unchanged.push({name:i}):o.updates.push({name:i,metaRequest:await buildMetaRequest({trn:customDomainTrn(n,e,i),appName:r.name,appId:r.id}),details:[`takes SDK ownership; the domain itself is unchanged`]});else{if(s.transferToWorkspaceId!==void 0)continue;let t=await buildMetaRequest({trn:customDomainTrn(n,e,i),appName:r.name,appId:r.id});o.creates.push({name:i,request:{workspaceId:n,staticWebsiteName:e,domain:i},metaRequest:t})}}if(p.has(e))for(let e of u)t.has(e)||o.deletes.push({name:e,request:{workspaceId:n,domain:e}});for(let[r,i]of t){let t=a.get(r),o=b.get(r),l=i.transferToWorkspaceId;if(l===void 0){o&&s.deletes.push({name:r,staticWebsiteName:e,request:{workspaceId:n,domain:r},details:[`withdraws the offer to workspace ${o.targetWorkspaceId}`]});continue}if(!t){if(o){c.push({kind:`transfer-pending`,staticWebsiteName:e,domain:r,message:`transfer to workspace ${o.targetWorkspaceId} is pending`});continue}let t=S.get(r);if(t?.status===dn.COMPLETED&&t.sourceWorkspaceId===n){c.push({kind:`transfer-completed`,staticWebsiteName:e,domain:r,message:`transfer to workspace ${t.targetWorkspaceId} completed — remove this entry`});continue}throw E({code:`CUSTOM_DOMAIN_TRANSFER_INCOMPLETE`,message:`Custom domain "${r}" is not on static website "${e}", and no transfer from this workspace completed it.`,suggestion:`Remove this entry, or correct the domain it names.`,details:`This happens when the domain was removed outside the SDK, or when the entry names a domain this static website never held.`,context:{resourceType:`staticwebsite.custom_domain`,staticWebsiteName:e,domain:r}})}if(o&&o.targetWorkspaceId===l){c.push({kind:`transfer-pending`,staticWebsiteName:e,domain:r,message:o.requestPurgedAt?`transfer to workspace ${l} is pending`:`transfer to workspace ${l} is pending; the receiving site cannot accept it yet`});continue}o&&s.deletes.push({name:r,staticWebsiteName:e,request:{workspaceId:n,domain:r},details:[`withdraws the offer to workspace ${o.targetWorkspaceId}`]});let u=S.get(r);s.creates.push({name:r,staticWebsiteName:e,request:{workspaceId:n,domain:r,targetWorkspaceId:l},details:[`offers "${r}" to workspace ${l}`,...o?[`replaces the offer to workspace ${o.targetWorkspaceId}`]:[],...u&&!o?[describePreviousTransfer(u)]:[]]})}}return{changeSet:a,customDomainChangeSet:o,customDomainTransferChangeSet:s,customDomainNotes:c,customDomainLiveOffers:b,...l.result}}async function applyAIGateway(e,t,n=`create-update`){let{changeSet:r}=t;n===`create-update`?await Promise.all([...r.creates.map(async t=>{t.request.cors=await Dt(e,a(t.request.workspaceId,`request missing workspaceId`),t.request.cors,`AIGateway CORS`),await e.createAIGateway(t.request),await writeMetadataLabels(e,t.metaRequest)}),...r.updates.map(async t=>{t.request.cors=await Dt(e,a(t.request.workspaceId,`request missing workspaceId`),t.request.cors,`AIGateway CORS`),await e.updateAIGateway(t.request),await writeMetadataLabels(e,t.metaRequest)})]):await Promise.all(r.deletes.map(t=>e.deleteAIGateway(t.request)))}function normalizeComparableAIGatewayShape(e){return{authNamespace:e.authNamespace,cors:e.cors.toSorted()}}function normalizeComparableAIGateway(e){return normalizeComparableAIGatewayShape({authNamespace:e.authNamespace||``,cors:[...e.cors||[]]})}function areAIGatewaysEqual(e,t){return areNormalizedEqual(normalizeComparableAIGateway(e),normalizeComparableAIGateway(t))}async function planAIGateway(e){let{client:t,workspaceId:n,application:r,forRemoval:i}=e,a=createChangeSet(`AIGateways`),o=createOwnershipTracker(r.name,r.id),s=await fetchExistingResourcesWithLabels({client:t,fetchPage:async(e,r)=>{let{aigateways:i,nextPageToken:a}=await t.listAIGateways({workspaceId:n,pageToken:e,pageSize:r});return[i,a]},getName:e=>e.name,getTrn:e=>resourceTrn(n,`aigateway`,e)}),c=i?[]:r.aiGatewayServices,l=expectedLocalStaticWebsiteNames(e);for(let e of c){let i=e,c=e.name,u=s[c],d=await buildMetaRequest({trn:resourceTrn(n,`aigateway`,c),appName:r.name,appId:r.id}),f=await Dt(t,n,i.cors?[...i.cors]:[],`AIGateway CORS`,{expectedLocalNames:l}),p=normalizeComparableAIGateway({...i,cors:f}),m={workspaceId:n,aigatewayName:c,authNamespace:i.authNamespace,cors:i.cors?[...i.cors]:[]};if(u){let e=o.ownsDesired(u.allLabels,{resourceType:`aigateway`,resourceLabel:`AIGateway`,resourceName:c})&&areAIGatewaysEqual(u.resource,p);e&&hasMatchingSdkVersion(u.allLabels,d.labels)?a.unchanged.push({name:c}):a.updates.push({name:c,request:m,metaRequest:d,...e&&{forcedBySdkVersion:!0}}),delete s[c]}else a.creates.push({name:c,request:m,metaRequest:d})}return Object.entries(s).forEach(([e,t])=>{o.ownsRemaining(t?.allLabels)&&a.deletes.push({name:e,request:{workspaceId:n,aigatewayName:e}})}),{changeSet:a,...o.result}}async function applyApplication(e,t,n=`create-update`){if(n===`create-update`){let n=[...t.updates,...t.unchanged];await Promise.all([...t.creates.map(async t=>{t.request.cors=await Dt(e,a(t.request.workspaceId,`request missing workspaceId`),t.request.cors,`CORS`),await e.createApplication(t.request),await writeMetadataLabels(e,t.metaRequest)}),...n.map(async t=>{t.request.cors=await Dt(e,a(t.request.workspaceId,`request missing workspaceId`),t.request.cors,`CORS`),await e.updateApplication(t.request),await writeMetadataLabels(e,t.metaRequest)})])}else await Promise.all(t.deletes.map(async t=>{await e.deleteApplication(t.request)}))}async function recomposeApplication(e,t){let n=[...t.creates.map(e=>e.request),...[...t.updates,...t.unchanged].map(e=>e.request)];await Promise.all(n.map(t=>e.updateApplication(t)))}function sortStrings(e){return(e??[]).toSorted()}function normalizeSubgraphs(e){return[...e??[]].map(e=>({serviceType:a(e.serviceType,`subgraph missing serviceType`),serviceNamespace:e.serviceNamespace??``})).toSorted((e,t)=>e.serviceType===t.serviceType?e.serviceNamespace.localeCompare(t.serviceNamespace):e.serviceType-t.serviceType)}function normalizeHttpAdapters(e){return[...e??[]].map(e=>({name:e.name??``,pathPattern:e.pathPattern??``,methods:sortStrings(e.methods),inputScript:e.inputScript??``,outputScript:e.outputScript??``,enabled:e.enabled??!0,priority:e.priority??0})).toSorted((e,t)=>e.name.localeCompare(t.name))}function toComparableApplication(e){return{authNamespace:e.authNamespace,authIdpConfigName:e.authIdpConfigName,cors:sortStrings(e.cors),subgraphs:[...e.subgraphs],allowedIpAddresses:sortStrings(e.allowedIpAddresses),disableIntrospection:e.disableIntrospection,disabled:e.disabled,httpAdapters:[...e.httpAdapters]}}function normalizeComparableApplication(e,t,n,r,i){return toComparableApplication({authNamespace:t??``,authIdpConfigName:n??``,cors:r,subgraphs:normalizeSubgraphs(e.subgraphs.map(e=>protoSubgraph(e))),allowedIpAddresses:e.config.allowedIpAddresses??[],disableIntrospection:e.config.disableIntrospection??!1,disabled:!1,httpAdapters:normalizeHttpAdapters(i)})}function normalizeComparableExistingApplication(e){return toComparableApplication({authNamespace:e.authNamespace,authIdpConfigName:e.authIdpConfigName,cors:e.cors,subgraphs:normalizeSubgraphs(e.subgraphs),allowedIpAddresses:e.allowedIpAddresses,disableIntrospection:e.disableIntrospection,disabled:e.disabled,httpAdapters:normalizeHttpAdapters(e.httpAdapters)})}function areApplicationsEqual(e,t){return areNormalizedEqual(normalizeComparableExistingApplication(e),t)}async function planApplication(e,t,n){let{client:r,workspaceId:i,application:o,forRemoval:s}=e,c=createOwnershipTracker(o.name,o.id),l=createChangeSet(`Applications`),u=n?.existingApplications??await F(async(e,t)=>{let{applications:n,nextPageToken:a}=await r.listApplications({workspaceId:i,pageToken:e,pageSize:t});return[n,a]});if(s){let e=o.id?u:u.filter(e=>e.name===o.name),t=await Promise.all(e.map(async e=>{let t=await fetchAppLabels(r,i,e.name);return c.ownsRemaining(t)?e.name:null}));for(let e of t)e&&l.deletes.push({name:e,request:{workspaceId:i,applicationName:e}});return Object.assign(l,c.result,{existingApplications:u,existingLabels:void 0})}if(o.subgraphs.length===0)return Object.assign(l,c.result,{existingApplications:u,existingLabels:void 0});let d,f;if(o.authService){d=o.authService.config.name;let e=o.authService.config.idProvider;e&&(f=e.name)}else if(o.config.auth){if(d=o.config.auth.name,e.externalAuthIdpConfigNames?.has(d))f=e.externalAuthIdpConfigNames.get(d);else{let e=await F(async(e,t)=>{let{idpConfigs:n,nextPageToken:o}=await r.listAuthIDPConfigs({workspaceId:i,namespaceName:a(d,`authNamespace must be set before listing IDP configs`),pageToken:e,pageSize:t});return[n,o]});if(e.length>0){let[t]=e;t&&(f=t.name)}}}let p=await buildMetaRequest({trn:resourceTrn(i,`application`,o.name),appName:o.name,appId:o.id,metadata:o.config.metadata}),m=n?n.existingLabels:await fetchAppLabels(r,i,o.name);assertLabelBudget(o.name,m,p);let h=diffMetadataDisplay(m,o.config.metadata),g=expectedLocalStaticWebsiteNames(e),_=await Dt(r,i,o.config.cors,`CORS`,{expectedLocalNames:g}),v=buildHttpAdapters(o,t),y=normalizeComparableApplication(o,d,f,_,v),b={workspaceId:i,applicationName:o.name,authNamespace:d,authIdpConfigName:f,cors:o.config.cors,subgraphs:o.subgraphs.map(e=>protoSubgraph(e)),allowedIpAddresses:o.config.allowedIpAddresses,disableIntrospection:o.config.disableIntrospection,httpAdapters:v},x=u.find(e=>e.name===o.name);if(o.id){let e=u.filter(e=>e.name!==o.name),t=await Promise.all(e.map(async e=>isOwnedByApp(await fetchAppLabels(r,i,e.name),o.name,o.id)?e.name:null));for(let e of t)e&&l.deletes.push({name:e,request:{workspaceId:i,applicationName:e}})}if(x){let e=c.ownsDesired(m,{resourceType:`application`,resourceLabel:`Application`,resourceName:o.name}),t={name:o.name,request:b,metaRequest:p},n=e&&areApplicationsEqual(x,y)&&h.length===0;if(n&&hasMatchingSdkVersion(m,p.labels))l.unchanged.push(t);else{let e=[...diffHttpAdapterDisplay(x.httpAdapters,v),...h];e.length>0&&(t.details=e),l.updates.push({...t,...n&&{forcedBySdkVersion:!0}})}}else{let e=[...diffHttpAdapterDisplay(void 0,v),...h];l.creates.push({name:o.name,request:b,metaRequest:p,details:e.length>0?e:void 0})}return Object.assign(l,c.result,{existingApplications:u,existingLabels:m})}async function fetchAppLabels(e,t,n){return(await P(async()=>{let{metadata:r}=await e.getMetadata({trn:resourceTrn(t,`application`,n)});return r}))?.labels}function diffHttpAdapterDisplay(e,t){let n=new Map((e??[]).map(e=>[e.name??``,e])),r=new Map(t.map(e=>[e.name??``,e])),i=[];for(let[e,t]of r){let r=n.get(e);r?areNormalizedEqual(normalizeHttpAdapters([r])[0],normalizeHttpAdapters([t])[0])||i.push({name:e,symbol:O.update}):i.push({name:e,symbol:O.create})}for(let e of n.keys())r.has(e)||i.push({name:e,symbol:O.delete});return i.toSorted((e,t)=>e.name.localeCompare(t.name)).map(e=>`${e.symbol} ${e.name} (httpAdapter)`)}function assertLabelBudget(e,t,n){let r=/* @__PURE__ */ new Set([...Object.keys(t??{}),...Object.keys(n.labels??{})]);for(let e of n.remove??[])r.delete(e);if(r.size<=20)return;let i=new Set(Object.keys(n.labels??{})),a=[...r].filter(e=>!i.has(e)).toSorted();throw E({code:`DEPLOY_LABEL_LIMIT_EXCEEDED`,message:`Application '${e}' would store ${r.size} labels, over the platform's limit of 20.`,details:`${i.size} come from this deploy and ${a.length} are kept from earlier deploys or other tools${a.length?` (${a.join(`, `)})`:``}.`,suggestion:`Remove entries from 'metadata' in the config, or delete labels the application no longer needs.`})}function diffMetadataDisplay(e,t){let n=e??{},isStored=e=>Object.hasOwn(n,e);return Object.entries(t??{}).filter(([e,t])=>!isStored(e)||n[e]!==t).toSorted(([e],[t])=>e.localeCompare(t)).map(([e])=>`${isStored(e)?O.update:O.create} ${e} (metadata)`)}function buildHttpAdapters(e,t){let n=e.httpAdapterService?.adapters??[];return n.length===0?[]:n.map(e=>{let n=t?.bundledInputs.get(e.adapter.name);if(!n)throw b(`HTTP adapter "${e.adapter.name}" was loaded but no bundled input script is available`);let r=``;if(e.hasOutput){let n=t?.bundledOutputs.get(e.adapter.name);if(!n)throw b(`HTTP adapter "${e.adapter.name}" declares an output handler but no bundled output script is available`);r=n}return{name:e.adapter.name,pathPattern:e.adapter.pathPattern,methods:e.methods.map(e=>$e[e]),inputScript:n,outputScript:r,enabled:e.adapter.enabled,priority:e.adapter.priority}})}function protoSubgraph(e){let t;switch(e.Type){case`tailordb`:t=Ut.TAILORDB;break;case`pipeline`:t=Ut.PIPELINE;break;case`idp`:t=Ut.IDP;break;case`auth`:t=Ut.AUTH;break;default:throw b(`Unknown subgraph type: ${e.Type}`)}return{serviceType:t,serviceNamespace:e.Name}}const ha=U.object({hash:U.string(),updateTime:U.string().optional()}),ga=U.object({vaults:U.record(U.string(),U.record(U.string(),ha)),connections:U.record(U.string(),U.string()).optional()}),_a=U.object({version:U.literal(2),workspaceId:U.string(),applicationKey:U.string(),state:ga});function getSecretsStatePath(e){let t=hashValue(JSON.stringify([e.workspaceId,applicationStateKey(e)]));return H.join(Ze(),`secrets-state`,`${t}.json`)}function loadPersistedSecretsState(e){try{let t=Zr(getSecretsStatePath(e),`utf-8`),n=_a.safeParse(JSON.parse(t));return!n.success||n.data.workspaceId!==e.workspaceId||n.data.applicationKey!==applicationStateKey(e)?void 0:n.data}catch{return}}function applicationStateKey(e){if(!e.applicationId)throw b(`Application "${e.applicationName}" has no stable id for secrets state`);return`id:${e.applicationId}`}function loadSecretsState(e){return e.applicationId?loadPersistedSecretsState(e)?.state??{vaults:{}}:{vaults:{}}}function saveSecretsState(e,t){if(!e.applicationId)return;let n=getSecretsStatePath(e),r=H.dirname(n);Xr(r,{recursive:!0});let i=`${n}.tmp-${mi()}`;ri(i,JSON.stringify({version:2,workspaceId:e.workspaceId,applicationKey:applicationStateKey(e),state:t},null,2),`utf-8`),$r(i,n)}function hashValue(e){return pi(`sha256`).update(e).digest(`hex`)}function serializeUpdateTime(e){return e===void 0?void 0:`${e.seconds}.${e.nanos}`}const va=/* @__PURE__ */ new Map;async function withSecretsStateLock(e,t){if(!e.applicationId)return t();let n=`${getSecretsStatePath(e)}.lock`,r=va.get(n);return r||(r=di(1),va.set(n,r)),r(async()=>{let e=await acquireFileLock(n),r=setInterval(()=>refreshLock(n,e),1e4);r.unref();try{return await t()}finally{clearInterval(r),releaseFileLock(n,e)}})}async function acquireFileLock(e){Xr(H.dirname(e),{recursive:!0});let t=mi(),n=Date.now()+3e5;for(;;){let r=!0;try{Xr(e)}catch(e){if(e.code!==`EEXIST`)throw e;r=!1}if(r){try{ri(H.join(e,`owner.json`),JSON.stringify({pid:process.pid,token:t}))}catch(t){throw ei(e,{recursive:!0,force:!0}),t}return t}if(!(isLockExpired(e)&&stealLock(e))){if(Date.now()>=n){let t=H.resolve(e);throw E({code:`DEPLOY_LOCK_TIMEOUT`,message:`Timed out waiting for another deploy to the same workspace and application to finish.`,suggestion:`Wait for it to complete and retry; an interrupted deploy recovers automatically within a minute. If the error persists, stop any \`tailor deploy\` still running from this project directory, then delete the lock directory ${t} and retry.`,context:{lockPath:t}})}await new Promise(e=>setTimeout(e,100))}}}function isLockExpired(e){try{return Date.now()-ti(e).mtimeMs>6e4}catch{return!1}}function readLockToken(e){try{return JSON.parse(Zr(H.join(e,`owner.json`),`utf-8`)).token}catch{return}}function refreshLock(e,t){if(readLockToken(e)!==t)return;let n=/* @__PURE__ */ new Date;try{ni(e,n,n)}catch{}}function releaseFileLock(e,t){readLockToken(e)===t&&ei(e,{recursive:!0,force:!0})}function stealLock(e){let t=`${e}.stale-${process.pid}-${Date.now()}`;try{$r(e,t)}catch{return!1}if(isLockExpired(t))return ei(t,{recursive:!0,force:!0}),!0;try{$r(t,e)}catch{ei(t,{recursive:!0,force:!0})}return!1}function buildConnectionRequest(e,t,n){return{workspaceId:e,connection:{name:t,type:Zn.OAUTH2,config:{case:`oauth2`,value:{providerUrl:n.providerUrl,issuerUrl:n.issuerUrl,clientId:n.clientId,clientSecret:n.clientSecret,authUrl:n.authUrl??``,tokenUrl:n.tokenUrl??``}}}}}function buildUpdateMask(e,t,n){if(e.config.case!==`oauth2`){let e=[`type`,`oauth2.provider_url`,`oauth2.issuer_url`,`oauth2.client_id`,`oauth2.auth_url`,`oauth2.token_url`];return t.clientSecret&&e.push(`oauth2.client_secret`),{paths:e}}let r=[],i=e.config.value;return i.providerUrl!==t.providerUrl&&r.push(`oauth2.provider_url`),i.issuerUrl!==t.issuerUrl&&r.push(`oauth2.issuer_url`),i.clientId!==t.clientId&&r.push(`oauth2.client_id`),i.authUrl!==(t.authUrl??``)&&r.push(`oauth2.auth_url`),i.tokenUrl!==(t.tokenUrl??``)&&r.push(`oauth2.token_url`),n&&t.clientSecret&&r.push(`oauth2.client_secret`),{paths:r}}async function planAuthConnections(e,t,n,r,i){let a={workspaceId:t,applicationId:r,applicationName:n},o=createChangeSet(`Auth connections`),s=createOwnershipTracker(n,r),c={};for(let e of i)for(let[t,n]of Object.entries(e.connections))c[t]=n,C.registerSecret(n.clientSecret);let l=await F(async(n,r)=>{let{connections:i,nextPageToken:a}=await e.listAuthConnections({workspaceId:t,pageToken:n,pageSize:r});return[i,a]}),u={};await Promise.all(l.map(async n=>{let{metadata:r}=await e.getMetadata({trn:resourceTrn(t,`auth_connection`,n.name)});u[n.name]={resource:n,allLabels:r?.labels}}));let d=loadSecretsState(a);for(let[e,i]of Object.entries(c)){let a=u[e],c=await buildMetaRequest({trn:resourceTrn(t,`auth_connection`,e),appName:n,appId:r});if(a){let n=s.ownsDesired(a.allLabels,{resourceType:`auth.connection`,resourceLabel:`Auth connection`,resourceName:e}),r=hashValue(i.clientSecret)!==d.connections?.[e],l=buildUpdateMask(a.resource,i,r);l.paths.length>0?o.replaces.push({name:e,updateRequest:{...buildConnectionRequest(t,e,i),updateMask:l},metaRequest:c}):n?o.unchanged.push({name:e}):o.updates.push({name:e,metaRequest:c}),delete u[e]}else o.creates.push({name:e,request:buildConnectionRequest(t,e,i),metaRequest:c})}for(let[e,n]of Object.entries(u))n&&s.ownsRemaining(n.allLabels)&&o.deletes.push({name:e,request:{workspaceId:t,connectionName:e}});return{changeSet:o,...s.result,stateScope:a}}async function applyAuthConnections(e,t,n){let{changeSet:r,stateScope:i}=t;n===`create-update`?((r.creates.length>0||r.replaces.length>0)&&await withSecretsStateLock(i,async()=>{await Promise.all(r.creates.map(async t=>{await e.createAuthConnection(t.request),await writeMetadataLabels(e,t.metaRequest),C.info(`Connection "${t.name}" was created. Authorize it with:\n tailor authconnection authorize --name ${t.name}\nOr via the Console: tailor authconnection open`)}));for(let t of r.replaces)(await e.updateAuthConnection(t.updateRequest)).connection?.status===fn.UNAUTHORIZED&&C.warn(`Connection "${t.name}" requires re-authorization. Authorize with:\n tailor authconnection authorize --name ${t.name}\nOr via the Console: tailor authconnection open`),await writeMetadataLabels(e,t.metaRequest);let t=r.replaces.filter(e=>e.updateRequest.updateMask?.paths?.includes(`oauth2.client_secret`));if(r.creates.length>0||t.length>0){let e=loadSecretsState(i);e.connections||={};for(let t of r.creates){let n=t.request.connection;n?.config?.case===`oauth2`&&(e.connections[t.name]=hashValue(n.config.value.clientSecret??``))}for(let n of t){let t=n.updateRequest.connection;t?.config?.case===`oauth2`&&(e.connections[n.name]=hashValue(t.config.value.clientSecret??``))}saveSecretsState(i,e)}}),await Promise.all(r.updates.map(async t=>{await writeMetadataLabels(e,t.metaRequest)}))):r.deletes.length>0&&await withSecretsStateLock(i,async()=>{await Promise.all(r.deletes.map(async t=>{await e.deleteAuthConnection(t.request)}));let t=loadSecretsState(i);if(t.connections){for(let e of r.deletes)delete t.connections[e.name];saveSecretsState(i,t)}})}const ya=65536;function computeContentHash(e){return fi.createHash(`sha256`).update(e,`utf-8`).digest(`hex`)}const ba=`workflow--`;function resolverFunctionName(e,t){return`resolver--${e}--${t}`}function executorFunctionName(e){return`executor--${e}`}function workflowJobFunctionName(e){return`${ba}${e}`}function collectWorkflowJobStates(e){let jobNames=e=>new Set(e.filter(e=>e.name.startsWith(ba)).map(e=>e.name.slice(10)));return{unchanged:jobNames(e.unchanged),forcedBySdkVersion:jobNames(e.updates.filter(e=>e.forcedBySdkVersion))}}function splitFunctionRegistryChanges(e){function partition(e){let t={workflowJob:[],resolver:[],executor:[],authHook:[],other:[]};for(let n of e)n.name.startsWith(`workflow--`)?t.workflowJob.push(n):n.name.startsWith(`resolver--`)?t.resolver.push(n):n.name.startsWith(`executor--`)?t.executor.push(n):n.name.startsWith(`auth-hook--`)?t.authHook.push(n):t.other.push(n);return t}let t=partition(e.creates),n=partition(e.updates),r=partition(e.deletes),i=partition(e.replaces),a=partition(e.unchanged);function collect(e){return{creates:t[e],updates:n[e],deletes:r[e],replaces:i[e],unchanged:a[e]}}return{workflowJobChanges:collect(`workflowJob`),resolverFunctionChanges:collect(`resolver`),executorFunctionChanges:collect(`executor`),authHookFunctionChanges:collect(`authHook`),otherChanges:collect(`other`)}}function authHookFunctionName(e,t){return`auth-hook--${e}--${t}`}function collectFunctionEntries(e,t,n){let r=[];for(let t of e.applications)for(let e of t.resolverServices)for(let t of Object.values(e.resolvers)){let i=n.resolvers.get(ut(e.namespace,t.name));i?r.push({name:resolverFunctionName(e.namespace,t.name),scriptContent:i,contentHash:computeContentHash(i),description:`Resolver: ${e.namespace}/${t.name}`}):C.warn(`Bundled code not found for resolver: ${e.namespace}/${t.name}`)}if(e.executorService){let t=e.executorService.executors;for(let e of Object.values(t))if(e.operation.kind===`function`||e.operation.kind===`jobFunction`){let t=n.executors.get(e.name);if(!t){C.warn(`Bundled code not found for executor: ${e.name}`);continue}r.push({name:executorFunctionName(e.name),scriptContent:t,contentHash:computeContentHash(t),description:`Executor: ${e.name}`})}}for(let e of t){let t=n.workflowJobs.get(e.name);t?r.push({name:workflowJobFunctionName(e.name),scriptContent:t,contentHash:computeContentHash(t),description:`Workflow job: ${e.name}`}):C.warn(`Bundled code not found for workflow job: ${e.name}`)}for(let t of e.applications)if(t.authService?.config.hooks?.beforeLogin){let e=t.authService.config.name,i=authHookFunctionName(e,`before-login`),a=n.authHooks.get(i);if(!a){C.warn(`Bundled code not found for auth hook: ${i}`);continue}r.push({name:i,scriptContent:a,contentHash:computeContentHash(a),description:`Auth hook: ${e}/before-login`})}return r}function filterBundledWorkflowJobs(e,t){let n=new Set(t);return e.filter(e=>n.has(e.name))}async function planFunctionRegistry(e,t,n,r,i,a){let o=createChangeSet(`Function registry`),s=createOwnershipTracker(n,r),c=a??await fetchExistingResourcesWithLabels({client:e,fetchPage:async(n,r)=>{let i=await e.listFunctionRegistries({workspaceId:t,pageToken:n,pageSize:r});return[i.functions.map(e=>({name:e.name,contentHash:e.contentHash})),i.nextPageToken]},getName:e=>e.name,getTrn:e=>resourceTrn(t,`function_registry`,e)}),l={...c};for(let e of i){let i=l[e.name],a=await buildMetaRequest({trn:resourceTrn(t,`function_registry`,e.name),appName:n,appId:r});if(i){let t=s.ownsDesired(i.allLabels,{resourceType:`function_registry`,resourceLabel:`Function registry`,resourceName:e.name})&&i.resource.contentHash===e.contentHash;t&&hasMatchingSdkVersion(i.allLabels,a.labels)?o.unchanged.push({name:e.name}):o.updates.push({name:e.name,entry:e,metaRequest:a,...t&&{forcedBySdkVersion:!0}}),delete l[e.name]}else o.creates.push({name:e.name,entry:e,metaRequest:a})}for(let[e,n]of Object.entries(l))n&&s.ownsRemaining(n.allLabels)&&o.deletes.push({name:e,workspaceId:t});let{workflowJobChanges:u,resolverFunctionChanges:d,executorFunctionChanges:f,authHookFunctionChanges:p}=splitFunctionRegistryChanges(o);return{changeSet:o,workflowJobChanges:u,resolverFunctionChanges:d,executorFunctionChanges:f,authHookFunctionChanges:p,...s.result,existingMap:c}}async function uploadFunctionScript(e,t,n,r){let i=Buffer.from(n.scriptContent,`utf-8`),a={workspaceId:t,name:n.name,description:n.description,sizeBytes:BigInt(i.length),contentHash:n.contentHash};if(r){async function*createStream(){yield{payload:{case:`info`,value:a}};for(let e=0;e<i.length;e+=ya)yield{payload:{case:`chunk`,value:i.subarray(e,Math.min(e+ya,i.length))}}}await e.createFunctionRegistry(createStream())}else{async function*updateStream(){yield{payload:{case:`info`,value:a}};for(let e=0;e<i.length;e+=ya)yield{payload:{case:`chunk`,value:i.subarray(e,Math.min(e+ya,i.length))}}}await e.updateFunctionRegistry(updateStream())}}async function applyFunctionRegistry(e,t,n,r=`create-update`){let{changeSet:i}=n;if(r===`create-update`){let n=At();await Promise.all([...i.creates.map(r=>n(async()=>{await uploadFunctionScript(e,t,r.entry,!0),await writeMetadataLabels(e,r.metaRequest)})),...i.updates.map(r=>n(async()=>{await uploadFunctionScript(e,t,r.entry,!1),await writeMetadataLabels(e,r.metaRequest)}))])}else await Promise.all(i.deletes.map(async t=>{try{await e.deleteFunctionRegistry({workspaceId:t.workspaceId,name:t.name})}catch(e){if(!Ot(e))throw e}}))}function forcedFunctionUpdateNames(e){return new Set(e?.updates.filter(e=>e.forcedBySdkVersion).map(e=>e.name)??[])}function createRelatedFunctionRegistryNameSets(e){return{creates:new Set(e?.creates.map(e=>e.name)??[]),updates:new Set(e?.updates.map(e=>e.name)??[]),deletes:new Set(e?.deletes.map(e=>e.name)??[]),replaces:new Set(e?.replaces.map(e=>e.name)??[])}}const xa={create:O.create,update:O.update,delete:O.delete,replace:O.replace};function formatChangeSetEntries(e,t=[],n){function toEntry(e,r){return{action:e,symbol:xa[e],name:r.name,labels:[...t],namespace:n?.(r),...r.forcedBySdkVersion&&{forcedBySdkVersion:!0}}}return[...e.creates.map(e=>toEntry(`create`,e)),...e.deletes.map(e=>toEntry(`delete`,e)),...e.updates.map(e=>toEntry(`update`,e)),...e.replaces.map(e=>toEntry(`replace`,e))]}function formatGroupedDisplayLine(e){return`${e.labels.length>0?`${e.symbol} ${e.name} (${e.labels.join(`, `)})`:`${e.symbol} ${e.name}`}${forcedBySdkVersionSuffix(e)}`}function parseFunctionRegistryName(e){if(e.startsWith(`resolver--`)){let[,t,n]=e.split(`--`);if(t&&n)return{displayName:n,namespace:t}}if(e.startsWith(`workflow--`)||e.startsWith(`executor--`))return{displayName:e.slice(10)};if(e.startsWith(`auth-hook--`)){let[,t,n]=e.split(`--`);if(t&&n)return{displayName:n,namespace:t}}return{displayName:e}}function buildRemainingFunctionRegistryEntries(e,t,n=createRelatedFunctionRegistryNameSets()){return[[`create`,e.creates,n.creates],[`delete`,e.deletes,n.deletes],[`update`,e.updates,n.updates],[`replace`,e.replaces,n.replaces]].flatMap(([e,n,r])=>[...n].filter(e=>!r.has(e)).map(n=>{let{displayName:r,namespace:i}=parseFunctionRegistryName(n);return{action:e,symbol:xa[e],name:r,labels:[`function`],namespace:i,...e===`update`&&t.has(n)&&{forcedBySdkVersion:!0}}}))}function formatChangeEntriesWithFunctionRegistry(e,t,n,r,i){let{getNamespace:a,getDisplayName:o}=i??{},s=createRelatedFunctionRegistryNameSets(n),c=forcedFunctionUpdateNames(n),l=createRelatedFunctionRegistryNameSets();function processItems(t,n,i,s){return t.map(t=>{let l=r(t,n).filter(e=>i.has(e));for(let e of l)s.add(e);let u=t.forcedBySdkVersion&&l.every(e=>c.has(e));return{action:n,symbol:xa[n],name:o?.(t)??t.name,labels:l.length>0?[e,`function`]:[e],namespace:a?.(t),...u&&{forcedBySdkVersion:!0}}})}return[...processItems(t.creates,`create`,s.creates,l.creates),...processItems(t.deletes,`delete`,s.deletes,l.deletes),...processItems(t.updates,`update`,s.updates,l.updates),...t.replaces.map(t=>({action:`replace`,symbol:xa.replace,name:o?.(t)??t.name,labels:[e],namespace:a?.(t)})),...buildRemainingFunctionRegistryEntries(s,c,l)]}function extractServiceActions(e){return[...e.creates.map(e=>({name:e.name,action:`create`})),...e.deletes.map(e=>({name:e.name,action:`delete`})),...e.updates.map(e=>({name:e.name,action:`update`,...e.forcedBySdkVersion&&{forcedBySdkVersion:!0}})),...e.replaces.map(e=>({name:e.name,action:`replace`}))]}function buildGroupedDisplayLines(e,t,n){let r=/* @__PURE__ */ new Map;if(n)for(let e of n)r.set(e.name,e);if(t.length===0&&r.size===0)return[];let i=[h.bold(`${e}:`)],o=[],s=/* @__PURE__ */ new Map;for(let e of t){let t=e.namespace;s.has(t)||(o.push(t),s.set(t,[])),a(s.get(t),`namespace group missing`).push(e)}let c=/* @__PURE__ */ new Set;for(let e of o){let t=a(s.get(e),`namespace group missing`);if(e){let n=r.get(e),a=n?`${xa[n.action]} `:``,o=n?.forcedBySdkVersion?`${h.bold(e)}${forcedBySdkVersionSuffix(n)}${h.bold(`:`)}`:h.bold(`${e}:`);i.push(` ${a}${o}`),c.add(e);for(let e of t)i.push(` ${formatGroupedDisplayLine(e)}`)}else for(let e of t)i.push(` ${formatGroupedDisplayLine(e)}`)}for(let[e,t]of r)c.has(e)||i.push(` ${xa[t.action]} ${e}${forcedBySdkVersionSuffix(t)}`);return i}const Sa={tailorDBType:e=>`TailorDB table "${e}"`,resolver:e=>`Resolver "${e}"`,idpService:e=>`IdP service "${e}"`,workflow:e=>`Workflow "${e}"`,workflowJob:e=>`Job "${e}"`,workflowJobs:e=>`Jobs of workflow "${e}"`},Ca={tailorDBType:e=>({resource:Sa.tailorDBType(e),trigger:`record`}),resolver:e=>({resource:Sa.resolver(e),trigger:`resolverExecuted`}),idpService:e=>({resource:Sa.idpService(e),trigger:`idpUser`}),workflow:e=>({resource:Sa.workflow(e),trigger:`workflowExecution`}),workflowJob:e=>({resource:Sa.workflowJob(e),trigger:`workflowJobExecution`,subscribesTo:`a workflow that runs it`})};function publishEventsConflictError(e){let{resource:t,trigger:n,subscribesTo:r=`it`}=e;return`${t} has "publishEvents: false", but executors with ${n} triggers subscribe to ${r}. Either remove "publishEvents: false" or remove the matching executor triggers.`}function subscribesToEvents(e){return!e.disabled}function assertNoPublishEventsConflict(e){let{explicit:t,subscribed:n,conflict:r}=e;if(t===!1&&n)throw Error(publishEventsConflictError(r))}function resolvePublishEvents(e){return assertNoPublishEventsConflict(e),e.explicit??e.subscribed}const{normalizeActionPermission:wa}=ct({"=":`eq`,"!=":`ne`,in:`in`,"not in":`nin`});function normalizeIdPActionPermission(e){return wa(e)}function normalizeIdPPermission(e){return{create:e.create.map(e=>normalizeIdPActionPermission(e)),read:e.read.map(e=>normalizeIdPActionPermission(e)),update:e.update.map(e=>normalizeIdPActionPermission(e)),delete:e.delete.map(e=>normalizeIdPActionPermission(e)),sendPasswordResetEmail:(e.sendPasswordResetEmail??[]).map(e=>normalizeIdPActionPermission(e)),unenrollMfa:(e.unenrollMfa??[]).map(e=>normalizeIdPActionPermission(e))}}function parseIdPPermission(e){if(e)return normalizeIdPPermission(e)}function findOmittedPermitRules(e){if(!e)return[];let t=[];for(let n of Object.keys(e))e[n]?.forEach((e,r)=>{Me(e)&&t.push(`${String(n)}[${r}]`)});return t}function findLoggedInOnlyPermitRules(e){if(!e)return[];let t=normalizeIdPPermission(e),n=[];for(let e of Object.keys(t))t[e].forEach((t,r)=>{t.permit===`allow`&&isLoggedInOnly(t.conditions)&&n.push(`${e}[${r}]`)});return n}function isLoggedInOperand(e){return typeof e==`object`&&!!e&&`user`in e&&e.user===`_loggedIn`}function isLoggedInOnly(e){let[t,...n]=e;if(!t||n.length>0)return!1;let[r,i,a]=t,o=isLoggedInOperand(r)?a:isLoggedInOperand(a)?r:void 0;switch(i){case`eq`:return o===!0;case`ne`:return o===!1;case`in`:return isLoggedInOperand(r)&&Array.isArray(o)&&o.includes(!0);case`nin`:return isLoggedInOperand(r)&&Array.isArray(o)&&!o.includes(!0);default:return!1}}async function resolveServiceReturnOrigins(e,t){let n=t.userAuthPolicy,r=n?.allowedReturnOrigins;if(!n||!r?.length)return;let i=await Dt(e,a(t.workspaceId,`request missing workspaceId`),r,`IdP service "${t.namespaceName??``}" allowedReturnOrigins`);if(i.length!==r.length)throw E({code:`IDP_RETURN_ORIGIN_UNRESOLVED`,message:`IdP service "${t.namespaceName??``}" allowedReturnOrigins: ${r.length-i.length} of ${r.length} entries could not be resolved.`,suggestion:`Check that each "<name>:url" entry refers to a deployed static website.`});n.allowedReturnOrigins=i}function idpClientVaultName(e,t){return`idp-${e}-${t}`}function idpClientSecretName(e,t){return`client-secret-${e}-${t}`}async function applyIdP(e,t,n=`create-update`){let{changeSet:r}=t;n===`create-update`?(await Promise.all([...r.service.creates.map(async t=>{await resolveServiceReturnOrigins(e,t.request),await e.createIdPService(t.request),await writeMetadataLabels(e,t.metaRequest)}),...r.service.updates.map(async t=>{await resolveServiceReturnOrigins(e,t.request),await e.updateIdPService(t.request),await writeMetadataLabels(e,t.metaRequest)}),...r.service.unchanged.flatMap(t=>t.metaRequest?[writeMetadataLabels(e,t.metaRequest)]:[])]),await Promise.all([...r.client.creates.map(async t=>{let n=await e.createIdPClient(t.request);n.client?.clientSecret&&C.registerSecret(n.client.clientSecret);let r=idpClientVaultName(a(t.request.namespaceName,`request missing namespaceName`),t.request.client?.name||``),i=idpClientSecretName(a(t.request.namespaceName,`request missing namespaceName`),t.request.client?.name||``);await e.createSecretManagerVault({workspaceId:t.request.workspaceId,secretmanagerVaultName:r}),await e.createSecretManagerSecret({workspaceId:t.request.workspaceId,secretmanagerVaultName:r,secretmanagerSecretName:i,secretmanagerSecretValue:n.client?.clientSecret})}),...r.client.updates.map(async t=>{let n=idpClientVaultName(t.namespaceName,t.name),r=idpClientSecretName(t.namespaceName,t.name);if(await P(async()=>await e.getSecretManagerVault({workspaceId:t.workspaceId,secretmanagerVaultName:n})))return;let{client:i}=await e.getIdPClient({workspaceId:t.workspaceId,namespaceName:t.namespaceName,name:t.name});i?.clientSecret&&C.registerSecret(i.clientSecret),await e.createSecretManagerVault({workspaceId:t.workspaceId,secretmanagerVaultName:n}),await e.createSecretManagerSecret({workspaceId:t.workspaceId,secretmanagerVaultName:n,secretmanagerSecretName:r,secretmanagerSecretValue:i?.clientSecret})})])):n===`delete-resources`?await Promise.all(r.client.deletes.map(async t=>{t.vaultOnly||await e.deleteIdPClient(t.request);let n=idpClientVaultName(a(t.request.namespaceName,`request missing namespaceName`),t.name);try{await e.deleteSecretManagerVault({workspaceId:t.request.workspaceId,secretmanagerVaultName:n})}catch(e){if(!Ot(e))throw e}})):await Promise.all(r.service.deletes.map(t=>e.deleteIdPService(t.request)))}async function planIdP(e){let{client:t,workspaceId:n,application:r,forRemoval:i,forceApplyAll:a=!1,idpUserTriggerTargets:o,dependentApps:s,runAppIds:c}=e,l=i?[]:r.idpServices,u=expectedLocalStaticWebsiteNames(e),{changeSet:d,conflicts:f,unmanaged:p,resourceOwners:m}=await planServices$3(t,n,r.name,r.id,l,o??/* @__PURE__ */ new Set,u,{dependentApps:s,runAppIds:c});return{changeSet:{service:d,client:await planClients(t,n,l,d.deletes.map(e=>e.name),a)},conflicts:f,unmanaged:p,resourceOwners:m}}function normalizeComparableUserAuthPolicy(e){return{useNonEmailIdentifier:e?.useNonEmailIdentifier??!1,allowSelfPasswordReset:e?.allowSelfPasswordReset??!1,passwordRequireUppercase:e?.passwordRequireUppercase??!1,passwordRequireLowercase:e?.passwordRequireLowercase??!1,passwordRequireNonAlphanumeric:e?.passwordRequireNonAlphanumeric??!1,passwordRequireNumeric:e?.passwordRequireNumeric??!1,passwordMinLength:e?.passwordMinLength||6,passwordMaxLength:e?.passwordMaxLength||4096,allowedEmailDomains:[...new Set((e?.allowedEmailDomains??[]).map(e=>e.toLowerCase()))].toSorted(),allowGoogleOauth:e?.allowGoogleOauth??!1,disablePasswordAuth:e?.disablePasswordAuth??!1,allowMicrosoftOauth:e?.allowMicrosoftOauth??!1,enableMfa:e?.enableMfa??!1,requireMfa:e?.requireMfa??!1,allowedReturnOrigins:(e?.allowedReturnOrigins??[]).toSorted(),mfaIssuer:e?.mfaIssuer??``}}function normalizeComparableDisableGqlOperations(e){return{create:e?.create??!1,update:e?.update??!1,delete:e?.delete??!1,read:e?.read??!1,sendPasswordResetEmail:e?.sendPasswordResetEmail??!1,requestMfaSettingsUrl:e?.requestMfaSettingsUrl??!1,unenrollMfa:e?.unenrollMfa??!1}}function normalizeComparableEmailConfig(e){return{fromName:e?.fromName??``,passwordResetSubject:e?.passwordResetSubject??``}}function normalizeComparableIdPService(e){return{authorization:e.authorization||void 0,lang:e.lang===$t.UNSPECIFIED?$t.EN:e.lang,userAuthPolicy:e.userAuthPolicy,publishEvents:e.publishEvents,disableGqlOperations:e.disableGqlOperations,emailConfig:e.emailConfig,permission:e.permission}}function normalizeComparablePermission(e){if(!e||e.create.length===0&&e.read.length===0&&e.update.length===0&&e.delete.length===0&&e.sendPasswordResetEmail.length===0&&e.unenrollMfa.length===0)return;let normalizePolicy=e=>({conditions:e.conditions.map(e=>({left:e.left?{kind:e.left.kind}:void 0,operator:e.operator,right:e.right?{kind:e.right.kind}:void 0})),permit:e.permit,description:e.description||void 0});return{create:e.create.map(normalizePolicy),read:e.read.map(normalizePolicy),update:e.update.map(normalizePolicy),delete:e.delete.map(normalizePolicy),sendPasswordResetEmail:e.sendPasswordResetEmail.map(normalizePolicy),unenrollMfa:e.unenrollMfa.map(normalizePolicy)}}function areIdPServicesEqual(e,t){return areNormalizedEqual(normalizeComparableIdPService({authorization:e.authorization,lang:e.lang,userAuthPolicy:normalizeComparableUserAuthPolicy(e.userAuthPolicy),publishEvents:e.publishUserEvents,disableGqlOperations:normalizeComparableDisableGqlOperations(e.disableGqlOperations),emailConfig:normalizeComparableEmailConfig(e.emailConfig),permission:normalizeComparablePermission(e.permission)}),t)}async function planServices$3(e,t,n,r,i,a,o,s){let c=createChangeSet(`IdP services`),l=createOwnershipTracker(n,r),u=await fetchExistingResourcesWithLabels({client:e,fetchPage:async(n,r)=>{let{idpServices:i,nextPageToken:a}=await e.listIdPServices({workspaceId:t,pageToken:n,pageSize:r});return[i,a]},getName:e=>e.namespace?.name,getTrn:e=>resourceTrn(t,`idp`,e)});for(let d of i){let i=d.name,f=u[i],p=addDependencyRecords(await buildMetaRequest({trn:resourceTrn(t,`idp`,i),appName:n,appId:r}),{key:Z.idp(i),dependentApps:s.dependentApps,runAppIds:s.runAppIds,pinned:d.publishEvents!==void 0}),m;switch(d.authorization){case`insecure`:m=`true==true`;break;case`loggedIn`:m=`user != null && size(user.id) > 0`;break;case void 0:m=void 0;break;default:m=d.authorization.cel}let h=convertLang(d.lang),g=d.userAuthPolicy,_=resolvePublishEvents({explicit:d.publishEvents,subscribed:a.has(i),conflict:Ca.idpService(i)}),v=d.emailConfig;d.permission||C.warn(`IdP service "${i}" has no permission configured.`);let y=findOmittedPermitRules(d.permission);y.length>0&&C.warn(`IdP service "${i}" has permission rule(s) ${y.join(`, `)} in object form without an explicit "permit"; they default to "deny". Set permit: true (allow) or permit: false (deny) to silence this warning.`);let b=findLoggedInOnlyPermitRules(d.permission);b.length>0&&C.warn(`IdP service "${i}" permits every authenticated user in permission rule(s) ${b.join(`, `)} (their only condition is on "_loggedIn"). Any signed-in user can then run these operations against any IdP user, for example reading and changing login information (such as email addresses) or sending password reset emails to anyone. Restrict these rules to an administrator role unless every user who can sign in is trusted.`),Qe(g)&&C.warn(`IdP service "${i}" leaves userAuthPolicy.allowedEmailDomains empty, which currently allows every email domain. The platform will stop treating an empty list as "allow every domain", so set allowedEmailDomains: ["*"] to keep that behavior, or list the domains you accept.`);let x=parseIdPPermission(d.permission),S=x?protoIdPPermission(x):void 0,w=await Dt(e,t,g?.allowedReturnOrigins?[...g.allowedReturnOrigins]:[],`IdP service "${i}" allowedReturnOrigins`,{expectedLocalNames:o}),T=g&&{...g,allowedReturnOrigins:w},E=normalizeComparableIdPService({authorization:m,lang:h,userAuthPolicy:normalizeComparableUserAuthPolicy(T),publishEvents:_,disableGqlOperations:normalizeComparableDisableGqlOperations(convertGqlOperationsToDisable(d.gqlOperations)),emailConfig:normalizeComparableEmailConfig(v),permission:S}),D={workspaceId:t,namespaceName:i,authorization:m,lang:h,userAuthPolicy:g,publishUserEvents:_,disableGqlOperations:convertGqlOperationsToDisable(d.gqlOperations),emailConfig:v,permission:S};if(f){let e=l.ownsDesired(f.allLabels,{resourceType:`idp.service`,resourceLabel:`IdP service`,resourceName:d.name})&&areIdPServicesEqual(f.resource,E);e&&hasMatchingSdkVersion(f.allLabels,p.labels)?c.unchanged.push({name:i,metaRequest:p}):c.updates.push({name:i,request:D,metaRequest:p,...e&&{forcedBySdkVersion:!0}}),delete u[i]}else c.creates.push({name:i,request:D,metaRequest:p})}return Object.entries(u).forEach(([e])=>{let n=u[e];l.ownsRemaining(n?.allLabels)&&c.deletes.push({name:e,request:{workspaceId:t,namespaceName:e}})}),{changeSet:c,...l.result}}async function planClients(e,t,n,r,i=!1){let o=createChangeSet(`IdP clients`),fetchClients=n=>F(async(r,i)=>{let{clients:a,nextPageToken:o}=await e.listIdPClients({workspaceId:t,namespaceName:n,pageToken:r,pageSize:i});return[a,o]}),isDeletableName=e=>mt.safeParse(e).success,s=await Promise.all(n.map(e=>fetchClients(e.name)));for(let[e,r]of n.entries()){let n=r.name,c=a(s[e],`clientsByIdp missing entry for idp index`),l=/* @__PURE__ */ new Set;c.forEach(e=>{l.add(e.name),C.registerSecret(e.clientSecret)});for(let e of r.clients)l.has(e)?(i?o.updates.push({name:e,workspaceId:t,namespaceName:n,forcedBySdkVersion:!0}):o.unchanged.push({name:e}),l.delete(e)):o.creates.push({name:e,request:{workspaceId:t,namespaceName:n,client:{name:e}}});l.forEach(e=>{isDeletableName(e)?o.deletes.push({name:e,request:{workspaceId:t,namespaceName:n,name:e}}):C.warn(`IdP client "${e}" in "${n}" will not be deleted, because the platform cannot delete a client with this name. The client and its secret vault stay in the workspace. Both are deleted when that IdP is removed.`)})}let c=await Promise.all(r.map(e=>fetchClients(e)));for(let[e,n]of r.entries())a(c[e],`deletedClientsByService missing entry for service index`).forEach(e=>{C.registerSecret(e.clientSecret),o.deletes.push({name:e.name,request:{workspaceId:t,namespaceName:n,name:e.name},...!isDeletableName(e.name)&&{vaultOnly:!0}})});return o}function convertLang(e){switch(e){case`en`:return $t.EN;case`ja`:return $t.JA;default:return $t.UNSPECIFIED}}function convertGqlOperationsToDisable(e){if(e)return{create:e.create===!1,update:e.update===!1,delete:e.delete===!1,read:e.read===!1,sendPasswordResetEmail:e.sendPasswordResetEmail===!1,requestMfaSettingsUrl:e.requestMfaSettingsUrl===!1,unenrollMfa:e.unenrollMfa===!1}}function protoIdPPermission(e){return{create:e.create.map(e=>protoIdPPolicy(e)),read:e.read.map(e=>protoIdPPolicy(e)),update:e.update.map(e=>protoIdPPolicy(e)),delete:e.delete.map(e=>protoIdPPolicy(e)),sendPasswordResetEmail:e.sendPasswordResetEmail.map(e=>protoIdPPolicy(e)),unenrollMfa:e.unenrollMfa.map(e=>protoIdPPolicy(e))}}function protoIdPPolicy(e){let t;switch(e.permit){case`allow`:t=ir.ALLOW;break;case`deny`:t=ir.DENY;break;default:throw b(`Unknown permission: ${e.permit}`)}return{conditions:e.conditions.map(e=>protoIdPCondition(e)),permit:t,description:e.description}}function protoIdPCondition(e){let[t,n,r]=e,i=protoIdPOperand(t),a=protoIdPOperand(r),o;switch(n){case`eq`:o=on.EQ;break;case`ne`:o=on.NE;break;case`in`:o=on.IN;break;case`nin`:o=on.NIN;break;default:throw b(`Unknown operator: ${n}`)}return{left:i,operator:o,right:a}}function protoIdPOperand(e){if(typeof e==`object`&&!Array.isArray(e)){if(`user`in e)return{kind:{case:`userField`,value:e.user}};if(`idpUser`in e)return{kind:{case:`idpUserField`,value:e.idpUser}};if(`newIdpUser`in e)return{kind:{case:`newIdpUserField`,value:e.newIdpUser}};if(`oldIdpUser`in e)return{kind:{case:`oldIdpUserField`,value:e.oldIdpUser}};throw b(`Unknown operand: ${JSON.stringify(e)}`)}return{kind:{case:`value`,value:Jr(ai,e)}}}async function applyAuth(e,t,n=`create-update`){let{changeSet:r}=t;(n===`create-update-prerequisites`||n===`create-update`)&&(await(async()=>{await Promise.all([...r.service.creates.map(async t=>{await e.createAuthService(t.request),await writeMetadataLabels(e,t.metaRequest)}),...r.service.updates.map(async t=>{await e.updateAuthService(t.request),await writeMetadataLabels(e,t.metaRequest)})])})(),await(async()=>{await Promise.all([...r.machineUser.creates.map(async t=>{let n=await e.createAuthMachineUser(t.request);return n.machineUser?.clientSecret&&C.registerSecret(n.machineUser.clientSecret),n}),...r.machineUser.updates.map(async t=>{let n=await e.updateAuthMachineUser(t.request);return n.machineUser?.clientSecret&&C.registerSecret(n.machineUser.clientSecret),n})])})()),(n===`create-update-dependents`||n===`create-update`)&&await(async()=>{await applyAuthConnections(e,{changeSet:r.connection,stateScope:t.connectionStateScope},`create-update`),await Promise.all([...r.idpConfig.creates.map(async t=>(t.idpConfig.kind===`BuiltInIdP`&&(a(t.request.idpConfig,`request missing idpConfig`).config=await protoBuiltinIdPConfig(e,a(t.request.workspaceId,`request missing workspaceId`),t.idpConfig)),e.createAuthIDPConfig(t.request))),...r.idpConfig.updates.map(async t=>(t.idpConfig.kind===`BuiltInIdP`&&(a(t.request.idpConfig,`request missing idpConfig`).config=await protoBuiltinIdPConfig(e,a(t.request.workspaceId,`request missing workspaceId`),t.idpConfig)),e.updateAuthIDPConfig(t.request)))]),await Promise.all([...r.userProfileConfig.creates.map(t=>e.createUserProfileConfig(t.request)),...r.userProfileConfig.updates.map(t=>e.updateUserProfileConfig(t.request))]),await Promise.all([...r.tenantConfig.creates.map(t=>e.createTenantConfig(t.request)),...r.tenantConfig.updates.map(t=>e.updateTenantConfig(t.request))]),await Promise.all([...r.authHook.creates.map(t=>e.createAuthHook(t.request)),...r.authHook.updates.map(t=>e.updateAuthHook(t.request))]),await Promise.all([...r.oauth2Client.creates.map(async t=>{let n=a(t.request.oauth2Client,`request missing oauth2Client`);n.redirectUris=await Dt(e,a(t.request.workspaceId,`request missing workspaceId`),n.redirectUris,`OAuth2 redirect URIs`);let r=await e.createAuthOAuth2Client(t.request);return r.oauth2Client?.clientSecret&&C.registerSecret(r.oauth2Client.clientSecret),r}),...r.oauth2Client.updates.map(async t=>{let n=a(t.request.oauth2Client,`request missing oauth2Client`);n.redirectUris=await Dt(e,a(t.request.workspaceId,`request missing workspaceId`),n.redirectUris,`OAuth2 redirect URIs`);let r=await e.updateAuthOAuth2Client(t.request);return r.oauth2Client?.clientSecret&&C.registerSecret(r.oauth2Client.clientSecret),r})]);for(let t of r.oauth2Client.replaces){await e.deleteAuthOAuth2Client(t.deleteRequest);let n=a(t.createRequest.oauth2Client,`createRequest missing oauth2Client`);n.redirectUris=await Dt(e,a(t.createRequest.workspaceId,`createRequest missing workspaceId`),n.redirectUris,`OAuth2 redirect URIs`);let r=await e.createAuthOAuth2Client(t.createRequest);r.oauth2Client?.clientSecret&&C.registerSecret(r.oauth2Client.clientSecret)}await Promise.all([...r.scim.creates.map(t=>e.createAuthSCIMConfig(t.request)),...r.scim.updates.map(t=>e.updateAuthSCIMConfig(t.request))]),await Promise.all([...r.scimResource.creates.map(t=>e.createAuthSCIMResource(t.request)),...r.scimResource.updates.map(t=>e.updateAuthSCIMResource(t.request))])})(),n===`delete-resources`?(await Promise.all(r.scimResource.deletes.map(t=>e.deleteAuthSCIMResource(t.request))),await Promise.all(r.scim.deletes.map(t=>e.deleteAuthSCIMConfig(t.request))),await Promise.all(r.oauth2Client.deletes.map(t=>e.deleteAuthOAuth2Client(t.request))),await Promise.all(r.authHook.deletes.map(t=>e.deleteAuthHook(t.request))),await Promise.all(r.machineUser.deletes.map(t=>e.deleteAuthMachineUser(t.request))),await Promise.all(r.tenantConfig.deletes.map(t=>e.deleteTenantConfig(t.request))),await(async()=>{await Promise.all(r.userProfileConfig.deletes.map(t=>e.deleteUserProfileConfig(t.request)))})(),await Promise.all(r.idpConfig.deletes.map(t=>e.deleteAuthIDPConfig(t.request))),await applyAuthConnections(e,{changeSet:r.connection,stateScope:t.connectionStateScope},`delete-resources`)):n===`delete-services`&&await Promise.all(r.service.deletes.map(t=>e.deleteAuthService(t.request)))}async function planAuth(e){let{client:t,workspaceId:n,application:r,forRemoval:i,forceApplyAll:a=!1}=e,o=[];!i&&r.authService&&(await r.authService.resolveNamespaces(),o.push(r.authService));let{changeSet:s,conflicts:c,unmanaged:l,resourceOwners:u}=await planServices$2(t,n,r.name,r.id,o,a),d=s.deletes.map(e=>e.name),f=expectedLocalStaticWebsiteNames(e),[p,m,h,g,_,v,y,b,x]=await Promise.all([planIdPConfigs(t,n,o,d,a),planUserProfileConfigs(t,n,o,d,a),planTenantConfigs(t,n,o,d,a),planMachineUsers(t,n,o,d,a),planAuthHooks(t,n,o,d,a),planOAuth2Clients(t,n,o,d,f,a),planSCIMConfigs(t,n,o,d),planSCIMResources(t,n,o,d),planAuthConnections(t,n,r.name,r.id,o)]);return{changeSet:{service:s,idpConfig:p,userProfileConfig:m,tenantConfig:h,machineUser:g,authHook:_,oauth2Client:v,scim:y,scimResource:b,connection:x.changeSet},conflicts:[...c,...x.conflicts],unmanaged:[...l,...x.unmanaged],resourceOwners:/* @__PURE__ */ new Set([...u,...x.resourceOwners]),connectionStateScope:x.stateScope}}async function planServices$2(e,t,n,r,i,a=!1){let o=createChangeSet(`Auth services`),s=createOwnershipTracker(n,r),c=await fetchExistingResourcesWithLabels({client:e,fetchPage:async(n,r)=>{let{authServices:i,nextPageToken:a}=await e.listAuthServices({workspaceId:t,pageToken:n,pageSize:r});return[i,a]},getName:e=>e.namespace?.name,getTrn:e=>resourceTrn(t,`auth`,e)});for(let e of i){let{config:i}=e,l=c[i.name],u=await buildMetaRequest({trn:resourceTrn(t,`auth`,i.name),appName:n,appId:r}),d={workspaceId:t,namespaceName:i.name,publishSessionEvents:i.publishSessionEvents};if(l){let e=s.ownsDesired(l.allLabels,{resourceType:`auth.service`,resourceLabel:`Auth service`,resourceName:i.name})&&l.resource.publishSessionEvents===(i.publishSessionEvents??!1);!a&&e?o.unchanged.push({name:i.name}):o.updates.push({name:i.name,request:d,metaRequest:u,...e&&{forcedBySdkVersion:!0}}),delete c[i.name]}else o.creates.push({name:i.name,request:d,metaRequest:u})}return Object.entries(c).forEach(([e])=>{let n=c[e];s.ownsRemaining(n?.allLabels)&&o.deletes.push({name:e,request:{workspaceId:t,namespaceName:e}})}),{changeSet:o,...s.result}}async function planIdPConfigs(e,t,n,r,i=!1){let a=createChangeSet(`Auth idpConfigs`),fetchIdPConfigs=n=>F(async(r,i)=>{let{idpConfigs:a,nextPageToken:o}=await e.listAuthIDPConfigs({workspaceId:t,namespaceName:n,pageToken:r,pageSize:i});return[a,o]});for(let r of n){let{config:n}=r,o=await fetchIdPConfigs(n.name),s=/* @__PURE__ */ new Map;o.forEach(e=>{s.set(e.name,e)});let c=n.idProvider;if(c){let r=protoIdPConfig(c),o=s.get(c.name);if(o){let l=await protoIdPConfigForComparison(e,t,c,r);if(!l){a.updates.push({name:c.name,idpConfig:c,request:{workspaceId:t,namespaceName:n.name,idpConfig:r}}),s.delete(c.name);continue}let u=areAuthIdPConfigsEqual(o,l);!i&&u?a.unchanged.push({name:c.name}):a.updates.push({name:c.name,idpConfig:c,request:{workspaceId:t,namespaceName:n.name,idpConfig:r},...u&&{forcedBySdkVersion:!0}}),s.delete(c.name)}else a.creates.push({name:c.name,idpConfig:c,request:{workspaceId:t,namespaceName:n.name,idpConfig:r}})}s.forEach((e,r)=>{a.deletes.push({name:r,request:{workspaceId:t,namespaceName:n.name,name:r}})})}for(let e of r)(await fetchIdPConfigs(e)).forEach(n=>{a.deletes.push({name:n.name,request:{workspaceId:t,namespaceName:e,name:n.name}})});return a}async function protoIdPConfigForComparison(e,t,n,r){if(n.kind!==`BuiltInIdP`)return r;let i=await tryProtoBuiltinIdPConfig(e,t,n);return i?{name:r.name,authType:r.authType,config:i}:void 0}function normalizeComparableAuthIdPConfig(e){return toComparableProtoJson(Yn,e)}function areAuthIdPConfigsEqual(e,t){return areNormalizedEqual(normalizeComparableAuthIdPConfig(e),normalizeComparableAuthIdPConfig(t))}function protoIdPConfig(e){switch(e.kind){case`IDToken`:return{name:e.name,authType:cn.ID_TOKEN,config:{config:{case:`idToken`,value:{providerUrl:e.providerURL,clientId:e.clientID,issuerUrl:e.issuerURL,usernameClaim:e.usernameClaim}}}};case`SAML`:return{name:e.name,authType:cn.SAML,config:{config:{case:`saml`,value:{...e.metadataURL===void 0?{rawMetadata:a(e.rawMetadata,`SAML config missing rawMetadata`)}:{metadataUrl:e.metadataURL},enableSignRequest:e.enableSignRequest,defaultRedirectUrl:e.defaultRedirectURL}}}};case`OIDC`:return{name:e.name,authType:cn.OIDC,config:{config:{case:`oidc`,value:{clientIdKey:e.clientID,clientSecretKey:{vaultName:e.clientSecret.vaultName,secretKey:e.clientSecret.secretKey},providerUrl:e.providerURL,issuerUrl:e.issuerURL,usernameClaim:e.usernameClaim}}}};case`BuiltInIdP`:return{name:e.name,authType:cn.OIDC,config:{}};default:throw b(`Unexpected idp kind: ${e}`)}}async function protoBuiltinIdPConfig(e,t,n){let r=await tryProtoBuiltinIdPConfig(e,t,n);if(!r)throw E({code:`IDP_NOT_FOUND`,message:`Built-in IdP "${n.namespace}" not found.`,suggestion:`Ensure that idp is configured correctly.`});return r}async function tryProtoBuiltinIdPConfig(e,t,n){let r=await P(async()=>await e.getIdPService({workspaceId:t,namespaceName:n.namespace}));if(!r)return;let i=await P(async()=>await e.getIdPClient({workspaceId:t,namespaceName:n.namespace,name:n.clientName}));if(!i)return;let a=idpClientVaultName(n.namespace,n.clientName),o=idpClientSecretName(n.namespace,n.clientName);return{config:{case:`oidc`,value:{clientIdKey:i.client?.clientId,clientSecretKey:{vaultName:a,secretKey:o},providerUrl:r.idpService?.providerUrl,usernameClaim:`name`}}}}async function planUserProfileConfigs(e,t,n,r,i=!1){let a=createChangeSet(`Auth userProfileConfigs`);for(let r of n){let{config:n}=r,o=`${n.name}-user-profile-config`,s=await P(async()=>await e.getUserProfileConfig({workspaceId:t,namespaceName:n.name}));if(!s){let e=r.userProfile;e&&a.creates.push({name:o,request:{workspaceId:t,namespaceName:n.name,userProfileProviderConfig:protoUserProfileConfig(e)}});continue}let c=r.userProfile;if(c){let e=protoUserProfileConfig(c),r=areUserProfileConfigsEqual(s.userProfileProviderConfig??{},e);!i&&r?a.unchanged.push({name:o}):a.updates.push({name:o,request:{workspaceId:t,namespaceName:n.name,userProfileProviderConfig:e},...r&&{forcedBySdkVersion:!0}})}else a.deletes.push({name:o,request:{workspaceId:t,namespaceName:n.name}})}for(let n of r)await P(async()=>await e.getUserProfileConfig({workspaceId:t,namespaceName:n}))&&a.deletes.push({name:`${n}-user-profile-config`,request:{workspaceId:t,namespaceName:n}});return a}function protoUserProfileConfig(e){let t=e.attributes?Object.fromEntries(Object.keys(e.attributes).map(e=>[e,e])):void 0;return{providerType:En.TAILORDB,config:{config:{case:`tailordb`,value:{namespace:e.namespace,type:e.type.name,usernameField:e.usernameField,tenantIdField:void 0,attributesFields:e.attributeList,attributeMap:t}}}}}async function planTenantConfigs(e,t,n,r,i=!1){let a=createChangeSet(`Auth tenantConfigs`);for(let r of n){let{config:n}=r,o=`${n.name}-tenant-config`,s=await P(async()=>await e.getTenantConfig({workspaceId:t,namespaceName:n.name}));if(!s)n.tenantProvider&&a.creates.push({name:o,request:{workspaceId:t,namespaceName:n.name,tenantProviderConfig:protoTenantConfig(n.tenantProvider)}});else if(n.tenantProvider){let e=protoTenantConfig(n.tenantProvider),r=areTenantProviderConfigsEqual(s.tenantProviderConfig,e);!i&&r?a.unchanged.push({name:o}):a.updates.push({name:o,request:{workspaceId:t,namespaceName:n.name,tenantProviderConfig:e},...r&&{forcedBySdkVersion:!0}})}else a.deletes.push({name:o,request:{workspaceId:t,namespaceName:n.name}})}for(let n of r)await P(async()=>await e.getTenantConfig({workspaceId:t,namespaceName:n}))&&a.deletes.push({name:`${n}-tenant-config`,request:{workspaceId:t,namespaceName:n}});return a}function protoTenantConfig(e){return{providerType:tn.TAILORDB,config:{config:{case:`tailordb`,value:{namespace:e.namespace,type:e.type,signatureField:e.signatureField}}}}}async function planMachineUsers(e,t,n,r,i=!1){let a=createChangeSet(`Auth machineUsers`),fetchMachineUsers=n=>F(async(r,i)=>{let{machineUsers:a,nextPageToken:o}=await e.listAuthMachineUsers({workspaceId:t,authNamespace:n,pageToken:r,pageSize:i});return[a,o]});for(let e of n){let{config:n}=e,r=await fetchMachineUsers(n.name),o=/* @__PURE__ */ new Map;r.forEach(e=>{o.set(e.name,e),C.registerSecret(e.clientSecret)});for(let e of Object.keys(n.machineUsers??{})){let r=n.machineUsers?.[e];if(!r)continue;let s={attributes:r.attributeList,attributeMap:r.attributes?protoMachineUserAttributeMap(r.attributes):void 0},c=o.get(e);if(c){let l=areMachineUsersEqual(c,s);!i&&l?a.unchanged.push({name:e}):a.updates.push({name:e,request:{workspaceId:t,authNamespace:n.name,name:e,attributes:r.attributeList,attributeMap:s.attributeMap},...l&&{forcedBySdkVersion:!0}}),o.delete(e)}else a.creates.push({name:e,request:{workspaceId:t,authNamespace:n.name,name:e,attributes:r.attributeList,attributeMap:s.attributeMap}})}o.forEach((e,r)=>{a.deletes.push({name:r,request:{workspaceId:t,authNamespace:n.name,name:r}})})}for(let e of r)(await fetchMachineUsers(e)).forEach(n=>{C.registerSecret(n.clientSecret),a.deletes.push({name:n.name,request:{workspaceId:t,authNamespace:e,name:n.name}})});return a}function protoMachineUserAttributeMap(e){let t={};for(let[n,r]of Object.entries(e))t[n]=Jr(ai,r??null);return t}function normalizeComparableUserProfileConfig(e){let t=e.config?.config,n=t?.case===`tailordb`?t.value:void 0;return toComparableProtoJson(wn,{providerType:e.providerType,config:n?{config:{case:`tailordb`,value:{...n,tenantIdField:n.tenantIdField||``,attributesFields:normalizeStringArray(n.attributesFields),attributeMap:normalizeProtoConfig(n.attributeMap??{})}}}:void 0})}function areUserProfileConfigsEqual(e,t){return areNormalizedEqual(normalizeComparableUserProfileConfig(e),normalizeComparableUserProfileConfig(t))}function normalizeComparableTenantProviderConfig(e){return toComparableProtoJson(Tn,e??{})}function areTenantProviderConfigsEqual(e,t){return areNormalizedEqual(normalizeComparableTenantProviderConfig(e),normalizeComparableTenantProviderConfig(t))}function normalizeComparableMachineUser(e){return normalizeProtoConfig({attributes:normalizeStringArray(e.attributes),attributeMap:normalizeProtoConfig(e.attributeMap??{})})}function areMachineUsersEqual(e,t){return areNormalizedEqual(normalizeComparableMachineUser(e),normalizeComparableMachineUser(t))}function normalizeComparableOAuth2Client(e){let t=oauth2LifetimeToSeconds(e.accessTokenLifetime),n=oauth2LifetimeToSeconds(e.refreshTokenLifetime);return normalizeProtoConfig({...e,description:e.description||void 0,redirectUris:normalizeStringArray(e.redirectUris),grantTypes:(e.grantTypes??[]).toSorted((e,t)=>e-t),accessTokenLifetime:t??86400,refreshTokenLifetime:n??604800,requireDpop:e.requireDpop??!1})}function oauth2LifetimeToSeconds(e){if(typeof e==`number`)return e;if(e?.seconds!=null)return Number(e.seconds)}function areOAuth2ClientsEqual(e,t){return areNormalizedEqual(normalizeComparableOAuth2Client(e),normalizeComparableOAuth2Client(t))}async function planOAuth2Clients(e,t,n,r,i,o=!1){let s=createChangeSet(`Auth oauth2Clients`),fetchOAuth2Clients=n=>F(async(r,i)=>{let{oauth2Clients:a,nextPageToken:o}=await e.listAuthOAuth2Clients({workspaceId:t,namespaceName:n,pageToken:r,pageSize:i});return[a,o]});for(let r of n){let{config:n}=r,c=await fetchOAuth2Clients(n.name),l=/* @__PURE__ */ new Map;c.forEach(e=>{l.set(e.name,e),C.registerSecret(e.clientSecret)});for(let r of Object.keys(n.oauth2Clients??{})){let c=n.oauth2Clients?.[r];if(!c)continue;let u=protoOAuth2Client(r,c),d=await Dt(e,t,u.redirectUris??[],`OAuth2 redirect URIs`,{expectedLocalNames:i});if(l.has(r)){let e=a(l.get(r),`existingClientsMap missing entry for oauth2ClientName`);if(e.clientType!==u.clientType)s.replaces.push({name:r,deleteRequest:{workspaceId:t,namespaceName:n.name,name:r},createRequest:{workspaceId:t,namespaceName:n.name,oauth2Client:u}});else{let i={...u,redirectUris:d,accessTokenLifetime:oauth2LifetimeToSeconds(u.accessTokenLifetime),refreshTokenLifetime:oauth2LifetimeToSeconds(u.refreshTokenLifetime)},a=areOAuth2ClientsEqual({name:e.name,description:e.description,grantTypes:e.grantTypes,redirectUris:e.redirectUris,clientType:e.clientType,accessTokenLifetime:oauth2LifetimeToSeconds(e.accessTokenLifetime),refreshTokenLifetime:oauth2LifetimeToSeconds(e.refreshTokenLifetime),requireDpop:e.requireDpop},i);!o&&a?s.unchanged.push({name:r}):s.updates.push({name:r,request:{workspaceId:t,namespaceName:n.name,oauth2Client:u},...a&&{forcedBySdkVersion:!0}})}l.delete(r)}else s.creates.push({name:r,request:{workspaceId:t,namespaceName:n.name,oauth2Client:u}})}l.forEach((e,r)=>{s.deletes.push({name:r,request:{workspaceId:t,namespaceName:n.name,name:r}})})}for(let e of r)(await fetchOAuth2Clients(e)).forEach(n=>{C.registerSecret(n.clientSecret),s.deletes.push({name:n.name,request:{workspaceId:t,namespaceName:e,name:n.name}})});return s}function protoOAuth2Client(e,t){return{name:e,description:t.description,grantTypes:t.grantTypes.map(e=>{switch(e){case`authorization_code`:return Qt.AUTHORIZATION_CODE;case`refresh_token`:return Qt.REFRESH_TOKEN;default:throw b(`Unknown OAuth2 client grant type: ${e}`)}}),redirectUris:t.redirectURIs,clientType:{confidential:mn.CONFIDENTIAL,public:mn.PUBLIC,browser:mn.BROWSER}[t.clientType??`confidential`],accessTokenLifetime:t.accessTokenLifetimeSeconds,refreshTokenLifetime:t.refreshTokenLifetimeSeconds,requireDpop:t.requireDpop}}async function planSCIMConfigs(e,t,n,r){let i=createChangeSet(`Auth scimConfigs`);for(let r of n){let{config:n}=r,a=`${n.name}-scim-config`;await P(async()=>await e.getAuthSCIMConfig({workspaceId:t,namespaceName:n.name}))?n.scim?i.updates.push({name:a,request:{workspaceId:t,namespaceName:n.name,scimConfig:protoSCIMConfig(n.scim)}}):i.deletes.push({name:a,request:{workspaceId:t,namespaceName:n.name}}):n.scim&&i.creates.push({name:a,request:{workspaceId:t,namespaceName:n.name,scimConfig:protoSCIMConfig(n.scim)}})}for(let n of r)await P(async()=>await e.getAuthSCIMConfig({workspaceId:t,namespaceName:n}))&&i.deletes.push({name:`${n}-scim-config`,request:{workspaceId:t,namespaceName:n}});return i}function protoSCIMConfig(e){let t;switch(e.authorization.type){case`bearer`:t=Sr.BEARER;break;case`oauth2`:t=Sr.OAUTH2;break;default:throw b(`Unknown SCIM authorization type: ${e.authorization.type}`)}return{machineUserName:e.machineUserName,authorizationType:t,authorizationConfig:{case:`bearerSecret`,value:{vaultName:e.authorization.bearerSecret?.vaultName,secretKey:e.authorization.bearerSecret?.secretKey}}}}async function planSCIMResources(e,t,n,r){let i=createChangeSet(`Auth scimResources`),fetchSCIMResources=async n=>await P(async()=>{let{scimResources:r}=await e.getAuthSCIMResources({workspaceId:t,namespaceName:n});return r})??[];for(let e of n){let{config:n}=e,r=await fetchSCIMResources(n.name),a=/* @__PURE__ */ new Set;r.forEach(e=>{a.add(e.name)});for(let e of n.scim?.resources??[])a.has(e.name)?(i.updates.push({name:e.name,request:{workspaceId:t,namespaceName:n.name,scimResource:protoSCIMResource(e)}}),a.delete(e.name)):i.creates.push({name:e.name,request:{workspaceId:t,namespaceName:n.name,scimResource:protoSCIMResource(e)}});a.forEach(e=>{i.deletes.push({name:e,request:{workspaceId:t,namespaceName:n.name,name:e}})})}for(let e of r)(await fetchSCIMResources(e)).forEach(n=>{i.deletes.push({name:n.name,request:{workspaceId:t,namespaceName:e,name:n.name}})});return i}function protoSCIMResource(e){return{name:e.name,tailorDbNamespace:e.tailorDBNamespace,tailorDbType:e.tailorDBType,coreSchema:{name:e.coreSchema.name,attributes:e.coreSchema.attributes.map(e=>protoSCIMAttribute(e))},attributeMapping:e.attributeMapping.map(e=>({tailorDbField:e.tailorDBField,scimPath:e.scimPath}))}}function protoSCIMAttribute(e){let t;switch(e.type){case`string`:t=sn.STRING;break;case`number`:t=sn.NUMBER;break;case`boolean`:t=sn.BOOLEAN;break;case`datetime`:t=sn.DATETIME;break;case`complex`:t=sn.COMPLEX;break;default:throw b(`Unknown SCIM attribute type: ${e.type}`)}let n;if(e.mutability)switch(e.mutability){case`readOnly`:n=rn.READ_ONLY;break;case`readWrite`:n=rn.READ_WRITE;break;case`writeOnly`:n=rn.WRITE_ONLY;break;default:throw b(`Unknown SCIM attribute mutability: ${e.mutability}`)}let r;if(e.uniqueness)switch(e.uniqueness){case`none`:r=vn.NONE;break;case`server`:r=vn.SERVER;break;case`global`:r=vn.GLOBAL;break;default:throw b(`Unknown SCIM attribute uniqueness: ${e.uniqueness}`)}return{type:t,name:e.name,description:e.description,mutability:n,required:e.required,multiValued:e.multiValued,uniqueness:r,canonicalValues:e.canonicalValues??void 0,subAttributes:e.subAttributes?.map(e=>protoSCIMAttribute(e))}}function areAuthHooksEqual(e,t){return areNormalizedEqual({scriptRef:e.scriptRef??``,invoker:e.invoker?{namespace:e.invoker.namespace??``,machineUserName:e.invoker.machineUserName??``}:void 0},{scriptRef:t.scriptRef??``,invoker:t.invoker?{namespace:t.invoker.namespace??``,machineUserName:t.invoker.machineUserName??``}:void 0})}function formatAuthHookChangeEntries(e,t){return formatChangeEntriesWithFunctionRegistry(`authHook`,e,t,e=>{let[t,n]=e.name.split(`/`);return t&&n?[authHookFunctionName(t,n)]:[]},{getNamespace:e=>e.name.split(`/`)[0],getDisplayName:e=>e.name.split(`/`)[1]??e.name})}async function planAuthHooks(e,t,n,r,i=!1){let a=createChangeSet(`Auth hooks`);for(let r of n){let{config:n}=r,o=n.hooks?.beforeLogin,s=await P(async()=>{let{hook:r}=await e.getAuthHook({workspaceId:t,namespaceName:n.name,hookPoint:Gt.BEFORE_LOGIN});return r});if(o){let e={workspaceId:t,namespaceName:n.name,hook:{hookPoint:Gt.BEFORE_LOGIN,scriptRef:authHookFunctionName(n.name,`before-login`),invoker:{namespace:n.name,machineUserName:o.invoker}}};if(s){let t=areAuthHooksEqual(s,e.hook);!i&&t?a.unchanged.push({name:`${n.name}/before-login`}):a.updates.push({name:`${n.name}/before-login`,request:e,...t&&{forcedBySdkVersion:!0}})}else a.creates.push({name:`${n.name}/before-login`,request:e})}else s&&a.deletes.push({name:`${n.name}/before-login`,request:{workspaceId:t,namespaceName:n.name,hookPoint:Gt.BEFORE_LOGIN}})}for(let n of r)await P(async()=>await e.getAuthHook({workspaceId:t,namespaceName:n,hookPoint:Gt.BEFORE_LOGIN}))&&a.deletes.push({name:`${n}/before-login`,request:{workspaceId:t,namespaceName:n,hookPoint:Gt.BEFORE_LOGIN}});return a}function normalizeInvoker(e,t,n){if(e!==void 0){if(typeof e==`string`){if(!t)throw E({code:`INVOKER_AUTH_REQUIRED`,message:`${n} uses a string invoker ("${e}"), but no Auth service is configured.`,suggestion:`Configure an Auth service before using invoker.`});return{namespace:t,machineUserName:e}}return e}}async function applyExecutor(e,t,n=`create-update`){let{changeSet:r}=t;n===`create-update`?await Promise.all([...r.creates.map(async t=>{await e.createExecutorExecutor(t.request),await writeMetadataLabels(e,t.metaRequest)}),...r.updates.map(async t=>{await e.updateExecutorExecutor(t.request),await writeMetadataLabels(e,t.metaRequest)})]):await Promise.all(r.deletes.map(t=>e.deleteExecutorExecutor(t.request)))}async function planExecutor(e,t){let{client:n,workspaceId:r,application:i,forRemoval:a}=e,o=createChangeSet(`Executors`),s=createOwnershipTracker(i.name,i.id),c=t??await fetchExistingResourcesWithLabels({client:n,fetchPage:async(e,t)=>{let{executors:i,nextPageToken:a}=await n.listExecutorExecutors({workspaceId:r,pageToken:e,pageSize:t});return[i,a]},getName:e=>e.name,getTrn:e=>resourceTrn(r,`executor`,e)}),l={...c},u=a?{}:await i.executorService?.loadExecutors()??{};for(let t of Object.values(u)){let n=l[t.name],a=await buildMetaRequest({trn:resourceTrn(r,`executor`,t.name),appName:i.name,appId:i.id}),c=protoExecutor(e,t,i.env);if(n){let e=s.ownsDesired(n.allLabels,{resourceType:`executor`,resourceLabel:`Executor`,resourceName:t.name})&&areExecutorsEqual(n.resource,c);e&&hasMatchingSdkVersion(n.allLabels,a.labels)?o.unchanged.push({name:t.name}):o.updates.push({name:t.name,request:{workspaceId:r,executor:c},metaRequest:a,...e&&{forcedBySdkVersion:!0}}),delete l[t.name]}else o.creates.push({name:t.name,request:{workspaceId:r,executor:c},metaRequest:a})}return Object.entries(l).forEach(([e])=>{let t=l[e];s.ownsRemaining(t?.allLabels)&&o.deletes.push({name:e,request:{workspaceId:r,name:e}})}),{changeSet:o,...s.result,existingExecutors:c}}function isFunctionBackedExecutor(e){return e?.targetType===I.FUNCTION||e?.targetType===I.JOB_FUNCTION}function buildPlannedExecutorsByName(e){return Object.fromEntries([...e.creates,...e.updates].map(e=>[e.name,e.request.executor]))}function formatExecutorChangeEntries(e,t,n){return formatChangeEntriesWithFunctionRegistry(`executor`,e,n,(e,n)=>{if(n===`delete`)return[executorFunctionName(e.name)];let r=t[e.name];return r&&isFunctionBackedExecutor(r)?[executorFunctionName(e.name)]:[]})}function normalizeComparableExecutor(e){let t=normalizeProtoConfig(e),n=t.targetConfig?.config?.case===`webhook`?(t.targetConfig.config.value.headers??[]).toSorted((e,t)=>(e.key??``).localeCompare(t.key??``)):void 0,r=t.triggerConfig?.config?.case===`incomingWebhook`?{...t.triggerConfig,config:{...t.triggerConfig.config,value:{...t.triggerConfig.config.value,secret:void 0}}}:t.triggerConfig?.config?.case===`event`?{...t.triggerConfig,config:{...t.triggerConfig.config,value:{...t.triggerConfig.config.value,eventType:void 0}}}:t.triggerConfig,i=normalizeProtoConfig({name:t.name,description:t.description??``,disabled:t.disabled??!1,triggerType:t.triggerType,triggerConfig:r,targetType:t.targetType,targetConfig:t.targetConfig?.config?.case===`webhook`?{...t.targetConfig,config:{...t.targetConfig.config,value:{...t.targetConfig.config.value,headers:n}}}:t.targetConfig?.config?.case===`function`?{...t.targetConfig,config:{...t.targetConfig.config,value:{...t.targetConfig.config.value,script:void 0}}}:t.targetConfig});return toComparableProtoJson(or,i)}function areExecutorsEqual(e,t){return areNormalizedEqual(normalizeComparableExecutor(e),normalizeComparableExecutor(t))}function resolveSameRunNamespace(e,t,n){if(!e?.has(t))return;let r=e.get(t);if(!r)throw E({code:`DEPLOY_RESOURCE_NAMESPACE_AMBIGUOUS`,message:`${n} "${t}" is defined in multiple namespaces in this deploy run. Move the trigger to the application that owns it or use unique names.`});return r}function findTailorDBNamespace(e,t){return e.tailorDBServices.find(e=>Object.hasOwn(e.types,t))?.namespace}function findResolverNamespace(e,t){return e.resolverServices.find(e=>Object.values(e.resolvers).some(e=>e.name===t))?.namespace}function resolveNamespace(e){let{resourceLabel:t,resourceName:n,localNamespaces:r,findLocalNamespace:i,sameRunNamespaces:a}=e,o=i();if(o!==void 0)return o;let s=resolveSameRunNamespace(a,n,t);if(s!==void 0)return s;let c=a?[...new Set([...a.values()].filter(e=>e!==void 0))]:[],l=[...r,...c];throw E({code:`DEPLOY_RESOURCE_NOT_FOUND`,message:`${t} "${n}" not found in any namespace. Available namespaces: ${l.join(`, `)}`})}function resolveTailorDBNamespace(e,t,n){return resolveNamespace({resourceLabel:`TailorDB table`,resourceName:t,localNamespaces:e.tailorDBServices.map(e=>e.namespace),findLocalNamespace:()=>findTailorDBNamespace(e,t),sameRunNamespaces:n})}function resolveResolverNamespace(e,t,n){return resolveNamespace({resourceLabel:`Resolver`,resourceName:t,localNamespaces:e.resolverServices.map(e=>e.namespace),findLocalNamespace:()=>findResolverNamespace(e,t),sameRunNamespaces:n})}function collectApplicationIdpNames(e){let t=new Set(e.idpServices.map(e=>e.name));for(let n of e.subgraphs)n.Type===`idp`&&t.add(n.Name);return t}function resolveIdpNamespace(e,t,n,r){let i=collectApplicationIdpNames(e);if(n!==void 0){let e=r??i;if(!e.has(n)){let r=[...e].join(`, `);throw E({code:`EXECUTOR_IDP_NOT_FOUND`,message:`Executor "${t}" specifies IdP "${n}" in its idpUser trigger, but no IdP with that name is configured. Available IdPs: ${r}`})}return n}if(i.size===0)throw E({code:`EXECUTOR_IDP_REQUIRED`,message:`Executor "${t}" uses an idpUser trigger but no IdP is configured.`});if(i.size>1){let e=[...i].join(`, `);throw E({code:`EXECUTOR_IDP_AMBIGUOUS`,message:`Executor "${t}" uses an idpUser trigger but the project defines multiple IdPs (${e}). Specify which IdP to subscribe to via the trigger's "idp" option.`})}return a([...i][0],`idp service missing`)}function protoExecutor(e,t,n){let{application:r}=e,i=r.name,a=t.trigger,o,s,c=Ke(a.kind,n);function typedEventTrigger(e){return{config:{case:`event`,value:{typedConfig:e}}}}switch(a.kind){case`schedule`:o=tr.SCHEDULE,s={config:{case:`schedule`,value:{timezone:a.timezone,frequency:a.cron}}};break;case`tailordb`:o=tr.EVENT,s=typedEventTrigger({case:`tailordb`,value:{eventTypes:a.events,namespaceName:resolveTailorDBNamespace(r,a.tableName,e.tailorDBTypeNamespaces),typeName:a.tableName,...a.condition?{condition:{expr:`(${st(a.condition)})(${c})`}}:{}}});break;case`resolverExecuted`:o=tr.EVENT,s=typedEventTrigger({case:`pipeline`,value:{eventTypes:[`pipeline.resolver.executed`],namespaceName:resolveResolverNamespace(r,a.resolverName,e.resolverNamespaces),resolverName:a.resolverName,...a.condition?{condition:{expr:`(${st(a.condition)})(${c})`}}:{}}});break;case`incomingWebhook`:o=tr.INCOMING_WEBHOOK,s={config:{case:`incomingWebhook`,value:a.response?{response:{...a.response.body?{body:{expr:`(${st(a.response.body)})(${c})`}}:{},...a.response.statusCode==null?{}:{statusCode:a.response.statusCode}}}:{}}};break;case`idpUser`:o=tr.EVENT,s=typedEventTrigger({case:`idp`,value:{eventTypes:a.events,namespaceName:resolveIdpNamespace(r,t.name,a.idp,e.idpNames)}});break;case`authAccessToken`:o=tr.EVENT,s=typedEventTrigger({case:`auth`,value:{eventTypes:a.events,namespaceName:rt(r)}});break;case`workflowExecution`:case`workflowJobExecution`:o=tr.EVENT,s=typedEventTrigger({case:`workflow`,value:{eventTypes:a.events,workflowName:a.workflowName,...a.condition?{condition:{expr:`(${st(a.condition)})(${c})`}}:{}}});break;default:throw b(`Unknown trigger: ${a}`)}let l=t.operation,u,d,f=tt(r),p=`Executor "${t.name}"`;switch(l.kind){case`webhook`:u=I.WEBHOOK,d={config:{case:`webhook`,value:{url:{expr:`(${st(l.url)})(${c})`},headers:l.headers?Object.entries(l.headers).map(([e,t])=>{let n;return n=typeof t==`string`?{case:`rawValue`,value:t}:{case:`secretValue`,value:{vaultName:t.vault,secretKey:t.key}},{key:e,value:n}}):void 0,body:l.requestBody?{expr:`(${st(l.requestBody)})(${c})`}:void 0}}};break;case`graphql`:u=I.TAILOR_GRAPHQL,d={config:{case:`tailorGraphql`,value:{appName:l.appName??i,query:l.query,variables:l.variables?{expr:`(${st(l.variables)})(${c})`}:void 0,invoker:normalizeInvoker(l.invoker,f,p)}}};break;case`function`:case`jobFunction`:u=l.kind===`function`?I.FUNCTION:I.JOB_FUNCTION,d={config:{case:`function`,value:{name:`operation`,scriptRef:executorFunctionName(t.name),variables:{expr:c},invoker:normalizeInvoker(l.invoker,f,p)}}};break;case`workflow`:u=I.WORKFLOW,d={config:{case:`workflow`,value:{workflowName:l.workflowName,variables:l.args===void 0?void 0:typeof l.args==`function`?{expr:`(${st(l.args)})(${c})`}:{expr:JSON.stringify(l.args)},invoker:normalizeInvoker(l.invoker,f,p)}}};break;default:throw b(`Unknown target: ${l}`)}return{name:t.name,description:t.description,disabled:t.disabled,triggerType:o,triggerConfig:s,targetType:u,targetConfig:d}}const Ta={uuid:{kind:`ScalarType`,name:`ID`},string:{kind:`ScalarType`,name:`String`},integer:{kind:`ScalarType`,name:`Int`},float:{kind:`ScalarType`,name:`Float`},decimal:{kind:`CustomScalarType`,name:`Decimal`},boolean:{kind:`ScalarType`,name:`Boolean`},date:{kind:`CustomScalarType`,name:`Date`},datetime:{kind:`CustomScalarType`,name:`DateTime`},time:{kind:`CustomScalarType`,name:`Time`}};async function applyPipeline(e,t,n=`create-update`){let{changeSet:r}=t;n===`create-update`?(await Promise.all([...r.service.creates.map(async t=>{await e.createPipelineService(t.request),await writeMetadataLabels(e,t.metaRequest)}),...r.service.updates.map(async t=>{await e.updatePipelineService(t.request),await writeMetadataLabels(e,t.metaRequest)})]),await Promise.all([...r.resolver.creates.map(async t=>{await e.createPipelineResolver(t.request),await writeMetadataLabels(e,t.metaRequest)}),...r.resolver.updates.map(async t=>{await e.updatePipelineResolver(t.request),await writeMetadataLabels(e,t.metaRequest)}),...r.resolver.unchanged.flatMap(t=>t.metaRequest?[writeMetadataLabels(e,t.metaRequest)]:[])])):n===`delete-resources`?await Promise.all(r.resolver.deletes.map(t=>e.deletePipelineResolver(t.request))):await Promise.all(r.service.deletes.map(t=>e.deletePipelineService(t.request)))}async function planPipeline(e,t){let{client:n,workspaceId:r,application:i,forRemoval:a,forceApplyAll:o=!1}=e,s=[];if(!a)for(let e of i.resolverServices)await e.loadResolvers(),s.push(e);let c=a?[]:Object.values(await i.executorService?.loadExecutors()??{}),{changeSet:l,conflicts:u,unmanaged:d,resourceOwners:f,existingServices:p}=await planServices$1(n,r,i.name,i.id,s,t?.existingServices),m=l.deletes.map(e=>e.name),{changeSet:h,existingResolversByNamespace:g}=await planResolvers(n,r,s,c,e.executorUsedResolvers??/* @__PURE__ */ new Set,m,i.env,tt(i),o,{appName:i.name,appId:i.id,dependentApps:e.dependentApps,runAppIds:e.runAppIds},t?.existingResolvers);return{changeSet:{service:l,resolver:h},conflicts:u,unmanaged:d,resourceOwners:f,existingServices:p,existingResolvers:g}}async function planServices$1(e,t,n,r,i,a){let o=createChangeSet(`Pipeline services`),s=createOwnershipTracker(n,r),c=a??await fetchExistingResourcesWithLabels({client:e,fetchPage:async(n,r)=>{let{pipelineServices:i,nextPageToken:a}=await e.listPipelineServices({workspaceId:t,pageToken:n,pageSize:r});return[i,a]},getName:e=>e.namespace?.name,getTrn:e=>resourceTrn(t,`pipeline`,e)}),l={...c};for(let e of i){let i=l[e.namespace],a=await buildMetaRequest({trn:resourceTrn(t,`pipeline`,e.namespace),appName:n,appId:r});if(i){let n=s.ownsDesired(i.allLabels,{resourceType:`pipeline.service`,resourceLabel:`Pipeline service`,resourceName:e.namespace});n&&hasMatchingSdkVersion(i.allLabels,a.labels)?o.unchanged.push({name:e.namespace}):o.updates.push({name:e.namespace,request:{workspaceId:t,namespaceName:e.namespace},metaRequest:a,...n&&{forcedBySdkVersion:!0}}),delete l[e.namespace]}else o.creates.push({name:e.namespace,request:{workspaceId:t,namespaceName:e.namespace},metaRequest:a})}return Object.entries(l).forEach(([e])=>{let n=l[e];s.ownsRemaining(n?.allLabels)&&o.deletes.push({name:e,request:{workspaceId:t,namespaceName:e}})}),{changeSet:o,...s.result,existingServices:c}}async function planResolvers(e,t,n,r,i,a,o,s,c=!1,l={},u){let d=createChangeSet(`Pipeline resolvers`),{appName:f,appId:p,dependentApps:m,runAppIds:h}=l,resolverMetaRequest=async(e,n)=>addDependencyRecords(await buildMetaRequest({trn:resolverTrn(t,e,n.name),appName:f??``,appId:p}),{key:Z.resolver(e,n.name),dependentApps:m,runAppIds:h,pinned:n.publishEvents!==void 0}),fetchResolvers=n=>{let r=u?.get(n);return r?Promise.resolve(r.existingResolvers):F(async(r,i)=>{let{pipelineResolvers:a,nextPageToken:o}=await e.listPipelineResolvers({workspaceId:t,namespaceName:n,pageToken:r,pageSize:i});return[a,o]})},g=/* @__PURE__ */ new Map,_=new Set(i);for(let e of r)subscribesToEvents(e)&&e.trigger.kind===`resolverExecuted`&&_.add(e.trigger.resolverName);for(let e of n)for(let t of Object.values(e.resolvers))assertNoPublishEventsConflict({explicit:t.publishEvents,subscribed:_.has(t.name),conflict:Ca.resolver(t.name)});for(let r of n){let n=await fetchResolvers(r.namespace),i=new Map(n.map(e=>[e.name,e])),a=u?.get(r.namespace)?.existingResolverDetails,l=/* @__PURE__ */ new Map;for(let n of Object.values(r.resolvers)){let u=processResolver(r.namespace,n,_,o,s),f=i.get(n.name),p=await resolverMetaRequest(r.namespace,n);if(f){let o=a?.has(n.name)?a.get(n.name):(await e.getPipelineResolver({workspaceId:t,namespaceName:r.namespace,resolverName:n.name})).pipelineResolver;l.set(n.name,o);let s=!!o&&areResolversEqual(o,u);!c&&s?d.unchanged.push({name:n.name,metaRequest:p}):d.updates.push({name:n.name,request:{workspaceId:t,namespaceName:r.namespace,pipelineResolver:u},metaRequest:p,...s&&{forcedBySdkVersion:!0}}),i.delete(n.name)}else d.creates.push({name:n.name,request:{workspaceId:t,namespaceName:r.namespace,pipelineResolver:u},metaRequest:p})}g.set(r.namespace,{existingResolvers:n,existingResolverDetails:l}),i.forEach((e,n)=>{d.deletes.push({name:n,request:{workspaceId:t,namespaceName:r.namespace,resolverName:n}})})}for(let e of a){let n=await fetchResolvers(e);n.forEach(n=>{d.deletes.push({name:n.name,request:{workspaceId:t,namespaceName:e,resolverName:n.name}})}),g.set(e,{existingResolvers:n,existingResolverDetails:u?.get(e)?.existingResolverDetails??/* @__PURE__ */ new Map})}return{changeSet:d,existingResolversByNamespace:g}}function formatResolverChangeEntries(e,t){return formatChangeEntriesWithFunctionRegistry(`resolver`,e,t,e=>{let t=e.request.namespaceName;return t?[resolverFunctionName(t,e.name)]:[]},{getNamespace:e=>e.request.namespaceName})}function normalizeComparableResolver(e){return toComparableProtoJson(_n,e)}function areResolversEqual(e,t){return areNormalizedEqual(normalizeComparableResolver(e),normalizeComparableResolver(t))}function processResolver(e,t,n,r,i){let o=[{name:`body`,operationName:`body`,description:`${t.name} function body`,operationType:xr.FUNCTION,operationSourceRef:resolverFunctionName(e,t.name),operationHook:{expr:Pe(r)},postScript:`args.body`,invoker:normalizeInvoker(t.invoker,i,`Resolver "${t.name}"`)}],s=wi.camelize(t.name),c=t.input?protoFields(t.input,`${s}Input`,!0):[],l=a(protoFields({"":t.output},`${s}Output`,!1)[0],`resolver output field missing`),u=t.description||`${t.name} resolver`,d=t.output.metadata.description,f=d?`${u}\n\nReturns:\n${d}`:u,p=resolvePublishEvents({explicit:t.publishEvents,subscribed:n.has(t.name),conflict:Ca.resolver(t.name)});return{authorization:`true==true`,description:f,inputs:c,name:t.name,operationType:t.operation,response:l,pipelines:o,publishExecutionEvents:p}}function protoFields(e,t,n){return Object.entries(e).map(([e,r])=>{let i,a=n&&r.metadata.hooks?.create!==void 0?!1:r.metadata.required??!0;if(r.type===`nested`){let o=r.metadata.typeName??`${t}${wi.camelize(e)}`;i={kind:`UserDefined`,name:o,description:r.metadata.description??``,required:a,fields:protoFields(r.fields,o,n)}}else i=r.type===`enum`?{kind:`EnumType`,name:r.metadata.typeName??`${t}${wi.camelize(e)}`,required:a,allowedValues:r.metadata.allowedValues}:{...Ta[r.type],required:a};return{name:e,description:r.metadata.description,array:r.metadata.array??!1,required:a,type:i}})}function vaultCreateRequest(e){return{workspaceId:e.workspaceId,secretmanagerVaultName:e.name}}function secretCreateRequest(e){return{workspaceId:e.workspaceId,secretmanagerVaultName:e.vaultName,secretmanagerSecretName:e.secretName,secretmanagerSecretValue:e.value}}function secretUpdateRequest(e){return{workspaceId:e.workspaceId,secretmanagerVaultName:e.vaultName,secretmanagerSecretName:e.secretName,secretmanagerSecretValue:e.value}}function collectIdPClientVaultNames(e){return new Set(e.flatMap(e=>e.clients.map(t=>idpClientVaultName(e.name,t))))}const Ea=`tailor--`;function validateDeclaredVaultNames(e,t){for(let{vaultName:n}of e){if(t.has(n))throw E({code:`RESERVED_VAULT_NAME`,message:`Vault "${n}" has the name of the vault the SDK creates for an IdP client.`,suggestion:`Rename the vault in defineSecretManager(). If this application already manages a vault with that name, renaming it and removing the declaration both delete the old vault and its secrets on the next deploy, including the secret of an IdP client that already exists.`});n.startsWith(Ea)&&C.warn(`Vault "${n}" starts with "${Ea}", a prefix reserved for vaults the platform manages. In v3 this will be an error; rename the vault in defineSecretManager().`)}}async function planSecretManager(e){let{client:t,workspaceId:n,application:r,forRemoval:i,forceApplyAll:a=!1}=e,o=i?[]:r.secrets;validateDeclaredVaultNames(o,collectIdPClientVaultNames(r.idpServices));let s=createChangeSet(`Secret Manager vaults`),c=createChangeSet(`Secret Manager secrets`),l=createOwnershipTracker(r.name,r.id),u=await fetchExistingResourcesWithLabels({client:t,fetchPage:async(e,r)=>{let{vaults:i,nextPageToken:a}=await t.listSecretManagerVaults({workspaceId:n,pageToken:e,pageSize:r});return[i,a]},getName:e=>e.name,getTrn:e=>resourceTrn(n,`vault`,e)}),d={workspaceId:n,applicationId:r.id,applicationName:r.name},f=loadSecretsState(d),p=[];await Promise.all(o.map(async e=>{let i=e.vaultName,o=u[i];if(o){let e=await buildMetaRequest({trn:resourceTrn(n,`vault`,i),appName:r.name,appId:r.id}),t=l.ownsDesired(o.allLabels,{resourceType:`secret.vault`,resourceLabel:`Secret Manager vault`,resourceName:i});t&&hasMatchingSdkVersion(o.allLabels,e.labels)?s.unchanged.push({name:i}):s.updates.push({name:i,workspaceId:n,...t&&{forcedBySdkVersion:!0}}),delete u[i]}else s.creates.push({name:i,workspaceId:n});let d=/* @__PURE__ */ new Map;if(o){let e=await F(async(e,r)=>{let{secrets:a,nextPageToken:o}=await t.listSecretManagerSecrets({workspaceId:n,secretmanagerVaultName:i,pageToken:e,pageSize:r});return[a,o]});for(let t of e)d.set(t.name,serializeUpdateTime(t.updateTime))}let m=new Set(d.keys());for(let t of e.secrets)if(t.value==null)m.delete(t.name),p.push(`${i}/${t.name}`);else if(C.registerSecret(t.value),m.has(t.name)){let e=f.vaults[i]?.[t.name],r=d.get(t.name),o=e!==void 0&&e.hash===hashValue(t.value)&&e.updateTime!==void 0&&e.updateTime===r;(a||!o)&&c.updates.push({name:`${i}/${t.name}`,secretName:t.name,workspaceId:n,vaultName:i,value:t.value,...o&&{forcedBySdkVersion:!0}}),m.delete(t.name)}else c.creates.push({name:`${i}/${t.name}`,secretName:t.name,workspaceId:n,vaultName:i,value:t.value});for(let e of m)c.deletes.push({name:`${i}/${e}`,secretName:e,workspaceId:n,vaultName:i})}));for(let[e,r]of Object.entries(u))if(r&&l.ownsRemaining(r.allLabels)){let r=await F(async(r,i)=>{let{secrets:a,nextPageToken:o}=await t.listSecretManagerSecrets({workspaceId:n,secretmanagerVaultName:e,pageToken:r,pageSize:i});return[a,o]});for(let t of r)c.deletes.push({name:`${e}/${t.name}`,secretName:t.name,workspaceId:n,vaultName:e});s.deletes.push({name:e,workspaceId:n})}return{vaultChangeSet:s,secretChangeSet:c,skippedSecrets:p,...l.result,stateScope:d}}async function applySecretManager(e,t,n=`create-update`,r){let{vaultChangeSet:i,secretChangeSet:o,stateScope:s}=t;if(n===`create-update`){await Promise.all(i.creates.map(async t=>{await e.createSecretManagerVault(vaultCreateRequest(t)),r&&await writeMetadataLabels(e,await buildMetaRequest({trn:resourceTrn(t.workspaceId,`vault`,t.name),appName:r.name,appId:r.id}))})),r&&await Promise.all(i.updates.map(async t=>{await writeMetadataLabels(e,await buildMetaRequest({trn:resourceTrn(t.workspaceId,`vault`,t.name),appName:r.name,appId:r.id}))}));let t=[...o.creates,...o.updates];t.length>0&&await withSecretsStateLock(s,async()=>{let n=/* @__PURE__ */ new Map;if(await Promise.all(o.creates.map(async t=>{let r=await e.createSecretManagerSecret(secretCreateRequest(t));n.set(t.name,serializeUpdateTime(r.secret?.updateTime))})),await Promise.all(o.updates.map(async t=>{let r=await e.updateSecretManagerSecret(secretUpdateRequest(t));n.set(t.name,serializeUpdateTime(r.secret?.updateTime))})),r){let e=loadSecretsState(s);for(let r of t){Object.hasOwn(e.vaults,r.vaultName)||(e.vaults[r.vaultName]={});let t=n.get(r.name);a(e.vaults[r.vaultName],`vault state entry missing`)[r.secretName]={hash:hashValue(r.value),...t===void 0?{}:{updateTime:t}}}saveSecretsState(s,e)}})}else(o.deletes.length>0||i.deletes.length>0)&&await withSecretsStateLock(s,async()=>{await Promise.all(o.deletes.map(t=>e.deleteSecretManagerSecret({workspaceId:t.workspaceId,secretmanagerVaultName:t.vaultName,secretmanagerSecretName:t.secretName}))),await Promise.all(i.deletes.map(t=>e.deleteSecretManagerVault({workspaceId:t.workspaceId,secretmanagerVaultName:t.name})));let t=loadSecretsState(s);for(let e of o.deletes)Object.hasOwn(t.vaults,e.vaultName)&&(delete a(t.vaults[e.vaultName],`vault state entry missing`)[e.secretName],Object.keys(a(t.vaults[e.vaultName],`vault state entry missing`)).length===0&&delete t.vaults[e.vaultName]);for(let e of i.deletes)delete t.vaults[e.name];saveSecretsState(s,t)})}const Da=[`array`,`index`,`unique`,`foreignKey`,`vector`,`optionalOnCreate`];function isSnapshotFieldRefOperand(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function getNestedMember(e,t){return t.reduce((e,t)=>e?.fields&&Object.hasOwn(e.fields,t)?e.fields[t]:void 0,e)}function collectNestedMemberChanges(e,t){return e.type===t.type?collectMemberChanges(e.fields??{},t.fields??{},[]):[]}function collectMemberChanges(e,t,n){let r=[],i=[],a=[];for(let[i,o]of Object.entries(e)){let e=[...n,i],s=Object.hasOwn(t,i)?t[i]:void 0;s?(o.type===s.type&&a.push(...collectMemberChanges(o.fields??{},s.fields??{},e)),areOwnFieldConfigsDifferent(o,s)&&a.push({kind:`modified`,path:e,before:o,after:s})):r.push({kind:`removed`,path:e,before:o})}for(let[r,a]of Object.entries(t))Object.hasOwn(e,r)||i.push({kind:`added`,path:[...n,r],after:a});return[...r,...i,...a]}function areOwnFieldConfigsDifferent(e,t){if(e.type!==t.type||e.required!==t.required)return!0;for(let n of Da)if((e[n]??!1)!==(t[n]??!1))return!0;if(e.foreignKeyType!==t.foreignKeyType||e.foreignKeyField!==t.foreignKeyField||(e.description??``)!==(t.description??``))return!0;let n=e.allowedValues??[],r=t.allowedValues??[];if(n.length!==r.length)return!0;let i=new Map(r.map(e=>[e.value,e.description]));for(let e of n)if(!i.has(e.value)||(e.description??``)!==(i.get(e.value)??``))return!0;let o=e.hooks,s=t.hooks;if(!!o!=!!s||o&&s&&((o.create?.expr??``)!==(s.create?.expr??``)||(o.update?.expr??``)!==(s.update?.expr??``)))return!0;let c=e.validate??[],l=t.validate??[];if(c.length!==l.length)return!0;for(let e=0;e<c.length;e++){let t=a(c[e],`oldValidate missing index ${e}`),n=a(l[e],`newValidate missing index ${e}`);if((t.script?.expr??``)!==(n.script?.expr??``)||t.errorMessage!==n.errorMessage)return!0}let u=e.serial,d=t.serial;return!!(!!u!=!!d||u&&d&&(u.start!==d.start||u.maxValue!==d.maxValue||(u.format??``)!==(d.format??``)||(u.gapless??!1)!==(d.gapless??!1))||e.scale!==t.scale||e.default!==t.default&&(typeof e.default!=typeof t.default||JSON.stringify(e.default)!==JSON.stringify(t.default)))}function hasChanges(e){return e.changes.length>0}function formatMigrationDiff(e){if(e.changes.length===0)return`No schema differences detected.`;let t=[],n=/* @__PURE__ */ new Map;for(let t of e.changes){let e=n.get(t.tableName)??[];e.push(t),n.set(t.tableName,e)}for(let[r,i]of n){t.push(`${e.namespace}.${r}:`);for(let e of i)t.push(formatDiffChange(e))}return t.join(`
|
|
4
|
-
`)}function formatDiffChange(e){switch(e.kind){case`table_added`:return` + [Table] ${e.tableName} (new table)`;case`table_removed`:return` - [Table] ${e.tableName} (removed)`;case`table_renamed`:return` ~ [Table] ${e.previousTableName} → ${e.tableName} (renamed)`;case`table_modified`:return` ~ [Table] ${e.tableName}: ${e.reason}`;case`table_settings_modified`:return` ~ [Table Settings] ${e.tableName}: ${e.reason??`settings changed`}`;case`field_added`:{let t=formatFieldType(e.after);return` + ${e.fieldName}: ${t}`}case`field_removed`:return` - ${e.fieldName}: ${e.before.type}`;case`field_modified`:return` ~ ${e.fieldName}: ${formatFieldModification(e.before,e.after,e.memberRenames)}`;case`field_type_modified`:return` ~ ${e.fieldName}: ${formatFieldModification(e.before,e.after)}`;case`field_renamed`:return` ~ ${e.previousFieldName} → ${e.fieldName}: ${formatFieldType(e.after)} (renamed)`;case`index_added`:return` + [Index] ${e.indexName}`;case`index_removed`:return` - [Index] ${e.indexName}`;case`index_modified`:return` ~ [Index] ${e.indexName}: ${e.reason??`modified`}`;case`file_added`:return` + [File] ${e.fieldName}`;case`file_removed`:return` - [File] ${e.fieldName}`;case`file_modified`:return` ~ [File] ${e.fieldName}: ${e.reason??`modified`}`;case`relationship_added`:return` + [Relationship${e.relationshipType?` (${e.relationshipType})`:``}] ${e.relationshipName}`;case`relationship_removed`:return` - [Relationship${e.relationshipType?` (${e.relationshipType})`:``}] ${e.relationshipName}`;case`relationship_modified`:return` ~ [Relationship${e.relationshipType?` (${e.relationshipType})`:``}] ${e.relationshipName}: ${e.reason??`modified`}`;case`permission_modified`:return` ~ [Permission] ${e.reason??`modified`}`;case`table_scripts_modified`:return` ~ [Table Scripts] ${e.tableName}: ${e.reason??`table-level hooks/validate changed`}`;default:{let t=e;return` ? ${t.tableName}.${t.fieldName??``}`}}}function formatFieldType(e){let t=e.type;return e.array&&(t+=`[]`),e.required?t+=` (required)`:t+=` (optional)`,t}function formatFieldModification(e,t,n=[]){let r=[];e.type!==t.type&&r.push(`type: ${e.type} → ${t.type}`),e.required!==t.required&&r.push(`required: ${e.required} → ${t.required}`),!!e.array!=!!t.array&&r.push(`array: ${e.array??!1} → ${t.array??!1}`),!!e.index!=!!t.index&&r.push(`index: ${e.index??!1} → ${t.index??!1}`),!!e.unique!=!!t.unique&&r.push(`unique: ${e.unique??!1} → ${t.unique??!1}`),!!e.vector!=!!t.vector&&r.push(`vector: ${e.vector??!1} → ${t.vector??!1}`);let i=e.allowedValues??[],a=t.allowedValues??[],o=new Set(a.map(e=>e.value));if(i.length!==a.length||i.some(e=>!o.has(e.value))){let e=i.map(e=>e.value).join(`, `),t=a.map(e=>e.value).join(`, `);r.push(`allowedValues: [${e}] → [${t}]`)}let s=e.hooks,c=t.hooks;((s?.create?.expr??``)!==(c?.create?.expr??``)||(s?.update?.expr??``)!==(c?.update?.expr??``))&&r.push(`hooks modified`);let l=e.validate??[],u=t.validate??[];l.length!==u.length&&r.push(`validations: ${l.length} → ${u.length}`),!!e.serial!=!!t.serial&&r.push(`serial: ${e.serial?`enabled`:`disabled`} → ${t.serial?`enabled`:`disabled`}`);let d=new Set(n.flatMap(e=>[e.previousPath.join(`.`),e.path.join(`.`)])),f=collectNestedMemberChanges(e,t).filter(e=>!d.has(e.path.join(`.`))).map(e=>`${
|
|
3
|
+
If a value is genuinely safe to keep in 'env', allow it where it is defined: ${a}: { value: ..., allowSecretReason: "<why this is safe>" }`)}async function scanWithProviderRules(e){let[{lintSource:t},{rules:n}]=await Promise.all([import(`@secretlint/core`),import(`@secretlint/secretlint-rule-preset-recommend`)]),r=[],i=``;for(let[t,n]of e){let e=`${t}=${String(n)}`;r.push({key:t,start:i.length,end:i.length+e.length}),i+=`${e}\n`}let a=await t({source:{filePath:`/tailor-config-env`,content:i,contentType:`text`},options:{maskSecrets:!0,noPhysicFilePath:!0,config:{rules:n.filter(e=>e.meta.id!==`@secretlint/secretlint-rule-filter-comments`).map(e=>({id:e.meta.id,rule:e,...e.meta.id===`@secretlint/secretlint-rule-aws`?{options:{enableIDScanRule:!0}}:{}}))}}}),o=[],s=/* @__PURE__ */ new Set;for(let e of a.messages){let t=r.find(t=>e.range[0]>=t.start&&e.range[0]<t.end);if(!t)continue;let n=e.ruleId.startsWith(`@secretlint/secretlint-rule-`)?e.ruleId.slice(28):e.ruleId,i=JSON.stringify([t.key,n,e.messageId]);s.has(i)||(s.add(i),o.push({key:t.key,detector:n,rule:e.messageId,...e.docsUrl?{docsUrl:e.docsUrl}:{},severity:`error`}))}return o}function isAllowedSecret(e){return typeof e==`object`}function looksRandomlyGenerated(e){return e.length<20||!la.test(e)?!1:shannonEntropyPerChar(e)>=4.2}function shannonEntropyPerChar(e){let t=/* @__PURE__ */ new Map;for(let n of e)t.set(n,(t.get(n)??0)+1);let n=0;for(let r of t.values()){let t=r/e.length;n-=t*Math.log2(t)}return n}function installCliTailordbStub(){Wt()}async function loadConfig(e,t={}){installCliTailordbStub();let n=Ee(e);if(!n)throw Error(`Configuration file not found: tailor.config.ts not found in current or parent directories`);let r=H.resolve(process.cwd(),n);if(!W.existsSync(r))throw Error(`Configuration file not found: ${e}`);let i=di(r),a=t.importNonce??yt();a&&i.searchParams.set(Ct,a);let o;try{o=await import(i.href)}catch(e){throw atConfigSource(e,r)}if(typeof o!=`object`||!o||!(`default`in o)||!o.default)throw atConfigFile(/* @__PURE__ */ Error(`Invalid Tailor config module: default export not found`),r);let s=sa.safeParse(o.default);if(!s.success)throw f({file:r,exportName:`default`,subject:`Tailor config`,error:s.error});let c=o.default;try{await assertEnvHasNoSecrets({env:c.env,configPath:r})}catch(e){throw e instanceof Error?atConfigFile(e,r):e}let l=c.env?Object.fromEntries(Object.entries(c.env).map(([e,t])=>[e,resolveEnvValue(t)])):void 0,u=[];if(Object.hasOwn(o,`plugins`)){let e=o.plugins;if(!Array.isArray(e))throw atConfigFile(/* @__PURE__ */ Error(`Invalid \`plugins\` export in ${r}: expected an array returned by definePlugins(), got ${typeof e}`),r);let t=/* @__PURE__ */ new Set;for(let[n,i]of e.entries()){let e=ca.safeParse(i);if(!e.success)throw f({file:r,exportName:`plugins`,subject:"`plugins` export",error:e.error,pathPrefix:[n]});if(t.has(e.data.id))throw atConfigFile(/* @__PURE__ */ Error(`Duplicate plugin ID "${e.data.id}" detected in ${r}. Each plugin must have a unique ID.`),r);t.add(e.data.id),u.push(i)}}return{config:{...c,...l?{env:l}:{},path:r},plugins:u}}function atConfigFile(e,t){return l(e,{location:{file:t}})}function atConfigSource(e,t){return o(e)||(e instanceof Error?s(e).location?e:atConfigFile(e,t):e)}async function assertWritable(e){let t=e?.profile||process.env.TAILOR_PLATFORM_PROFILE;if(!t)return;let n=(await Oe()).profiles[t];if(n&&n.readonly===!0)throw E({code:`PROFILE_READONLY`,message:`Profile "${t}" is read-only.`,details:`This profile blocks platform-state mutations (apply, create/update/delete, deploy, etc.). Application-data operations remain available because their permissions are governed by the machine user.`,suggestion:`Use a different profile, unset TAILOR_PLATFORM_PROFILE, or run ${w({command:`tailor`,args:te(t,[`--permission`,`write`])})}.`})}function hasEnvAccessToken(){return!!(process.env.TAILOR_PLATFORM_TOKEN??process.env.TAILOR_TOKEN)}async function apiCall(e){let t=await A({profile:e.profile}),n;try{n=await De({profile:e.profile})}catch(e){if(!hasEnvAccessToken())throw e}let r;r=e.endpoint.includes(`/`)?e.endpoint:`tailor.v1.OperatorService/${e.endpoint}`;let i=new URL(r,Et(n)),a=await fetch(i.toString(),{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${t}`,"User-Agent":await Ht()},body:e.body??`{}`}),o=await a.json();if(!a.ok)throw E({code:`API_REQUEST_FAILED`,message:`API call failed (${a.status}): ${JSON.stringify(o)}`,context:{status:a.status}});return{status:a.status,data:o}}function printMutationResult(e){C.jsonMode&&C.out(e)}async function loadOperatorWorkspaceContext(e){let t=await A({profile:e.profile});return{client:await N(t),workspaceId:await xe({profile:e.profile,workspaceId:e.workspaceId})}}function canPrompt(){return _()&&!C.jsonMode}function withGuard(e,t){return async n=>{let{suggestion:r,...i}=n;if(!canPrompt()){let e=new x(t);throw r===void 0?e:l(e,{suggestion:r})}try{return await e(i)}catch(e){throw e instanceof yi&&process.exit(130),e}}}const X={confirm:withGuard(bi,`Interactive confirmations are not available in this environment. Use --yes to skip confirmation prompts, or provide the required options explicitly.`),text:withGuard(xi),password:withGuard(Si),select:e=>withGuard(Ci)(e)};async function fetchWithinLimit(e,t){if(!e)return{items:await t(e),truncated:!1};let n=await t(Math.min(e+1,2**53-1));return n.length<=e?{items:n,truncated:!1}:{items:n.slice(0,e),truncated:!0}}async function reportTruncation(e,t){e.truncated&&(process.stdout.writableLength>0&&await new Promise(e=>process.stdout.write(``,()=>e())),C.info(`More results exist beyond --limit ${t}. Raise --limit to see more.`))}const da=`forced by SDK version`;function forcedBySdkVersionSuffix(e){return e.forcedBySdkVersion?` ${h.dim(`[${da}]`)}`:``}function createChangeSet(e){let t=[],n=[],r=[],i=[],a=[],isEmpty=()=>t.length===0&&n.length===0&&r.length===0&&i.length===0;return{title:e,creates:t,updates:n,deletes:r,replaces:i,unchanged:a,isEmpty,lines:()=>{if(isEmpty())return[];let itemLines=e=>t=>[` ${e} ${t.name}${forcedBySdkVersionSuffix(t)}`,...(t.details??[]).map(e=>` ${e}`)];return[h.bold(`${e}:`),...t.flatMap(itemLines(D.create)),...r.flatMap(itemLines(D.delete)),...n.flatMap(itemLines(D.update)),...i.flatMap(itemLines(D.replace))]}}}function summarizeChangeSets(e){let t={create:0,update:0,delete:0,replace:0,forcedBySdkVersion:0};for(let n of e)t.create+=n.creates.length,t.update+=n.updates.length,t.delete+=n.deletes.length,t.replace+=n.replaces.length,t.forcedBySdkVersion+=n.updates.filter(e=>e.forcedBySdkVersion).length;return t}function formatPlanSummary(e){let t=[`${e.create} to create`,e.forcedBySdkVersion>0?`${e.update} to update (${e.forcedBySdkVersion} ${da})`:`${e.update} to update`,`${e.delete} to delete`];return e.replace>0&&t.push(`${e.replace} to replace`),`Plan: ${t.join(`, `)}`}function toComparableProtoJson(e,t){return Qr(e,Yr(e,t))}function stableStringify$1(e){return Array.isArray(e)?`[${e.map(e=>e===void 0?`null`:stableStringify$1(e)).join(`,`)}]`:e&&typeof e==`object`?`{${Object.entries(e).filter(([e,t])=>e!==`$typeName`&&t!==void 0).toSorted(([e],[t])=>e.localeCompare(t)).map(([e,t])=>`${JSON.stringify(e)}:${stableStringify$1(t)}`).join(`,`)}}`:JSON.stringify(typeof e==`bigint`?e.toString():e)}function normalizeProtoConfig(e){return e==null?e:JSON.parse(stableStringify$1(e))}function normalizeStringArray(e){return(e??[]).toSorted()}function areNormalizedEqual(e,t){return stableStringify$1(normalizeProtoConfig(e))===stableStringify$1(normalizeProtoConfig(t))}function trnPrefix(e){return`trn:v1:workspace:${e}`}function resourceTrn(e,t,n){return`${trnPrefix(e)}:${t}:${n}`}function nestedResourceTrn(e,t,n){return`${trnPrefix(e)}:${t[0]}:${t[1]}:${n[0]}:${n[1]}`}function tailorDBTypeTrn(e,t,n){return nestedResourceTrn(e,[`tailordb`,t],[`type`,n])}function resolverTrn(e,t,n){return nestedResourceTrn(e,[`pipeline`,t],[`resolver`,n])}const fa=`sdk-name`,pa=`sdk-version`,ma=`sdk-app-id`;function sdkAppIdLabelValue(e){return`app-${e}`}function hasMatchingSdkVersion(e,t){return e?.[pa]===t?.[pa]}function isOwnedByApp(e,t,n){if(!e)return!1;let r=e[ma];return r?n!==void 0&&r===sdkAppIdLabelValue(n):e[fa]===t}function prefixFor(e){return e===`jobs`?`sdk-job-depended-by-app-`:`sdk-depended-by-app-`}const ha=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;function dependedByAppLabelKey(e,t=`resource`){return ha.test(e)?`${prefixFor(t)}${e}`:void 0}function recordedDependencies(e,t=`resource`){if(!e)return[];let n=prefixFor(t);return Object.entries(e).toSorted(([e],[t])=>e<t?-1:+(e>t)).flatMap(([e,t])=>{if(!e.startsWith(n))return[];let r=e.slice(n.length);return ha.test(r)?[{appId:r,reason:t}]:[]})}const Z={tailorDBType:(e,t)=>`tailordb:${e}:type:${t}`,resolver:(e,t)=>`pipeline:${e}:resolver:${t}`,idp:e=>`idp:${e}`,workflow:e=>`workflow:${e}`,workflowJobs:e=>`workflow:${e}:jobs`};function dependencyLabelWrite(e){let{existingLabels:t,dependentApps:n,runAppIds:r,pinned:i,scope:a=`resource`}=e;if(i)return{labels:{},remove:recordedDependencies(t,a).flatMap(({appId:e})=>dependedByAppLabelKey(e,a)??[])};let o=n??/* @__PURE__ */ new Map,s=r??/* @__PURE__ */ new Set,c={};for(let[e,t]of o){let n=dependedByAppLabelKey(e,a);if(!n)throw E({code:`APP_ID_INVALID`,message:`Application id "${e}" cannot be recorded as a dependency of this deploy.`,suggestion:`Ids are written by deploy as lowercase UUIDs; restore the generated value in the config's "id".`});c[n]=t}return{labels:c,remove:recordedDependencies(t,a).flatMap(({appId:e})=>{if(!s.has(e)||o.has(e))return[];let t=dependedByAppLabelKey(e,a);return t?[t]:[]})}}async function buildMetaRequest(e){let{trn:t,appName:n,appId:r,metadata:i}=e,a=await Vt(),o=a.version?`v${a.version.replace(/\./g,`-`)}`:`unknown`;return{trn:t,labels:{...i,[fa]:n,[pa]:o,...r?{[ma]:sdkAppIdLabelValue(r)}:{}},remove:r?void 0:[ma]}}function addDependencyRecords(e,t){let{key:n,dependentApps:r,runAppIds:i,pinned:a,scope:o}=t;return e.dependencies=[...e.dependencies??[],{dependentApps:r?.get(n),runAppIds:i,pinned:a,scope:o}],e}const ga=Symbol(`metadataWriteBatch`);var MetadataWriteBatch=class{#e;#t=/* @__PURE__ */ new Map;#n;constructor(e){this.#e=e}async enqueue(e){if(this.#n){await this.#n.catch(()=>void 0),await writeMetadataLabelsDirect(this.#e,e);return}let t=this.#t.get(e.trn)??[];t.push(e),this.#t.set(e.trn,t)}flush(){return this.#n??=this.#r(),this.#n}async#r(){let e=[...this.#t].toSorted(([e],[t])=>e<t?-1:+(e>t)),readRequest=async([e,t])=>{let n=(await P(()=>this.#e.getMetadata({trn:e})))?.metadata?.labels??{},r=t.reduce(applyMetadataLabelWrite,n);return areSameLabels(n,r)?void 0:{trn:e,labels:r}},t=[],n=0;for(;n<e.length||t.length>0;){let r=t.length===0?[]:void 0;for(;n<e.length&&t.length<100;){t.length>0&&(r=void 0);let i=e.slice(n,n+100);n+=i.length;let a=await Promise.all(i.map(async e=>{let t=await readRequest(e);return t?{entry:e,request:t}:void 0}));for(let e of a)e&&(t.push(e.entry),r?.push(e.request))}let i=t.splice(0,100),a=r??(await Promise.all(i.map(e=>readRequest(e)))).filter(e=>e!==void 0);a.length>0&&await this.#e.bulkSetMetadata({requests:a})}}};function hasMetadataLabelChange(e){return!!(Object.keys(e.labels??{}).length||e.remove?.length||e.dependencies?.length)}function applyMetadataLabelWrite(e,t){let{labels:n,remove:r,dependencies:i}=t,a=(i??[]).map(t=>dependencyLabelWrite({...t,existingLabels:e})),o={...e,...n,...Object.assign({},...a.map(e=>e.labels))};for(let e of[...r??[],...a.flatMap(e=>e.remove)])delete o[e];return o}function metadataRecoveryError(e,t){let describeCause=e=>m(e)?S(e.format()):T(e).message;return l(AggregateError([e,t],`Resource apply failed: ${describeCause(e)}\nQueued metadata recovery failed: ${describeCause(t)}`,{cause:t}),{code:`DEPLOY_METADATA_RECOVERY_FAILED`,suggestion:`Some resources may already have changed and deployment metadata could not be saved. Inspect the current resources and resolve both failures before deploying again.`,causes:{apply:e,recovery:t}})}async function withMetadataWriteBatch(e,t){let n=new MetadataWriteBatch(e),r=new Proxy(e,{get(e,t,r){return t===ga?n:Reflect.get(e,t,r)}}),i;try{i=await t(r)}catch(e){try{await n.flush()}catch(t){throw metadataRecoveryError(e,t)}throw e}return await n.flush(),i}async function writeMetadataLabels(e,t){if(!hasMetadataLabelChange(t))return;let n=e[ga];n?await n.enqueue(t):await writeMetadataLabelsDirect(e,t)}async function writeMetadataLabelsDirect(e,t){if(!hasMetadataLabelChange(t))return!1;let{trn:n}=t,r=(await P(()=>e.getMetadata({trn:n})))?.metadata?.labels??{},i=applyMetadataLabelWrite(r,t);return!areSameLabels(r,i)&&(await e.setMetadata({trn:n,labels:i}),!0)}function areSameLabels(e,t){let n=Object.keys(e);return n.length===Object.keys(t).length&&n.every(n=>e[n]===t[n])}async function fetchExistingResourcesWithLabels(e){let{client:t,fetchPage:n,getName:r,getTrn:i}=e,a=await F(n),o={};return await Promise.all(a.map(async e=>{let n=r(e);if(!n)return;let{metadata:a}=await t.getMetadata({trn:i(n)});o[n]={resource:e,allLabels:a?.labels}})),o}function createOwnershipTracker(e,t){let n={conflicts:[],unmanaged:[],resourceOwners:/* @__PURE__ */ new Set};return{result:n,ownsDesired(r,i){if(isOwnedByApp(r,e,t))return!0;let a=r?.[fa];return a?n.conflicts.push({...i,currentOwner:a}):n.unmanaged.push(i),!1},ownsRemaining(r){if(isOwnedByApp(r,e,t))return!0;let i=r?.[fa];return i&&n.resourceOwners.add(i),!1}}}async function applyStaticWebsite(e,t,n=`create-update`){let{changeSet:r,customDomainChangeSet:i,customDomainTransferChangeSet:a}=t;n===`create-update`?(await Promise.all([...r.creates.map(async t=>{await e.createStaticWebsite(t.request),await writeMetadataLabels(e,t.metaRequest)}),...r.updates.map(async t=>{await e.updateStaticWebsite(t.request),await writeMetadataLabels(e,t.metaRequest)})]),await Promise.all([...i.creates.map(async t=>{let{transfer:n}=await e.addCustomDomain(t.request);await writeMetadataLabels(e,t.metaRequest),n&&C.info(`Custom domain "${t.name}" was transferred from workspace ${n.sourceWorkspaceId}.`)}),...i.updates.map(t=>writeMetadataLabels(e,t.metaRequest))]),await Promise.all(i.deletes.map(t=>e.removeCustomDomain(t.request))),await Promise.all(a.deletes.map(t=>e.cancelCustomDomainTransfer(t.request))),await Promise.all(a.creates.map(t=>e.requestCustomDomainTransfer(t.request)))):await Promise.all(r.deletes.map(t=>e.deleteStaticWebsite(t.request)))}function customDomainTrn(e,t,n){return`trn:v1:workspace:${e}:staticwebsite:${t}:custom_domain:${n}`}const _a={[mn.COMPLETED]:`completed`,[mn.CANCELLED]:`was cancelled`,[mn.EXPIRED]:`expired`};function describePreviousTransfer(e){let t=_a[e.status]??`ended`;return`a previous transfer to workspace ${e.targetWorkspaceId} ${t}`}function assertStaticWebsiteDeletesNotOffered(e){let t=[...e.customDomainLiveOffers.values()];for(let n of e.changeSet.deletes){let e=t.find(e=>e.sourceStaticWebsiteName===n.name);if(e)throw E({code:`STATIC_WEBSITE_TRANSFER_IN_FLIGHT`,message:`Static website "${n.name}" cannot be deleted: its custom domain "${e.domain}" is offered to workspace ${e.targetWorkspaceId}.`,suggestion:`Cancel the pending transfer before deleting the static website.`,details:`The platform refuses to delete a static website while one of its custom domains is still offered. Changing the entry back to a plain string and deploying cancels the offer.`,context:{resourceType:`staticwebsite`,staticWebsiteName:n.name,domain:e.domain,targetWorkspaceId:e.targetWorkspaceId}})}}function normalizeComparableStaticWebsiteShape(e){return{description:e.description,allowedIpAddresses:e.allowedIpAddresses.toSorted()}}function normalizeComparableStaticWebsite(e){return normalizeComparableStaticWebsiteShape({description:e.description||``,allowedIpAddresses:[...e.allowedIpAddresses||[]]})}function areStaticWebsitesEqual(e,t){return areNormalizedEqual(normalizeComparableStaticWebsite(e),normalizeComparableStaticWebsite(t))}function expectedLocalStaticWebsiteNames(e){return e.expectedLocalStaticWebsiteNames??new Set(e.application.staticWebsiteServices.map(e=>e.name))}async function planStaticWebsite(e){let{client:t,workspaceId:n,application:r,forRemoval:i}=e,a=createChangeSet(`StaticWebsites`),o=createChangeSet(`CustomDomains`),s=createChangeSet(`CustomDomainTransfers`),c=[],l=createOwnershipTracker(r.name,r.id),u=await fetchExistingResourcesWithLabels({client:t,fetchPage:async(e,r)=>{let{staticwebsites:i,nextPageToken:a}=await t.listStaticWebsites({workspaceId:n,pageToken:e,pageSize:r});return[i,a]},getName:e=>e.name,getTrn:e=>resourceTrn(n,`staticwebsite`,e)}),d=/* @__PURE__ */ new Set,f=i?[]:r.staticWebsiteServices;for(let e of f){let t=e,i=e.name,o=u[i],s=await buildMetaRequest({trn:resourceTrn(n,`staticwebsite`,i),appName:r.name,appId:r.id}),c=normalizeComparableStaticWebsite(t),f={workspaceId:n,staticwebsite:{name:i,description:t.description||``,allowedIpAddresses:t.allowedIpAddresses||[]}};if(o){let e=l.ownsDesired(o.allLabels,{resourceType:`staticwebsite`,resourceLabel:`StaticWebsite`,resourceName:i}),t=e&&areStaticWebsitesEqual(o.resource,c);t&&hasMatchingSdkVersion(o.allLabels,s.labels)?a.unchanged.push({name:i}):a.updates.push({name:i,request:f,metaRequest:s,...t&&{forcedBySdkVersion:!0}}),e&&d.add(i),delete u[i]}else a.creates.push({name:i,request:f,metaRequest:s}),d.add(i)}Object.entries(u).forEach(([e])=>{let t=u[e];l.ownsRemaining(t?.allLabels)&&a.deletes.push({name:e,request:{workspaceId:n,name:e}})});let p=/* @__PURE__ */ new Map;for(let e of f)e.customDomains!==void 0&&d.has(e.name)&&p.set(e.name,new Map(e.customDomains.map(e=>{let t=typeof e==`string`?{domain:e}:{domain:e.domain,transferToWorkspaceId:e.transferTo.workspaceId};return[t.domain,t]})));let m=/* @__PURE__ */ new Map,h=[...d].filter(e=>!a.creates.some(t=>t.name===e)),g=Promise.all(h.map(async e=>{let r=await P(async()=>{let{customDomains:r}=await t.listCustomDomains({workspaceId:n,staticWebsiteName:e});return r});if(!r)return;let i=await Promise.all(r.map(async r=>{let{metadata:i}=await t.getMetadata({trn:customDomainTrn(n,e,r.domain)});return{domain:r.domain,status:r.status,allLabels:i?.labels}}));m.set(e,i)})),_=p.size>0||a.deletes.length>0?F(async(e,r)=>{let{transfers:i,nextPageToken:a}=await t.listCustomDomainTransfers({workspaceId:n,status:mn.PENDING,pageToken:e,pageSize:r});return[i,a]}):Promise.resolve([]),[,v]=await Promise.all([g,_]),y=v.filter(e=>e.sourceWorkspaceId===n),b=new Map(y.map(e=>[e.domain,e])),x=/* @__PURE__ */ new Set;for(let e of p.values())for(let t of e.values())t.transferToWorkspaceId!==void 0&&!b.has(t.domain)&&x.add(t.domain);let S=/* @__PURE__ */ new Map;await Promise.all([...x].map(async e=>{let r=await P(()=>t.getCustomDomainTransfer({workspaceId:n,domain:e}));r?.transfer&&S.set(e,r.transfer)}));for(let e of d){let t=p.get(e)??/* @__PURE__ */ new Map,i=m.get(e)??[],a=new Map(i.map(e=>[e.domain,e])),u=new Set(i.filter(e=>isOwnedByApp(e.allLabels,r.name,r.id)).map(e=>e.domain));for(let[i,s]of t){let t=a.get(i);if(t?.status===Qt.REMOVING)throw E({code:`CUSTOM_DOMAIN_REMOVING`,message:`Custom domain "${i}" on static website "${e}" is being removed.`,suggestion:`Delete this entry, or wait for the removal to finish and deploy again to re-add it.`,details:`A domain reaches this state when it is removed outside the SDK. The platform refuses to re-add, offer or accept it until the removal completes.`,context:{resourceType:`staticwebsite.custom_domain`,staticWebsiteName:e,domain:i}});if(t)l.ownsDesired(t.allLabels,{resourceType:`staticwebsite.custom_domain`,resourceLabel:`StaticWebsite custom domain`,resourceName:i})?o.unchanged.push({name:i}):o.updates.push({name:i,metaRequest:await buildMetaRequest({trn:customDomainTrn(n,e,i),appName:r.name,appId:r.id}),details:[`takes SDK ownership; the domain itself is unchanged`]});else{if(s.transferToWorkspaceId!==void 0)continue;let t=await buildMetaRequest({trn:customDomainTrn(n,e,i),appName:r.name,appId:r.id});o.creates.push({name:i,request:{workspaceId:n,staticWebsiteName:e,domain:i},metaRequest:t})}}if(p.has(e))for(let e of u)t.has(e)||o.deletes.push({name:e,request:{workspaceId:n,domain:e}});for(let[r,i]of t){let t=a.get(r),o=b.get(r),l=i.transferToWorkspaceId;if(l===void 0){o&&s.deletes.push({name:r,staticWebsiteName:e,request:{workspaceId:n,domain:r},details:[`withdraws the offer to workspace ${o.targetWorkspaceId}`]});continue}if(!t){if(o){c.push({kind:`transfer-pending`,staticWebsiteName:e,domain:r,message:`transfer to workspace ${o.targetWorkspaceId} is pending`});continue}let t=S.get(r);if(t?.status===mn.COMPLETED&&t.sourceWorkspaceId===n){c.push({kind:`transfer-completed`,staticWebsiteName:e,domain:r,message:`transfer to workspace ${t.targetWorkspaceId} completed — remove this entry`});continue}throw E({code:`CUSTOM_DOMAIN_TRANSFER_INCOMPLETE`,message:`Custom domain "${r}" is not on static website "${e}", and no transfer from this workspace completed it.`,suggestion:`Remove this entry, or correct the domain it names.`,details:`This happens when the domain was removed outside the SDK, or when the entry names a domain this static website never held.`,context:{resourceType:`staticwebsite.custom_domain`,staticWebsiteName:e,domain:r}})}if(o&&o.targetWorkspaceId===l){c.push({kind:`transfer-pending`,staticWebsiteName:e,domain:r,message:o.requestPurgedAt?`transfer to workspace ${l} is pending`:`transfer to workspace ${l} is pending; the receiving site cannot accept it yet`});continue}o&&s.deletes.push({name:r,staticWebsiteName:e,request:{workspaceId:n,domain:r},details:[`withdraws the offer to workspace ${o.targetWorkspaceId}`]});let u=S.get(r);s.creates.push({name:r,staticWebsiteName:e,request:{workspaceId:n,domain:r,targetWorkspaceId:l},details:[`offers "${r}" to workspace ${l}`,...o?[`replaces the offer to workspace ${o.targetWorkspaceId}`]:[],...u&&!o?[describePreviousTransfer(u)]:[]]})}}return{changeSet:a,customDomainChangeSet:o,customDomainTransferChangeSet:s,customDomainNotes:c,customDomainLiveOffers:b,...l.result}}async function applyAIGateway(e,t,n=`create-update`){let{changeSet:r}=t;n===`create-update`?await Promise.all([...r.creates.map(async t=>{t.request.cors=await jt(e,a(t.request.workspaceId,`request missing workspaceId`),t.request.cors,`AIGateway CORS`),await e.createAIGateway(t.request),await writeMetadataLabels(e,t.metaRequest)}),...r.updates.map(async t=>{t.request.cors=await jt(e,a(t.request.workspaceId,`request missing workspaceId`),t.request.cors,`AIGateway CORS`),await e.updateAIGateway(t.request),await writeMetadataLabels(e,t.metaRequest)})]):await Promise.all(r.deletes.map(t=>e.deleteAIGateway(t.request)))}function normalizeComparableAIGatewayShape(e){return{authNamespace:e.authNamespace,cors:e.cors.toSorted()}}function normalizeComparableAIGateway(e){return normalizeComparableAIGatewayShape({authNamespace:e.authNamespace||``,cors:[...e.cors||[]]})}function areAIGatewaysEqual(e,t){return areNormalizedEqual(normalizeComparableAIGateway(e),normalizeComparableAIGateway(t))}async function planAIGateway(e){let{client:t,workspaceId:n,application:r,forRemoval:i}=e,a=createChangeSet(`AIGateways`),o=createOwnershipTracker(r.name,r.id),s=await fetchExistingResourcesWithLabels({client:t,fetchPage:async(e,r)=>{let{aigateways:i,nextPageToken:a}=await t.listAIGateways({workspaceId:n,pageToken:e,pageSize:r});return[i,a]},getName:e=>e.name,getTrn:e=>resourceTrn(n,`aigateway`,e)}),c=i?[]:r.aiGatewayServices,l=expectedLocalStaticWebsiteNames(e);for(let e of c){let i=e,c=e.name,u=s[c],d=await buildMetaRequest({trn:resourceTrn(n,`aigateway`,c),appName:r.name,appId:r.id}),f=await jt(t,n,i.cors?[...i.cors]:[],`AIGateway CORS`,{expectedLocalNames:l}),p=normalizeComparableAIGateway({...i,cors:f}),m={workspaceId:n,aigatewayName:c,authNamespace:i.authNamespace,cors:i.cors?[...i.cors]:[]};if(u){let e=o.ownsDesired(u.allLabels,{resourceType:`aigateway`,resourceLabel:`AIGateway`,resourceName:c})&&areAIGatewaysEqual(u.resource,p);e&&hasMatchingSdkVersion(u.allLabels,d.labels)?a.unchanged.push({name:c}):a.updates.push({name:c,request:m,metaRequest:d,...e&&{forcedBySdkVersion:!0}}),delete s[c]}else a.creates.push({name:c,request:m,metaRequest:d})}return Object.entries(s).forEach(([e,t])=>{o.ownsRemaining(t?.allLabels)&&a.deletes.push({name:e,request:{workspaceId:n,aigatewayName:e}})}),{changeSet:a,...o.result}}async function applyApplication(e,t,n=`create-update`){if(n===`create-update`){let n=[...t.updates,...t.unchanged];await Promise.all([...t.creates.map(async t=>{t.request.cors=await jt(e,a(t.request.workspaceId,`request missing workspaceId`),t.request.cors,`CORS`),await e.createApplication(t.request),await writeMetadataLabels(e,t.metaRequest)}),...n.map(async t=>{t.request.cors=await jt(e,a(t.request.workspaceId,`request missing workspaceId`),t.request.cors,`CORS`),await e.updateApplication(t.request),await writeMetadataLabels(e,t.metaRequest)})])}else await Promise.all(t.deletes.map(async t=>{await e.deleteApplication(t.request)}))}async function recomposeApplication(e,t){let n=[...t.creates.map(e=>e.request),...[...t.updates,...t.unchanged].map(e=>e.request)];await Promise.all(n.map(t=>e.updateApplication(t)))}function sortStrings(e){return(e??[]).toSorted()}function normalizeSubgraphs(e){return[...e??[]].map(e=>({serviceType:a(e.serviceType,`subgraph missing serviceType`),serviceNamespace:e.serviceNamespace??``})).toSorted((e,t)=>e.serviceType===t.serviceType?e.serviceNamespace.localeCompare(t.serviceNamespace):e.serviceType-t.serviceType)}function normalizeHttpAdapters(e){return[...e??[]].map(e=>({name:e.name??``,pathPattern:e.pathPattern??``,methods:sortStrings(e.methods),inputScript:e.inputScript??``,outputScript:e.outputScript??``,enabled:e.enabled??!0,priority:e.priority??0})).toSorted((e,t)=>e.name.localeCompare(t.name))}function toComparableApplication(e){return{authNamespace:e.authNamespace,authIdpConfigName:e.authIdpConfigName,cors:sortStrings(e.cors),subgraphs:[...e.subgraphs],allowedIpAddresses:sortStrings(e.allowedIpAddresses),disableIntrospection:e.disableIntrospection,disabled:e.disabled,httpAdapters:[...e.httpAdapters]}}function normalizeComparableApplication(e,t,n,r,i){return toComparableApplication({authNamespace:t??``,authIdpConfigName:n??``,cors:r,subgraphs:normalizeSubgraphs(e.subgraphs.map(e=>protoSubgraph(e))),allowedIpAddresses:e.config.allowedIpAddresses??[],disableIntrospection:e.config.disableIntrospection??!1,disabled:!1,httpAdapters:normalizeHttpAdapters(i)})}function normalizeComparableExistingApplication(e){return toComparableApplication({authNamespace:e.authNamespace,authIdpConfigName:e.authIdpConfigName,cors:e.cors,subgraphs:normalizeSubgraphs(e.subgraphs),allowedIpAddresses:e.allowedIpAddresses,disableIntrospection:e.disableIntrospection,disabled:e.disabled,httpAdapters:normalizeHttpAdapters(e.httpAdapters)})}function areApplicationsEqual(e,t){return areNormalizedEqual(normalizeComparableExistingApplication(e),t)}async function planApplication(e,t,n){let{client:r,workspaceId:i,application:o,forRemoval:s}=e,c=createOwnershipTracker(o.name,o.id),l=createChangeSet(`Applications`),u=n?.existingApplications??await F(async(e,t)=>{let{applications:n,nextPageToken:a}=await r.listApplications({workspaceId:i,pageToken:e,pageSize:t});return[n,a]});if(s){let e=o.id?u:u.filter(e=>e.name===o.name),t=await Promise.all(e.map(async e=>{let t=await fetchAppLabels(r,i,e.name);return c.ownsRemaining(t)?e.name:null}));for(let e of t)e&&l.deletes.push({name:e,request:{workspaceId:i,applicationName:e}});return Object.assign(l,c.result,{existingApplications:u,existingLabels:void 0})}if(o.subgraphs.length===0)return Object.assign(l,c.result,{existingApplications:u,existingLabels:void 0});let d,f;if(o.authService){d=o.authService.config.name;let e=o.authService.config.idProvider;e&&(f=e.name)}else if(o.config.auth){if(d=o.config.auth.name,e.externalAuthIdpConfigNames?.has(d))f=e.externalAuthIdpConfigNames.get(d);else{let e=await F(async(e,t)=>{let{idpConfigs:n,nextPageToken:o}=await r.listAuthIDPConfigs({workspaceId:i,namespaceName:a(d,`authNamespace must be set before listing IDP configs`),pageToken:e,pageSize:t});return[n,o]});if(e.length>0){let[t]=e;t&&(f=t.name)}}}let p=await buildMetaRequest({trn:resourceTrn(i,`application`,o.name),appName:o.name,appId:o.id,metadata:o.config.metadata}),m=n?n.existingLabels:await fetchAppLabels(r,i,o.name);assertLabelBudget(o.name,m,p);let h=diffMetadataDisplay(m,o.config.metadata),g=expectedLocalStaticWebsiteNames(e),_=await jt(r,i,o.config.cors,`CORS`,{expectedLocalNames:g}),v=buildHttpAdapters(o,t),y=normalizeComparableApplication(o,d,f,_,v),b={workspaceId:i,applicationName:o.name,authNamespace:d,authIdpConfigName:f,cors:o.config.cors,subgraphs:o.subgraphs.map(e=>protoSubgraph(e)),allowedIpAddresses:o.config.allowedIpAddresses,disableIntrospection:o.config.disableIntrospection,httpAdapters:v},x=u.find(e=>e.name===o.name);if(o.id){let e=u.filter(e=>e.name!==o.name),t=await Promise.all(e.map(async e=>isOwnedByApp(await fetchAppLabels(r,i,e.name),o.name,o.id)?e.name:null));for(let e of t)e&&l.deletes.push({name:e,request:{workspaceId:i,applicationName:e}})}if(x){let e=c.ownsDesired(m,{resourceType:`application`,resourceLabel:`Application`,resourceName:o.name}),t={name:o.name,request:b,metaRequest:p},n=e&&areApplicationsEqual(x,y)&&h.length===0;if(n&&hasMatchingSdkVersion(m,p.labels))l.unchanged.push(t);else{let e=[...diffHttpAdapterDisplay(x.httpAdapters,v),...h];e.length>0&&(t.details=e),l.updates.push({...t,...n&&{forcedBySdkVersion:!0}})}}else{let e=[...diffHttpAdapterDisplay(void 0,v),...h];l.creates.push({name:o.name,request:b,metaRequest:p,details:e.length>0?e:void 0})}return Object.assign(l,c.result,{existingApplications:u,existingLabels:m})}async function fetchAppLabels(e,t,n){return(await P(async()=>{let{metadata:r}=await e.getMetadata({trn:resourceTrn(t,`application`,n)});return r}))?.labels}function diffHttpAdapterDisplay(e,t){let n=new Map((e??[]).map(e=>[e.name??``,e])),r=new Map(t.map(e=>[e.name??``,e])),i=[];for(let[e,t]of r){let r=n.get(e);r?areNormalizedEqual(normalizeHttpAdapters([r])[0],normalizeHttpAdapters([t])[0])||i.push({name:e,symbol:D.update}):i.push({name:e,symbol:D.create})}for(let e of n.keys())r.has(e)||i.push({name:e,symbol:D.delete});return i.toSorted((e,t)=>e.name.localeCompare(t.name)).map(e=>`${e.symbol} ${e.name} (httpAdapter)`)}function assertLabelBudget(e,t,n){let r=/* @__PURE__ */ new Set([...Object.keys(t??{}),...Object.keys(n.labels??{})]);for(let e of n.remove??[])r.delete(e);if(r.size<=20)return;let i=new Set(Object.keys(n.labels??{})),a=[...r].filter(e=>!i.has(e)).toSorted();throw E({code:`DEPLOY_LABEL_LIMIT_EXCEEDED`,message:`Application '${e}' would store ${r.size} labels, over the platform's limit of 20.`,details:`${i.size} come from this deploy and ${a.length} are kept from earlier deploys or other tools${a.length?` (${a.join(`, `)})`:``}.`,suggestion:`Remove entries from 'metadata' in the config, or delete labels the application no longer needs.`})}function diffMetadataDisplay(e,t){let n=e??{},isStored=e=>Object.hasOwn(n,e);return Object.entries(t??{}).filter(([e,t])=>!isStored(e)||n[e]!==t).toSorted(([e],[t])=>e.localeCompare(t)).map(([e])=>`${isStored(e)?D.update:D.create} ${e} (metadata)`)}function buildHttpAdapters(e,t){let n=e.httpAdapterService?.adapters??[];return n.length===0?[]:n.map(e=>{let n=t?.bundledInputs.get(e.adapter.name);if(!n)throw b(`HTTP adapter "${e.adapter.name}" was loaded but no bundled input script is available`);let r=``;if(e.hasOutput){let n=t?.bundledOutputs.get(e.adapter.name);if(!n)throw b(`HTTP adapter "${e.adapter.name}" declares an output handler but no bundled output script is available`);r=n}return{name:e.adapter.name,pathPattern:e.adapter.pathPattern,methods:e.methods.map(e=>et[e]),inputScript:n,outputScript:r,enabled:e.adapter.enabled,priority:e.adapter.priority}})}function protoSubgraph(e){let t;switch(e.Type){case`tailordb`:t=Kt.TAILORDB;break;case`pipeline`:t=Kt.PIPELINE;break;case`idp`:t=Kt.IDP;break;case`auth`:t=Kt.AUTH;break;default:throw b(`Unknown subgraph type: ${e.Type}`)}return{serviceType:t,serviceNamespace:e.Name}}const va=U.object({hash:U.string(),updateTime:U.string().optional()}),ya=U.object({vaults:U.record(U.string(),U.record(U.string(),va)),connections:U.record(U.string(),U.string()).optional()}),ba=U.object({version:U.literal(2),workspaceId:U.string(),applicationKey:U.string(),state:ya});function getSecretsStatePath(e){let t=hashValue(JSON.stringify([e.workspaceId,applicationStateKey(e)]));return H.join(Qe(),`secrets-state`,`${t}.json`)}function loadPersistedSecretsState(e){try{let t=ei(getSecretsStatePath(e),`utf-8`),n=ba.safeParse(JSON.parse(t));return!n.success||n.data.workspaceId!==e.workspaceId||n.data.applicationKey!==applicationStateKey(e)?void 0:n.data}catch{return}}function applicationStateKey(e){if(!e.applicationId)throw b(`Application "${e.applicationName}" has no stable id for secrets state`);return`id:${e.applicationId}`}function loadSecretsState(e){return e.applicationId?loadPersistedSecretsState(e)?.state??{vaults:{}}:{vaults:{}}}function saveSecretsState(e,t){if(!e.applicationId)return;let n=getSecretsStatePath(e),r=H.dirname(n);$r(r,{recursive:!0});let i=`${n}.tmp-${_i()}`;oi(i,JSON.stringify({version:2,workspaceId:e.workspaceId,applicationKey:applicationStateKey(e),state:t},null,2),`utf-8`),ni(i,n)}function hashValue(e){return gi(`sha256`).update(e).digest(`hex`)}function serializeUpdateTime(e){return e===void 0?void 0:`${e.seconds}.${e.nanos}`}const xa=/* @__PURE__ */ new Map;async function withSecretsStateLock(e,t){if(!e.applicationId)return t();let n=`${getSecretsStatePath(e)}.lock`,r=xa.get(n);return r||(r=mi(1),xa.set(n,r)),r(async()=>{let e=await acquireFileLock(n),r=setInterval(()=>refreshLock(n,e),1e4);r.unref();try{return await t()}finally{clearInterval(r),releaseFileLock(n,e)}})}async function acquireFileLock(e){$r(H.dirname(e),{recursive:!0});let t=_i(),n=Date.now()+3e5;for(;;){let r=!0;try{$r(e)}catch(e){if(e.code!==`EEXIST`)throw e;r=!1}if(r){try{oi(H.join(e,`owner.json`),JSON.stringify({pid:process.pid,token:t}))}catch(t){throw ri(e,{recursive:!0,force:!0}),t}return t}if(!(isLockExpired(e)&&stealLock(e))){if(Date.now()>=n){let t=H.resolve(e);throw E({code:`DEPLOY_LOCK_TIMEOUT`,message:`Timed out waiting for another deploy to the same workspace and application to finish.`,suggestion:`Wait for it to complete and retry; an interrupted deploy recovers automatically within a minute. If the error persists, stop any \`tailor deploy\` still running from this project directory, then delete the lock directory ${t} and retry.`,context:{lockPath:t}})}await new Promise(e=>setTimeout(e,100))}}}function isLockExpired(e){try{return Date.now()-ii(e).mtimeMs>6e4}catch{return!1}}function readLockToken(e){try{return JSON.parse(ei(H.join(e,`owner.json`),`utf-8`)).token}catch{return}}function refreshLock(e,t){if(readLockToken(e)!==t)return;let n=/* @__PURE__ */ new Date;try{ai(e,n,n)}catch{}}function releaseFileLock(e,t){readLockToken(e)===t&&ri(e,{recursive:!0,force:!0})}function stealLock(e){let t=`${e}.stale-${process.pid}-${Date.now()}`;try{ni(e,t)}catch{return!1}if(isLockExpired(t))return ri(t,{recursive:!0,force:!0}),!0;try{ni(t,e)}catch{ri(t,{recursive:!0,force:!0})}return!1}function buildConnectionRequest(e,t,n){return{workspaceId:e,connection:{name:t,type:er.OAUTH2,config:{case:`oauth2`,value:{providerUrl:n.providerUrl,issuerUrl:n.issuerUrl,clientId:n.clientId,clientSecret:n.clientSecret,authUrl:n.authUrl??``,tokenUrl:n.tokenUrl??``}}}}}function buildUpdateMask(e,t,n){if(e.config.case!==`oauth2`){let e=[`type`,`oauth2.provider_url`,`oauth2.issuer_url`,`oauth2.client_id`,`oauth2.auth_url`,`oauth2.token_url`];return t.clientSecret&&e.push(`oauth2.client_secret`),{paths:e}}let r=[],i=e.config.value;return i.providerUrl!==t.providerUrl&&r.push(`oauth2.provider_url`),i.issuerUrl!==t.issuerUrl&&r.push(`oauth2.issuer_url`),i.clientId!==t.clientId&&r.push(`oauth2.client_id`),i.authUrl!==(t.authUrl??``)&&r.push(`oauth2.auth_url`),i.tokenUrl!==(t.tokenUrl??``)&&r.push(`oauth2.token_url`),n&&t.clientSecret&&r.push(`oauth2.client_secret`),{paths:r}}async function planAuthConnections(e,t,n,r,i){let a={workspaceId:t,applicationId:r,applicationName:n},o=createChangeSet(`Auth connections`),s=createOwnershipTracker(n,r),c={};for(let e of i)for(let[t,n]of Object.entries(e.connections))c[t]=n,C.registerSecret(n.clientSecret);let l=await F(async(n,r)=>{let{connections:i,nextPageToken:a}=await e.listAuthConnections({workspaceId:t,pageToken:n,pageSize:r});return[i,a]}),u={};await Promise.all(l.map(async n=>{let{metadata:r}=await e.getMetadata({trn:resourceTrn(t,`auth_connection`,n.name)});u[n.name]={resource:n,allLabels:r?.labels}}));let d=loadSecretsState(a);for(let[e,i]of Object.entries(c)){let a=u[e],c=await buildMetaRequest({trn:resourceTrn(t,`auth_connection`,e),appName:n,appId:r});if(a){let n=s.ownsDesired(a.allLabels,{resourceType:`auth.connection`,resourceLabel:`Auth connection`,resourceName:e}),r=hashValue(i.clientSecret)!==d.connections?.[e],l=buildUpdateMask(a.resource,i,r);l.paths.length>0?o.replaces.push({name:e,updateRequest:{...buildConnectionRequest(t,e,i),updateMask:l},metaRequest:c}):n?o.unchanged.push({name:e}):o.updates.push({name:e,metaRequest:c}),delete u[e]}else o.creates.push({name:e,request:buildConnectionRequest(t,e,i),metaRequest:c})}for(let[e,n]of Object.entries(u))n&&s.ownsRemaining(n.allLabels)&&o.deletes.push({name:e,request:{workspaceId:t,connectionName:e}});return{changeSet:o,...s.result,stateScope:a}}async function applyAuthConnections(e,t,n){let{changeSet:r,stateScope:i}=t;n===`create-update`?((r.creates.length>0||r.replaces.length>0)&&await withSecretsStateLock(i,async()=>{await Promise.all(r.creates.map(async t=>{await e.createAuthConnection(t.request),await writeMetadataLabels(e,t.metaRequest),C.info(`Connection "${t.name}" was created. Authorize it with:\n tailor authconnection authorize --name ${t.name}\nOr via the Console: tailor authconnection open`)}));for(let t of r.replaces)(await e.updateAuthConnection(t.updateRequest)).connection?.status===hn.UNAUTHORIZED&&C.warn(`Connection "${t.name}" requires re-authorization. Authorize with:\n tailor authconnection authorize --name ${t.name}\nOr via the Console: tailor authconnection open`),await writeMetadataLabels(e,t.metaRequest);let t=r.replaces.filter(e=>e.updateRequest.updateMask?.paths?.includes(`oauth2.client_secret`));if(r.creates.length>0||t.length>0){let e=loadSecretsState(i);e.connections||={};for(let t of r.creates){let n=t.request.connection;n?.config?.case===`oauth2`&&(e.connections[t.name]=hashValue(n.config.value.clientSecret??``))}for(let n of t){let t=n.updateRequest.connection;t?.config?.case===`oauth2`&&(e.connections[n.name]=hashValue(t.config.value.clientSecret??``))}saveSecretsState(i,e)}}),await Promise.all(r.updates.map(async t=>{await writeMetadataLabels(e,t.metaRequest)}))):r.deletes.length>0&&await withSecretsStateLock(i,async()=>{await Promise.all(r.deletes.map(async t=>{await e.deleteAuthConnection(t.request)}));let t=loadSecretsState(i);if(t.connections){for(let e of r.deletes)delete t.connections[e.name];saveSecretsState(i,t)}})}const Sa=65536;function computeContentHash(e){return hi.createHash(`sha256`).update(e,`utf-8`).digest(`hex`)}const Ca=`workflow--`;function resolverFunctionName(e,t){return`resolver--${e}--${t}`}function executorFunctionName(e){return`executor--${e}`}function workflowJobFunctionName(e){return`${Ca}${e}`}function collectWorkflowJobStates(e){let jobNames=e=>new Set(e.filter(e=>e.name.startsWith(Ca)).map(e=>e.name.slice(10)));return{unchanged:jobNames(e.unchanged),forcedBySdkVersion:jobNames(e.updates.filter(e=>e.forcedBySdkVersion))}}function splitFunctionRegistryChanges(e){function partition(e){let t={workflowJob:[],resolver:[],executor:[],authHook:[],other:[]};for(let n of e)n.name.startsWith(`workflow--`)?t.workflowJob.push(n):n.name.startsWith(`resolver--`)?t.resolver.push(n):n.name.startsWith(`executor--`)?t.executor.push(n):n.name.startsWith(`auth-hook--`)?t.authHook.push(n):t.other.push(n);return t}let t=partition(e.creates),n=partition(e.updates),r=partition(e.deletes),i=partition(e.replaces),a=partition(e.unchanged);function collect(e){return{creates:t[e],updates:n[e],deletes:r[e],replaces:i[e],unchanged:a[e]}}return{workflowJobChanges:collect(`workflowJob`),resolverFunctionChanges:collect(`resolver`),executorFunctionChanges:collect(`executor`),authHookFunctionChanges:collect(`authHook`),otherChanges:collect(`other`)}}function authHookFunctionName(e,t){return`auth-hook--${e}--${t}`}function collectFunctionEntries(e,t,n){let r=[];for(let t of e.applications)for(let e of t.resolverServices)for(let t of Object.values(e.resolvers)){let i=n.resolvers.get(dt(e.namespace,t.name));i?r.push({name:resolverFunctionName(e.namespace,t.name),scriptContent:i,contentHash:computeContentHash(i),description:`Resolver: ${e.namespace}/${t.name}`}):C.warn(`Bundled code not found for resolver: ${e.namespace}/${t.name}`)}if(e.executorService){let t=e.executorService.executors;for(let e of Object.values(t))if(e.operation.kind===`function`||e.operation.kind===`jobFunction`){let t=n.executors.get(e.name);if(!t){C.warn(`Bundled code not found for executor: ${e.name}`);continue}r.push({name:executorFunctionName(e.name),scriptContent:t,contentHash:computeContentHash(t),description:`Executor: ${e.name}`})}}for(let e of t){let t=n.workflowJobs.get(e.name);t?r.push({name:workflowJobFunctionName(e.name),scriptContent:t,contentHash:computeContentHash(t),description:`Workflow job: ${e.name}`}):C.warn(`Bundled code not found for workflow job: ${e.name}`)}for(let t of e.applications)if(t.authService?.config.hooks?.beforeLogin){let e=t.authService.config.name,i=authHookFunctionName(e,`before-login`),a=n.authHooks.get(i);if(!a){C.warn(`Bundled code not found for auth hook: ${i}`);continue}r.push({name:i,scriptContent:a,contentHash:computeContentHash(a),description:`Auth hook: ${e}/before-login`})}return r}function filterBundledWorkflowJobs(e,t){let n=new Set(t);return e.filter(e=>n.has(e.name))}async function planFunctionRegistry(e,t,n,r,i,a){let o=createChangeSet(`Function registry`),s=createOwnershipTracker(n,r),c=a??await fetchExistingResourcesWithLabels({client:e,fetchPage:async(n,r)=>{let i=await e.listFunctionRegistries({workspaceId:t,pageToken:n,pageSize:r});return[i.functions.map(e=>({name:e.name,contentHash:e.contentHash})),i.nextPageToken]},getName:e=>e.name,getTrn:e=>resourceTrn(t,`function_registry`,e)}),l={...c};for(let e of i){let i=l[e.name],a=await buildMetaRequest({trn:resourceTrn(t,`function_registry`,e.name),appName:n,appId:r});if(i){let t=s.ownsDesired(i.allLabels,{resourceType:`function_registry`,resourceLabel:`Function registry`,resourceName:e.name})&&i.resource.contentHash===e.contentHash;t&&hasMatchingSdkVersion(i.allLabels,a.labels)?o.unchanged.push({name:e.name}):o.updates.push({name:e.name,entry:e,metaRequest:a,...t&&{forcedBySdkVersion:!0}}),delete l[e.name]}else o.creates.push({name:e.name,entry:e,metaRequest:a})}for(let[e,n]of Object.entries(l))n&&s.ownsRemaining(n.allLabels)&&o.deletes.push({name:e,workspaceId:t});let{workflowJobChanges:u,resolverFunctionChanges:d,executorFunctionChanges:f,authHookFunctionChanges:p}=splitFunctionRegistryChanges(o);return{changeSet:o,workflowJobChanges:u,resolverFunctionChanges:d,executorFunctionChanges:f,authHookFunctionChanges:p,...s.result,existingMap:c}}async function uploadFunctionScript(e,t,n,r){let i=Buffer.from(n.scriptContent,`utf-8`),a={workspaceId:t,name:n.name,description:n.description,sizeBytes:BigInt(i.length),contentHash:n.contentHash};if(r){async function*createStream(){yield{payload:{case:`info`,value:a}};for(let e=0;e<i.length;e+=Sa)yield{payload:{case:`chunk`,value:i.subarray(e,Math.min(e+Sa,i.length))}}}await e.createFunctionRegistry(createStream())}else{async function*updateStream(){yield{payload:{case:`info`,value:a}};for(let e=0;e<i.length;e+=Sa)yield{payload:{case:`chunk`,value:i.subarray(e,Math.min(e+Sa,i.length))}}}await e.updateFunctionRegistry(updateStream())}}async function applyFunctionRegistry(e,t,n,r=`create-update`){let{changeSet:i}=n;if(r===`create-update`){let n=Bt();await Promise.all([...i.creates.map(r=>n(async()=>{await uploadFunctionScript(e,t,r.entry,!0),await writeMetadataLabels(e,r.metaRequest)})),...i.updates.map(r=>n(async()=>{await uploadFunctionScript(e,t,r.entry,!1),await writeMetadataLabels(e,r.metaRequest)}))])}else await Promise.all(i.deletes.map(async t=>{try{await e.deleteFunctionRegistry({workspaceId:t.workspaceId,name:t.name})}catch(e){if(!At(e))throw e}}))}function forcedFunctionUpdateNames(e){return new Set(e?.updates.filter(e=>e.forcedBySdkVersion).map(e=>e.name)??[])}function createRelatedFunctionRegistryNameSets(e){return{creates:new Set(e?.creates.map(e=>e.name)??[]),updates:new Set(e?.updates.map(e=>e.name)??[]),deletes:new Set(e?.deletes.map(e=>e.name)??[]),replaces:new Set(e?.replaces.map(e=>e.name)??[])}}const wa={create:D.create,update:D.update,delete:D.delete,replace:D.replace};function formatChangeSetEntries(e,t=[],n){function toEntry(e,r){return{action:e,symbol:wa[e],name:r.name,labels:[...t],namespace:n?.(r),...r.forcedBySdkVersion&&{forcedBySdkVersion:!0}}}return[...e.creates.map(e=>toEntry(`create`,e)),...e.deletes.map(e=>toEntry(`delete`,e)),...e.updates.map(e=>toEntry(`update`,e)),...e.replaces.map(e=>toEntry(`replace`,e))]}function formatGroupedDisplayLine(e){return`${e.labels.length>0?`${e.symbol} ${e.name} (${e.labels.join(`, `)})`:`${e.symbol} ${e.name}`}${forcedBySdkVersionSuffix(e)}`}function parseFunctionRegistryName(e){if(e.startsWith(`resolver--`)){let[,t,n]=e.split(`--`);if(t&&n)return{displayName:n,namespace:t}}if(e.startsWith(`workflow--`)||e.startsWith(`executor--`))return{displayName:e.slice(10)};if(e.startsWith(`auth-hook--`)){let[,t,n]=e.split(`--`);if(t&&n)return{displayName:n,namespace:t}}return{displayName:e}}function buildRemainingFunctionRegistryEntries(e,t,n=createRelatedFunctionRegistryNameSets()){return[[`create`,e.creates,n.creates],[`delete`,e.deletes,n.deletes],[`update`,e.updates,n.updates],[`replace`,e.replaces,n.replaces]].flatMap(([e,n,r])=>[...n].filter(e=>!r.has(e)).map(n=>{let{displayName:r,namespace:i}=parseFunctionRegistryName(n);return{action:e,symbol:wa[e],name:r,labels:[`function`],namespace:i,...e===`update`&&t.has(n)&&{forcedBySdkVersion:!0}}}))}function formatChangeEntriesWithFunctionRegistry(e,t,n,r,i){let{getNamespace:a,getDisplayName:o}=i??{},s=createRelatedFunctionRegistryNameSets(n),c=forcedFunctionUpdateNames(n),l=createRelatedFunctionRegistryNameSets();function processItems(t,n,i,s){return t.map(t=>{let l=r(t,n).filter(e=>i.has(e));for(let e of l)s.add(e);let u=t.forcedBySdkVersion&&l.every(e=>c.has(e));return{action:n,symbol:wa[n],name:o?.(t)??t.name,labels:l.length>0?[e,`function`]:[e],namespace:a?.(t),...u&&{forcedBySdkVersion:!0}}})}return[...processItems(t.creates,`create`,s.creates,l.creates),...processItems(t.deletes,`delete`,s.deletes,l.deletes),...processItems(t.updates,`update`,s.updates,l.updates),...t.replaces.map(t=>({action:`replace`,symbol:wa.replace,name:o?.(t)??t.name,labels:[e],namespace:a?.(t)})),...buildRemainingFunctionRegistryEntries(s,c,l)]}function extractServiceActions(e){return[...e.creates.map(e=>({name:e.name,action:`create`})),...e.deletes.map(e=>({name:e.name,action:`delete`})),...e.updates.map(e=>({name:e.name,action:`update`,...e.forcedBySdkVersion&&{forcedBySdkVersion:!0}})),...e.replaces.map(e=>({name:e.name,action:`replace`}))]}function buildGroupedDisplayLines(e,t,n){let r=/* @__PURE__ */ new Map;if(n)for(let e of n)r.set(e.name,e);if(t.length===0&&r.size===0)return[];let i=[h.bold(`${e}:`)],o=[],s=/* @__PURE__ */ new Map;for(let e of t){let t=e.namespace;s.has(t)||(o.push(t),s.set(t,[])),a(s.get(t),`namespace group missing`).push(e)}let c=/* @__PURE__ */ new Set;for(let e of o){let t=a(s.get(e),`namespace group missing`);if(e){let n=r.get(e),a=n?`${wa[n.action]} `:``,o=n?.forcedBySdkVersion?`${h.bold(e)}${forcedBySdkVersionSuffix(n)}${h.bold(`:`)}`:h.bold(`${e}:`);i.push(` ${a}${o}`),c.add(e);for(let e of t)i.push(` ${formatGroupedDisplayLine(e)}`)}else for(let e of t)i.push(` ${formatGroupedDisplayLine(e)}`)}for(let[e,t]of r)c.has(e)||i.push(` ${wa[t.action]} ${e}${forcedBySdkVersionSuffix(t)}`);return i}const Ta={tailorDBType:e=>`TailorDB table "${e}"`,resolver:e=>`Resolver "${e}"`,idpService:e=>`IdP service "${e}"`,workflow:e=>`Workflow "${e}"`,workflowJob:e=>`Job "${e}"`,workflowJobs:e=>`Jobs of workflow "${e}"`},Ea={tailorDBType:e=>({resource:Ta.tailorDBType(e),trigger:`record`}),resolver:e=>({resource:Ta.resolver(e),trigger:`resolverExecuted`}),idpService:e=>({resource:Ta.idpService(e),trigger:`idpUser`}),workflow:e=>({resource:Ta.workflow(e),trigger:`workflowExecution`}),workflowJob:e=>({resource:Ta.workflowJob(e),trigger:`workflowJobExecution`,subscribesTo:`a workflow that runs it`})};function publishEventsConflictError(e){let{resource:t,trigger:n,subscribesTo:r=`it`}=e;return`${t} has "publishEvents: false", but executors with ${n} triggers subscribe to ${r}. Either remove "publishEvents: false" or remove the matching executor triggers.`}function subscribesToEvents(e){return!e.disabled}function assertNoPublishEventsConflict(e){let{explicit:t,subscribed:n,conflict:r}=e;if(t===!1&&n)throw Error(publishEventsConflictError(r))}function resolvePublishEvents(e){return assertNoPublishEventsConflict(e),e.explicit??e.subscribed}const{normalizeActionPermission:Da}=lt({"=":`eq`,"!=":`ne`,in:`in`,"not in":`nin`});function normalizeIdPActionPermission(e){return Da(e)}function normalizeIdPPermission(e){return{create:e.create.map(e=>normalizeIdPActionPermission(e)),read:e.read.map(e=>normalizeIdPActionPermission(e)),update:e.update.map(e=>normalizeIdPActionPermission(e)),delete:e.delete.map(e=>normalizeIdPActionPermission(e)),sendPasswordResetEmail:(e.sendPasswordResetEmail??[]).map(e=>normalizeIdPActionPermission(e)),unenrollMfa:(e.unenrollMfa??[]).map(e=>normalizeIdPActionPermission(e))}}function parseIdPPermission(e){if(e)return normalizeIdPPermission(e)}function findOmittedPermitRules(e){if(!e)return[];let t=[];for(let n of Object.keys(e))e[n]?.forEach((e,r)=>{Me(e)&&t.push(`${String(n)}[${r}]`)});return t}function findLoggedInOnlyPermitRules(e){if(!e)return[];let t=normalizeIdPPermission(e),n=[];for(let e of Object.keys(t))t[e].forEach((t,r)=>{t.permit===`allow`&&isLoggedInOnly(t.conditions)&&n.push(`${e}[${r}]`)});return n}function isLoggedInOperand(e){return typeof e==`object`&&!!e&&`user`in e&&e.user===`_loggedIn`}function isLoggedInOnly(e){let[t,...n]=e;if(!t||n.length>0)return!1;let[r,i,a]=t,o=isLoggedInOperand(r)?a:isLoggedInOperand(a)?r:void 0;switch(i){case`eq`:return o===!0;case`ne`:return o===!1;case`in`:return isLoggedInOperand(r)&&Array.isArray(o)&&o.includes(!0);case`nin`:return isLoggedInOperand(r)&&Array.isArray(o)&&!o.includes(!0);default:return!1}}async function resolveServiceReturnOrigins(e,t){let n=t.userAuthPolicy,r=n?.allowedReturnOrigins;if(!n||!r?.length)return;let i=await jt(e,a(t.workspaceId,`request missing workspaceId`),r,`IdP service "${t.namespaceName??``}" allowedReturnOrigins`);if(i.length!==r.length)throw E({code:`IDP_RETURN_ORIGIN_UNRESOLVED`,message:`IdP service "${t.namespaceName??``}" allowedReturnOrigins: ${r.length-i.length} of ${r.length} entries could not be resolved.`,suggestion:`Check that each "<name>:url" entry refers to a deployed static website.`});n.allowedReturnOrigins=i}function idpClientVaultName(e,t){return`idp-${e}-${t}`}function idpClientSecretName(e,t){return`client-secret-${e}-${t}`}async function applyIdP(e,t,n=`create-update`){let{changeSet:r}=t;n===`create-update`?(await Promise.all([...r.service.creates.map(async t=>{await resolveServiceReturnOrigins(e,t.request),await e.createIdPService(t.request),await writeMetadataLabels(e,t.metaRequest)}),...r.service.updates.map(async t=>{await resolveServiceReturnOrigins(e,t.request),await e.updateIdPService(t.request),await writeMetadataLabels(e,t.metaRequest)}),...r.service.unchanged.flatMap(t=>t.metaRequest?[writeMetadataLabels(e,t.metaRequest)]:[])]),await Promise.all([...r.client.creates.map(async t=>{let n=await e.createIdPClient(t.request);n.client?.clientSecret&&C.registerSecret(n.client.clientSecret);let r=idpClientVaultName(a(t.request.namespaceName,`request missing namespaceName`),t.request.client?.name||``),i=idpClientSecretName(a(t.request.namespaceName,`request missing namespaceName`),t.request.client?.name||``);await e.createSecretManagerVault({workspaceId:t.request.workspaceId,secretmanagerVaultName:r}),await e.createSecretManagerSecret({workspaceId:t.request.workspaceId,secretmanagerVaultName:r,secretmanagerSecretName:i,secretmanagerSecretValue:n.client?.clientSecret})}),...r.client.updates.map(async t=>{let n=idpClientVaultName(t.namespaceName,t.name),r=idpClientSecretName(t.namespaceName,t.name);if(await P(async()=>await e.getSecretManagerVault({workspaceId:t.workspaceId,secretmanagerVaultName:n})))return;let{client:i}=await e.getIdPClient({workspaceId:t.workspaceId,namespaceName:t.namespaceName,name:t.name});i?.clientSecret&&C.registerSecret(i.clientSecret),await e.createSecretManagerVault({workspaceId:t.workspaceId,secretmanagerVaultName:n}),await e.createSecretManagerSecret({workspaceId:t.workspaceId,secretmanagerVaultName:n,secretmanagerSecretName:r,secretmanagerSecretValue:i?.clientSecret})})])):n===`delete-resources`?await Promise.all(r.client.deletes.map(async t=>{t.vaultOnly||await e.deleteIdPClient(t.request);let n=idpClientVaultName(a(t.request.namespaceName,`request missing namespaceName`),t.name);try{await e.deleteSecretManagerVault({workspaceId:t.request.workspaceId,secretmanagerVaultName:n})}catch(e){if(!At(e))throw e}})):await Promise.all(r.service.deletes.map(t=>e.deleteIdPService(t.request)))}async function planIdP(e){let{client:t,workspaceId:n,application:r,forRemoval:i,forceApplyAll:a=!1,idpUserTriggerTargets:o,dependentApps:s,runAppIds:c}=e,l=i?[]:r.idpServices,u=expectedLocalStaticWebsiteNames(e),{changeSet:d,conflicts:f,unmanaged:p,resourceOwners:m}=await planServices$3(t,n,r.name,r.id,l,o??/* @__PURE__ */ new Set,u,{dependentApps:s,runAppIds:c});return{changeSet:{service:d,client:await planClients(t,n,l,d.deletes.map(e=>e.name),a)},conflicts:f,unmanaged:p,resourceOwners:m}}function normalizeComparableUserAuthPolicy(e){return{useNonEmailIdentifier:e?.useNonEmailIdentifier??!1,allowSelfPasswordReset:e?.allowSelfPasswordReset??!1,passwordRequireUppercase:e?.passwordRequireUppercase??!1,passwordRequireLowercase:e?.passwordRequireLowercase??!1,passwordRequireNonAlphanumeric:e?.passwordRequireNonAlphanumeric??!1,passwordRequireNumeric:e?.passwordRequireNumeric??!1,passwordMinLength:e?.passwordMinLength||6,passwordMaxLength:e?.passwordMaxLength||4096,allowedEmailDomains:[...new Set((e?.allowedEmailDomains??[]).map(e=>e.toLowerCase()))].toSorted(),allowGoogleOauth:e?.allowGoogleOauth??!1,disablePasswordAuth:e?.disablePasswordAuth??!1,allowMicrosoftOauth:e?.allowMicrosoftOauth??!1,enableMfa:e?.enableMfa??!1,requireMfa:e?.requireMfa??!1,allowedReturnOrigins:(e?.allowedReturnOrigins??[]).toSorted(),mfaIssuer:e?.mfaIssuer??``}}function normalizeComparableDisableGqlOperations(e){return{create:e?.create??!1,update:e?.update??!1,delete:e?.delete??!1,read:e?.read??!1,sendPasswordResetEmail:e?.sendPasswordResetEmail??!1,requestMfaSettingsUrl:e?.requestMfaSettingsUrl??!1,unenrollMfa:e?.unenrollMfa??!1}}function normalizeComparableEmailConfig(e){return{fromName:e?.fromName??``,passwordResetSubject:e?.passwordResetSubject??``}}function normalizeComparableIdPService(e){return{authorization:e.authorization||void 0,lang:e.lang===nn.UNSPECIFIED?nn.EN:e.lang,userAuthPolicy:e.userAuthPolicy,publishEvents:e.publishEvents,disableGqlOperations:e.disableGqlOperations,emailConfig:e.emailConfig,permission:e.permission}}function normalizeComparablePermission(e){if(!e||e.create.length===0&&e.read.length===0&&e.update.length===0&&e.delete.length===0&&e.sendPasswordResetEmail.length===0&&e.unenrollMfa.length===0)return;let normalizePolicy=e=>({conditions:e.conditions.map(e=>({left:e.left?{kind:e.left.kind}:void 0,operator:e.operator,right:e.right?{kind:e.right.kind}:void 0})),permit:e.permit,description:e.description||void 0});return{create:e.create.map(normalizePolicy),read:e.read.map(normalizePolicy),update:e.update.map(normalizePolicy),delete:e.delete.map(normalizePolicy),sendPasswordResetEmail:e.sendPasswordResetEmail.map(normalizePolicy),unenrollMfa:e.unenrollMfa.map(normalizePolicy)}}function areIdPServicesEqual(e,t){return areNormalizedEqual(normalizeComparableIdPService({authorization:e.authorization,lang:e.lang,userAuthPolicy:normalizeComparableUserAuthPolicy(e.userAuthPolicy),publishEvents:e.publishUserEvents,disableGqlOperations:normalizeComparableDisableGqlOperations(e.disableGqlOperations),emailConfig:normalizeComparableEmailConfig(e.emailConfig),permission:normalizeComparablePermission(e.permission)}),t)}async function planServices$3(e,t,n,r,i,a,o,s){let c=createChangeSet(`IdP services`),l=createOwnershipTracker(n,r),u=await fetchExistingResourcesWithLabels({client:e,fetchPage:async(n,r)=>{let{idpServices:i,nextPageToken:a}=await e.listIdPServices({workspaceId:t,pageToken:n,pageSize:r});return[i,a]},getName:e=>e.namespace?.name,getTrn:e=>resourceTrn(t,`idp`,e)});for(let d of i){let i=d.name,f=u[i],p=addDependencyRecords(await buildMetaRequest({trn:resourceTrn(t,`idp`,i),appName:n,appId:r}),{key:Z.idp(i),dependentApps:s.dependentApps,runAppIds:s.runAppIds,pinned:d.publishEvents!==void 0}),m;switch(d.authorization){case`insecure`:m=`true==true`;break;case`loggedIn`:m=`user != null && size(user.id) > 0`;break;case void 0:m=void 0;break;default:m=d.authorization.cel}let h=convertLang(d.lang),g=d.userAuthPolicy,_=resolvePublishEvents({explicit:d.publishEvents,subscribed:a.has(i),conflict:Ea.idpService(i)}),v=d.emailConfig;d.permission||C.warn(`IdP service "${i}" has no permission configured.`);let y=findOmittedPermitRules(d.permission);y.length>0&&C.warn(`IdP service "${i}" has permission rule(s) ${y.join(`, `)} in object form without an explicit "permit"; they default to "deny". Set permit: true (allow) or permit: false (deny) to silence this warning.`);let b=findLoggedInOnlyPermitRules(d.permission);b.length>0&&C.warn(`IdP service "${i}" permits every authenticated user in permission rule(s) ${b.join(`, `)} (their only condition is on "_loggedIn"). Any signed-in user can then run these operations against any IdP user, for example reading and changing login information (such as email addresses) or sending password reset emails to anyone. Restrict these rules to an administrator role unless every user who can sign in is trusted.`),$e(g)&&C.warn(`IdP service "${i}" leaves userAuthPolicy.allowedEmailDomains empty, which currently allows every email domain. The platform will stop treating an empty list as "allow every domain", so set allowedEmailDomains: ["*"] to keep that behavior, or list the domains you accept.`);let x=parseIdPPermission(d.permission),S=x?protoIdPPermission(x):void 0,w=await jt(e,t,g?.allowedReturnOrigins?[...g.allowedReturnOrigins]:[],`IdP service "${i}" allowedReturnOrigins`,{expectedLocalNames:o}),T=g&&{...g,allowedReturnOrigins:w},E=normalizeComparableIdPService({authorization:m,lang:h,userAuthPolicy:normalizeComparableUserAuthPolicy(T),publishEvents:_,disableGqlOperations:normalizeComparableDisableGqlOperations(convertGqlOperationsToDisable(d.gqlOperations)),emailConfig:normalizeComparableEmailConfig(v),permission:S}),ee={workspaceId:t,namespaceName:i,authorization:m,lang:h,userAuthPolicy:g,publishUserEvents:_,disableGqlOperations:convertGqlOperationsToDisable(d.gqlOperations),emailConfig:v,permission:S};if(f){let e=l.ownsDesired(f.allLabels,{resourceType:`idp.service`,resourceLabel:`IdP service`,resourceName:d.name})&&areIdPServicesEqual(f.resource,E);e&&hasMatchingSdkVersion(f.allLabels,p.labels)?c.unchanged.push({name:i,metaRequest:p}):c.updates.push({name:i,request:ee,metaRequest:p,...e&&{forcedBySdkVersion:!0}}),delete u[i]}else c.creates.push({name:i,request:ee,metaRequest:p})}return Object.entries(u).forEach(([e])=>{let n=u[e];l.ownsRemaining(n?.allLabels)&&c.deletes.push({name:e,request:{workspaceId:t,namespaceName:e}})}),{changeSet:c,...l.result}}async function planClients(e,t,n,r,i=!1){let o=createChangeSet(`IdP clients`),fetchClients=n=>F(async(r,i)=>{let{clients:a,nextPageToken:o}=await e.listIdPClients({workspaceId:t,namespaceName:n,pageToken:r,pageSize:i});return[a,o]}),isDeletableName=e=>gt.safeParse(e).success,s=await Promise.all(n.map(e=>fetchClients(e.name)));for(let[e,r]of n.entries()){let n=r.name,c=a(s[e],`clientsByIdp missing entry for idp index`),l=/* @__PURE__ */ new Set;c.forEach(e=>{l.add(e.name),C.registerSecret(e.clientSecret)});for(let e of r.clients)l.has(e)?(i?o.updates.push({name:e,workspaceId:t,namespaceName:n,forcedBySdkVersion:!0}):o.unchanged.push({name:e}),l.delete(e)):o.creates.push({name:e,request:{workspaceId:t,namespaceName:n,client:{name:e}}});l.forEach(e=>{isDeletableName(e)?o.deletes.push({name:e,request:{workspaceId:t,namespaceName:n,name:e}}):C.warn(`IdP client "${e}" in "${n}" will not be deleted, because the platform cannot delete a client with this name. The client and its secret vault stay in the workspace. Both are deleted when that IdP is removed.`)})}let c=await Promise.all(r.map(e=>fetchClients(e)));for(let[e,n]of r.entries())a(c[e],`deletedClientsByService missing entry for service index`).forEach(e=>{C.registerSecret(e.clientSecret),o.deletes.push({name:e.name,request:{workspaceId:t,namespaceName:n,name:e.name},...!isDeletableName(e.name)&&{vaultOnly:!0}})});return o}function convertLang(e){switch(e){case`en`:return nn.EN;case`ja`:return nn.JA;default:return nn.UNSPECIFIED}}function convertGqlOperationsToDisable(e){if(e)return{create:e.create===!1,update:e.update===!1,delete:e.delete===!1,read:e.read===!1,sendPasswordResetEmail:e.sendPasswordResetEmail===!1,requestMfaSettingsUrl:e.requestMfaSettingsUrl===!1,unenrollMfa:e.unenrollMfa===!1}}function protoIdPPermission(e){return{create:e.create.map(e=>protoIdPPolicy(e)),read:e.read.map(e=>protoIdPPolicy(e)),update:e.update.map(e=>protoIdPPolicy(e)),delete:e.delete.map(e=>protoIdPPolicy(e)),sendPasswordResetEmail:e.sendPasswordResetEmail.map(e=>protoIdPPolicy(e)),unenrollMfa:e.unenrollMfa.map(e=>protoIdPPolicy(e))}}function protoIdPPolicy(e){let t;switch(e.permit){case`allow`:t=sr.ALLOW;break;case`deny`:t=sr.DENY;break;default:throw b(`Unknown permission: ${e.permit}`)}return{conditions:e.conditions.map(e=>protoIdPCondition(e)),permit:t,description:e.description}}function protoIdPCondition(e){let[t,n,r]=e,i=protoIdPOperand(t),a=protoIdPOperand(r),o;switch(n){case`eq`:o=ln.EQ;break;case`ne`:o=ln.NE;break;case`in`:o=ln.IN;break;case`nin`:o=ln.NIN;break;default:throw b(`Unknown operator: ${n}`)}return{left:i,operator:o,right:a}}function protoIdPOperand(e){if(typeof e==`object`&&!Array.isArray(e)){if(`user`in e)return{kind:{case:`userField`,value:e.user}};if(`idpUser`in e)return{kind:{case:`idpUserField`,value:e.idpUser}};if(`newIdpUser`in e)return{kind:{case:`newIdpUserField`,value:e.newIdpUser}};if(`oldIdpUser`in e)return{kind:{case:`oldIdpUserField`,value:e.oldIdpUser}};throw b(`Unknown operand: ${JSON.stringify(e)}`)}return{kind:{case:`value`,value:Zr(ci,e)}}}async function applyAuth(e,t,n=`create-update`){let{changeSet:r}=t;(n===`create-update-prerequisites`||n===`create-update`)&&(await(async()=>{await Promise.all([...r.service.creates.map(async t=>{await e.createAuthService(t.request),await writeMetadataLabels(e,t.metaRequest)}),...r.service.updates.map(async t=>{await e.updateAuthService(t.request),await writeMetadataLabels(e,t.metaRequest)})])})(),await(async()=>{await Promise.all([...r.machineUser.creates.map(async t=>{let n=await e.createAuthMachineUser(t.request);return n.machineUser?.clientSecret&&C.registerSecret(n.machineUser.clientSecret),n}),...r.machineUser.updates.map(async t=>{let n=await e.updateAuthMachineUser(t.request);return n.machineUser?.clientSecret&&C.registerSecret(n.machineUser.clientSecret),n})])})()),(n===`create-update-dependents`||n===`create-update`)&&await(async()=>{await applyAuthConnections(e,{changeSet:r.connection,stateScope:t.connectionStateScope},`create-update`),await Promise.all([...r.idpConfig.creates.map(async t=>(t.idpConfig.kind===`BuiltInIdP`&&(a(t.request.idpConfig,`request missing idpConfig`).config=await protoBuiltinIdPConfig(e,a(t.request.workspaceId,`request missing workspaceId`),t.idpConfig)),e.createAuthIDPConfig(t.request))),...r.idpConfig.updates.map(async t=>(t.idpConfig.kind===`BuiltInIdP`&&(a(t.request.idpConfig,`request missing idpConfig`).config=await protoBuiltinIdPConfig(e,a(t.request.workspaceId,`request missing workspaceId`),t.idpConfig)),e.updateAuthIDPConfig(t.request)))]),await Promise.all([...r.userProfileConfig.creates.map(t=>e.createUserProfileConfig(t.request)),...r.userProfileConfig.updates.map(t=>e.updateUserProfileConfig(t.request))]),await Promise.all([...r.tenantConfig.creates.map(t=>e.createTenantConfig(t.request)),...r.tenantConfig.updates.map(t=>e.updateTenantConfig(t.request))]),await Promise.all([...r.authHook.creates.map(t=>e.createAuthHook(t.request)),...r.authHook.updates.map(t=>e.updateAuthHook(t.request))]),await Promise.all([...r.oauth2Client.creates.map(async t=>{let n=a(t.request.oauth2Client,`request missing oauth2Client`);n.redirectUris=await jt(e,a(t.request.workspaceId,`request missing workspaceId`),n.redirectUris,`OAuth2 redirect URIs`);let r=await e.createAuthOAuth2Client(t.request);return r.oauth2Client?.clientSecret&&C.registerSecret(r.oauth2Client.clientSecret),r}),...r.oauth2Client.updates.map(async t=>{let n=a(t.request.oauth2Client,`request missing oauth2Client`);n.redirectUris=await jt(e,a(t.request.workspaceId,`request missing workspaceId`),n.redirectUris,`OAuth2 redirect URIs`);let r=await e.updateAuthOAuth2Client(t.request);return r.oauth2Client?.clientSecret&&C.registerSecret(r.oauth2Client.clientSecret),r})]);for(let t of r.oauth2Client.replaces){await e.deleteAuthOAuth2Client(t.deleteRequest);let n=a(t.createRequest.oauth2Client,`createRequest missing oauth2Client`);n.redirectUris=await jt(e,a(t.createRequest.workspaceId,`createRequest missing workspaceId`),n.redirectUris,`OAuth2 redirect URIs`);let r=await e.createAuthOAuth2Client(t.createRequest);r.oauth2Client?.clientSecret&&C.registerSecret(r.oauth2Client.clientSecret)}await Promise.all([...r.scim.creates.map(t=>e.createAuthSCIMConfig(t.request)),...r.scim.updates.map(t=>e.updateAuthSCIMConfig(t.request))]),await Promise.all([...r.scimResource.creates.map(t=>e.createAuthSCIMResource(t.request)),...r.scimResource.updates.map(t=>e.updateAuthSCIMResource(t.request))])})(),n===`delete-resources`?(await Promise.all(r.scimResource.deletes.map(t=>e.deleteAuthSCIMResource(t.request))),await Promise.all(r.scim.deletes.map(t=>e.deleteAuthSCIMConfig(t.request))),await Promise.all(r.oauth2Client.deletes.map(t=>e.deleteAuthOAuth2Client(t.request))),await Promise.all(r.authHook.deletes.map(t=>e.deleteAuthHook(t.request))),await Promise.all(r.machineUser.deletes.map(t=>e.deleteAuthMachineUser(t.request))),await Promise.all(r.tenantConfig.deletes.map(t=>e.deleteTenantConfig(t.request))),await(async()=>{await Promise.all(r.userProfileConfig.deletes.map(t=>e.deleteUserProfileConfig(t.request)))})(),await Promise.all(r.idpConfig.deletes.map(t=>e.deleteAuthIDPConfig(t.request))),await applyAuthConnections(e,{changeSet:r.connection,stateScope:t.connectionStateScope},`delete-resources`)):n===`delete-services`&&await Promise.all(r.service.deletes.map(t=>e.deleteAuthService(t.request)))}async function planAuth(e){let{client:t,workspaceId:n,application:r,forRemoval:i,forceApplyAll:a=!1}=e,o=[];!i&&r.authService&&(await r.authService.resolveNamespaces(),o.push(r.authService));let{changeSet:s,conflicts:c,unmanaged:l,resourceOwners:u}=await planServices$2(t,n,r.name,r.id,o,a),d=s.deletes.map(e=>e.name),f=expectedLocalStaticWebsiteNames(e),[p,m,h,g,_,v,y,b,x]=await Promise.all([planIdPConfigs(t,n,o,d,a),planUserProfileConfigs(t,n,o,d,a),planTenantConfigs(t,n,o,d,a),planMachineUsers(t,n,o,d,a),planAuthHooks(t,n,o,d,a),planOAuth2Clients(t,n,o,d,f,a),planSCIMConfigs(t,n,o,d),planSCIMResources(t,n,o,d),planAuthConnections(t,n,r.name,r.id,o)]);return{changeSet:{service:s,idpConfig:p,userProfileConfig:m,tenantConfig:h,machineUser:g,authHook:_,oauth2Client:v,scim:y,scimResource:b,connection:x.changeSet},conflicts:[...c,...x.conflicts],unmanaged:[...l,...x.unmanaged],resourceOwners:/* @__PURE__ */ new Set([...u,...x.resourceOwners]),connectionStateScope:x.stateScope}}async function planServices$2(e,t,n,r,i,a=!1){let o=createChangeSet(`Auth services`),s=createOwnershipTracker(n,r),c=await fetchExistingResourcesWithLabels({client:e,fetchPage:async(n,r)=>{let{authServices:i,nextPageToken:a}=await e.listAuthServices({workspaceId:t,pageToken:n,pageSize:r});return[i,a]},getName:e=>e.namespace?.name,getTrn:e=>resourceTrn(t,`auth`,e)});for(let e of i){let{config:i}=e,l=c[i.name],u=await buildMetaRequest({trn:resourceTrn(t,`auth`,i.name),appName:n,appId:r}),d={workspaceId:t,namespaceName:i.name,publishSessionEvents:i.publishSessionEvents};if(l){let e=s.ownsDesired(l.allLabels,{resourceType:`auth.service`,resourceLabel:`Auth service`,resourceName:i.name})&&l.resource.publishSessionEvents===(i.publishSessionEvents??!1);!a&&e?o.unchanged.push({name:i.name}):o.updates.push({name:i.name,request:d,metaRequest:u,...e&&{forcedBySdkVersion:!0}}),delete c[i.name]}else o.creates.push({name:i.name,request:d,metaRequest:u})}return Object.entries(c).forEach(([e])=>{let n=c[e];s.ownsRemaining(n?.allLabels)&&o.deletes.push({name:e,request:{workspaceId:t,namespaceName:e}})}),{changeSet:o,...s.result}}async function planIdPConfigs(e,t,n,r,i=!1){let a=createChangeSet(`Auth idpConfigs`),fetchIdPConfigs=n=>F(async(r,i)=>{let{idpConfigs:a,nextPageToken:o}=await e.listAuthIDPConfigs({workspaceId:t,namespaceName:n,pageToken:r,pageSize:i});return[a,o]});for(let r of n){let{config:n}=r,o=await fetchIdPConfigs(n.name),s=/* @__PURE__ */ new Map;o.forEach(e=>{s.set(e.name,e)});let c=n.idProvider;if(c){let r=protoIdPConfig(c),o=s.get(c.name);if(o){let l=await protoIdPConfigForComparison(e,t,c,r);if(!l){a.updates.push({name:c.name,idpConfig:c,request:{workspaceId:t,namespaceName:n.name,idpConfig:r}}),s.delete(c.name);continue}let u=areAuthIdPConfigsEqual(o,l);!i&&u?a.unchanged.push({name:c.name}):a.updates.push({name:c.name,idpConfig:c,request:{workspaceId:t,namespaceName:n.name,idpConfig:r},...u&&{forcedBySdkVersion:!0}}),s.delete(c.name)}else a.creates.push({name:c.name,idpConfig:c,request:{workspaceId:t,namespaceName:n.name,idpConfig:r}})}s.forEach((e,r)=>{a.deletes.push({name:r,request:{workspaceId:t,namespaceName:n.name,name:r}})})}for(let e of r)(await fetchIdPConfigs(e)).forEach(n=>{a.deletes.push({name:n.name,request:{workspaceId:t,namespaceName:e,name:n.name}})});return a}async function protoIdPConfigForComparison(e,t,n,r){if(n.kind!==`BuiltInIdP`)return r;let i=await tryProtoBuiltinIdPConfig(e,t,n);return i?{name:r.name,authType:r.authType,config:i}:void 0}function normalizeComparableAuthIdPConfig(e){return toComparableProtoJson(Qn,e)}function areAuthIdPConfigsEqual(e,t){return areNormalizedEqual(normalizeComparableAuthIdPConfig(e),normalizeComparableAuthIdPConfig(t))}function protoIdPConfig(e){switch(e.kind){case`IDToken`:return{name:e.name,authType:dn.ID_TOKEN,config:{config:{case:`idToken`,value:{providerUrl:e.providerURL,clientId:e.clientID,issuerUrl:e.issuerURL,usernameClaim:e.usernameClaim}}}};case`SAML`:return{name:e.name,authType:dn.SAML,config:{config:{case:`saml`,value:{...e.metadataURL===void 0?{rawMetadata:a(e.rawMetadata,`SAML config missing rawMetadata`)}:{metadataUrl:e.metadataURL},enableSignRequest:e.enableSignRequest,defaultRedirectUrl:e.defaultRedirectURL}}}};case`OIDC`:return{name:e.name,authType:dn.OIDC,config:{config:{case:`oidc`,value:{clientIdKey:e.clientID,clientSecretKey:{vaultName:e.clientSecret.vaultName,secretKey:e.clientSecret.secretKey},providerUrl:e.providerURL,issuerUrl:e.issuerURL,usernameClaim:e.usernameClaim}}}};case`BuiltInIdP`:return{name:e.name,authType:dn.OIDC,config:{}};default:throw b(`Unexpected idp kind: ${e}`)}}async function protoBuiltinIdPConfig(e,t,n){let r=await tryProtoBuiltinIdPConfig(e,t,n);if(!r)throw E({code:`IDP_NOT_FOUND`,message:`Built-in IdP "${n.namespace}" not found.`,suggestion:`Ensure that idp is configured correctly.`});return r}async function tryProtoBuiltinIdPConfig(e,t,n){let r=await P(async()=>await e.getIdPService({workspaceId:t,namespaceName:n.namespace}));if(!r)return;let i=await P(async()=>await e.getIdPClient({workspaceId:t,namespaceName:n.namespace,name:n.clientName}));if(!i)return;let a=idpClientVaultName(n.namespace,n.clientName),o=idpClientSecretName(n.namespace,n.clientName);return{config:{case:`oidc`,value:{clientIdKey:i.client?.clientId,clientSecretKey:{vaultName:a,secretKey:o},providerUrl:r.idpService?.providerUrl,usernameClaim:`name`}}}}async function planUserProfileConfigs(e,t,n,r,i=!1){let a=createChangeSet(`Auth userProfileConfigs`);for(let r of n){let{config:n}=r,o=`${n.name}-user-profile-config`,s=await P(async()=>await e.getUserProfileConfig({workspaceId:t,namespaceName:n.name}));if(!s){let e=r.userProfile;e&&a.creates.push({name:o,request:{workspaceId:t,namespaceName:n.name,userProfileProviderConfig:protoUserProfileConfig(e)}});continue}let c=r.userProfile;if(c){let e=protoUserProfileConfig(c),r=areUserProfileConfigsEqual(s.userProfileProviderConfig??{},e);!i&&r?a.unchanged.push({name:o}):a.updates.push({name:o,request:{workspaceId:t,namespaceName:n.name,userProfileProviderConfig:e},...r&&{forcedBySdkVersion:!0}})}else a.deletes.push({name:o,request:{workspaceId:t,namespaceName:n.name}})}for(let n of r)await P(async()=>await e.getUserProfileConfig({workspaceId:t,namespaceName:n}))&&a.deletes.push({name:`${n}-user-profile-config`,request:{workspaceId:t,namespaceName:n}});return a}function protoUserProfileConfig(e){let t=e.attributes?Object.fromEntries(Object.keys(e.attributes).map(e=>[e,e])):void 0;return{providerType:kn.TAILORDB,config:{config:{case:`tailordb`,value:{namespace:e.namespace,type:e.type.name,usernameField:e.usernameField,tenantIdField:void 0,attributesFields:e.attributeList,attributeMap:t}}}}}async function planTenantConfigs(e,t,n,r,i=!1){let a=createChangeSet(`Auth tenantConfigs`);for(let r of n){let{config:n}=r,o=`${n.name}-tenant-config`,s=await P(async()=>await e.getTenantConfig({workspaceId:t,namespaceName:n.name}));if(!s)n.tenantProvider&&a.creates.push({name:o,request:{workspaceId:t,namespaceName:n.name,tenantProviderConfig:protoTenantConfig(n.tenantProvider)}});else if(n.tenantProvider){let e=protoTenantConfig(n.tenantProvider),r=areTenantProviderConfigsEqual(s.tenantProviderConfig,e);!i&&r?a.unchanged.push({name:o}):a.updates.push({name:o,request:{workspaceId:t,namespaceName:n.name,tenantProviderConfig:e},...r&&{forcedBySdkVersion:!0}})}else a.deletes.push({name:o,request:{workspaceId:t,namespaceName:n.name}})}for(let n of r)await P(async()=>await e.getTenantConfig({workspaceId:t,namespaceName:n}))&&a.deletes.push({name:`${n}-tenant-config`,request:{workspaceId:t,namespaceName:n}});return a}function protoTenantConfig(e){return{providerType:an.TAILORDB,config:{config:{case:`tailordb`,value:{namespace:e.namespace,type:e.type,signatureField:e.signatureField}}}}}async function planMachineUsers(e,t,n,r,i=!1){let a=createChangeSet(`Auth machineUsers`);for(let r of n){let{config:n}=r,o=await Ft(e,t,n.name),s=/* @__PURE__ */ new Map;o.forEach(e=>{s.set(e.name,e),C.registerSecret(e.clientSecret)});for(let e of Object.keys(n.machineUsers??{})){let r=n.machineUsers?.[e];if(!r)continue;let o={attributes:r.attributeList,attributeMap:r.attributes?protoMachineUserAttributeMap(r.attributes):void 0},c=s.get(e);if(c){let l=areMachineUsersEqual(c,o);!i&&l?a.unchanged.push({name:e}):a.updates.push({name:e,request:{workspaceId:t,authNamespace:n.name,name:e,attributes:r.attributeList,attributeMap:o.attributeMap},...l&&{forcedBySdkVersion:!0}}),s.delete(e)}else a.creates.push({name:e,request:{workspaceId:t,authNamespace:n.name,name:e,attributes:r.attributeList,attributeMap:o.attributeMap}})}s.forEach((e,r)=>{a.deletes.push({name:r,request:{workspaceId:t,authNamespace:n.name,name:r}})})}for(let n of r)(await Ft(e,t,n)).forEach(e=>{C.registerSecret(e.clientSecret),a.deletes.push({name:e.name,request:{workspaceId:t,authNamespace:n,name:e.name}})});return a}function protoMachineUserAttributeMap(e){let t={};for(let[n,r]of Object.entries(e))t[n]=Zr(ci,r??null);return t}function normalizeComparableUserProfileConfig(e){let t=e.config?.config,n=t?.case===`tailordb`?t.value:void 0;return toComparableProtoJson(Dn,{providerType:e.providerType,config:n?{config:{case:`tailordb`,value:{...n,tenantIdField:n.tenantIdField||``,attributesFields:normalizeStringArray(n.attributesFields),attributeMap:normalizeProtoConfig(n.attributeMap??{})}}}:void 0})}function areUserProfileConfigsEqual(e,t){return areNormalizedEqual(normalizeComparableUserProfileConfig(e),normalizeComparableUserProfileConfig(t))}function normalizeComparableTenantProviderConfig(e){return toComparableProtoJson(On,e??{})}function areTenantProviderConfigsEqual(e,t){return areNormalizedEqual(normalizeComparableTenantProviderConfig(e),normalizeComparableTenantProviderConfig(t))}function normalizeComparableMachineUser(e){return normalizeProtoConfig({attributes:normalizeStringArray(e.attributes),attributeMap:normalizeProtoConfig(e.attributeMap??{})})}function areMachineUsersEqual(e,t){return areNormalizedEqual(normalizeComparableMachineUser(e),normalizeComparableMachineUser(t))}function normalizeComparableOAuth2Client(e){let t=oauth2LifetimeToSeconds(e.accessTokenLifetime),n=oauth2LifetimeToSeconds(e.refreshTokenLifetime);return normalizeProtoConfig({...e,description:e.description||void 0,redirectUris:normalizeStringArray(e.redirectUris),grantTypes:(e.grantTypes??[]).toSorted((e,t)=>e-t),accessTokenLifetime:t??86400,refreshTokenLifetime:n??604800,requireDpop:e.requireDpop??!1})}function oauth2LifetimeToSeconds(e){if(typeof e==`number`)return e;if(e?.seconds!=null)return Number(e.seconds)}function areOAuth2ClientsEqual(e,t){return areNormalizedEqual(normalizeComparableOAuth2Client(e),normalizeComparableOAuth2Client(t))}async function planOAuth2Clients(e,t,n,r,i,o=!1){let s=createChangeSet(`Auth oauth2Clients`),fetchOAuth2Clients=n=>F(async(r,i)=>{let{oauth2Clients:a,nextPageToken:o}=await e.listAuthOAuth2Clients({workspaceId:t,namespaceName:n,pageToken:r,pageSize:i});return[a,o]});for(let r of n){let{config:n}=r,c=await fetchOAuth2Clients(n.name),l=/* @__PURE__ */ new Map;c.forEach(e=>{l.set(e.name,e),C.registerSecret(e.clientSecret)});for(let r of Object.keys(n.oauth2Clients??{})){let c=n.oauth2Clients?.[r];if(!c)continue;let u=protoOAuth2Client(r,c),d=await jt(e,t,u.redirectUris??[],`OAuth2 redirect URIs`,{expectedLocalNames:i});if(l.has(r)){let e=a(l.get(r),`existingClientsMap missing entry for oauth2ClientName`);if(e.clientType!==u.clientType)s.replaces.push({name:r,deleteRequest:{workspaceId:t,namespaceName:n.name,name:r},createRequest:{workspaceId:t,namespaceName:n.name,oauth2Client:u}});else{let i={...u,redirectUris:d,accessTokenLifetime:oauth2LifetimeToSeconds(u.accessTokenLifetime),refreshTokenLifetime:oauth2LifetimeToSeconds(u.refreshTokenLifetime)},a=areOAuth2ClientsEqual({name:e.name,description:e.description,grantTypes:e.grantTypes,redirectUris:e.redirectUris,clientType:e.clientType,accessTokenLifetime:oauth2LifetimeToSeconds(e.accessTokenLifetime),refreshTokenLifetime:oauth2LifetimeToSeconds(e.refreshTokenLifetime),requireDpop:e.requireDpop},i);!o&&a?s.unchanged.push({name:r}):s.updates.push({name:r,request:{workspaceId:t,namespaceName:n.name,oauth2Client:u},...a&&{forcedBySdkVersion:!0}})}l.delete(r)}else s.creates.push({name:r,request:{workspaceId:t,namespaceName:n.name,oauth2Client:u}})}l.forEach((e,r)=>{s.deletes.push({name:r,request:{workspaceId:t,namespaceName:n.name,name:r}})})}for(let e of r)(await fetchOAuth2Clients(e)).forEach(n=>{C.registerSecret(n.clientSecret),s.deletes.push({name:n.name,request:{workspaceId:t,namespaceName:e,name:n.name}})});return s}function protoOAuth2Client(e,t){return{name:e,description:t.description,grantTypes:t.grantTypes.map(e=>{switch(e){case`authorization_code`:return tn.AUTHORIZATION_CODE;case`refresh_token`:return tn.REFRESH_TOKEN;default:throw b(`Unknown OAuth2 client grant type: ${e}`)}}),redirectUris:t.redirectURIs,clientType:{confidential:_n.CONFIDENTIAL,public:_n.PUBLIC,browser:_n.BROWSER}[t.clientType??`confidential`],accessTokenLifetime:t.accessTokenLifetimeSeconds,refreshTokenLifetime:t.refreshTokenLifetimeSeconds,requireDpop:t.requireDpop}}async function planSCIMConfigs(e,t,n,r){let i=createChangeSet(`Auth scimConfigs`);for(let r of n){let{config:n}=r,a=`${n.name}-scim-config`;await P(async()=>await e.getAuthSCIMConfig({workspaceId:t,namespaceName:n.name}))?n.scim?i.updates.push({name:a,request:{workspaceId:t,namespaceName:n.name,scimConfig:protoSCIMConfig(n.scim)}}):i.deletes.push({name:a,request:{workspaceId:t,namespaceName:n.name}}):n.scim&&i.creates.push({name:a,request:{workspaceId:t,namespaceName:n.name,scimConfig:protoSCIMConfig(n.scim)}})}for(let n of r)await P(async()=>await e.getAuthSCIMConfig({workspaceId:t,namespaceName:n}))&&i.deletes.push({name:`${n}-scim-config`,request:{workspaceId:t,namespaceName:n}});return i}function protoSCIMConfig(e){let t;switch(e.authorization.type){case`bearer`:t=Tr.BEARER;break;case`oauth2`:t=Tr.OAUTH2;break;default:throw b(`Unknown SCIM authorization type: ${e.authorization.type}`)}return{machineUserName:e.machineUserName,authorizationType:t,authorizationConfig:{case:`bearerSecret`,value:{vaultName:e.authorization.bearerSecret?.vaultName,secretKey:e.authorization.bearerSecret?.secretKey}}}}async function planSCIMResources(e,t,n,r){let i=createChangeSet(`Auth scimResources`),fetchSCIMResources=async n=>await P(async()=>{let{scimResources:r}=await e.getAuthSCIMResources({workspaceId:t,namespaceName:n});return r})??[];for(let e of n){let{config:n}=e,r=await fetchSCIMResources(n.name),a=/* @__PURE__ */ new Set;r.forEach(e=>{a.add(e.name)});for(let e of n.scim?.resources??[])a.has(e.name)?(i.updates.push({name:e.name,request:{workspaceId:t,namespaceName:n.name,scimResource:protoSCIMResource(e)}}),a.delete(e.name)):i.creates.push({name:e.name,request:{workspaceId:t,namespaceName:n.name,scimResource:protoSCIMResource(e)}});a.forEach(e=>{i.deletes.push({name:e,request:{workspaceId:t,namespaceName:n.name,name:e}})})}for(let e of r)(await fetchSCIMResources(e)).forEach(n=>{i.deletes.push({name:n.name,request:{workspaceId:t,namespaceName:e,name:n.name}})});return i}function protoSCIMResource(e){return{name:e.name,tailorDbNamespace:e.tailorDBNamespace,tailorDbType:e.tailorDBType,coreSchema:{name:e.coreSchema.name,attributes:e.coreSchema.attributes.map(e=>protoSCIMAttribute(e))},attributeMapping:e.attributeMapping.map(e=>({tailorDbField:e.tailorDBField,scimPath:e.scimPath}))}}function protoSCIMAttribute(e){let t;switch(e.type){case`string`:t=un.STRING;break;case`number`:t=un.NUMBER;break;case`boolean`:t=un.BOOLEAN;break;case`datetime`:t=un.DATETIME;break;case`complex`:t=un.COMPLEX;break;default:throw b(`Unknown SCIM attribute type: ${e.type}`)}let n;if(e.mutability)switch(e.mutability){case`readOnly`:n=sn.READ_ONLY;break;case`readWrite`:n=sn.READ_WRITE;break;case`writeOnly`:n=sn.WRITE_ONLY;break;default:throw b(`Unknown SCIM attribute mutability: ${e.mutability}`)}let r;if(e.uniqueness)switch(e.uniqueness){case`none`:r=xn.NONE;break;case`server`:r=xn.SERVER;break;case`global`:r=xn.GLOBAL;break;default:throw b(`Unknown SCIM attribute uniqueness: ${e.uniqueness}`)}return{type:t,name:e.name,description:e.description,mutability:n,required:e.required,multiValued:e.multiValued,uniqueness:r,canonicalValues:e.canonicalValues??void 0,subAttributes:e.subAttributes?.map(e=>protoSCIMAttribute(e))}}function areAuthHooksEqual(e,t){return areNormalizedEqual({scriptRef:e.scriptRef??``,invoker:e.invoker?{namespace:e.invoker.namespace??``,machineUserName:e.invoker.machineUserName??``}:void 0},{scriptRef:t.scriptRef??``,invoker:t.invoker?{namespace:t.invoker.namespace??``,machineUserName:t.invoker.machineUserName??``}:void 0})}function formatAuthHookChangeEntries(e,t){return formatChangeEntriesWithFunctionRegistry(`authHook`,e,t,e=>{let[t,n]=e.name.split(`/`);return t&&n?[authHookFunctionName(t,n)]:[]},{getNamespace:e=>e.name.split(`/`)[0],getDisplayName:e=>e.name.split(`/`)[1]??e.name})}async function planAuthHooks(e,t,n,r,i=!1){let a=createChangeSet(`Auth hooks`);for(let r of n){let{config:n}=r,o=n.hooks?.beforeLogin,s=await P(async()=>{let{hook:r}=await e.getAuthHook({workspaceId:t,namespaceName:n.name,hookPoint:Jt.BEFORE_LOGIN});return r});if(o){let e={workspaceId:t,namespaceName:n.name,hook:{hookPoint:Jt.BEFORE_LOGIN,scriptRef:authHookFunctionName(n.name,`before-login`),invoker:{namespace:n.name,machineUserName:o.invoker}}};if(s){let t=areAuthHooksEqual(s,e.hook);!i&&t?a.unchanged.push({name:`${n.name}/before-login`}):a.updates.push({name:`${n.name}/before-login`,request:e,...t&&{forcedBySdkVersion:!0}})}else a.creates.push({name:`${n.name}/before-login`,request:e})}else s&&a.deletes.push({name:`${n.name}/before-login`,request:{workspaceId:t,namespaceName:n.name,hookPoint:Jt.BEFORE_LOGIN}})}for(let n of r)await P(async()=>await e.getAuthHook({workspaceId:t,namespaceName:n,hookPoint:Jt.BEFORE_LOGIN}))&&a.deletes.push({name:`${n}/before-login`,request:{workspaceId:t,namespaceName:n,hookPoint:Jt.BEFORE_LOGIN}});return a}function normalizeInvoker(e,t,n,r){if(e!==void 0){if(typeof e==`string`){if(!t)throw E({code:`INVOKER_AUTH_REQUIRED`,message:`${n} uses a string invoker ("${e}"), but no Auth service is configured.`,suggestion:`Configure an Auth service before using invoker.`});if(r&&!r.has(e)){let i=[...r].toSorted();throw E({code:`INVOKER_MACHINE_USER_NOT_FOUND`,message:`${n} uses invoker "${e}", but Auth service "${t}" has no machine user with that name.`,suggestion:i.length?`Use one of the existing machine users: ${i.join(`, `)}.`:`Define the machine user in Auth service "${t}" before using it as invoker.`,context:{invoker:e,authNamespace:t,machineUsers:i}})}return{namespace:t,machineUserName:e}}return e}}async function listInvokerMachineUsers(e){let{client:t,workspaceId:n,application:r,plannedMachineUsers:i}=e,a=nt(r);if(!a)return;let o=i?.get(a);if(o)return o;let s=await Ft(t,n,a);return new Set(s.map(e=>e.name))}async function applyExecutor(e,t,n=`create-update`){let{changeSet:r}=t;n===`create-update`?await Promise.all([...r.creates.map(async t=>{await e.createExecutorExecutor(t.request),await writeMetadataLabels(e,t.metaRequest)}),...r.updates.map(async t=>{await e.updateExecutorExecutor(t.request),await writeMetadataLabels(e,t.metaRequest)})]):await Promise.all(r.deletes.map(t=>e.deleteExecutorExecutor(t.request)))}async function planExecutor(e,t){let{client:n,workspaceId:r,application:i,forRemoval:a}=e,o=createChangeSet(`Executors`),s=createOwnershipTracker(i.name,i.id),c=t??await fetchExistingResourcesWithLabels({client:n,fetchPage:async(e,t)=>{let{executors:i,nextPageToken:a}=await n.listExecutorExecutors({workspaceId:r,pageToken:e,pageSize:t});return[i,a]},getName:e=>e.name,getTrn:e=>resourceTrn(r,`executor`,e)}),l={...c},u=a?{}:await i.executorService?.loadExecutors()??{},d=Object.values(u).some(e=>`invoker`in e.operation&&typeof e.operation.invoker==`string`)?await listInvokerMachineUsers({client:n,workspaceId:r,application:i,plannedMachineUsers:e.plannedMachineUsers}):void 0;for(let t of Object.values(u)){let n=l[t.name],a=await buildMetaRequest({trn:resourceTrn(r,`executor`,t.name),appName:i.name,appId:i.id}),c=protoExecutor(e,t,i.env,d);if(n){let e=s.ownsDesired(n.allLabels,{resourceType:`executor`,resourceLabel:`Executor`,resourceName:t.name})&&areExecutorsEqual(n.resource,c);e&&hasMatchingSdkVersion(n.allLabels,a.labels)?o.unchanged.push({name:t.name}):o.updates.push({name:t.name,request:{workspaceId:r,executor:c},metaRequest:a,...e&&{forcedBySdkVersion:!0}}),delete l[t.name]}else o.creates.push({name:t.name,request:{workspaceId:r,executor:c},metaRequest:a})}return Object.entries(l).forEach(([e])=>{let t=l[e];s.ownsRemaining(t?.allLabels)&&o.deletes.push({name:e,request:{workspaceId:r,name:e}})}),{changeSet:o,...s.result,existingExecutors:c}}function isFunctionBackedExecutor(e){return e?.targetType===I.FUNCTION||e?.targetType===I.JOB_FUNCTION}function buildPlannedExecutorsByName(e){return Object.fromEntries([...e.creates,...e.updates].map(e=>[e.name,e.request.executor]))}function formatExecutorChangeEntries(e,t,n){return formatChangeEntriesWithFunctionRegistry(`executor`,e,n,(e,n)=>{if(n===`delete`)return[executorFunctionName(e.name)];let r=t[e.name];return r&&isFunctionBackedExecutor(r)?[executorFunctionName(e.name)]:[]})}function normalizeComparableExecutor(e){let t=normalizeProtoConfig(e),n=t.targetConfig?.config?.case===`webhook`?(t.targetConfig.config.value.headers??[]).toSorted((e,t)=>(e.key??``).localeCompare(t.key??``)):void 0,r=t.triggerConfig?.config?.case===`incomingWebhook`?{...t.triggerConfig,config:{...t.triggerConfig.config,value:{...t.triggerConfig.config.value,secret:void 0}}}:t.triggerConfig?.config?.case===`event`?{...t.triggerConfig,config:{...t.triggerConfig.config,value:{...t.triggerConfig.config.value,eventType:void 0}}}:t.triggerConfig,i=normalizeProtoConfig({name:t.name,description:t.description??``,disabled:t.disabled??!1,triggerType:t.triggerType,triggerConfig:r,targetType:t.targetType,targetConfig:t.targetConfig?.config?.case===`webhook`?{...t.targetConfig,config:{...t.targetConfig.config,value:{...t.targetConfig.config.value,headers:n}}}:t.targetConfig?.config?.case===`function`?{...t.targetConfig,config:{...t.targetConfig.config,value:{...t.targetConfig.config.value,script:void 0}}}:t.targetConfig});return toComparableProtoJson(lr,i)}function areExecutorsEqual(e,t){return areNormalizedEqual(normalizeComparableExecutor(e),normalizeComparableExecutor(t))}function resolveSameRunNamespace(e,t,n){if(!e?.has(t))return;let r=e.get(t);if(!r)throw E({code:`DEPLOY_RESOURCE_NAMESPACE_AMBIGUOUS`,message:`${n} "${t}" is defined in multiple namespaces in this deploy run. Move the trigger to the application that owns it or use unique names.`});return r}function findTailorDBNamespace(e,t){return e.tailorDBServices.find(e=>Object.hasOwn(e.types,t))?.namespace}function findResolverNamespace(e,t){return e.resolverServices.find(e=>Object.values(e.resolvers).some(e=>e.name===t))?.namespace}function resolveNamespace(e){let{resourceLabel:t,resourceName:n,localNamespaces:r,findLocalNamespace:i,sameRunNamespaces:a}=e,o=i();if(o!==void 0)return o;let s=resolveSameRunNamespace(a,n,t);if(s!==void 0)return s;let c=a?[...new Set([...a.values()].filter(e=>e!==void 0))]:[],l=[...r,...c];throw E({code:`DEPLOY_RESOURCE_NOT_FOUND`,message:`${t} "${n}" not found in any namespace. Available namespaces: ${l.join(`, `)}`})}function resolveTailorDBNamespace(e,t,n){return resolveNamespace({resourceLabel:`TailorDB table`,resourceName:t,localNamespaces:e.tailorDBServices.map(e=>e.namespace),findLocalNamespace:()=>findTailorDBNamespace(e,t),sameRunNamespaces:n})}function resolveResolverNamespace(e,t,n){return resolveNamespace({resourceLabel:`Resolver`,resourceName:t,localNamespaces:e.resolverServices.map(e=>e.namespace),findLocalNamespace:()=>findResolverNamespace(e,t),sameRunNamespaces:n})}function collectApplicationIdpNames(e){let t=new Set(e.idpServices.map(e=>e.name));for(let n of e.subgraphs)n.Type===`idp`&&t.add(n.Name);return t}function resolveIdpNamespace(e,t,n,r){let i=collectApplicationIdpNames(e);if(n!==void 0){let e=r??i;if(!e.has(n)){let r=[...e].join(`, `);throw E({code:`EXECUTOR_IDP_NOT_FOUND`,message:`Executor "${t}" specifies IdP "${n}" in its idpUser trigger, but no IdP with that name is configured. Available IdPs: ${r}`})}return n}if(i.size===0)throw E({code:`EXECUTOR_IDP_REQUIRED`,message:`Executor "${t}" uses an idpUser trigger but no IdP is configured.`});if(i.size>1){let e=[...i].join(`, `);throw E({code:`EXECUTOR_IDP_AMBIGUOUS`,message:`Executor "${t}" uses an idpUser trigger but the project defines multiple IdPs (${e}). Specify which IdP to subscribe to via the trigger's "idp" option.`})}return a([...i][0],`idp service missing`)}function protoExecutor(e,t,n,r){let{application:i}=e,a=i.name,o=t.trigger,s,c,l=qe(o.kind,n);function typedEventTrigger(e){return{config:{case:`event`,value:{typedConfig:e}}}}switch(o.kind){case`schedule`:s=ir.SCHEDULE,c={config:{case:`schedule`,value:{timezone:o.timezone,frequency:o.cron}}};break;case`tailordb`:s=ir.EVENT,c=typedEventTrigger({case:`tailordb`,value:{eventTypes:o.events,namespaceName:resolveTailorDBNamespace(i,o.tableName,e.tailorDBTypeNamespaces),typeName:o.tableName,...o.condition?{condition:{expr:`(${ct(o.condition)})(${l})`}}:{}}});break;case`resolverExecuted`:s=ir.EVENT,c=typedEventTrigger({case:`pipeline`,value:{eventTypes:[`pipeline.resolver.executed`],namespaceName:resolveResolverNamespace(i,o.resolverName,e.resolverNamespaces),resolverName:o.resolverName,...o.condition?{condition:{expr:`(${ct(o.condition)})(${l})`}}:{}}});break;case`incomingWebhook`:s=ir.INCOMING_WEBHOOK,c={config:{case:`incomingWebhook`,value:o.response?{response:{...o.response.body?{body:{expr:`(${ct(o.response.body)})(${l})`}}:{},...o.response.statusCode==null?{}:{statusCode:o.response.statusCode}}}:{}}};break;case`idpUser`:s=ir.EVENT,c=typedEventTrigger({case:`idp`,value:{eventTypes:o.events,namespaceName:resolveIdpNamespace(i,t.name,o.idp,e.idpNames)}});break;case`authAccessToken`:s=ir.EVENT,c=typedEventTrigger({case:`auth`,value:{eventTypes:o.events,namespaceName:it(i)}});break;case`workflowExecution`:case`workflowJobExecution`:s=ir.EVENT,c=typedEventTrigger({case:`workflow`,value:{eventTypes:o.events,workflowName:o.workflowName,...o.condition?{condition:{expr:`(${ct(o.condition)})(${l})`}}:{}}});break;default:throw b(`Unknown trigger: ${o}`)}let u=t.operation,d,f,p=nt(i),m=`Executor "${t.name}"`;switch(u.kind){case`webhook`:d=I.WEBHOOK,f={config:{case:`webhook`,value:{url:{expr:`(${ct(u.url)})(${l})`},headers:u.headers?Object.entries(u.headers).map(([e,t])=>{let n;return n=typeof t==`string`?{case:`rawValue`,value:t}:{case:`secretValue`,value:{vaultName:t.vault,secretKey:t.key}},{key:e,value:n}}):void 0,body:u.requestBody?{expr:`(${ct(u.requestBody)})(${l})`}:void 0}}};break;case`graphql`:d=I.TAILOR_GRAPHQL,f={config:{case:`tailorGraphql`,value:{appName:u.appName??a,query:u.query,variables:u.variables?{expr:`(${ct(u.variables)})(${l})`}:void 0,invoker:normalizeInvoker(u.invoker,p,m,r)}}};break;case`function`:case`jobFunction`:d=u.kind===`function`?I.FUNCTION:I.JOB_FUNCTION,f={config:{case:`function`,value:{name:`operation`,scriptRef:executorFunctionName(t.name),variables:{expr:l},invoker:normalizeInvoker(u.invoker,p,m,r)}}};break;case`workflow`:d=I.WORKFLOW,f={config:{case:`workflow`,value:{workflowName:u.workflowName,variables:u.args===void 0?void 0:typeof u.args==`function`?{expr:`(${ct(u.args)})(${l})`}:{expr:JSON.stringify(u.args)},invoker:normalizeInvoker(u.invoker,p,m,r)}}};break;default:throw b(`Unknown target: ${u}`)}return{name:t.name,description:t.description,disabled:t.disabled,triggerType:s,triggerConfig:c,targetType:d,targetConfig:f}}const Oa={uuid:{kind:`ScalarType`,name:`ID`},string:{kind:`ScalarType`,name:`String`},integer:{kind:`ScalarType`,name:`Int`},float:{kind:`ScalarType`,name:`Float`},decimal:{kind:`CustomScalarType`,name:`Decimal`},boolean:{kind:`ScalarType`,name:`Boolean`},date:{kind:`CustomScalarType`,name:`Date`},datetime:{kind:`CustomScalarType`,name:`DateTime`},time:{kind:`CustomScalarType`,name:`Time`}};async function applyPipeline(e,t,n=`create-update`){let{changeSet:r}=t;n===`create-update`?(await Promise.all([...r.service.creates.map(async t=>{await e.createPipelineService(t.request),await writeMetadataLabels(e,t.metaRequest)}),...r.service.updates.map(async t=>{await e.updatePipelineService(t.request),await writeMetadataLabels(e,t.metaRequest)})]),await Promise.all([...r.resolver.creates.map(async t=>{await e.createPipelineResolver(t.request),await writeMetadataLabels(e,t.metaRequest)}),...r.resolver.updates.map(async t=>{await e.updatePipelineResolver(t.request),await writeMetadataLabels(e,t.metaRequest)}),...r.resolver.unchanged.flatMap(t=>t.metaRequest?[writeMetadataLabels(e,t.metaRequest)]:[])])):n===`delete-resources`?await Promise.all(r.resolver.deletes.map(t=>e.deletePipelineResolver(t.request))):await Promise.all(r.service.deletes.map(t=>e.deletePipelineService(t.request)))}async function planPipeline(e,t){let{client:n,workspaceId:r,application:i,forRemoval:a,forceApplyAll:o=!1}=e,s=[];if(!a)for(let e of i.resolverServices)await e.loadResolvers(),s.push(e);let c=a?[]:Object.values(await i.executorService?.loadExecutors()??{}),{changeSet:l,conflicts:u,unmanaged:d,resourceOwners:f,existingServices:p}=await planServices$1(n,r,i.name,i.id,s,t?.existingServices),m=l.deletes.map(e=>e.name),h=s.some(e=>Object.values(e.resolvers).some(e=>typeof e.invoker==`string`))?await listInvokerMachineUsers({client:n,workspaceId:r,application:i,plannedMachineUsers:e.plannedMachineUsers}):void 0,{changeSet:g,existingResolversByNamespace:_}=await planResolvers(n,r,s,c,e.executorUsedResolvers??/* @__PURE__ */ new Set,m,i.env,nt(i),h,o,{appName:i.name,appId:i.id,dependentApps:e.dependentApps,runAppIds:e.runAppIds},t?.existingResolvers);return{changeSet:{service:l,resolver:g},conflicts:u,unmanaged:d,resourceOwners:f,existingServices:p,existingResolvers:_}}async function planServices$1(e,t,n,r,i,a){let o=createChangeSet(`Pipeline services`),s=createOwnershipTracker(n,r),c=a??await fetchExistingResourcesWithLabels({client:e,fetchPage:async(n,r)=>{let{pipelineServices:i,nextPageToken:a}=await e.listPipelineServices({workspaceId:t,pageToken:n,pageSize:r});return[i,a]},getName:e=>e.namespace?.name,getTrn:e=>resourceTrn(t,`pipeline`,e)}),l={...c};for(let e of i){let i=l[e.namespace],a=await buildMetaRequest({trn:resourceTrn(t,`pipeline`,e.namespace),appName:n,appId:r});if(i){let n=s.ownsDesired(i.allLabels,{resourceType:`pipeline.service`,resourceLabel:`Pipeline service`,resourceName:e.namespace});n&&hasMatchingSdkVersion(i.allLabels,a.labels)?o.unchanged.push({name:e.namespace}):o.updates.push({name:e.namespace,request:{workspaceId:t,namespaceName:e.namespace},metaRequest:a,...n&&{forcedBySdkVersion:!0}}),delete l[e.namespace]}else o.creates.push({name:e.namespace,request:{workspaceId:t,namespaceName:e.namespace},metaRequest:a})}return Object.entries(l).forEach(([e])=>{let n=l[e];s.ownsRemaining(n?.allLabels)&&o.deletes.push({name:e,request:{workspaceId:t,namespaceName:e}})}),{changeSet:o,...s.result,existingServices:c}}async function planResolvers(e,t,n,r,i,a,o,s,c,l=!1,u={},d){let f=createChangeSet(`Pipeline resolvers`),{appName:p,appId:m,dependentApps:h,runAppIds:g}=u,resolverMetaRequest=async(e,n)=>addDependencyRecords(await buildMetaRequest({trn:resolverTrn(t,e,n.name),appName:p??``,appId:m}),{key:Z.resolver(e,n.name),dependentApps:h,runAppIds:g,pinned:n.publishEvents!==void 0}),fetchResolvers=n=>{let r=d?.get(n);return r?Promise.resolve(r.existingResolvers):F(async(r,i)=>{let{pipelineResolvers:a,nextPageToken:o}=await e.listPipelineResolvers({workspaceId:t,namespaceName:n,pageToken:r,pageSize:i});return[a,o]})},_=/* @__PURE__ */ new Map,v=new Set(i);for(let e of r)subscribesToEvents(e)&&e.trigger.kind===`resolverExecuted`&&v.add(e.trigger.resolverName);for(let e of n)for(let t of Object.values(e.resolvers))assertNoPublishEventsConflict({explicit:t.publishEvents,subscribed:v.has(t.name),conflict:Ea.resolver(t.name)});for(let r of n){let n=await fetchResolvers(r.namespace),i=new Map(n.map(e=>[e.name,e])),a=d?.get(r.namespace)?.existingResolverDetails,u=/* @__PURE__ */ new Map;for(let n of Object.values(r.resolvers)){let d=processResolver(r.namespace,n,v,o,s,c),p=i.get(n.name),m=await resolverMetaRequest(r.namespace,n);if(p){let o=a?.has(n.name)?a.get(n.name):(await e.getPipelineResolver({workspaceId:t,namespaceName:r.namespace,resolverName:n.name})).pipelineResolver;u.set(n.name,o);let s=!!o&&areResolversEqual(o,d);!l&&s?f.unchanged.push({name:n.name,metaRequest:m}):f.updates.push({name:n.name,request:{workspaceId:t,namespaceName:r.namespace,pipelineResolver:d},metaRequest:m,...s&&{forcedBySdkVersion:!0}}),i.delete(n.name)}else f.creates.push({name:n.name,request:{workspaceId:t,namespaceName:r.namespace,pipelineResolver:d},metaRequest:m})}_.set(r.namespace,{existingResolvers:n,existingResolverDetails:u}),i.forEach((e,n)=>{f.deletes.push({name:n,request:{workspaceId:t,namespaceName:r.namespace,resolverName:n}})})}for(let e of a){let n=await fetchResolvers(e);n.forEach(n=>{f.deletes.push({name:n.name,request:{workspaceId:t,namespaceName:e,resolverName:n.name}})}),_.set(e,{existingResolvers:n,existingResolverDetails:d?.get(e)?.existingResolverDetails??/* @__PURE__ */ new Map})}return{changeSet:f,existingResolversByNamespace:_}}function formatResolverChangeEntries(e,t){return formatChangeEntriesWithFunctionRegistry(`resolver`,e,t,e=>{let t=e.request.namespaceName;return t?[resolverFunctionName(t,e.name)]:[]},{getNamespace:e=>e.request.namespaceName})}function normalizeComparableResolver(e){return toComparableProtoJson(bn,e)}function areResolversEqual(e,t){return areNormalizedEqual(normalizeComparableResolver(e),normalizeComparableResolver(t))}function processResolver(e,t,n,r,i,o){let s=[{name:`body`,operationName:`body`,description:`${t.name} function body`,operationType:wr.FUNCTION,operationSourceRef:resolverFunctionName(e,t.name),operationHook:{expr:Pe(r)},postScript:`args.body`,invoker:normalizeInvoker(t.invoker,i,`Resolver "${t.name}"`,o)}],c=Di.camelize(t.name),l=t.input?protoFields(t.input,`${c}Input`,!0):[],u=a(protoFields({"":t.output},`${c}Output`,!1)[0],`resolver output field missing`),d=t.description||`${t.name} resolver`,f=t.output.metadata.description,p=f?`${d}\n\nReturns:\n${f}`:d,m=resolvePublishEvents({explicit:t.publishEvents,subscribed:n.has(t.name),conflict:Ea.resolver(t.name)});return{authorization:`true==true`,description:p,inputs:l,name:t.name,operationType:t.operation,response:u,pipelines:s,publishExecutionEvents:m}}function protoFields(e,t,n){return Object.entries(e).map(([e,r])=>{let i,a=n&&r.metadata.hooks?.create!==void 0?!1:r.metadata.required??!0;if(r.type===`nested`){let o=r.metadata.typeName??`${t}${Di.camelize(e)}`;i={kind:`UserDefined`,name:o,description:r.metadata.description??``,required:a,fields:protoFields(r.fields,o,n)}}else i=r.type===`enum`?{kind:`EnumType`,name:r.metadata.typeName??`${t}${Di.camelize(e)}`,required:a,allowedValues:r.metadata.allowedValues}:{...Oa[r.type],required:a};return{name:e,description:r.metadata.description,array:r.metadata.array??!1,required:a,type:i}})}function vaultCreateRequest(e){return{workspaceId:e.workspaceId,secretmanagerVaultName:e.name}}function secretCreateRequest(e){return{workspaceId:e.workspaceId,secretmanagerVaultName:e.vaultName,secretmanagerSecretName:e.secretName,secretmanagerSecretValue:e.value}}function secretUpdateRequest(e){return{workspaceId:e.workspaceId,secretmanagerVaultName:e.vaultName,secretmanagerSecretName:e.secretName,secretmanagerSecretValue:e.value}}function collectIdPClientVaultNames(e){return new Set(e.flatMap(e=>e.clients.map(t=>idpClientVaultName(e.name,t))))}const ka=`tailor--`;function validateDeclaredVaultNames(e,t){for(let{vaultName:n}of e){if(t.has(n))throw E({code:`RESERVED_VAULT_NAME`,message:`Vault "${n}" has the name of the vault the SDK creates for an IdP client.`,suggestion:`Rename the vault in defineSecretManager(). If this application already manages a vault with that name, renaming it and removing the declaration both delete the old vault and its secrets on the next deploy, including the secret of an IdP client that already exists.`});n.startsWith(ka)&&C.warn(`Vault "${n}" starts with "${ka}", a prefix reserved for vaults the platform manages. In v3 this will be an error; rename the vault in defineSecretManager().`)}}async function planSecretManager(e){let{client:t,workspaceId:n,application:r,forRemoval:i,forceApplyAll:a=!1}=e,o=i?[]:r.secrets;validateDeclaredVaultNames(o,collectIdPClientVaultNames(r.idpServices));let s=createChangeSet(`Secret Manager vaults`),c=createChangeSet(`Secret Manager secrets`),l=createOwnershipTracker(r.name,r.id),u=await fetchExistingResourcesWithLabels({client:t,fetchPage:async(e,r)=>{let{vaults:i,nextPageToken:a}=await t.listSecretManagerVaults({workspaceId:n,pageToken:e,pageSize:r});return[i,a]},getName:e=>e.name,getTrn:e=>resourceTrn(n,`vault`,e)}),d={workspaceId:n,applicationId:r.id,applicationName:r.name},f=loadSecretsState(d),p=[];await Promise.all(o.map(async e=>{let i=e.vaultName,o=u[i];if(o){let e=await buildMetaRequest({trn:resourceTrn(n,`vault`,i),appName:r.name,appId:r.id}),t=l.ownsDesired(o.allLabels,{resourceType:`secret.vault`,resourceLabel:`Secret Manager vault`,resourceName:i});t&&hasMatchingSdkVersion(o.allLabels,e.labels)?s.unchanged.push({name:i}):s.updates.push({name:i,workspaceId:n,...t&&{forcedBySdkVersion:!0}}),delete u[i]}else s.creates.push({name:i,workspaceId:n});let d=/* @__PURE__ */ new Map;if(o){let e=await F(async(e,r)=>{let{secrets:a,nextPageToken:o}=await t.listSecretManagerSecrets({workspaceId:n,secretmanagerVaultName:i,pageToken:e,pageSize:r});return[a,o]});for(let t of e)d.set(t.name,serializeUpdateTime(t.updateTime))}let m=new Set(d.keys());for(let t of e.secrets)if(t.value==null)m.delete(t.name),p.push(`${i}/${t.name}`);else if(C.registerSecret(t.value),m.has(t.name)){let e=f.vaults[i]?.[t.name],r=d.get(t.name),o=e!==void 0&&e.hash===hashValue(t.value)&&e.updateTime!==void 0&&e.updateTime===r;(a||!o)&&c.updates.push({name:`${i}/${t.name}`,secretName:t.name,workspaceId:n,vaultName:i,value:t.value,...o&&{forcedBySdkVersion:!0}}),m.delete(t.name)}else c.creates.push({name:`${i}/${t.name}`,secretName:t.name,workspaceId:n,vaultName:i,value:t.value});for(let e of m)c.deletes.push({name:`${i}/${e}`,secretName:e,workspaceId:n,vaultName:i})}));for(let[e,r]of Object.entries(u))if(r&&l.ownsRemaining(r.allLabels)){let r=await F(async(r,i)=>{let{secrets:a,nextPageToken:o}=await t.listSecretManagerSecrets({workspaceId:n,secretmanagerVaultName:e,pageToken:r,pageSize:i});return[a,o]});for(let t of r)c.deletes.push({name:`${e}/${t.name}`,secretName:t.name,workspaceId:n,vaultName:e});s.deletes.push({name:e,workspaceId:n})}return{vaultChangeSet:s,secretChangeSet:c,skippedSecrets:p,...l.result,stateScope:d}}async function applySecretManager(e,t,n=`create-update`,r){let{vaultChangeSet:i,secretChangeSet:o,stateScope:s}=t;if(n===`create-update`){await Promise.all(i.creates.map(async t=>{await e.createSecretManagerVault(vaultCreateRequest(t)),r&&await writeMetadataLabels(e,await buildMetaRequest({trn:resourceTrn(t.workspaceId,`vault`,t.name),appName:r.name,appId:r.id}))})),r&&await Promise.all(i.updates.map(async t=>{await writeMetadataLabels(e,await buildMetaRequest({trn:resourceTrn(t.workspaceId,`vault`,t.name),appName:r.name,appId:r.id}))}));let t=[...o.creates,...o.updates];t.length>0&&await withSecretsStateLock(s,async()=>{let n=/* @__PURE__ */ new Map;if(await Promise.all(o.creates.map(async t=>{let r=await e.createSecretManagerSecret(secretCreateRequest(t));n.set(t.name,serializeUpdateTime(r.secret?.updateTime))})),await Promise.all(o.updates.map(async t=>{let r=await e.updateSecretManagerSecret(secretUpdateRequest(t));n.set(t.name,serializeUpdateTime(r.secret?.updateTime))})),r){let e=loadSecretsState(s);for(let r of t){Object.hasOwn(e.vaults,r.vaultName)||(e.vaults[r.vaultName]={});let t=n.get(r.name);a(e.vaults[r.vaultName],`vault state entry missing`)[r.secretName]={hash:hashValue(r.value),...t===void 0?{}:{updateTime:t}}}saveSecretsState(s,e)}})}else(o.deletes.length>0||i.deletes.length>0)&&await withSecretsStateLock(s,async()=>{await Promise.all(o.deletes.map(t=>e.deleteSecretManagerSecret({workspaceId:t.workspaceId,secretmanagerVaultName:t.vaultName,secretmanagerSecretName:t.secretName}))),await Promise.all(i.deletes.map(t=>e.deleteSecretManagerVault({workspaceId:t.workspaceId,secretmanagerVaultName:t.name})));let t=loadSecretsState(s);for(let e of o.deletes)Object.hasOwn(t.vaults,e.vaultName)&&(delete a(t.vaults[e.vaultName],`vault state entry missing`)[e.secretName],Object.keys(a(t.vaults[e.vaultName],`vault state entry missing`)).length===0&&delete t.vaults[e.vaultName]);for(let e of i.deletes)delete t.vaults[e.name];saveSecretsState(s,t)})}const Aa=[`array`,`index`,`unique`,`foreignKey`,`vector`,`optionalOnCreate`];function isSnapshotFieldRefOperand(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function getNestedMember(e,t){return t.reduce((e,t)=>e?.fields&&Object.hasOwn(e.fields,t)?e.fields[t]:void 0,e)}function collectNestedMemberChanges(e,t){return e.type===t.type?collectMemberChanges(e.fields??{},t.fields??{},[]):[]}function collectMemberChanges(e,t,n){let r=[],i=[],a=[];for(let[i,o]of Object.entries(e)){let e=[...n,i],s=Object.hasOwn(t,i)?t[i]:void 0;s?(o.type===s.type&&a.push(...collectMemberChanges(o.fields??{},s.fields??{},e)),areOwnFieldConfigsDifferent(o,s)&&a.push({kind:`modified`,path:e,before:o,after:s})):r.push({kind:`removed`,path:e,before:o})}for(let[r,a]of Object.entries(t))Object.hasOwn(e,r)||i.push({kind:`added`,path:[...n,r],after:a});return[...r,...i,...a]}function areOwnFieldConfigsDifferent(e,t){if(e.type!==t.type||e.required!==t.required)return!0;for(let n of Aa)if((e[n]??!1)!==(t[n]??!1))return!0;if(e.foreignKeyType!==t.foreignKeyType||e.foreignKeyField!==t.foreignKeyField||(e.description??``)!==(t.description??``))return!0;let n=e.allowedValues??[],r=t.allowedValues??[];if(n.length!==r.length)return!0;let i=new Map(r.map(e=>[e.value,e.description]));for(let e of n)if(!i.has(e.value)||(e.description??``)!==(i.get(e.value)??``))return!0;let o=e.hooks,s=t.hooks;if(!!o!=!!s||o&&s&&((o.create?.expr??``)!==(s.create?.expr??``)||(o.update?.expr??``)!==(s.update?.expr??``)))return!0;let c=e.validate??[],l=t.validate??[];if(c.length!==l.length)return!0;for(let e=0;e<c.length;e++){let t=a(c[e],`oldValidate missing index ${e}`),n=a(l[e],`newValidate missing index ${e}`);if((t.script?.expr??``)!==(n.script?.expr??``)||t.errorMessage!==n.errorMessage)return!0}let u=e.serial,d=t.serial;return!!(!!u!=!!d||u&&d&&(u.start!==d.start||u.maxValue!==d.maxValue||(u.format??``)!==(d.format??``)||(u.gapless??!1)!==(d.gapless??!1))||e.scale!==t.scale||e.default!==t.default&&(typeof e.default!=typeof t.default||JSON.stringify(e.default)!==JSON.stringify(t.default)))}function hasChanges(e){return e.changes.length>0}function formatMigrationDiff(e){if(e.changes.length===0)return`No schema differences detected.`;let t=[],n=/* @__PURE__ */ new Map;for(let t of e.changes){let e=n.get(t.tableName)??[];e.push(t),n.set(t.tableName,e)}for(let[r,i]of n){t.push(`${e.namespace}.${r}:`);for(let e of i)t.push(formatDiffChange(e))}return t.join(`
|
|
4
|
+
`)}function formatDiffChange(e){switch(e.kind){case`table_added`:return` + [Table] ${e.tableName} (new table)`;case`table_removed`:return` - [Table] ${e.tableName} (removed)`;case`table_renamed`:return` ~ [Table] ${e.previousTableName} → ${e.tableName} (renamed)`;case`table_modified`:return` ~ [Table] ${e.tableName}: ${e.reason}`;case`table_settings_modified`:return` ~ [Table Settings] ${e.tableName}: ${e.reason??`settings changed`}`;case`field_added`:{let t=formatFieldType(e.after);return` + ${e.fieldName}: ${t}`}case`field_removed`:return` - ${e.fieldName}: ${e.before.type}`;case`field_modified`:return` ~ ${e.fieldName}: ${formatFieldModification(e.before,e.after,e.memberRenames)}`;case`field_type_modified`:return` ~ ${e.fieldName}: ${formatFieldModification(e.before,e.after)}`;case`field_renamed`:return` ~ ${e.previousFieldName} → ${e.fieldName}: ${formatFieldType(e.after)} (renamed)`;case`index_added`:return` + [Index] ${e.indexName}`;case`index_removed`:return` - [Index] ${e.indexName}`;case`index_modified`:return` ~ [Index] ${e.indexName}: ${e.reason??`modified`}`;case`file_added`:return` + [File] ${e.fieldName}`;case`file_removed`:return` - [File] ${e.fieldName}`;case`file_modified`:return` ~ [File] ${e.fieldName}: ${e.reason??`modified`}`;case`relationship_added`:return` + [Relationship${e.relationshipType?` (${e.relationshipType})`:``}] ${e.relationshipName}`;case`relationship_removed`:return` - [Relationship${e.relationshipType?` (${e.relationshipType})`:``}] ${e.relationshipName}`;case`relationship_modified`:return` ~ [Relationship${e.relationshipType?` (${e.relationshipType})`:``}] ${e.relationshipName}: ${e.reason??`modified`}`;case`permission_modified`:return` ~ [Permission] ${e.reason??`modified`}`;case`table_scripts_modified`:return` ~ [Table Scripts] ${e.tableName}: ${e.reason??`table-level hooks/validate changed`}`;default:{let t=e;return` ? ${t.tableName}.${t.fieldName??``}`}}}function formatFieldType(e){let t=e.type;return e.array&&(t+=`[]`),e.required?t+=` (required)`:t+=` (optional)`,t}function formatFieldModification(e,t,n=[]){let r=[];e.type!==t.type&&r.push(`type: ${e.type} → ${t.type}`),e.required!==t.required&&r.push(`required: ${e.required} → ${t.required}`),!!e.array!=!!t.array&&r.push(`array: ${e.array??!1} → ${t.array??!1}`),!!e.index!=!!t.index&&r.push(`index: ${e.index??!1} → ${t.index??!1}`),!!e.unique!=!!t.unique&&r.push(`unique: ${e.unique??!1} → ${t.unique??!1}`),!!e.vector!=!!t.vector&&r.push(`vector: ${e.vector??!1} → ${t.vector??!1}`);let i=e.allowedValues??[],a=t.allowedValues??[],o=new Set(a.map(e=>e.value));if(i.length!==a.length||i.some(e=>!o.has(e.value))){let e=i.map(e=>e.value).join(`, `),t=a.map(e=>e.value).join(`, `);r.push(`allowedValues: [${e}] → [${t}]`)}let s=e.hooks,c=t.hooks;((s?.create?.expr??``)!==(c?.create?.expr??``)||(s?.update?.expr??``)!==(c?.update?.expr??``))&&r.push(`hooks modified`);let l=e.validate??[],u=t.validate??[];l.length!==u.length&&r.push(`validations: ${l.length} → ${u.length}`),!!e.serial!=!!t.serial&&r.push(`serial: ${e.serial?`enabled`:`disabled`} → ${t.serial?`enabled`:`disabled`}`);let d=new Set(n.flatMap(e=>[e.previousPath.join(`.`),e.path.join(`.`)])),f=collectNestedMemberChanges(e,t).filter(e=>!d.has(e.path.join(`.`))).map(e=>`${ja[e.kind]}${e.path.join(`.`)}`);return f.push(...n.map(e=>`${e.previousPath.join(`.`)} → ${e.path.join(`.`)} (renamed)`)),f.length>0&&r.push(`members: ${f.join(`, `)}`),r.length>0?r.join(`, `):`configuration changed`}const ja={removed:`-`,added:`+`,modified:`~`};function formatBreakingChanges(e){if(e.length===0)return``;let t=[`Breaking changes detected:`,``];for(let n of e){let e=n.fieldName?`${n.tableName}.${n.fieldName}`:n.tableName;t.push(` - ${e}: ${n.reason}`)}return t.join(`
|
|
5
5
|
`)}function formatWarnings(e){if(e.length===0)return``;let t=[`Warning: data loss possible:`,``];for(let n of e){let e=n.fieldName?`${n.tableName}.${n.fieldName}`:n.tableName;t.push(` - ${e}: ${n.reason}`)}return t.join(`
|
|
6
|
-
`)}const ka={table_added:`table(s) added`,table_removed:`table(s) removed`,table_renamed:`table(s) renamed`,table_modified:`table(s) modified`,table_settings_modified:`table setting(s) modified`,field_added:`field(s) added`,field_removed:`field(s) removed`,field_modified:`field(s) modified`,field_renamed:`field(s) renamed`,field_type_modified:`field type(s) modified`,index_added:`index(es) added`,index_removed:`index(es) removed`,index_modified:`index(es) modified`,file_added:`file field(s) added`,file_removed:`file field(s) removed`,file_modified:`file field(s) modified`,relationship_added:`relationship(s) added`,relationship_removed:`relationship(s) removed`,relationship_modified:`relationship(s) modified`,permission_modified:`permission(s) modified`,table_scripts_modified:`table script(s) modified`};function formatDiffSummary(e){let t={};for(let n of e.changes)t[n.kind]=(t[n.kind]??0)+1;let n=Object.keys(t).map(e=>`${t[e]} ${ka[e]}`);return n.length>0?n.join(`, `):`No changes`}function formatMigrationNumber(e){return e.toString().padStart(4,`0`)}function parseMigrationNumberArg(e){if(/^\d{4}$/.test(e))return parseInt(e,10);if(/^(0|[1-9]\d*)$/.test(e)){let t=parseInt(e,10);if(t>9999)throw E({code:`MIGRATION_NUMBER_INVALID`,message:`Migration number ${e} is out of range. Expected 0-9999.`});return t}throw E({code:`MIGRATION_NUMBER_INVALID`,message:`Invalid migration number format: ${e}. Expected 4-digit format (e.g., 0001) or integer 0-9999 (e.g., 1).`})}const Aa=`MIGRATION_FILE_VERSION_UNSUPPORTED`;function assertSupportedMigrationFileVersion(e,t){if(typeof t!=`object`||!t||!(`version`in t))return;let n=t.version;if(typeof n!=`number`||Number.isInteger(n)&&n>=1&&n<=8)return;let r;throw r=n>8?`Upgrade to an SDK that supports migration file format version ${n}.`:n<1?`Re-baseline with an SDK that still supports this migration history, then upgrade the SDK.`:`Restore the migration file from version control or regenerate it.`,E({code:Aa,message:`Unsupported migration file format version ${n} at ${e}.`,details:`This SDK supports migration file format versions 1-8.`,suggestion:r})}const ja=/* @__PURE__ */ new Map([[`type_added`,`table_added`],[`type_removed`,`table_removed`],[`type_renamed`,`table_renamed`],[`type_modified`,`table_modified`],[`type_settings_modified`,`table_settings_modified`],[`type_scripts_modified`,`table_scripts_modified`]]);function normalizeLegacyChangeKinds(e){if(typeof e!=`object`||!e||!(`changes`in e))return e;let t=e.changes;if(!Array.isArray(t))return e;let n=t.map(e=>{if(typeof e!=`object`||!e||!(`kind`in e))return e;let t=e.kind;if(typeof t!=`string`)return e;let n=ja.get(t);return n===void 0?e:{...e,kind:n}});return{...e,changes:n}}const Ma=/* @__PURE__ */ new Map([[`typeName`,`tableName`],[`previousTypeName`,`previousTableName`]]);function renameLegacyEntryFields(e){if(typeof e!=`object`||!e||Array.isArray(e))return e;let t=e,n={},r=!1;for(let[e,i]of Object.entries(t)){let a=Ma.get(e);a!==void 0&&!(a in t)?(n[a]=i,r=!0):n[e]=i}return r?n:e}const Na=[`changes`,`breakingChanges`,`warnings`];function normalizeLegacyTablesKey(e){if(typeof e!=`object`||!e)return e;let t=e;if(!(`types`in t)||`tables`in t)return e;let{types:n,...r}=t;return{...r,tables:n}}function normalizeLegacyFieldNames(e){if(typeof e!=`object`||!e)return e;let t=e,n={...t};for(let e of Na){let r=t[e];Array.isArray(r)&&(n[e]=r.map(renameLegacyEntryFields))}return n}function createSnapshotRecord(){return Object.create(null)}function copySnapshotRecord(e){let t=createSnapshotRecord();for(let[n,r]of Object.entries(e??{}))t[n]=r;return t}function normalizeSnapshotField(e){let t=e.fields?Object.fromEntries(Object.entries(e.fields).map(([e,t])=>[e,normalizeSnapshotField(t)])):void 0;return{...e,...e.type===`decimal`&&e.scale===void 0&&{scale:6},...t&&{fields:t}}}function normalizeSnapshotType(e){let t=e.pluralForm||wi.pluralize(e.name),n=createSnapshotRecord();for(let[t,r]of Object.entries(e.fields))n[t]=normalizeSnapshotField(r);return{...e,pluralForm:t,fields:n}}function normalizeSchemaSnapshot(e){let t=createSnapshotRecord();for(let[n,r]of Object.entries(e.tables))t[n]=normalizeSnapshotType(r);return{...e,tables:t}}const Pa=/* @__PURE__ */ new Set([`boolean:string`,`decimal:float`,`decimal:string`,`enum:string`,`float:decimal`,`float:string`,`integer:decimal`,`integer:float`,`integer:string`,`uuid:string`]);function supportsInPlaceFieldTypeChange(e,t){return e.type===t.type||e.array||t.array||e.type===`nested`||t.type===`nested`||e.serial||t.serial||e.vector||t.vector||e.foreignKey||t.foreignKey||!Pa.has(`${e.type}:${t.type}`)?!1:!(e.unique??!1)||t.type!==`decimal`||e.type!==`float`}function formatFieldShape(e){return e.array?`${e.type}[]`:e.type}function hasFieldShapeChange(e,t){return e.type!==t.type||(e.array??!1)!==(t.array??!1)}function isSingleValueToArrayChange(e,t){if(e.type!==t.type||e.array||!t.array||e.type===`decimal`&&(t.scale??6)<(e.scale??6))return!1;let n=new Set((t.allowedValues??[]).map(e=>e.value));return(e.allowedValues??[]).every(e=>n.has(e.value))}function getExpandContractFieldChangeEligibility(e,t){return hasFieldShapeChange(e,t)?supportsInPlaceFieldTypeChange(e,t)?{eligible:!1,reason:`the ${e.type} to ${t.type} change is already supported in place`}:e.unique||t.unique?{eligible:!1,reason:`the field is unique`}:e.array?{eligible:!1,reason:`the field is an array`}:e.type===`nested`||t.type===`nested`?{eligible:!1,reason:`the field is nested`}:e.serial||t.serial?{eligible:!1,reason:`the field uses a serial sequence`}:e.vector||t.vector?{eligible:!1,reason:`the field is a vector`}:e.foreignKey||t.foreignKey?{eligible:!1,reason:`the field is a foreign key`}:{eligible:!0}:{eligible:!1,reason:`the field type did not change`}}function collectForeignKeyReferences(e){let t=[],visit=(e,n)=>{for(let[r,i]of Object.entries(e)){let e=`${n}${r}`;i.foreignKeyType!==void 0&&t.push({table:i.foreignKeyType,field:i.foreignKeyField,path:e}),i.fields&&visit(i.fields,`${e}.`)}};return visit(e,``),t}function collectForeignKeyTargets(e){return[...new Set(collectForeignKeyReferences(e).map(e=>e.table))]}const Fa=/* @__PURE__ */ new Set([`index`,`unique`,`vector`]);function isRenameCompatible(e,t){if(e.type!==t.type)return!1;for(let n of Da)if(!Fa.has(n)&&(e[n]??!1)!==(t[n]??!1))return!1;if((e.foreignKeyType??``)!==(t.foreignKeyType??``)||(e.foreignKeyField??``)!==(t.foreignKeyField??``)||e.serial||t.serial)return!1;if(e.type===`enum`){let n=new Set((t.allowedValues??[]).map(e=>e.value));if((e.allowedValues??[]).some(e=>!n.has(e.value)))return!1}let n=e.fields??{},r=t.fields??{},i=Object.keys(n),a=Object.keys(r);if(i.length!==a.length)return!1;for(let e of i){let t=n[e],i=r[e];if(!t||!i||t.required!==i.required||!isRenameCompatible(t,i))return!1}return!0}function findRenameCandidates(e){let t=/* @__PURE__ */ new Map,n=/* @__PURE__ */ new Map;for(let r of e.changes)if(r.kind===`field_removed`){let e=t.get(r.tableName)??[];e.push(r),t.set(r.tableName,e)}else if(r.kind===`field_added`){let e=n.get(r.tableName)??[];e.push(r),n.set(r.tableName,e)}let r=[];for(let[e,i]of t){let t=n.get(e);if(t)for(let n of i){let i=t.filter(e=>isRenameCompatible(n.before,e.after));i.length>0&&r.push({tableName:e,removed:n,added:i})}}return r}function renameSpecApplies(e,t,n){let r=t.tables[e.tableName]?.fields,i=n.tables[e.tableName]?.fields;return!(!r?.[e.previousFieldName]||i?.[e.previousFieldName]||!i?.[e.fieldName]||r[e.fieldName])}function assertValidFieldRenames(e,t,n){let r=/* @__PURE__ */ new Set;for(let i of n){let{tableName:n,previousFieldName:a,fieldName:o}=i,s=`${n}.${a}:${o}`;for(let e of[`${n}.${a}`,`${n}.${o}`]){if(r.has(e))throw E({code:`MIGRATION_RENAME_INVALID`,message:`Field "${e}" appears in more than one rename.`});r.add(e)}let c=e.tables[n],l=t.tables[n];if(!c||!l)throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${s}: table "${n}" must exist in both the previous and the current schema.`});let u=c.fields[a];if(!u)throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${s}: field "${a}" does not exist in the previous schema.`});if(l.fields[a])throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${s}: field "${a}" still exists in the current schema.`});let d=l.fields[o];if(!d)throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${s}: field "${o}" does not exist in the current schema.`});if(c.fields[o])throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${s}: field "${o}" already exists in the previous schema.`});if(!isRenameCompatible(u,d))throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${s}: the fields are not rename-compatible (the field type, array-ness, and foreign key target must match, enum values must not be removed, nested member names, requiredness, and types must match recursively, and serial fields cannot be renamed).`})}}const Ia=/^([^.:\s]+)\.([^.:\s]+):([^.:\s]+)$/;function parseRenameOption(e){let[,t,n,r]=e.match(Ia)??[];if(!t||!n||!r)throw E({code:`MIGRATION_RENAME_FLAG_INVALID`,message:`Invalid --rename value "${e}". Expected format: "Table.oldField:newField".`,command:`tailordb migration generate`});if(n===r)throw E({code:`MIGRATION_RENAME_FLAG_INVALID`,message:`Invalid --rename value "${e}": old and new field names are identical.`,command:`tailordb migration generate`});return{tableName:t,previousFieldName:n,fieldName:r}}const La=/^([^.:\s]+)\.([^.:\s]+)$/;function parseDropOption(e){let[,t,n]=e.match(La)??[];if(!t||!n)throw E({code:`MIGRATION_DROP_FLAG_INVALID`,message:`Invalid --drop value "${e}". Expected format: "Table.field".`,command:`tailordb migration generate`});return{tableName:t,fieldName:n}}function dropSpecApplies(e,t,n){let r=t.tables[e.tableName]?.fields,i=n.tables[e.tableName]?.fields;return!(!r?.[e.fieldName]||i?.[e.fieldName])}function parseExpandContractOption(e){let[,t,n]=e.match(La)??[];if(!t||!n)throw E({code:`MIGRATION_EXPAND_CONTRACT_FLAG_INVALID`,message:`Invalid --expand-contract value "${e}". Expected format: "Table.field".`,command:`tailordb migration generate`});return{tableName:t,fieldName:n}}function isNestedMemberRenameCompatible(e,t){if(e.type!==t.type||e.required!==t.required)return!1;for(let n of Da)if(!Fa.has(n)&&(e[n]??!1)!==(t[n]??!1))return!1;if((e.foreignKeyType??``)!==(t.foreignKeyType??``)||(e.foreignKeyField??``)!==(t.foreignKeyField??``)||e.serial||t.serial||(e.scale??null)!==(t.scale??null)||(e.hooks?.create?.expr??``)!==(t.hooks?.create?.expr??``)||(e.hooks?.update?.expr??``)!==(t.hooks?.update?.expr??``))return!1;let n=e.validate??[],r=t.validate??[];if(n.length!==r.length)return!1;for(let[e,t]of n.entries()){let n=r[e];if((t.script?.expr??``)!==(n?.script?.expr??``)||t.errorMessage!==n?.errorMessage)return!1}if(e.type===`enum`){let n=new Set((t.allowedValues??[]).map(e=>e.value));if((e.allowedValues??[]).some(e=>!n.has(e.value)))return!1}let i=e.fields??{},a=t.fields??{},o=Object.keys(i);if(o.length!==Object.keys(a).length)return!1;for(let e of o){let t=i[e],n=Object.hasOwn(a,e)?a[e]:void 0;if(!t||!n||!isNestedMemberRenameCompatible(t,n))return!1}return!0}function haveSameParent(e,t){return e.length===t.length&&e.slice(0,-1).every((e,n)=>e===t[n])}function findNestedMemberRenameCandidates(e){let t=[];for(let n of e.changes){if(n.kind!==`field_modified`)continue;let e=collectNestedMemberChanges(n.before,n.after);for(let r of e){if(r.kind!==`removed`)continue;let i=e.filter(e=>e.kind===`added`&&haveSameParent(e.path,r.path)&&isNestedMemberRenameCompatible(r.before,e.after)).map(e=>e.path[e.path.length-1]).filter(e=>e!==void 0);i.length>0&&t.push({tableName:n.tableName,fieldName:n.fieldName,previousPath:r.path,removed:r.before,added:i})}}return t}function nestedMemberRenameSpecApplies(e,t,n){let r=t.tables[e.tableName]?.fields[e.fieldName],i=n.tables[e.tableName]?.fields[e.fieldName];return!(!getNestedMember(r,e.previousPath)||getNestedMember(i,e.previousPath)||!getNestedMember(i,e.path)||getNestedMember(r,e.path))}function assertValidNestedMemberRenames(e,t,n){let r=/* @__PURE__ */ new Set;for(let i of n){let{tableName:n,fieldName:a,previousPath:o,path:s}=i,c=`${n}.${a}.${o.join(`.`)}`,l=`${c}:${s[s.length-1]??``}`;for(let e of[c,`${n}.${a}.${s.join(`.`)}`]){if(r.has(e))throw E({code:`MIGRATION_RENAME_INVALID`,message:`Member "${e}" appears in more than one rename.`});r.add(e)}if(o.length===0||!haveSameParent(o,s))throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${l}: the old and new member must share the same parent inside "${a}".`});let u=e.tables[n]?.fields[a],d=t.tables[n]?.fields[a];if(u?.type!==`nested`||d?.type!==`nested`)throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${l}: "${n}.${a}" must be a nested field in both the previous and the current schema.`});for(let e=0;e<o.length;e++){let t=o.slice(0,e),r=getNestedMember(u,t),i=getNestedMember(d,t);if(r?.type!==`nested`||i?.type!==`nested`||(r.array??!1)!==(i.array??!1))throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${l}: ancestor "${[n,a,...t].join(`.`)}" must keep its nested type and array-ness. Split the ancestor change and rename into separate migrations.`})}let f=getNestedMember(u,o);if(!f)throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${l}: member "${o.join(`.`)}" does not exist in the previous schema.`});if(getNestedMember(d,o))throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${l}: member "${o.join(`.`)}" still exists in the current schema.`});let p=getNestedMember(d,s);if(!p)throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${l}: member "${s.join(`.`)}" does not exist in the current schema.`});if(getNestedMember(u,s))throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${l}: member "${s.join(`.`)}" already exists in the previous schema.`});if(!isNestedMemberRenameCompatible(f,p))throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${l}: the members are not rename-compatible (the member type, array-ness, requiredness, foreign key target, scale, hooks, and validations must match, enum values must not be removed, nested members must match recursively, and serial members cannot be renamed).`})}}const Ra=/^([^.:\s]+)\.([^.:\s]+)((?:\.[^.:\s]+)+):([^.:\s]+)$/;function parseNestedMemberRenameOption(e){let[,t,n,r,i]=e.match(Ra)??[];if(!t||!n||!r||!i)throw E({code:`MIGRATION_RENAME_FLAG_INVALID`,message:`Invalid --rename value "${e}". Expected format: "Table.field.member:newName".`,command:`tailordb migration generate`});let a=r.slice(1).split(`.`);if(a[a.length-1]===i)throw E({code:`MIGRATION_RENAME_FLAG_INVALID`,message:`Invalid --rename value "${e}": old and new member names are identical.`,command:`tailordb migration generate`});return{tableName:t,fieldName:n,previousPath:a,path:[...a.slice(0,-1),i]}}const za=/^([^.:\s]+)\.([^.:\s]+)((?:\.[^.:\s]+)+)$/;function parseNestedMemberDropOption(e){let[,t,n,r]=e.match(za)??[];if(!t||!n||!r)throw E({code:`MIGRATION_DROP_FLAG_INVALID`,message:`Invalid --drop value "${e}". Expected format: "Table.field.member".`,command:`tailordb migration generate`});return{tableName:t,fieldName:n,path:r.slice(1).split(`.`)}}function nestedMemberDropSpecApplies(e,t,n){let r=t.tables[e.tableName]?.fields[e.fieldName],i=n.tables[e.tableName]?.fields[e.fieldName];return!!(getNestedMember(r,e.path)&&!getNestedMember(i,e.path)&&getNestedMember(i,e.path.slice(0,-1)))}function retargetSelfReferences(e,t,n){let r=e.fields?Object.fromEntries(Object.entries(e.fields).map(([e,r])=>[e,retargetSelfReferences(r,t,n)])):void 0;return{...e,...e.foreignKeyType===t&&{foreignKeyType:n},...r&&{fields:r}}}function stableStringify(e){return Array.isArray(e)?`[${e.map(stableStringify).join(`,`)}]`:typeof e==`object`&&e?`{${Object.entries(e).filter(([,e])=>e!==void 0).toSorted(([e],[t])=>e.localeCompare(t)).map(([e,t])=>`${JSON.stringify(e)}:${stableStringify(t)}`).join(`,`)}}`:JSON.stringify(e)}function hasRequiredReferenceTo(e,t){return e.foreignKeyType===t&&e.required?!0:Object.values(e.fields??{}).some(e=>hasRequiredReferenceTo(e,t))}function hasSelfReferenceKeyedToSelfReference(e){return collectForeignKeyReferences(e.fields).some(t=>t.table===e.name&&t.field!==void 0&&e.fields[t.field]?.foreignKeyType===e.name)}function hasUniqueNestedSelfReference(e){let t=new Set(Object.values(e.indexes??{}).flatMap(e=>e.unique?e.fields:[]));return Object.entries(e.fields).some(([n,r])=>r.fields!==void 0&&(r.unique||t.has(n))&&collectForeignKeyReferences(r.fields).some(t=>t.table===e.name))}function isTypeRenameFieldCompatible(e,t){if(!isRenameCompatible(e,t)||e.required!==t.required||(e.unique??!1)!==(t.unique??!1)||(e.scale??null)!==(t.scale??null))return!1;for(let[n,r]of Object.entries(e.fields??{})){let e=t.fields?.[n];if(!e||!isTypeRenameFieldCompatible(r,e))return!1}return!0}function isTypeRenameCompatible(e,t){if(Object.keys(e.files??{}).length>0||Object.keys(t.files??{}).length>0||hasSelfReferenceKeyedToSelfReference(e)||hasUniqueNestedSelfReference(e))return!1;let n=Object.keys(e.fields),r=Object.keys(t.fields);if(n.length!==r.length)return!1;for(let r of n){let n=e.fields[r],i=t.fields[r];if(!n||!i||hasRequiredReferenceTo(n,e.name)||!isTypeRenameFieldCompatible(retargetSelfReferences(n,e.name,t.name),i))return!1}return stableStringify(e.indexes??{})===stableStringify(t.indexes??{})}function findTypeRenameCandidates(e){let t=e.changes.filter(e=>e.kind===`table_removed`),n=e.changes.filter(e=>e.kind===`table_added`),r=[];for(let e of t){let t=n.filter(t=>isTypeRenameCompatible(e.before,t.after));t.length>0&&r.push({removed:e,added:t})}return r}function typeRenameSpecApplies(e,t,n){return!(!t.tables[e.previousTableName]||n.tables[e.previousTableName]||!n.tables[e.tableName]||t.tables[e.tableName])}function assertValidTypeRenames(e,t,n){let r=/* @__PURE__ */ new Set;for(let i of n){let{previousTableName:n,tableName:a}=i,o=`${n}:${a}`;for(let e of[n,a]){if(r.has(e))throw E({code:`MIGRATION_RENAME_INVALID`,message:`Table "${e}" appears in more than one rename.`});r.add(e)}let s=e.tables[n];if(!s)throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${o}: table "${n}" does not exist in the previous schema.`});if(t.tables[n])throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${o}: table "${n}" still exists in the current schema.`});let c=t.tables[a];if(!c)throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${o}: table "${a}" does not exist in the current schema.`});if(e.tables[a])throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${o}: table "${a}" already exists in the previous schema.`});if(!isTypeRenameCompatible(s,c))throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${o}: the tables are not rename-compatible (every field must keep its name, type, array-ness, required/unique constraints, foreign key target, and scale, enum values must not be removed, indexes must match, self-referential foreign keys must be optional, and tables with serial or file fields cannot be renamed).`})}}function isBreakingForeignKeyRetarget(e,t,n){return!(!e.foreignKeyType||!t.foreignKeyType||e.foreignKeyType===t.foreignKeyType||n?.get(e.foreignKeyType)===t.foreignKeyType&&(e.foreignKeyField??``)===(t.foreignKeyField??``))}const Ba=/^([^.:\s]+):([^.:\s]+)$/;function parseTypeRenameOption(e){let[,t,n]=e.match(Ba)??[];if(!t||!n)throw E({code:`MIGRATION_RENAME_FLAG_INVALID`,message:`Invalid --rename value "${e}". Expected format: "Table.oldField:newField" or "OldTable:NewTable".`,command:`tailordb migration generate`});if(t===n)throw E({code:`MIGRATION_RENAME_FLAG_INVALID`,message:`Invalid --rename value "${e}": old and new table names are identical.`,command:`tailordb migration generate`});return{previousTableName:t,tableName:n}}const Va=/^([^.:\s]+)$/;function parseTypeDropOption(e){let[,t]=e.match(Va)??[];if(!t)throw E({code:`MIGRATION_DROP_FLAG_INVALID`,message:`Invalid --drop value "${e}". Expected format: "Table.field" or "Table".`,command:`tailordb migration generate`});return{tableName:t}}function typeDropSpecApplies(e,t,n){return!(!t.tables[e.tableName]||n.tables[e.tableName])}const Ha=`Field removed (existing data will no longer be accessible through the schema)`,Ua=`Table removed (all records in this table will be deleted during post-migration cleanup)`;function collectNestedMemberRemovalWarnings(e){let t=collectNestedMemberChanges(e.before,e.after),n=new Set((e.memberRenames??[]).flatMap(e=>[e.previousPath.join(`.`),e.path.join(`.`)])),r=[];for(let i of t){if(i.kind!==`removed`||n.has(i.path.join(`.`)))continue;let a=t.filter(e=>e.kind===`added`&&!n.has(e.path.join(`.`))&&haveSameParent(e.path,i.path)&&isNestedMemberRenameCompatible(i.before,e.after)).map(e=>e.path.at(-1)),o=a.length>0?`. Possibly renamed to ${a.join(`, `)}: confirm it with --rename "${e.tableName}.${e.fieldName}.${i.path.join(`.`)}:<newName>" to scaffold a copy script, or keep the removal and copy the values yourself`:``;r.push({tableName:e.tableName,fieldName:[e.fieldName,...i.path].join(`.`),reason:`Nested member removed (existing values will no longer be accessible through the schema)${o}`})}return r}function deriveWarningsFromChanges(e){let t=[];for(let n of e.changes)n.kind===`field_removed`?t.push({tableName:n.tableName,fieldName:n.fieldName,reason:Ha}):n.kind===`table_removed`?t.push({tableName:n.tableName,reason:Ua}):n.kind===`field_modified`&&t.push(...collectNestedMemberRemovalWarnings(n));return t}function areFieldsDifferent(e,t){return areOwnFieldConfigsDifferent(e,t)||collectNestedMemberChanges(e,t).length>0}function addsForeignKey(e,t){return!e.foreignKeyType&&!!t.foreignKeyType}function getBreakingFieldChanges(e,t,n,r,i,a=!1){let o=[];if(!n&&r&&r.required&&o.push({tableName:e,fieldName:t,reason:`Required field added`}),n&&r&&n.type!==r.type){let i=!a&&supportsInPlaceFieldTypeChange(n,r);o.push({tableName:e,fieldName:t,reason:`Field type changed from ${n.type} to ${r.type}`,...!i&&{unsupported:!0,showThreeStepHint:!0}})}if(n&&r&&!n.required&&r.required&&o.push({tableName:e,fieldName:t,reason:`Field changed from optional to required`}),n&&r&&(n.array??!1)!==(r.array??!1)){let[r,i]=n.array?[`array`,`single value`]:[`single value`,`array`];o.push({tableName:e,fieldName:t,reason:`Field changed from ${r} to ${i}`,unsupported:!0,showThreeStepHint:!0})}if(n&&r&&isBreakingForeignKeyRetarget(n,r,i)&&o.push({tableName:e,fieldName:t,reason:`Foreign key target type changed from ${n.foreignKeyType} to ${r.foreignKeyType}`,...a&&{unsupported:!0,showThreeStepHint:!0}}),!a&&n&&r&&addsForeignKey(n,r)&&o.push({tableName:e,fieldName:t,reason:`Foreign key to ${r.foreignKeyType} added to field`}),n&&r&&!(n.unique??!1)&&(r.unique??!1)&&o.push({tableName:e,fieldName:t,reason:`Unique constraint added to field`}),n?.type===`decimal`&&r?.type===`decimal`&&n.scale!==r.scale&&o.push({tableName:e,fieldName:t,reason:`Decimal scale changed from ${n.scale} to ${r.scale}`,...a&&{unsupported:!0,showThreeStepHint:!0}}),n&&r&&n.type===`enum`&&r.type===`enum`){let i=n.allowedValues??[],a=r.allowedValues??[],s=i.map(e=>e.value),c=new Set(a.map(e=>e.value)),l=s.filter(e=>!c.has(e));l.length>0&&o.push({tableName:e,fieldName:t,reason:`Enum values removed: ${l.join(`, `)}`})}return o}function collectBreakingNestedMemberChanges(e,t){return collectNestedMemberChanges(e.before,e.after).flatMap(n=>n.kind===`removed`||n.kind===`added`&&e.memberRenames?.some(e=>e.path.length===n.path.length&&e.path.every((e,t)=>e===n.path[t]))?[]:getBreakingFieldChanges(e.tableName,[e.fieldName,...n.path].join(`.`),n.kind===`modified`?n.before:void 0,n.after,t,!0))}function addChange(e,t,n,r){if(e.changes.push(t),!t.fieldName)return;t.kind===`field_modified`&&(e.warnings.push(...collectNestedMemberRemovalWarnings(t)),e.breakingChanges.push(...collectBreakingNestedMemberChanges(t,e.typeRenameTargets)));let i=getBreakingFieldChanges(t.tableName,t.fieldName,n,r,e.typeRenameTargets);i.length>0?e.breakingChanges.push(...i):t.kind===`field_removed`&&e.warnings.push({tableName:t.tableName,fieldName:t.fieldName,reason:Ha})}function compareTypeFields(e,t,n,r,i=[],o=[]){let s=new Set(Object.keys(n.fields)),c=new Set(Object.keys(r.fields)),l=new Set(i.map(e=>e.previousFieldName)),u=new Set(i.map(e=>e.fieldName));for(let o of i){let i=a(n.fields[o.previousFieldName],`renamed field "${o.previousFieldName}" missing from prevType`),s=a(r.fields[o.fieldName],`renamed field "${o.fieldName}" missing from currType`);e.changes.push({kind:`field_renamed`,tableName:t,fieldName:o.fieldName,previousFieldName:o.previousFieldName,before:i,after:s}),e.breakingChanges.push({tableName:t,fieldName:o.fieldName,reason:`Field renamed from ${o.previousFieldName} to ${o.fieldName} (existing values must be copied by the migration script)`})}for(let n of c)if(!u.has(n)&&!s.has(n)){let i=a(r.fields[n],`field "${n}" missing from currType`);addChange(e,{kind:`field_added`,tableName:t,fieldName:n,after:i},void 0,i)}for(let r of s)if(!l.has(r)&&!c.has(r)){let i=a(n.fields[r],`field "${r}" missing from prevType`);addChange(e,{kind:`field_removed`,tableName:t,fieldName:r,before:i},i,void 0)}for(let i of c){if(!s.has(i))continue;let c=a(n.fields[i],`field "${i}" missing from prevType`),l=a(r.fields[i],`field "${i}" missing from currType`);if(!areFieldsDifferent(c,l))continue;if(c.type!==l.type){addChange(e,{kind:`field_type_modified`,tableName:t,fieldName:i,before:c,after:l},c,l);continue}let u=o.filter(e=>e.fieldName===i).map(({previousPath:e,path:t})=>({previousPath:e,path:t}));addChange(e,{kind:`field_modified`,tableName:t,fieldName:i,before:c,after:l,...u.length>0&&{memberRenames:u}},c,l);for(let n of u)e.breakingChanges.push({tableName:t,fieldName:[i,...n.path].join(`.`),reason:`Nested member renamed from ${n.previousPath.join(`.`)} to ${n.path.join(`.`)} (existing values must be copied by the migration script)`})}}function isBreakingIndexChange(e,t,n,r){return!r||!(r.unique??!1)?null:!n||!(n.unique??!1)?{tableName:e,reason:`Unique constraint added to index "${t}"`}:JSON.stringify(n.fields.toSorted())===JSON.stringify(r.fields.toSorted())?null:{tableName:e,reason:`Unique index fields changed on index "${t}"`}}function compareIndexes(e,t,n,r){let i=new Set(Object.keys(n||{})),o=new Set(Object.keys(r||{}));for(let[n,a]of Object.entries(r??{}))if(!i.has(n)){e.changes.push({kind:`index_added`,tableName:t,indexName:n,after:a});let r=isBreakingIndexChange(t,n,void 0,a);r&&e.breakingChanges.push(r)}for(let[r,i]of Object.entries(n??{}))o.has(r)||e.changes.push({kind:`index_removed`,tableName:t,indexName:r,before:i});for(let[o,s]of Object.entries(r??{}))if(i.has(o)){let r=a(a(n,`oldIndexes is undefined when oldKeys has entry`)[o],`index "${o}" missing from oldIndexes`),i=JSON.stringify(r.fields.toSorted()),c=JSON.stringify(s.fields.toSorted());if(i!==c||(r.unique??!1)!==(s.unique??!1)){let n=[];i!==c&&n.push(`fields changed`),(r.unique??!1)!==(s.unique??!1)&&n.push(`unique constraint changed`),e.changes.push({kind:`index_modified`,tableName:t,indexName:o,reason:n.join(`, `),before:r,after:s});let a=isBreakingIndexChange(t,o,r,s);a&&e.breakingChanges.push(a)}}}function compareFiles(e,t,n,r){let i=new Set(Object.keys(n||{})),o=new Set(Object.keys(r||{}));for(let[n,a]of Object.entries(r??{}))i.has(n)||e.changes.push({kind:`file_added`,tableName:t,fieldName:n,after:a});for(let[r,i]of Object.entries(n??{}))o.has(r)||e.changes.push({kind:`file_removed`,tableName:t,fieldName:r,before:i});for(let[o,s]of Object.entries(r??{}))if(i.has(o)){let r=a(a(n,`oldFiles is undefined when oldKeys has entry`)[o],`file "${o}" missing from oldFiles`);r!==s&&e.changes.push({kind:`file_modified`,tableName:t,fieldName:o,reason:`description changed`,before:r,after:s})}}function compareRelationships(e,t,n,r,i){let o=new Set(Object.keys(r||{})),s=new Set(Object.keys(i||{}));for(let[r,a]of Object.entries(i??{}))o.has(r)||e.changes.push({kind:`relationship_added`,tableName:t,relationshipName:r,relationshipType:n,after:a});for(let[i,a]of Object.entries(r??{}))s.has(i)||e.changes.push({kind:`relationship_removed`,tableName:t,relationshipName:i,relationshipType:n,before:a});for(let[s,c]of Object.entries(i??{}))if(o.has(s)){let i=a(a(r,`oldRelationships is undefined when oldKeys has entry`)[s],`relationship "${s}" missing from oldRelationships`),o=[];i.targetType!==c.targetType&&o.push(`targetType changed`),i.targetField!==c.targetField&&o.push(`targetField changed`),i.sourceField!==c.sourceField&&o.push(`sourceField changed`),i.isArray!==c.isArray&&o.push(`isArray changed`),i.description!==c.description&&o.push(`description changed`),o.length>0&&e.changes.push({kind:`relationship_modified`,tableName:t,relationshipName:s,relationshipType:n,reason:o.join(`, `),before:i,after:c})}}function comparePermissions(e,t,n,r,i,a){let o=comparableRecordPermission(n),s=comparableRecordPermission(r),c=JSON.stringify(o??null)!==JSON.stringify(s??null),l=comparableGqlPermission(i),u=comparableGqlPermission(a),d=JSON.stringify(l??null)!==JSON.stringify(u??null);if(c||d){let n=[];c&&n.push(`record permission`),d&&n.push(`GQL permission`),e.changes.push({kind:`permission_modified`,tableName:t,reason:`${n.join(` and `)} changed`,before:{recordPermission:o,gqlPermission:l},after:{recordPermission:s,gqlPermission:u}})}}const Wa={all:0,create:1,read:2,update:3,delete:4,aggregate:5,bulkUpsert:6};function sortByJson(e){return e.map(e=>[JSON.stringify(e),e]).toSorted(([e],[t])=>e<t?-1:+(e>t)).map(([,e])=>e)}function comparableGqlPermission(e){let t=e?.map(e=>({...e,conditions:sortByJson(e.conditions),actions:e.actions.toSorted((e,t)=>Wa[e]-Wa[t])}));return t&&t.length>0?sortByJson(t):void 0}function comparableRecordPermission(e){if(e&&Object.values(e).some(e=>e.length>0))return{create:sortByJson(e.create.map(canonicalActionPermission)),read:sortByJson(e.read.map(canonicalActionPermission)),update:sortByJson(e.update.map(canonicalActionPermission)),delete:sortByJson(e.delete.map(canonicalActionPermission))}}function canonicalActionPermission(e){return{...e,conditions:sortByJson(e.conditions)}}function normalizeComparableGqlOperations(e){if(e)return{create:e.create??!0,update:e.update??!0,delete:e.delete??!0,read:e.read??!0}}function normalizeComparableSettings(e){let t={};e?.aggregation===!0&&(t.aggregation=!0),e?.bulkUpsert===!0&&(t.bulkUpsert=!0),e?.publishEvents===!0&&(t.publishEvents=!0);let n=normalizeComparableGqlOperations(e?.gqlOperations);return n&&(t.gqlOperations=n),Object.keys(t).length>0?t:void 0}function typeSettingsState(e,t,n){return{...e?{description:e}:{},pluralForm:t,...n&&{settings:n}}}function comparableTypeSettings(e){return typeSettingsState(e.description,wi.camelize(e.pluralForm,!0),normalizeComparableSettings(e.settings))}function snapshotTypeSettingsState(e){return typeSettingsState(e.description,e.pluralForm,e.settings??{})}function compareTypeSettings(e,t,n,r){let i=comparableTypeSettings(n),a=comparableTypeSettings(r);JSON.stringify(i)!==JSON.stringify(a)&&e.changes.push({kind:`table_settings_modified`,tableName:t,reason:`settings changed`,before:snapshotTypeSettingsState(n),after:snapshotTypeSettingsState(r)})}function typeScriptsState(e){return{...e.typeHookExpr&&{typeHookExpr:e.typeHookExpr},...e.typeValidateExpr!==void 0&&{typeValidateExpr:e.typeValidateExpr}}}function compareTypeScripts(e,t,n,r){let i=typeScriptsState(n),a=typeScriptsState(r);JSON.stringify(i)!==JSON.stringify(a)&&e.changes.push({kind:`table_scripts_modified`,tableName:t,reason:`table-level scripts changed`,before:i,after:a})}function buildExpandBaseSnapshot(e,t){let n=copySnapshotRecord(e.tables);for(let e of t){let t=n[e.tableName],r=t?.fields[e.fieldName];if(!t||!r)continue;let i=copySnapshotRecord(t.fields);i[e.fieldName]={...r,required:!1},n[e.tableName]={...t,fields:i}}return normalizeSchemaSnapshot({...e,tables:n})}function buildExpandDiff(e,t,n){return{...compareSnapshots(buildExpandBaseSnapshot(e,n),t),requiresMigrationScript:!0}}function buildIntermediateSnapshot(e,t){let n=copySnapshotRecord(e.tables);for(let e of t){let t=n[e.tableName];if(!t)continue;let r=copySnapshotRecord(t.fields),{hooks:i,validate:a,...o}=e.after;r[e.tempFieldName]={...o,required:!1,unique:!1},delete r[e.fieldName],n[e.tableName]={...t,fields:r}}return normalizeSchemaSnapshot({...e,tables:n})}function compareSnapshots(e,t,n){let r=n?.fieldRenames??[];assertValidFieldRenames(e,t,r);let i=/* @__PURE__ */ new Map;for(let e of r){let t=i.get(e.tableName)??[];t.push(e),i.set(e.tableName,t)}let o=n?.nestedMemberRenames??[];assertValidNestedMemberRenames(e,t,o);let s=/* @__PURE__ */ new Map;for(let e of o){let t=s.get(e.tableName)??[];t.push(e),s.set(e.tableName,t)}let c=n?.typeRenames??[];assertValidTypeRenames(e,t,c);let l=new Map(c.map(e=>[e.previousTableName,e.tableName])),u=new Set(c.map(e=>e.tableName)),d={changes:[],breakingChanges:[],warnings:[],typeRenameTargets:l},f=new Set(Object.keys(e.tables)),p=new Set(Object.keys(t.tables));for(let n of c){let r=a(e.tables[n.previousTableName],`renamed table "${n.previousTableName}" missing from previous snapshot`),i=a(t.tables[n.tableName],`renamed table "${n.tableName}" missing from current snapshot`);d.changes.push({kind:`table_renamed`,tableName:n.tableName,previousTableName:n.previousTableName,before:r,after:i}),d.breakingChanges.push({tableName:n.tableName,reason:`Table renamed from ${n.previousTableName} to ${n.tableName} (existing records must be copied by the migration script)`}),d.breakingChanges.push({tableName:n.tableName,reason:`GraphQL API names derived from ${n.previousTableName}/${r.pluralForm} change to ${n.tableName}/${i.pluralForm} — breaking for API clients`})}for(let[e,n]of Object.entries(t.tables))u.has(e)||f.has(e)||d.changes.push({kind:`table_added`,tableName:e,after:n});for(let[t,n]of Object.entries(e.tables))l.has(t)||p.has(t)||(d.changes.push({kind:`table_removed`,tableName:t,before:n}),d.warnings.push({tableName:t,reason:Ua}));for(let n of p){if(!f.has(n))continue;let r=a(e.tables[n],`table "${n}" missing from previous snapshot`),o=a(t.tables[n],`table "${n}" missing from current snapshot`);compareTypeSettings(d,n,r,o),compareTypeScripts(d,n,r,o),compareTypeFields(d,n,r,o,i.get(n),s.get(n)),compareIndexes(d,n,r.indexes,o.indexes),compareFiles(d,n,r.files,o.files),compareRelationships(d,n,`forward`,r.forwardRelationships,o.forwardRelationships),compareRelationships(d,n,`backward`,r.backwardRelationships,o.backwardRelationships),comparePermissions(d,n,r.permissions?.record,o.permissions?.record,r.permissions?.gql,o.permissions?.gql)}return{version:8,namespace:t.namespace,createdAt:(/* @__PURE__ */ new Date()).toISOString(),changes:d.changes,hasBreakingChanges:d.breakingChanges.length>0,breakingChanges:d.breakingChanges,hasWarnings:d.warnings.length>0,warnings:d.warnings,requiresMigrationScript:d.breakingChanges.length>0}}function compareLocalTypesWithSnapshot(e,t,n){let r={version:8,namespace:n,createdAt:(/* @__PURE__ */ new Date()).toISOString(),tables:t};return compareSnapshots(normalizeSchemaSnapshot(e),normalizeSchemaSnapshot(r))}const Ga=`sdk-migration`,Ka=`sdk-migration-history`,qa=`sdk-migration-in-progress`,Ja=`-main`,Ya=`sdk-migration-execution`,Xa=`sdk-maintenance-mode`,Za=`sdk-migration-cleanup`,Qa=/^[a-z][a-z0-9_-]{0,62}$/;function sanitizeMigrationLabel(e){return(`m`+formatMigrationNumber(e)).slice(0,63)}function parseMigrationLabelNumber(e){if(!e.startsWith(`m`))return null;let t=e.slice(1);if(!/^\d+$/.test(t))return null;let n=parseInt(t,10);return n>9999?null:n}function inProgressLabel(e,t){let n=sanitizeMigrationLabel(e);return t===`main`?`${n}${Ja}`:n}function parseInProgressLabel(e){let t=e.endsWith(Ja)?`main`:`steps`,n=parseMigrationLabelNumber(t===`main`?e.slice(0,-5):e);return n===null?null:{number:n,kind:t}}function parseMigrationHistoryId(e){return Qa.test(e)?e:null}function executionIdToLabel(e){return`e${e.replaceAll(`-`,``).toLowerCase()}`}function parseExecutionLabel(e){let t=/^e([0-9a-f]{8})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{12})$/.exec(e);return t?t.slice(1).join(`-`):null}function createMigrationHistoryId(){return`h${mi().replaceAll(`-`,``)}`}function handleOptionalToRequiredError(e,t){if(e instanceof q&&e.code===K.FailedPrecondition&&e.message.includes(`cannot be updated from non-required to required when records exist`)){C.error(`Schema change failed: Cannot change field from optional to required when records exist.`),C.newline();for(let e of t)C.info(e)}throw e}function snapshotRecordSchema(e){return U.custom(e=>typeof e==`object`&&!!e&&!Array.isArray(e),{message:`Expected record`}).transform((t,n)=>{let r=Object.create(null);for(let i of Object.keys(t)){let a=e.safeParse(t[i]);if(a.success)r[i]=a.data;else for(let e of a.error.issues)n.addIssue({...e,path:[i,...e.path]})}return r})}const $a=U.looseObject({expr:U.string()}),eo=U.looseObject({script:U.looseObject({expr:U.string()}).optional(),errorMessage:U.string()}),to=U.looseObject({start:U.number(),maxValue:U.number().optional(),format:U.string().optional(),gapless:U.boolean().optional()}),no=U.looseObject({value:U.string(),description:U.string().optional()}),ro=U.looseObject({type:U.string(),required:U.boolean().default(!0),array:U.boolean().optional(),index:U.boolean().optional(),unique:U.boolean().optional(),allowedValues:U.array(no).optional(),foreignKey:U.boolean().optional(),foreignKeyType:U.string().optional(),foreignKeyField:U.string().optional(),description:U.string().optional(),vector:U.boolean().optional(),hooks:U.looseObject({create:$a.optional(),update:$a.optional()}).optional(),validate:U.array(eo).optional(),serial:to.optional(),scale:U.number().optional(),default:U.unknown().optional(),fields:U.lazy(()=>snapshotRecordSchema(ro)).optional()}),io=U.looseObject({fields:U.array(U.string()),unique:U.boolean().optional()}),ao=U.looseObject({targetType:U.string(),targetField:U.string(),sourceField:U.string(),isArray:U.boolean(),description:U.string()}),oo=[`user`,`record`,`newRecord`,`oldRecord`],so=U.unknown().refine(e=>{if(typeof e!=`object`||!e||Array.isArray(e))return!0;let t=Object.keys(e);return oo.filter(e=>t.includes(e)).length<2},`Ambiguous field-ref operand: contains more than one of user/record/newRecord/oldRecord`),co=U.unknown().refine(e=>{if(typeof e!=`object`||!e||Array.isArray(e))return!0;let t=Object.keys(e);return oo.filter(e=>t.includes(e)).length<2},`Ambiguous field-ref operand: contains more than one of user/record/newRecord/oldRecord`).refine(e=>{if(typeof e!=`object`||!e||Array.isArray(e))return!0;let t=Object.keys(e);return![`record`,`newRecord`,`oldRecord`].some(e=>t.includes(e))},`GQL permissions only support { user } field references`),lo=U.string(),uo=U.tuple([so,lo,so]).rest(U.unknown()),fo=U.tuple([co,lo,co]).rest(U.unknown()),po=U.looseObject({conditions:U.array(uo),description:U.string().optional(),permit:U.enum([`allow`,`deny`])}),mo=U.looseObject({create:U.array(po).default([]),read:U.array(po).default([]),update:U.array(po).default([]),delete:U.array(po).default([])}),ho=U.string(),go=U.looseObject({conditions:U.array(fo),actions:U.array(ho),permit:U.enum([`allow`,`deny`]),description:U.string().optional()}),_o=U.array(go),vo=U.looseObject({name:U.string(),pluralForm:U.string().optional(),description:U.string().optional(),fields:snapshotRecordSchema(ro),settings:U.looseObject({aggregation:U.boolean().optional(),bulkUpsert:U.boolean().optional(),gqlOperations:U.looseObject({create:U.boolean().optional(),update:U.boolean().optional(),delete:U.boolean().optional(),read:U.boolean().optional()}).optional(),publishEvents:U.boolean().optional()}).optional(),indexes:snapshotRecordSchema(io).optional(),files:snapshotRecordSchema(U.string()).optional(),forwardRelationships:snapshotRecordSchema(ao).optional(),backwardRelationships:snapshotRecordSchema(ao).optional(),permissions:U.looseObject({record:mo.optional(),gql:_o.optional()}).optional()}),yo=U.looseObject({historyId:U.string().regex(Qa),replacedHistoryId:U.string().regex(Qa).nullable(),replacedLatestMigration:U.number().int().min(0).max(9999)}),bo=U.looseObject({version:U.number(),namespace:U.string(),createdAt:U.string(),tables:snapshotRecordSchema(vo),rebaseline:yo.optional()}),xo=U.looseObject({indexes:snapshotRecordSchema(io).optional(),files:snapshotRecordSchema(U.string()).optional()}),So=U.looseObject({description:U.string().optional(),pluralForm:U.string(),settings:U.looseObject({aggregation:U.boolean().optional(),bulkUpsert:U.boolean().optional(),gqlOperations:U.looseObject({create:U.boolean().optional(),update:U.boolean().optional(),delete:U.boolean().optional(),read:U.boolean().optional()}).optional(),publishEvents:U.boolean().optional()}).optional()}),Co=U.looseObject({recordPermission:mo.optional(),gqlPermission:_o.optional()}),wo=U.looseObject({kind:U.literal(`table_added`),tableName:U.string(),reason:U.string().optional(),after:vo}),To=U.looseObject({kind:U.literal(`table_removed`),tableName:U.string(),reason:U.string().optional(),before:vo}),Eo=U.looseObject({kind:U.literal(`table_renamed`),tableName:U.string(),reason:U.string().optional(),previousTableName:U.string(),before:vo,after:vo}),Do=U.looseObject({kind:U.literal(`table_modified`),tableName:U.string(),reason:U.string().optional(),before:xo.optional(),after:xo.optional()}),Oo=U.looseObject({kind:U.literal(`table_settings_modified`),tableName:U.string(),reason:U.string().optional(),before:So,after:So}),ko=U.looseObject({kind:U.literal(`field_added`),tableName:U.string(),reason:U.string().optional(),fieldName:U.string(),after:ro}),Ao=U.looseObject({kind:U.literal(`field_removed`),tableName:U.string(),reason:U.string().optional(),fieldName:U.string(),before:ro}),jo=U.looseObject({kind:U.literal(`field_modified`),tableName:U.string(),reason:U.string().optional(),fieldName:U.string(),before:ro,after:ro,memberRenames:U.array(U.looseObject({previousPath:U.array(U.string()).min(1),path:U.array(U.string()).min(1)}).refine(({previousPath:e,path:t})=>e.length===t.length&&e.slice(0,-1).every((e,n)=>e===t[n])&&e.at(-1)!==t.at(-1),{message:`memberRenames entries must rename a member within its parent`})).optional()}),Mo=U.looseObject({kind:U.literal(`field_renamed`),tableName:U.string(),reason:U.string().optional(),fieldName:U.string(),previousFieldName:U.string(),before:ro,after:ro}),No=U.looseObject({kind:U.literal(`field_type_modified`),tableName:U.string(),reason:U.string().optional(),fieldName:U.string(),before:ro,after:ro}),Po=U.looseObject({kind:U.literal(`index_added`),tableName:U.string(),reason:U.string().optional(),indexName:U.string(),after:io}),Fo=U.looseObject({kind:U.literal(`index_removed`),tableName:U.string(),reason:U.string().optional(),indexName:U.string(),before:io}),Io=U.looseObject({kind:U.literal(`index_modified`),tableName:U.string(),reason:U.string().optional(),indexName:U.string(),before:io,after:io}),Lo=U.looseObject({kind:U.literal(`file_added`),tableName:U.string(),reason:U.string().optional(),fieldName:U.string(),after:U.string()}),Ro=U.looseObject({kind:U.literal(`file_removed`),tableName:U.string(),reason:U.string().optional(),fieldName:U.string(),before:U.string()}),zo=U.looseObject({kind:U.literal(`file_modified`),tableName:U.string(),reason:U.string().optional(),fieldName:U.string(),before:U.string(),after:U.string()}),Bo=U.looseObject({kind:U.literal(`relationship_added`),tableName:U.string(),reason:U.string().optional(),relationshipName:U.string(),relationshipType:U.enum([`forward`,`backward`]).optional(),after:ao}),Vo=U.looseObject({kind:U.literal(`relationship_removed`),tableName:U.string(),reason:U.string().optional(),relationshipName:U.string(),relationshipType:U.enum([`forward`,`backward`]).optional(),before:ao}),Ho=U.looseObject({kind:U.literal(`relationship_modified`),tableName:U.string(),reason:U.string().optional(),relationshipName:U.string(),relationshipType:U.enum([`forward`,`backward`]).optional(),before:ao,after:ao}),Uo=U.looseObject({kind:U.literal(`permission_modified`),tableName:U.string(),reason:U.string().optional(),before:Co.optional(),after:Co.optional()}),Wo=U.looseObject({typeHookExpr:U.looseObject({create:U.string().optional(),update:U.string().optional()}).optional(),typeValidateExpr:U.string().optional()}),Go=U.looseObject({kind:U.literal(`table_scripts_modified`),tableName:U.string(),reason:U.string().optional(),before:Wo,after:Wo}),Ko=U.discriminatedUnion(`kind`,[wo,To,Eo,Do,Oo,ko,Ao,jo,Mo,No,Po,Fo,Io,Lo,Ro,zo,Bo,Vo,Ho,Uo,Go]),qo=U.looseObject({tableName:U.string(),fieldName:U.string().optional(),reason:U.string(),unsupported:U.boolean().optional(),showThreeStepHint:U.boolean().optional()}),Jo=U.looseObject({tableName:U.string(),fieldName:U.string().optional(),reason:U.string()}),Yo=U.looseObject({reason:U.string().trim().min(1),acknowledgedAt:U.string()}),Xo=U.looseObject({version:U.number(),namespace:U.string(),createdAt:U.string(),description:U.string().optional(),changes:U.array(Ko),hasBreakingChanges:U.boolean(),breakingChanges:U.array(qo),hasWarnings:U.boolean().optional(),warnings:U.array(Jo).optional(),requiresMigrationScript:U.boolean(),scriptSkipped:Yo.optional(),temporal:U.boolean().optional(),dateRepresentation:U.enum([`temporal`,`date`]).optional()}),Zo=0,Qo=`schema.json`,$o=`diff.json`,es=`migrate.ts`,ts=`migrate.test.ts`,ns=`db.ts`,rs=`db.pglite.ts`,is=`migrate.pglite.test.ts`,as=/^\d{4}$/;function isValidMigrationNumber(e){return as.test(e)}const os={schema:Qo,diff:$o,migrate:es,test:ts,db:ns,pgliteSchema:rs,pgliteTest:is};function getMigrationDirPath(e,t){let n=formatMigrationNumber(t);return H.join(e,n)}function getMigrationFilePath(e,t,n){let r=getMigrationDirPath(e,t);return H.join(r,os[n])}function loadSnapshot(e){let t=W.readFileSync(e,`utf-8`),n;try{n=JSON.parse(t)}catch(t){throw E({code:`MIGRATION_FILE_INVALID`,message:`Invalid schema snapshot at ${e}: ${String(t)}`,cause:t})}assertSupportedMigrationFileVersion(e,n);let r=bo.safeParse(normalizeLegacyTablesKey(n));if(!r.success){let t=u(r.error.issues);throw E({code:`MIGRATION_FILE_INVALID`,message:`Invalid schema snapshot at ${e}:\n${d(t)}`,context:{file:e,issues:t},cause:r.error})}let i=r.data;return normalizeSchemaSnapshot(i)}function loadDiff(e){let t=W.readFileSync(e,`utf-8`),n;try{n=JSON.parse(t)}catch(t){throw E({code:`MIGRATION_FILE_INVALID`,message:`Invalid migration diff at ${e}: ${String(t)}`,cause:t})}assertSupportedMigrationFileVersion(e,n);let r=Xo.safeParse(normalizeLegacyFieldNames(normalizeLegacyChangeKinds(n)));if(!r.success){let t=u(r.error.issues);throw E({code:`MIGRATION_FILE_INVALID`,message:`Invalid migration diff at ${e}:\n${d(t)}`,context:{file:e,issues:t},cause:r.error})}let i=r.data,a=i.warnings??deriveWarningsFromChanges(i);return{...i,warnings:a,hasWarnings:a.length>0}}function getMigrationFiles(e){if(!W.existsSync(e))return[];let t=W.readdirSync(e,{withFileTypes:!0}),n=[];for(let r of t){if(!r.isDirectory()||!isValidMigrationNumber(r.name))continue;let t=parseInt(r.name,10),i=H.join(e,r.name),a=H.join(i,Qo);W.existsSync(a)&&n.push({number:t,type:`schema`,path:a});let o=H.join(i,$o);W.existsSync(o)&&n.push({number:t,type:`diff`,path:o})}return n.toSorted((e,t)=>e.number-t.number)}const ss=Object.keys(os);function getMigrationArtifacts(e){return W.existsSync(e)?W.readdirSync(e,{withFileTypes:!0}).filter(e=>e.isDirectory()&&isValidMigrationNumber(e.name)).map(t=>{let n=Number.parseInt(t.name,10);return{number:n,fileTypes:ss.filter(t=>W.existsSync(getMigrationFilePath(e,n,t)))}}).filter(({fileTypes:e})=>e.length>0).toSorted((e,t)=>e.number-t.number):[]}function getNextMigrationNumber(e){let t=getMigrationFiles(e);return t.length===0?0:Math.max(...t.map(e=>e.number))+1}function getLatestMigrationNumber(e){return latestMigrationNumber(getMigrationFiles(e))}function latestMigrationNumber(e){return e.length===0?0:Math.max(...e.map(e=>e.number))}function assertMigrationNumberExists(e,t){let n=getMigrationFiles(e);if(t!==0&&!n.some(e=>e.number===t))throw E({code:`MIGRATION_NOT_FOUND`,message:`Migration ${formatMigrationNumber(t)} does not exist in working tree (latest is ${formatMigrationNumber(latestMigrationNumber(n))}).`});return latestMigrationNumber(n)}function formatMigrationScriptHint(e){let{migrationNumber:t,namespace:n,configPath:r,noScript:i}=e,a=namespaceMigrationArgs({subcommand:[`script`,formatMigrationNumber(t)],namespace:n,configPath:r});return i&&a.push(`--no-script`,`--reason`,`<reason>`),w({command:`tailor`,args:a})}function formatRebaselineHint(e){return formatNamespaceMigrationHint({...e,subcommand:[`rebaseline`]})}function migrationCommandContext(e){return{configPath:e.configPath,contextArgs:[...Se(e),...e.extraArgs??[]]}}function migrationContextArgs(e){let t=Ae(e.configPath);return[...t===void 0?[]:[t],...e.contextArgs??[]]}function migrationCommandArgs(e,t){return[`tailordb`,`migration`,...e,...migrationContextArgs(t)]}function namespaceMigrationArgs(e){let{subcommand:t,namespace:n,...r}=e;return migrationCommandArgs([...t,`--namespace`,n],r)}function formatNamespaceMigrationHint(e){return w({command:`tailor`,args:namespaceMigrationArgs(e)})}function formatCheckpointSyncHint(e){let{migrationNumber:t,replaceHistoryId:n,...r}=e,i=formatNamespaceMigrationHint({...r,subcommand:[`sync`,formatMigrationNumber(t),...n?[`--force`]:[]]});return n?`${i} (replaces the migration history ID)`:i}function applyDiffToSnapshot(e,t){let n=copySnapshotRecord(e.tables);for(let e of t.changes)switch(e.kind){case`table_added`:n[e.tableName]=e.after;break;case`table_removed`:delete n[e.tableName];break;case`table_modified`:{let t=n[e.tableName];if(t&&e.after){let r=e.after;n[e.tableName]={...t,...r.indexes!==void 0&&{indexes:r.indexes},...r.files!==void 0&&{files:r.files}}}break}case`table_settings_modified`:{let t=n[e.tableName];t&&(n[e.tableName]={...t,description:e.after.description,pluralForm:e.after.pluralForm,settings:e.after.settings??{}});break}case`table_scripts_modified`:{let t=n[e.tableName];if(t){let{typeHookExpr:r,typeValidateExpr:i,...a}=t;n[e.tableName]={...a,...e.after.typeHookExpr&&{typeHookExpr:e.after.typeHookExpr},...e.after.typeValidateExpr!==void 0&&{typeValidateExpr:e.after.typeValidateExpr}}}break}case`field_added`:case`field_modified`:case`field_type_modified`:{let t=n[e.tableName];if(t){let r=copySnapshotRecord(t.fields);r[e.fieldName]=e.after,n[e.tableName]={...t,fields:r}}break}case`field_removed`:{let t=n[e.tableName];if(t){let r=copySnapshotRecord(t.fields);delete r[e.fieldName],n[e.tableName]={...t,fields:r}}break}case`field_renamed`:{let t=n[e.tableName];if(t){let r=copySnapshotRecord(t.fields);delete r[e.previousFieldName],r[e.fieldName]=e.after,n[e.tableName]={...t,fields:r}}break}case`table_renamed`:delete n[e.previousTableName],n[e.tableName]=e.after;break;case`index_added`:case`index_modified`:{let t=n[e.tableName];if(t){let r=copySnapshotRecord(t.indexes);r[e.indexName]=e.after,n[e.tableName]={...t,indexes:r}}break}case`index_removed`:{let t=n[e.tableName];if(t&&t.indexes){let r=copySnapshotRecord(t.indexes);delete r[e.indexName],n[e.tableName]={...t,indexes:Object.keys(r).length>0?r:void 0}}break}case`file_added`:case`file_modified`:{let t=n[e.tableName];if(t){let r=copySnapshotRecord(t.files);r[e.fieldName]=e.after,n[e.tableName]={...t,files:r}}break}case`file_removed`:{let t=n[e.tableName];if(t&&t.files){let r=copySnapshotRecord(t.files);delete r[e.fieldName],n[e.tableName]={...t,files:Object.keys(r).length>0?r:void 0}}break}case`relationship_added`:case`relationship_modified`:{let t=n[e.tableName];if(t){let r=e.after;if((e.relationshipType??(t.forwardRelationships?.[e.relationshipName]?`forward`:t.backwardRelationships?.[e.relationshipName]?`backward`:`forward`))===`forward`){let i=copySnapshotRecord(t.forwardRelationships);i[e.relationshipName]=r,n[e.tableName]={...t,forwardRelationships:i}}else{let i=copySnapshotRecord(t.backwardRelationships);i[e.relationshipName]=r,n[e.tableName]={...t,backwardRelationships:i}}}break}case`relationship_removed`:{let t=n[e.tableName];if(t){let r=e.relationshipType??(t.forwardRelationships?.[e.relationshipName]?`forward`:t.backwardRelationships?.[e.relationshipName]?`backward`:null);if(r===`forward`&&t.forwardRelationships?.[e.relationshipName]){let r=copySnapshotRecord(t.forwardRelationships);delete r[e.relationshipName],n[e.tableName]={...t,forwardRelationships:Object.keys(r).length>0?r:void 0}}else if(r===`backward`&&t.backwardRelationships?.[e.relationshipName]){let r=copySnapshotRecord(t.backwardRelationships);delete r[e.relationshipName],n[e.tableName]={...t,backwardRelationships:Object.keys(r).length>0?r:void 0}}}break}case`permission_modified`:{let t=n[e.tableName];if(t&&e.after){let r=e.after;n[e.tableName]={...t,permissions:{record:r.recordPermission,gql:r.gqlPermission}}}break}}return normalizeSchemaSnapshot({...e,tables:n,createdAt:t.createdAt})}function reconstructSnapshotFromMigrations(e,t){let n=getMigrationFiles(e);if(n.length===0)return null;let r=n.find(e=>e.type===`schema`&&e.number===0);if(!r)throw E({code:`MIGRATION_BASELINE_NOT_FOUND`,message:`No initial schema file found in ${e}. Expected ${formatMigrationNumber(0)}/schema.json`});let i=loadSnapshot(r.path);for(let e of n)if(e.type===`diff`&&e.number>r.number){if(t!==void 0&&e.number>t)continue;let n=loadDiff(e.path);i=applyDiffToSnapshot(i,n)}return i}function validateMigrationFiles(e){let t=[];if(!W.existsSync(e))return t;let n=getMigrationArtifacts(e);if(n.length===0)return t;let r=[],i=[];for(let{number:e,fileTypes:t}of n)t.includes(`schema`)&&r.push(e),t.includes(`diff`)&&i.push(e);let a=n.map(({number:e})=>e),o=Math.max(0,...i),s=o>0;if(!r.includes(0)){let e=formatMigrationNumber(0);t.push({type:`missing_schema`,message:`Initial schema snapshot (${e}/${Qo}) is missing`,suggestion:s||a.includes(0)?missingFileSuggestion(e,Qo,!s):void 0,migrationNumber:0})}for(let e of r)e!==0&&t.push({type:`invalid_schema_number`,message:`Schema file found at migration ${formatMigrationNumber(e)}, but schema should only exist at ${formatMigrationNumber(0)}`,migrationNumber:e});i.includes(0)&&t.push({type:`invalid_diff_number`,message:`Migration ${formatMigrationNumber(0)} must not have ${$o}`,migrationNumber:0});for(let e of r)e!==0&&i.includes(e)&&t.push({type:`duplicate`,message:`Migration ${formatMigrationNumber(e)} has both schema and diff files`,migrationNumber:e});let c=Math.max(...a);for(let e=0;e<=c;e++)a.includes(e)||t.push({type:`gap`,message:`Migration ${formatMigrationNumber(e)} is missing (gap in sequence)`,migrationNumber:e});for(let{number:e,fileTypes:r}of n){if(e===0||r.includes(`diff`))continue;if(r.includes(`schema`)){t.push({type:`missing_diff`,message:`Migration ${formatMigrationNumber(e)} is missing diff file`,migrationNumber:e});continue}let n=formatMigrationNumber(e),i=r.map(e=>os[e]).join(`, `);t.push({type:`missing_diff`,message:`Migration ${n} has ${i} but no ${$o}`,suggestion:missingFileSuggestion(n,$o,e>o),migrationNumber:e})}return t}function missingFileSuggestion(e,t,n){return n?`Delete migration directory ${e} if it is a leftover, or restore its ${t}.`:`Restore ${t} in migration directory ${e}.`}function assertValidMigrationFiles(e,t,n){let r=validateMigrationFiles(e);if(r.length>0){let e=r.map(e=>` - ${e.message}`).join(`
|
|
6
|
+
`)}const Ma={table_added:`table(s) added`,table_removed:`table(s) removed`,table_renamed:`table(s) renamed`,table_modified:`table(s) modified`,table_settings_modified:`table setting(s) modified`,field_added:`field(s) added`,field_removed:`field(s) removed`,field_modified:`field(s) modified`,field_renamed:`field(s) renamed`,field_type_modified:`field type(s) modified`,index_added:`index(es) added`,index_removed:`index(es) removed`,index_modified:`index(es) modified`,file_added:`file field(s) added`,file_removed:`file field(s) removed`,file_modified:`file field(s) modified`,relationship_added:`relationship(s) added`,relationship_removed:`relationship(s) removed`,relationship_modified:`relationship(s) modified`,permission_modified:`permission(s) modified`,table_scripts_modified:`table script(s) modified`};function formatDiffSummary(e){let t={};for(let n of e.changes)t[n.kind]=(t[n.kind]??0)+1;let n=Object.keys(t).map(e=>`${t[e]} ${Ma[e]}`);return n.length>0?n.join(`, `):`No changes`}function formatMigrationNumber(e){return e.toString().padStart(4,`0`)}function parseMigrationNumberArg(e){if(/^\d{4}$/.test(e))return parseInt(e,10);if(/^(0|[1-9]\d*)$/.test(e)){let t=parseInt(e,10);if(t>9999)throw E({code:`MIGRATION_NUMBER_INVALID`,message:`Migration number ${e} is out of range. Expected 0-9999.`});return t}throw E({code:`MIGRATION_NUMBER_INVALID`,message:`Invalid migration number format: ${e}. Expected 4-digit format (e.g., 0001) or integer 0-9999 (e.g., 1).`})}const Na=`MIGRATION_FILE_VERSION_UNSUPPORTED`;function assertSupportedMigrationFileVersion(e,t){if(typeof t!=`object`||!t||!(`version`in t))return;let n=t.version;if(typeof n!=`number`||Number.isInteger(n)&&n>=1&&n<=8)return;let r;throw r=n>8?`Upgrade to an SDK that supports migration file format version ${n}.`:n<1?`Re-baseline with an SDK that still supports this migration history, then upgrade the SDK.`:`Restore the migration file from version control or regenerate it.`,E({code:Na,message:`Unsupported migration file format version ${n} at ${e}.`,details:`This SDK supports migration file format versions 1-8.`,suggestion:r})}const Pa=/* @__PURE__ */ new Map([[`type_added`,`table_added`],[`type_removed`,`table_removed`],[`type_renamed`,`table_renamed`],[`type_modified`,`table_modified`],[`type_settings_modified`,`table_settings_modified`],[`type_scripts_modified`,`table_scripts_modified`]]);function normalizeLegacyChangeKinds(e){if(typeof e!=`object`||!e||!(`changes`in e))return e;let t=e.changes;if(!Array.isArray(t))return e;let n=t.map(e=>{if(typeof e!=`object`||!e||!(`kind`in e))return e;let t=e.kind;if(typeof t!=`string`)return e;let n=Pa.get(t);return n===void 0?e:{...e,kind:n}});return{...e,changes:n}}const Fa=/* @__PURE__ */ new Map([[`typeName`,`tableName`],[`previousTypeName`,`previousTableName`]]);function renameLegacyEntryFields(e){if(typeof e!=`object`||!e||Array.isArray(e))return e;let t=e,n={},r=!1;for(let[e,i]of Object.entries(t)){let a=Fa.get(e);a!==void 0&&!(a in t)?(n[a]=i,r=!0):n[e]=i}return r?n:e}const Ia=[`changes`,`breakingChanges`,`warnings`];function normalizeLegacyTablesKey(e){if(typeof e!=`object`||!e)return e;let t=e;if(!(`types`in t)||`tables`in t)return e;let{types:n,...r}=t;return{...r,tables:n}}function normalizeLegacyFieldNames(e){if(typeof e!=`object`||!e)return e;let t=e,n={...t};for(let e of Ia){let r=t[e];Array.isArray(r)&&(n[e]=r.map(renameLegacyEntryFields))}return n}function createSnapshotRecord(){return Object.create(null)}function copySnapshotRecord(e){let t=createSnapshotRecord();for(let[n,r]of Object.entries(e??{}))t[n]=r;return t}function normalizeSnapshotField(e){let t=e.fields?Object.fromEntries(Object.entries(e.fields).map(([e,t])=>[e,normalizeSnapshotField(t)])):void 0;return{...e,...e.type===`decimal`&&e.scale===void 0&&{scale:6},...t&&{fields:t}}}function normalizeSnapshotType(e){let t=e.pluralForm||Di.pluralize(e.name),n=createSnapshotRecord();for(let[t,r]of Object.entries(e.fields))n[t]=normalizeSnapshotField(r);return{...e,pluralForm:t,fields:n}}function normalizeSchemaSnapshot(e){let t=createSnapshotRecord();for(let[n,r]of Object.entries(e.tables))t[n]=normalizeSnapshotType(r);return{...e,tables:t}}const La=/* @__PURE__ */ new Set([`boolean:string`,`decimal:float`,`decimal:string`,`enum:string`,`float:decimal`,`float:string`,`integer:decimal`,`integer:float`,`integer:string`,`uuid:string`]);function supportsInPlaceFieldTypeChange(e,t){return e.type===t.type||e.array||t.array||e.type===`nested`||t.type===`nested`||e.serial||t.serial||e.vector||t.vector||e.foreignKey||t.foreignKey||!La.has(`${e.type}:${t.type}`)?!1:!(e.unique??!1)||t.type!==`decimal`||e.type!==`float`}function formatFieldShape(e){return e.array?`${e.type}[]`:e.type}function hasFieldShapeChange(e,t){return e.type!==t.type||(e.array??!1)!==(t.array??!1)}function isSingleValueToArrayChange(e,t){if(e.type!==t.type||e.array||!t.array||e.type===`decimal`&&(t.scale??6)<(e.scale??6))return!1;let n=new Set((t.allowedValues??[]).map(e=>e.value));return(e.allowedValues??[]).every(e=>n.has(e.value))}function getExpandContractFieldChangeEligibility(e,t){return hasFieldShapeChange(e,t)?supportsInPlaceFieldTypeChange(e,t)?{eligible:!1,reason:`the ${e.type} to ${t.type} change is already supported in place`}:e.unique||t.unique?{eligible:!1,reason:`the field is unique`}:e.array?{eligible:!1,reason:`the field is an array`}:e.type===`nested`||t.type===`nested`?{eligible:!1,reason:`the field is nested`}:e.serial||t.serial?{eligible:!1,reason:`the field uses a serial sequence`}:e.vector||t.vector?{eligible:!1,reason:`the field is a vector`}:e.foreignKey||t.foreignKey?{eligible:!1,reason:`the field is a foreign key`}:{eligible:!0}:{eligible:!1,reason:`the field type did not change`}}function collectForeignKeyReferences(e){let t=[],visit=(e,n)=>{for(let[r,i]of Object.entries(e)){let e=`${n}${r}`;i.foreignKeyType!==void 0&&t.push({table:i.foreignKeyType,field:i.foreignKeyField,path:e}),i.fields&&visit(i.fields,`${e}.`)}};return visit(e,``),t}function collectForeignKeyTargets(e){return[...new Set(collectForeignKeyReferences(e).map(e=>e.table))]}const Ra=/* @__PURE__ */ new Set([`index`,`unique`,`vector`]);function isRenameCompatible(e,t){if(e.type!==t.type)return!1;for(let n of Aa)if(!Ra.has(n)&&(e[n]??!1)!==(t[n]??!1))return!1;if((e.foreignKeyType??``)!==(t.foreignKeyType??``)||(e.foreignKeyField??``)!==(t.foreignKeyField??``)||e.serial||t.serial)return!1;if(e.type===`enum`){let n=new Set((t.allowedValues??[]).map(e=>e.value));if((e.allowedValues??[]).some(e=>!n.has(e.value)))return!1}let n=e.fields??{},r=t.fields??{},i=Object.keys(n),a=Object.keys(r);if(i.length!==a.length)return!1;for(let e of i){let t=n[e],i=r[e];if(!t||!i||t.required!==i.required||!isRenameCompatible(t,i))return!1}return!0}function findRenameCandidates(e){let t=/* @__PURE__ */ new Map,n=/* @__PURE__ */ new Map;for(let r of e.changes)if(r.kind===`field_removed`){let e=t.get(r.tableName)??[];e.push(r),t.set(r.tableName,e)}else if(r.kind===`field_added`){let e=n.get(r.tableName)??[];e.push(r),n.set(r.tableName,e)}let r=[];for(let[e,i]of t){let t=n.get(e);if(t)for(let n of i){let i=t.filter(e=>isRenameCompatible(n.before,e.after));i.length>0&&r.push({tableName:e,removed:n,added:i})}}return r}function renameSpecApplies(e,t,n){let r=t.tables[e.tableName]?.fields,i=n.tables[e.tableName]?.fields;return!(!r?.[e.previousFieldName]||i?.[e.previousFieldName]||!i?.[e.fieldName]||r[e.fieldName])}function assertValidFieldRenames(e,t,n){let r=/* @__PURE__ */ new Set;for(let i of n){let{tableName:n,previousFieldName:a,fieldName:o}=i,s=`${n}.${a}:${o}`;for(let e of[`${n}.${a}`,`${n}.${o}`]){if(r.has(e))throw E({code:`MIGRATION_RENAME_INVALID`,message:`Field "${e}" appears in more than one rename.`});r.add(e)}let c=e.tables[n],l=t.tables[n];if(!c||!l)throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${s}: table "${n}" must exist in both the previous and the current schema.`});let u=c.fields[a];if(!u)throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${s}: field "${a}" does not exist in the previous schema.`});if(l.fields[a])throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${s}: field "${a}" still exists in the current schema.`});let d=l.fields[o];if(!d)throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${s}: field "${o}" does not exist in the current schema.`});if(c.fields[o])throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${s}: field "${o}" already exists in the previous schema.`});if(!isRenameCompatible(u,d))throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${s}: the fields are not rename-compatible (the field type, array-ness, and foreign key target must match, enum values must not be removed, nested member names, requiredness, and types must match recursively, and serial fields cannot be renamed).`})}}const za=/^([^.:\s]+)\.([^.:\s]+):([^.:\s]+)$/;function parseRenameOption(e){let[,t,n,r]=e.match(za)??[];if(!t||!n||!r)throw E({code:`MIGRATION_RENAME_FLAG_INVALID`,message:`Invalid --rename value "${e}". Expected format: "Table.oldField:newField".`,command:`tailordb migration generate`});if(n===r)throw E({code:`MIGRATION_RENAME_FLAG_INVALID`,message:`Invalid --rename value "${e}": old and new field names are identical.`,command:`tailordb migration generate`});return{tableName:t,previousFieldName:n,fieldName:r}}const Ba=/^([^.:\s]+)\.([^.:\s]+)$/;function parseDropOption(e){let[,t,n]=e.match(Ba)??[];if(!t||!n)throw E({code:`MIGRATION_DROP_FLAG_INVALID`,message:`Invalid --drop value "${e}". Expected format: "Table.field".`,command:`tailordb migration generate`});return{tableName:t,fieldName:n}}function dropSpecApplies(e,t,n){let r=t.tables[e.tableName]?.fields,i=n.tables[e.tableName]?.fields;return!(!r?.[e.fieldName]||i?.[e.fieldName])}function parseExpandContractOption(e){let[,t,n]=e.match(Ba)??[];if(!t||!n)throw E({code:`MIGRATION_EXPAND_CONTRACT_FLAG_INVALID`,message:`Invalid --expand-contract value "${e}". Expected format: "Table.field".`,command:`tailordb migration generate`});return{tableName:t,fieldName:n}}function isNestedMemberRenameCompatible(e,t){if(e.type!==t.type||e.required!==t.required)return!1;for(let n of Aa)if(!Ra.has(n)&&(e[n]??!1)!==(t[n]??!1))return!1;if((e.foreignKeyType??``)!==(t.foreignKeyType??``)||(e.foreignKeyField??``)!==(t.foreignKeyField??``)||e.serial||t.serial||(e.scale??null)!==(t.scale??null)||(e.hooks?.create?.expr??``)!==(t.hooks?.create?.expr??``)||(e.hooks?.update?.expr??``)!==(t.hooks?.update?.expr??``))return!1;let n=e.validate??[],r=t.validate??[];if(n.length!==r.length)return!1;for(let[e,t]of n.entries()){let n=r[e];if((t.script?.expr??``)!==(n?.script?.expr??``)||t.errorMessage!==n?.errorMessage)return!1}if(e.type===`enum`){let n=new Set((t.allowedValues??[]).map(e=>e.value));if((e.allowedValues??[]).some(e=>!n.has(e.value)))return!1}let i=e.fields??{},a=t.fields??{},o=Object.keys(i);if(o.length!==Object.keys(a).length)return!1;for(let e of o){let t=i[e],n=Object.hasOwn(a,e)?a[e]:void 0;if(!t||!n||!isNestedMemberRenameCompatible(t,n))return!1}return!0}function haveSameParent(e,t){return e.length===t.length&&e.slice(0,-1).every((e,n)=>e===t[n])}function findNestedMemberRenameCandidates(e){let t=[];for(let n of e.changes){if(n.kind!==`field_modified`)continue;let e=collectNestedMemberChanges(n.before,n.after);for(let r of e){if(r.kind!==`removed`)continue;let i=e.filter(e=>e.kind===`added`&&haveSameParent(e.path,r.path)&&isNestedMemberRenameCompatible(r.before,e.after)).map(e=>e.path[e.path.length-1]).filter(e=>e!==void 0);i.length>0&&t.push({tableName:n.tableName,fieldName:n.fieldName,previousPath:r.path,removed:r.before,added:i})}}return t}function nestedMemberRenameSpecApplies(e,t,n){let r=t.tables[e.tableName]?.fields[e.fieldName],i=n.tables[e.tableName]?.fields[e.fieldName];return!(!getNestedMember(r,e.previousPath)||getNestedMember(i,e.previousPath)||!getNestedMember(i,e.path)||getNestedMember(r,e.path))}function assertValidNestedMemberRenames(e,t,n){let r=/* @__PURE__ */ new Set;for(let i of n){let{tableName:n,fieldName:a,previousPath:o,path:s}=i,c=`${n}.${a}.${o.join(`.`)}`,l=`${c}:${s[s.length-1]??``}`;for(let e of[c,`${n}.${a}.${s.join(`.`)}`]){if(r.has(e))throw E({code:`MIGRATION_RENAME_INVALID`,message:`Member "${e}" appears in more than one rename.`});r.add(e)}if(o.length===0||!haveSameParent(o,s))throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${l}: the old and new member must share the same parent inside "${a}".`});let u=e.tables[n]?.fields[a],d=t.tables[n]?.fields[a];if(u?.type!==`nested`||d?.type!==`nested`)throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${l}: "${n}.${a}" must be a nested field in both the previous and the current schema.`});for(let e=0;e<o.length;e++){let t=o.slice(0,e),r=getNestedMember(u,t),i=getNestedMember(d,t);if(r?.type!==`nested`||i?.type!==`nested`||(r.array??!1)!==(i.array??!1))throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${l}: ancestor "${[n,a,...t].join(`.`)}" must keep its nested type and array-ness. Split the ancestor change and rename into separate migrations.`})}let f=getNestedMember(u,o);if(!f)throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${l}: member "${o.join(`.`)}" does not exist in the previous schema.`});if(getNestedMember(d,o))throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${l}: member "${o.join(`.`)}" still exists in the current schema.`});let p=getNestedMember(d,s);if(!p)throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${l}: member "${s.join(`.`)}" does not exist in the current schema.`});if(getNestedMember(u,s))throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${l}: member "${s.join(`.`)}" already exists in the previous schema.`});if(!isNestedMemberRenameCompatible(f,p))throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${l}: the members are not rename-compatible (the member type, array-ness, requiredness, foreign key target, scale, hooks, and validations must match, enum values must not be removed, nested members must match recursively, and serial members cannot be renamed).`})}}const Va=/^([^.:\s]+)\.([^.:\s]+)((?:\.[^.:\s]+)+):([^.:\s]+)$/;function parseNestedMemberRenameOption(e){let[,t,n,r,i]=e.match(Va)??[];if(!t||!n||!r||!i)throw E({code:`MIGRATION_RENAME_FLAG_INVALID`,message:`Invalid --rename value "${e}". Expected format: "Table.field.member:newName".`,command:`tailordb migration generate`});let a=r.slice(1).split(`.`);if(a[a.length-1]===i)throw E({code:`MIGRATION_RENAME_FLAG_INVALID`,message:`Invalid --rename value "${e}": old and new member names are identical.`,command:`tailordb migration generate`});return{tableName:t,fieldName:n,previousPath:a,path:[...a.slice(0,-1),i]}}const Ha=/^([^.:\s]+)\.([^.:\s]+)((?:\.[^.:\s]+)+)$/;function parseNestedMemberDropOption(e){let[,t,n,r]=e.match(Ha)??[];if(!t||!n||!r)throw E({code:`MIGRATION_DROP_FLAG_INVALID`,message:`Invalid --drop value "${e}". Expected format: "Table.field.member".`,command:`tailordb migration generate`});return{tableName:t,fieldName:n,path:r.slice(1).split(`.`)}}function nestedMemberDropSpecApplies(e,t,n){let r=t.tables[e.tableName]?.fields[e.fieldName],i=n.tables[e.tableName]?.fields[e.fieldName];return!!(getNestedMember(r,e.path)&&!getNestedMember(i,e.path)&&getNestedMember(i,e.path.slice(0,-1)))}function retargetSelfReferences(e,t,n){let r=e.fields?Object.fromEntries(Object.entries(e.fields).map(([e,r])=>[e,retargetSelfReferences(r,t,n)])):void 0;return{...e,...e.foreignKeyType===t&&{foreignKeyType:n},...r&&{fields:r}}}function stableStringify(e){return Array.isArray(e)?`[${e.map(stableStringify).join(`,`)}]`:typeof e==`object`&&e?`{${Object.entries(e).filter(([,e])=>e!==void 0).toSorted(([e],[t])=>e.localeCompare(t)).map(([e,t])=>`${JSON.stringify(e)}:${stableStringify(t)}`).join(`,`)}}`:JSON.stringify(e)}function hasRequiredReferenceTo(e,t){return e.foreignKeyType===t&&e.required?!0:Object.values(e.fields??{}).some(e=>hasRequiredReferenceTo(e,t))}function hasSelfReferenceKeyedToSelfReference(e){return collectForeignKeyReferences(e.fields).some(t=>t.table===e.name&&t.field!==void 0&&e.fields[t.field]?.foreignKeyType===e.name)}function hasUniqueNestedSelfReference(e){let t=new Set(Object.values(e.indexes??{}).flatMap(e=>e.unique?e.fields:[]));return Object.entries(e.fields).some(([n,r])=>r.fields!==void 0&&(r.unique||t.has(n))&&collectForeignKeyReferences(r.fields).some(t=>t.table===e.name))}function isTypeRenameFieldCompatible(e,t){if(!isRenameCompatible(e,t)||e.required!==t.required||(e.unique??!1)!==(t.unique??!1)||(e.scale??null)!==(t.scale??null))return!1;for(let[n,r]of Object.entries(e.fields??{})){let e=t.fields?.[n];if(!e||!isTypeRenameFieldCompatible(r,e))return!1}return!0}function isTypeRenameCompatible(e,t){if(Object.keys(e.files??{}).length>0||Object.keys(t.files??{}).length>0||hasSelfReferenceKeyedToSelfReference(e)||hasUniqueNestedSelfReference(e))return!1;let n=Object.keys(e.fields),r=Object.keys(t.fields);if(n.length!==r.length)return!1;for(let r of n){let n=e.fields[r],i=t.fields[r];if(!n||!i||hasRequiredReferenceTo(n,e.name)||!isTypeRenameFieldCompatible(retargetSelfReferences(n,e.name,t.name),i))return!1}return stableStringify(e.indexes??{})===stableStringify(t.indexes??{})}function findTypeRenameCandidates(e){let t=e.changes.filter(e=>e.kind===`table_removed`),n=e.changes.filter(e=>e.kind===`table_added`),r=[];for(let e of t){let t=n.filter(t=>isTypeRenameCompatible(e.before,t.after));t.length>0&&r.push({removed:e,added:t})}return r}function typeRenameSpecApplies(e,t,n){return!(!t.tables[e.previousTableName]||n.tables[e.previousTableName]||!n.tables[e.tableName]||t.tables[e.tableName])}function assertValidTypeRenames(e,t,n){let r=/* @__PURE__ */ new Set;for(let i of n){let{previousTableName:n,tableName:a}=i,o=`${n}:${a}`;for(let e of[n,a]){if(r.has(e))throw E({code:`MIGRATION_RENAME_INVALID`,message:`Table "${e}" appears in more than one rename.`});r.add(e)}let s=e.tables[n];if(!s)throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${o}: table "${n}" does not exist in the previous schema.`});if(t.tables[n])throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${o}: table "${n}" still exists in the current schema.`});let c=t.tables[a];if(!c)throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${o}: table "${a}" does not exist in the current schema.`});if(e.tables[a])throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${o}: table "${a}" already exists in the previous schema.`});if(!isTypeRenameCompatible(s,c))throw E({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${o}: the tables are not rename-compatible (every field must keep its name, type, array-ness, required/unique constraints, foreign key target, and scale, enum values must not be removed, indexes must match, self-referential foreign keys must be optional, and tables with serial or file fields cannot be renamed).`})}}function isBreakingForeignKeyRetarget(e,t,n){return!(!e.foreignKeyType||!t.foreignKeyType||e.foreignKeyType===t.foreignKeyType||n?.get(e.foreignKeyType)===t.foreignKeyType&&(e.foreignKeyField??``)===(t.foreignKeyField??``))}const Ua=/^([^.:\s]+):([^.:\s]+)$/;function parseTypeRenameOption(e){let[,t,n]=e.match(Ua)??[];if(!t||!n)throw E({code:`MIGRATION_RENAME_FLAG_INVALID`,message:`Invalid --rename value "${e}". Expected format: "Table.oldField:newField" or "OldTable:NewTable".`,command:`tailordb migration generate`});if(t===n)throw E({code:`MIGRATION_RENAME_FLAG_INVALID`,message:`Invalid --rename value "${e}": old and new table names are identical.`,command:`tailordb migration generate`});return{previousTableName:t,tableName:n}}const Wa=/^([^.:\s]+)$/;function parseTypeDropOption(e){let[,t]=e.match(Wa)??[];if(!t)throw E({code:`MIGRATION_DROP_FLAG_INVALID`,message:`Invalid --drop value "${e}". Expected format: "Table.field" or "Table".`,command:`tailordb migration generate`});return{tableName:t}}function typeDropSpecApplies(e,t,n){return!(!t.tables[e.tableName]||n.tables[e.tableName])}const Ga=`Field removed (existing data will no longer be accessible through the schema)`,Ka=`Table removed (all records in this table will be deleted during post-migration cleanup)`;function collectNestedMemberRemovalWarnings(e){let t=collectNestedMemberChanges(e.before,e.after),n=new Set((e.memberRenames??[]).flatMap(e=>[e.previousPath.join(`.`),e.path.join(`.`)])),r=[];for(let i of t){if(i.kind!==`removed`||n.has(i.path.join(`.`)))continue;let a=t.filter(e=>e.kind===`added`&&!n.has(e.path.join(`.`))&&haveSameParent(e.path,i.path)&&isNestedMemberRenameCompatible(i.before,e.after)).map(e=>e.path.at(-1)),o=a.length>0?`. Possibly renamed to ${a.join(`, `)}: confirm it with --rename "${e.tableName}.${e.fieldName}.${i.path.join(`.`)}:<newName>" to scaffold a copy script, or keep the removal and copy the values yourself`:``;r.push({tableName:e.tableName,fieldName:[e.fieldName,...i.path].join(`.`),reason:`Nested member removed (existing values will no longer be accessible through the schema)${o}`})}return r}function deriveWarningsFromChanges(e){let t=[];for(let n of e.changes)n.kind===`field_removed`?t.push({tableName:n.tableName,fieldName:n.fieldName,reason:Ga}):n.kind===`table_removed`?t.push({tableName:n.tableName,reason:Ka}):n.kind===`field_modified`&&t.push(...collectNestedMemberRemovalWarnings(n));return t}function areFieldsDifferent(e,t){return areOwnFieldConfigsDifferent(e,t)||collectNestedMemberChanges(e,t).length>0}function addsForeignKey(e,t){return!e.foreignKeyType&&!!t.foreignKeyType}function getBreakingFieldChanges(e,t,n,r,i,a=!1){let o=[];if(!n&&r&&r.required&&o.push({tableName:e,fieldName:t,reason:`Required field added`}),n&&r&&n.type!==r.type){let i=!a&&supportsInPlaceFieldTypeChange(n,r);o.push({tableName:e,fieldName:t,reason:`Field type changed from ${n.type} to ${r.type}`,...!i&&{unsupported:!0,showThreeStepHint:!0}})}if(n&&r&&!n.required&&r.required&&o.push({tableName:e,fieldName:t,reason:`Field changed from optional to required`}),n&&r&&(n.array??!1)!==(r.array??!1)){let[r,i]=n.array?[`array`,`single value`]:[`single value`,`array`];o.push({tableName:e,fieldName:t,reason:`Field changed from ${r} to ${i}`,unsupported:!0,showThreeStepHint:!0})}if(n&&r&&isBreakingForeignKeyRetarget(n,r,i)&&o.push({tableName:e,fieldName:t,reason:`Foreign key target type changed from ${n.foreignKeyType} to ${r.foreignKeyType}`,...a&&{unsupported:!0,showThreeStepHint:!0}}),!a&&n&&r&&addsForeignKey(n,r)&&o.push({tableName:e,fieldName:t,reason:`Foreign key to ${r.foreignKeyType} added to field`}),n&&r&&!(n.unique??!1)&&(r.unique??!1)&&o.push({tableName:e,fieldName:t,reason:`Unique constraint added to field`}),n?.type===`decimal`&&r?.type===`decimal`&&n.scale!==r.scale&&o.push({tableName:e,fieldName:t,reason:`Decimal scale changed from ${n.scale} to ${r.scale}`,...a&&{unsupported:!0,showThreeStepHint:!0}}),n&&r&&n.type===`enum`&&r.type===`enum`){let i=n.allowedValues??[],a=r.allowedValues??[],s=i.map(e=>e.value),c=new Set(a.map(e=>e.value)),l=s.filter(e=>!c.has(e));l.length>0&&o.push({tableName:e,fieldName:t,reason:`Enum values removed: ${l.join(`, `)}`})}return o}function collectBreakingNestedMemberChanges(e,t){return collectNestedMemberChanges(e.before,e.after).flatMap(n=>n.kind===`removed`||n.kind===`added`&&e.memberRenames?.some(e=>e.path.length===n.path.length&&e.path.every((e,t)=>e===n.path[t]))?[]:getBreakingFieldChanges(e.tableName,[e.fieldName,...n.path].join(`.`),n.kind===`modified`?n.before:void 0,n.after,t,!0))}function addChange(e,t,n,r){if(e.changes.push(t),!t.fieldName)return;t.kind===`field_modified`&&(e.warnings.push(...collectNestedMemberRemovalWarnings(t)),e.breakingChanges.push(...collectBreakingNestedMemberChanges(t,e.typeRenameTargets)));let i=getBreakingFieldChanges(t.tableName,t.fieldName,n,r,e.typeRenameTargets);i.length>0?e.breakingChanges.push(...i):t.kind===`field_removed`&&e.warnings.push({tableName:t.tableName,fieldName:t.fieldName,reason:Ga})}function compareTypeFields(e,t,n,r,i=[],o=[]){let s=new Set(Object.keys(n.fields)),c=new Set(Object.keys(r.fields)),l=new Set(i.map(e=>e.previousFieldName)),u=new Set(i.map(e=>e.fieldName));for(let o of i){let i=a(n.fields[o.previousFieldName],`renamed field "${o.previousFieldName}" missing from prevType`),s=a(r.fields[o.fieldName],`renamed field "${o.fieldName}" missing from currType`);e.changes.push({kind:`field_renamed`,tableName:t,fieldName:o.fieldName,previousFieldName:o.previousFieldName,before:i,after:s}),e.breakingChanges.push({tableName:t,fieldName:o.fieldName,reason:`Field renamed from ${o.previousFieldName} to ${o.fieldName} (existing values must be copied by the migration script)`})}for(let n of c)if(!u.has(n)&&!s.has(n)){let i=a(r.fields[n],`field "${n}" missing from currType`);addChange(e,{kind:`field_added`,tableName:t,fieldName:n,after:i},void 0,i)}for(let r of s)if(!l.has(r)&&!c.has(r)){let i=a(n.fields[r],`field "${r}" missing from prevType`);addChange(e,{kind:`field_removed`,tableName:t,fieldName:r,before:i},i,void 0)}for(let i of c){if(!s.has(i))continue;let c=a(n.fields[i],`field "${i}" missing from prevType`),l=a(r.fields[i],`field "${i}" missing from currType`);if(!areFieldsDifferent(c,l))continue;if(c.type!==l.type){addChange(e,{kind:`field_type_modified`,tableName:t,fieldName:i,before:c,after:l},c,l);continue}let u=o.filter(e=>e.fieldName===i).map(({previousPath:e,path:t})=>({previousPath:e,path:t}));addChange(e,{kind:`field_modified`,tableName:t,fieldName:i,before:c,after:l,...u.length>0&&{memberRenames:u}},c,l);for(let n of u)e.breakingChanges.push({tableName:t,fieldName:[i,...n.path].join(`.`),reason:`Nested member renamed from ${n.previousPath.join(`.`)} to ${n.path.join(`.`)} (existing values must be copied by the migration script)`})}}function isBreakingIndexChange(e,t,n,r){return!r||!(r.unique??!1)?null:!n||!(n.unique??!1)?{tableName:e,reason:`Unique constraint added to index "${t}"`}:JSON.stringify(n.fields.toSorted())===JSON.stringify(r.fields.toSorted())?null:{tableName:e,reason:`Unique index fields changed on index "${t}"`}}function compareIndexes(e,t,n,r){let i=new Set(Object.keys(n||{})),o=new Set(Object.keys(r||{}));for(let[n,a]of Object.entries(r??{}))if(!i.has(n)){e.changes.push({kind:`index_added`,tableName:t,indexName:n,after:a});let r=isBreakingIndexChange(t,n,void 0,a);r&&e.breakingChanges.push(r)}for(let[r,i]of Object.entries(n??{}))o.has(r)||e.changes.push({kind:`index_removed`,tableName:t,indexName:r,before:i});for(let[o,s]of Object.entries(r??{}))if(i.has(o)){let r=a(a(n,`oldIndexes is undefined when oldKeys has entry`)[o],`index "${o}" missing from oldIndexes`),i=JSON.stringify(r.fields.toSorted()),c=JSON.stringify(s.fields.toSorted());if(i!==c||(r.unique??!1)!==(s.unique??!1)){let n=[];i!==c&&n.push(`fields changed`),(r.unique??!1)!==(s.unique??!1)&&n.push(`unique constraint changed`),e.changes.push({kind:`index_modified`,tableName:t,indexName:o,reason:n.join(`, `),before:r,after:s});let a=isBreakingIndexChange(t,o,r,s);a&&e.breakingChanges.push(a)}}}function compareFiles(e,t,n,r){let i=new Set(Object.keys(n||{})),o=new Set(Object.keys(r||{}));for(let[n,a]of Object.entries(r??{}))i.has(n)||e.changes.push({kind:`file_added`,tableName:t,fieldName:n,after:a});for(let[r,i]of Object.entries(n??{}))o.has(r)||e.changes.push({kind:`file_removed`,tableName:t,fieldName:r,before:i});for(let[o,s]of Object.entries(r??{}))if(i.has(o)){let r=a(a(n,`oldFiles is undefined when oldKeys has entry`)[o],`file "${o}" missing from oldFiles`);r!==s&&e.changes.push({kind:`file_modified`,tableName:t,fieldName:o,reason:`description changed`,before:r,after:s})}}function compareRelationships(e,t,n,r,i){let o=new Set(Object.keys(r||{})),s=new Set(Object.keys(i||{}));for(let[r,a]of Object.entries(i??{}))o.has(r)||e.changes.push({kind:`relationship_added`,tableName:t,relationshipName:r,relationshipType:n,after:a});for(let[i,a]of Object.entries(r??{}))s.has(i)||e.changes.push({kind:`relationship_removed`,tableName:t,relationshipName:i,relationshipType:n,before:a});for(let[s,c]of Object.entries(i??{}))if(o.has(s)){let i=a(a(r,`oldRelationships is undefined when oldKeys has entry`)[s],`relationship "${s}" missing from oldRelationships`),o=[];i.targetType!==c.targetType&&o.push(`targetType changed`),i.targetField!==c.targetField&&o.push(`targetField changed`),i.sourceField!==c.sourceField&&o.push(`sourceField changed`),i.isArray!==c.isArray&&o.push(`isArray changed`),i.description!==c.description&&o.push(`description changed`),o.length>0&&e.changes.push({kind:`relationship_modified`,tableName:t,relationshipName:s,relationshipType:n,reason:o.join(`, `),before:i,after:c})}}function comparePermissions(e,t,n,r,i,a){let o=comparableRecordPermission(n),s=comparableRecordPermission(r),c=JSON.stringify(o??null)!==JSON.stringify(s??null),l=comparableGqlPermission(i),u=comparableGqlPermission(a),d=JSON.stringify(l??null)!==JSON.stringify(u??null);if(c||d){let n=[];c&&n.push(`record permission`),d&&n.push(`GQL permission`),e.changes.push({kind:`permission_modified`,tableName:t,reason:`${n.join(` and `)} changed`,before:{recordPermission:o,gqlPermission:l},after:{recordPermission:s,gqlPermission:u}})}}const qa={all:0,create:1,read:2,update:3,delete:4,aggregate:5,bulkUpsert:6};function sortByJson(e){return e.map(e=>[JSON.stringify(e),e]).toSorted(([e],[t])=>e<t?-1:+(e>t)).map(([,e])=>e)}function comparableGqlPermission(e){let t=e?.map(e=>({...e,conditions:sortByJson(e.conditions),actions:e.actions.toSorted((e,t)=>qa[e]-qa[t])}));return t&&t.length>0?sortByJson(t):void 0}function comparableRecordPermission(e){if(e&&Object.values(e).some(e=>e.length>0))return{create:sortByJson(e.create.map(canonicalActionPermission)),read:sortByJson(e.read.map(canonicalActionPermission)),update:sortByJson(e.update.map(canonicalActionPermission)),delete:sortByJson(e.delete.map(canonicalActionPermission))}}function canonicalActionPermission(e){return{...e,conditions:sortByJson(e.conditions)}}function normalizeComparableGqlOperations(e){if(e)return{create:e.create??!0,update:e.update??!0,delete:e.delete??!0,read:e.read??!0}}function normalizeComparableSettings(e){let t={};e?.aggregation===!0&&(t.aggregation=!0),e?.bulkUpsert===!0&&(t.bulkUpsert=!0),e?.publishEvents===!0&&(t.publishEvents=!0);let n=normalizeComparableGqlOperations(e?.gqlOperations);return n&&(t.gqlOperations=n),Object.keys(t).length>0?t:void 0}function typeSettingsState(e,t,n){return{...e?{description:e}:{},pluralForm:t,...n&&{settings:n}}}function comparableTypeSettings(e){return typeSettingsState(e.description,Di.camelize(e.pluralForm,!0),normalizeComparableSettings(e.settings))}function snapshotTypeSettingsState(e){return typeSettingsState(e.description,e.pluralForm,e.settings??{})}function compareTypeSettings(e,t,n,r){let i=comparableTypeSettings(n),a=comparableTypeSettings(r);JSON.stringify(i)!==JSON.stringify(a)&&e.changes.push({kind:`table_settings_modified`,tableName:t,reason:`settings changed`,before:snapshotTypeSettingsState(n),after:snapshotTypeSettingsState(r)})}function typeScriptsState(e){return{...e.typeHookExpr&&{typeHookExpr:e.typeHookExpr},...e.typeValidateExpr!==void 0&&{typeValidateExpr:e.typeValidateExpr}}}function compareTypeScripts(e,t,n,r){let i=typeScriptsState(n),a=typeScriptsState(r);JSON.stringify(i)!==JSON.stringify(a)&&e.changes.push({kind:`table_scripts_modified`,tableName:t,reason:`table-level scripts changed`,before:i,after:a})}function buildExpandBaseSnapshot(e,t){let n=copySnapshotRecord(e.tables);for(let e of t){let t=n[e.tableName],r=t?.fields[e.fieldName];if(!t||!r)continue;let i=copySnapshotRecord(t.fields);i[e.fieldName]={...r,required:!1},n[e.tableName]={...t,fields:i}}return normalizeSchemaSnapshot({...e,tables:n})}function buildExpandDiff(e,t,n){return{...compareSnapshots(buildExpandBaseSnapshot(e,n),t),requiresMigrationScript:!0}}function buildIntermediateSnapshot(e,t){let n=copySnapshotRecord(e.tables);for(let e of t){let t=n[e.tableName];if(!t)continue;let r=copySnapshotRecord(t.fields),{hooks:i,validate:a,...o}=e.after;r[e.tempFieldName]={...o,required:!1,unique:!1},delete r[e.fieldName],n[e.tableName]={...t,fields:r}}return normalizeSchemaSnapshot({...e,tables:n})}function compareSnapshots(e,t,n){let r=n?.fieldRenames??[];assertValidFieldRenames(e,t,r);let i=/* @__PURE__ */ new Map;for(let e of r){let t=i.get(e.tableName)??[];t.push(e),i.set(e.tableName,t)}let o=n?.nestedMemberRenames??[];assertValidNestedMemberRenames(e,t,o);let s=/* @__PURE__ */ new Map;for(let e of o){let t=s.get(e.tableName)??[];t.push(e),s.set(e.tableName,t)}let c=n?.typeRenames??[];assertValidTypeRenames(e,t,c);let l=new Map(c.map(e=>[e.previousTableName,e.tableName])),u=new Set(c.map(e=>e.tableName)),d={changes:[],breakingChanges:[],warnings:[],typeRenameTargets:l},f=new Set(Object.keys(e.tables)),p=new Set(Object.keys(t.tables));for(let n of c){let r=a(e.tables[n.previousTableName],`renamed table "${n.previousTableName}" missing from previous snapshot`),i=a(t.tables[n.tableName],`renamed table "${n.tableName}" missing from current snapshot`);d.changes.push({kind:`table_renamed`,tableName:n.tableName,previousTableName:n.previousTableName,before:r,after:i}),d.breakingChanges.push({tableName:n.tableName,reason:`Table renamed from ${n.previousTableName} to ${n.tableName} (existing records must be copied by the migration script)`}),d.breakingChanges.push({tableName:n.tableName,reason:`GraphQL API names derived from ${n.previousTableName}/${r.pluralForm} change to ${n.tableName}/${i.pluralForm} — breaking for API clients`})}for(let[e,n]of Object.entries(t.tables))u.has(e)||f.has(e)||d.changes.push({kind:`table_added`,tableName:e,after:n});for(let[t,n]of Object.entries(e.tables))l.has(t)||p.has(t)||(d.changes.push({kind:`table_removed`,tableName:t,before:n}),d.warnings.push({tableName:t,reason:Ka}));for(let n of p){if(!f.has(n))continue;let r=a(e.tables[n],`table "${n}" missing from previous snapshot`),o=a(t.tables[n],`table "${n}" missing from current snapshot`);compareTypeSettings(d,n,r,o),compareTypeScripts(d,n,r,o),compareTypeFields(d,n,r,o,i.get(n),s.get(n)),compareIndexes(d,n,r.indexes,o.indexes),compareFiles(d,n,r.files,o.files),compareRelationships(d,n,`forward`,r.forwardRelationships,o.forwardRelationships),compareRelationships(d,n,`backward`,r.backwardRelationships,o.backwardRelationships),comparePermissions(d,n,r.permissions?.record,o.permissions?.record,r.permissions?.gql,o.permissions?.gql)}return{version:8,namespace:t.namespace,createdAt:(/* @__PURE__ */ new Date()).toISOString(),changes:d.changes,hasBreakingChanges:d.breakingChanges.length>0,breakingChanges:d.breakingChanges,hasWarnings:d.warnings.length>0,warnings:d.warnings,requiresMigrationScript:d.breakingChanges.length>0}}function compareLocalTypesWithSnapshot(e,t,n){let r={version:8,namespace:n,createdAt:(/* @__PURE__ */ new Date()).toISOString(),tables:t};return compareSnapshots(normalizeSchemaSnapshot(e),normalizeSchemaSnapshot(r))}const Ja=`sdk-migration`,Ya=`sdk-migration-history`,Xa=`sdk-migration-in-progress`,Za=`-main`,Qa=`sdk-migration-execution`,$a=`sdk-maintenance-mode`,eo=`sdk-migration-cleanup`,to=/^[a-z][a-z0-9_-]{0,62}$/;function sanitizeMigrationLabel(e){return(`m`+formatMigrationNumber(e)).slice(0,63)}function parseMigrationLabelNumber(e){if(!e.startsWith(`m`))return null;let t=e.slice(1);if(!/^\d+$/.test(t))return null;let n=parseInt(t,10);return n>9999?null:n}function inProgressLabel(e,t){let n=sanitizeMigrationLabel(e);return t===`main`?`${n}${Za}`:n}function parseInProgressLabel(e){let t=e.endsWith(Za)?`main`:`steps`,n=parseMigrationLabelNumber(t===`main`?e.slice(0,-5):e);return n===null?null:{number:n,kind:t}}function parseMigrationHistoryId(e){return to.test(e)?e:null}function executionIdToLabel(e){return`e${e.replaceAll(`-`,``).toLowerCase()}`}function parseExecutionLabel(e){let t=/^e([0-9a-f]{8})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{12})$/.exec(e);return t?t.slice(1).join(`-`):null}function createMigrationHistoryId(){return`h${_i().replaceAll(`-`,``)}`}function handleOptionalToRequiredError(e,t){if(e instanceof q&&e.code===K.FailedPrecondition&&e.message.includes(`cannot be updated from non-required to required when records exist`)){C.error(`Schema change failed: Cannot change field from optional to required when records exist.`),C.newline();for(let e of t)C.info(e)}throw e}function snapshotRecordSchema(e){return U.custom(e=>typeof e==`object`&&!!e&&!Array.isArray(e),{message:`Expected record`}).transform((t,n)=>{let r=Object.create(null);for(let i of Object.keys(t)){let a=e.safeParse(t[i]);if(a.success)r[i]=a.data;else for(let e of a.error.issues)n.addIssue({...e,path:[i,...e.path]})}return r})}const no=U.looseObject({expr:U.string()}),ro=U.looseObject({script:U.looseObject({expr:U.string()}).optional(),errorMessage:U.string()}),io=U.looseObject({start:U.number(),maxValue:U.number().optional(),format:U.string().optional(),gapless:U.boolean().optional()}),ao=U.looseObject({value:U.string(),description:U.string().optional()}),oo=U.looseObject({type:U.string(),required:U.boolean().default(!0),array:U.boolean().optional(),index:U.boolean().optional(),unique:U.boolean().optional(),allowedValues:U.array(ao).optional(),foreignKey:U.boolean().optional(),foreignKeyType:U.string().optional(),foreignKeyField:U.string().optional(),description:U.string().optional(),vector:U.boolean().optional(),hooks:U.looseObject({create:no.optional(),update:no.optional()}).optional(),validate:U.array(ro).optional(),serial:io.optional(),scale:U.number().optional(),default:U.unknown().optional(),fields:U.lazy(()=>snapshotRecordSchema(oo)).optional()}),so=U.looseObject({fields:U.array(U.string()),unique:U.boolean().optional()}),co=U.looseObject({targetType:U.string(),targetField:U.string(),sourceField:U.string(),isArray:U.boolean(),description:U.string()}),lo=[`user`,`record`,`newRecord`,`oldRecord`],uo=U.unknown().refine(e=>{if(typeof e!=`object`||!e||Array.isArray(e))return!0;let t=Object.keys(e);return lo.filter(e=>t.includes(e)).length<2},`Ambiguous field-ref operand: contains more than one of user/record/newRecord/oldRecord`),fo=U.unknown().refine(e=>{if(typeof e!=`object`||!e||Array.isArray(e))return!0;let t=Object.keys(e);return lo.filter(e=>t.includes(e)).length<2},`Ambiguous field-ref operand: contains more than one of user/record/newRecord/oldRecord`).refine(e=>{if(typeof e!=`object`||!e||Array.isArray(e))return!0;let t=Object.keys(e);return![`record`,`newRecord`,`oldRecord`].some(e=>t.includes(e))},`GQL permissions only support { user } field references`),po=U.string(),mo=U.tuple([uo,po,uo]).rest(U.unknown()),ho=U.tuple([fo,po,fo]).rest(U.unknown()),go=U.looseObject({conditions:U.array(mo),description:U.string().optional(),permit:U.enum([`allow`,`deny`])}),_o=U.looseObject({create:U.array(go).default([]),read:U.array(go).default([]),update:U.array(go).default([]),delete:U.array(go).default([])}),vo=U.string(),yo=U.looseObject({conditions:U.array(ho),actions:U.array(vo),permit:U.enum([`allow`,`deny`]),description:U.string().optional()}),bo=U.array(yo),xo=U.looseObject({name:U.string(),pluralForm:U.string().optional(),description:U.string().optional(),fields:snapshotRecordSchema(oo),settings:U.looseObject({aggregation:U.boolean().optional(),bulkUpsert:U.boolean().optional(),gqlOperations:U.looseObject({create:U.boolean().optional(),update:U.boolean().optional(),delete:U.boolean().optional(),read:U.boolean().optional()}).optional(),publishEvents:U.boolean().optional()}).optional(),indexes:snapshotRecordSchema(so).optional(),files:snapshotRecordSchema(U.string()).optional(),forwardRelationships:snapshotRecordSchema(co).optional(),backwardRelationships:snapshotRecordSchema(co).optional(),permissions:U.looseObject({record:_o.optional(),gql:bo.optional()}).optional()}),So=U.looseObject({historyId:U.string().regex(to),replacedHistoryId:U.string().regex(to).nullable(),replacedLatestMigration:U.number().int().min(0).max(9999)}),Co=U.looseObject({version:U.number(),namespace:U.string(),createdAt:U.string(),tables:snapshotRecordSchema(xo),rebaseline:So.optional()}),wo=U.looseObject({indexes:snapshotRecordSchema(so).optional(),files:snapshotRecordSchema(U.string()).optional()}),To=U.looseObject({description:U.string().optional(),pluralForm:U.string(),settings:U.looseObject({aggregation:U.boolean().optional(),bulkUpsert:U.boolean().optional(),gqlOperations:U.looseObject({create:U.boolean().optional(),update:U.boolean().optional(),delete:U.boolean().optional(),read:U.boolean().optional()}).optional(),publishEvents:U.boolean().optional()}).optional()}),Eo=U.looseObject({recordPermission:_o.optional(),gqlPermission:bo.optional()}),Do=U.looseObject({kind:U.literal(`table_added`),tableName:U.string(),reason:U.string().optional(),after:xo}),Oo=U.looseObject({kind:U.literal(`table_removed`),tableName:U.string(),reason:U.string().optional(),before:xo}),ko=U.looseObject({kind:U.literal(`table_renamed`),tableName:U.string(),reason:U.string().optional(),previousTableName:U.string(),before:xo,after:xo}),Ao=U.looseObject({kind:U.literal(`table_modified`),tableName:U.string(),reason:U.string().optional(),before:wo.optional(),after:wo.optional()}),jo=U.looseObject({kind:U.literal(`table_settings_modified`),tableName:U.string(),reason:U.string().optional(),before:To,after:To}),Mo=U.looseObject({kind:U.literal(`field_added`),tableName:U.string(),reason:U.string().optional(),fieldName:U.string(),after:oo}),No=U.looseObject({kind:U.literal(`field_removed`),tableName:U.string(),reason:U.string().optional(),fieldName:U.string(),before:oo}),Po=U.looseObject({kind:U.literal(`field_modified`),tableName:U.string(),reason:U.string().optional(),fieldName:U.string(),before:oo,after:oo,memberRenames:U.array(U.looseObject({previousPath:U.array(U.string()).min(1),path:U.array(U.string()).min(1)}).refine(({previousPath:e,path:t})=>e.length===t.length&&e.slice(0,-1).every((e,n)=>e===t[n])&&e.at(-1)!==t.at(-1),{message:`memberRenames entries must rename a member within its parent`})).optional()}),Fo=U.looseObject({kind:U.literal(`field_renamed`),tableName:U.string(),reason:U.string().optional(),fieldName:U.string(),previousFieldName:U.string(),before:oo,after:oo}),Io=U.looseObject({kind:U.literal(`field_type_modified`),tableName:U.string(),reason:U.string().optional(),fieldName:U.string(),before:oo,after:oo}),Lo=U.looseObject({kind:U.literal(`index_added`),tableName:U.string(),reason:U.string().optional(),indexName:U.string(),after:so}),Ro=U.looseObject({kind:U.literal(`index_removed`),tableName:U.string(),reason:U.string().optional(),indexName:U.string(),before:so}),zo=U.looseObject({kind:U.literal(`index_modified`),tableName:U.string(),reason:U.string().optional(),indexName:U.string(),before:so,after:so}),Bo=U.looseObject({kind:U.literal(`file_added`),tableName:U.string(),reason:U.string().optional(),fieldName:U.string(),after:U.string()}),Vo=U.looseObject({kind:U.literal(`file_removed`),tableName:U.string(),reason:U.string().optional(),fieldName:U.string(),before:U.string()}),Ho=U.looseObject({kind:U.literal(`file_modified`),tableName:U.string(),reason:U.string().optional(),fieldName:U.string(),before:U.string(),after:U.string()}),Uo=U.looseObject({kind:U.literal(`relationship_added`),tableName:U.string(),reason:U.string().optional(),relationshipName:U.string(),relationshipType:U.enum([`forward`,`backward`]).optional(),after:co}),Wo=U.looseObject({kind:U.literal(`relationship_removed`),tableName:U.string(),reason:U.string().optional(),relationshipName:U.string(),relationshipType:U.enum([`forward`,`backward`]).optional(),before:co}),Go=U.looseObject({kind:U.literal(`relationship_modified`),tableName:U.string(),reason:U.string().optional(),relationshipName:U.string(),relationshipType:U.enum([`forward`,`backward`]).optional(),before:co,after:co}),Ko=U.looseObject({kind:U.literal(`permission_modified`),tableName:U.string(),reason:U.string().optional(),before:Eo.optional(),after:Eo.optional()}),qo=U.looseObject({typeHookExpr:U.looseObject({create:U.string().optional(),update:U.string().optional()}).optional(),typeValidateExpr:U.string().optional()}),Jo=U.looseObject({kind:U.literal(`table_scripts_modified`),tableName:U.string(),reason:U.string().optional(),before:qo,after:qo}),Yo=U.discriminatedUnion(`kind`,[Do,Oo,ko,Ao,jo,Mo,No,Po,Fo,Io,Lo,Ro,zo,Bo,Vo,Ho,Uo,Wo,Go,Ko,Jo]),Xo=U.looseObject({tableName:U.string(),fieldName:U.string().optional(),reason:U.string(),unsupported:U.boolean().optional(),showThreeStepHint:U.boolean().optional()}),Zo=U.looseObject({tableName:U.string(),fieldName:U.string().optional(),reason:U.string()}),Qo=U.looseObject({reason:U.string().trim().min(1),acknowledgedAt:U.string()}),$o=U.looseObject({version:U.number(),namespace:U.string(),createdAt:U.string(),description:U.string().optional(),changes:U.array(Yo),hasBreakingChanges:U.boolean(),breakingChanges:U.array(Xo),hasWarnings:U.boolean().optional(),warnings:U.array(Zo).optional(),requiresMigrationScript:U.boolean(),scriptSkipped:Qo.optional(),temporal:U.boolean().optional(),dateRepresentation:U.enum([`temporal`,`date`]).optional()}),es=0,ts=`schema.json`,ns=`diff.json`,rs=`migrate.ts`,is=`migrate.test.ts`,as=`db.ts`,os=`db.pglite.ts`,ss=`migrate.pglite.test.ts`,cs=/^\d{4}$/;function isValidMigrationNumber(e){return cs.test(e)}const ls={schema:ts,diff:ns,migrate:rs,test:is,db:as,pgliteSchema:os,pgliteTest:ss};function getMigrationDirPath(e,t){let n=formatMigrationNumber(t);return H.join(e,n)}function getMigrationFilePath(e,t,n){let r=getMigrationDirPath(e,t);return H.join(r,ls[n])}function loadSnapshot(e){let t=W.readFileSync(e,`utf-8`),n;try{n=JSON.parse(t)}catch(t){throw E({code:`MIGRATION_FILE_INVALID`,message:`Invalid schema snapshot at ${e}: ${String(t)}`,cause:t})}assertSupportedMigrationFileVersion(e,n);let r=Co.safeParse(normalizeLegacyTablesKey(n));if(!r.success){let t=u(r.error.issues);throw E({code:`MIGRATION_FILE_INVALID`,message:`Invalid schema snapshot at ${e}:\n${d(t)}`,context:{file:e,issues:t},cause:r.error})}let i=r.data;return normalizeSchemaSnapshot(i)}function loadDiff(e){let t=W.readFileSync(e,`utf-8`),n;try{n=JSON.parse(t)}catch(t){throw E({code:`MIGRATION_FILE_INVALID`,message:`Invalid migration diff at ${e}: ${String(t)}`,cause:t})}assertSupportedMigrationFileVersion(e,n);let r=$o.safeParse(normalizeLegacyFieldNames(normalizeLegacyChangeKinds(n)));if(!r.success){let t=u(r.error.issues);throw E({code:`MIGRATION_FILE_INVALID`,message:`Invalid migration diff at ${e}:\n${d(t)}`,context:{file:e,issues:t},cause:r.error})}let i=r.data,a=i.warnings??deriveWarningsFromChanges(i);return{...i,warnings:a,hasWarnings:a.length>0}}function getMigrationFiles(e){if(!W.existsSync(e))return[];let t=W.readdirSync(e,{withFileTypes:!0}),n=[];for(let r of t){if(!r.isDirectory()||!isValidMigrationNumber(r.name))continue;let t=parseInt(r.name,10),i=H.join(e,r.name),a=H.join(i,ts);W.existsSync(a)&&n.push({number:t,type:`schema`,path:a});let o=H.join(i,ns);W.existsSync(o)&&n.push({number:t,type:`diff`,path:o})}return n.toSorted((e,t)=>e.number-t.number)}const us=Object.keys(ls);function getMigrationArtifacts(e){return W.existsSync(e)?W.readdirSync(e,{withFileTypes:!0}).filter(e=>e.isDirectory()&&isValidMigrationNumber(e.name)).map(t=>{let n=Number.parseInt(t.name,10);return{number:n,fileTypes:us.filter(t=>W.existsSync(getMigrationFilePath(e,n,t)))}}).filter(({fileTypes:e})=>e.length>0).toSorted((e,t)=>e.number-t.number):[]}function getNextMigrationNumber(e){let t=getMigrationFiles(e);return t.length===0?0:Math.max(...t.map(e=>e.number))+1}function getLatestMigrationNumber(e){return latestMigrationNumber(getMigrationFiles(e))}function latestMigrationNumber(e){return e.length===0?0:Math.max(...e.map(e=>e.number))}function assertMigrationNumberExists(e,t){let n=getMigrationFiles(e);if(t!==0&&!n.some(e=>e.number===t))throw E({code:`MIGRATION_NOT_FOUND`,message:`Migration ${formatMigrationNumber(t)} does not exist in working tree (latest is ${formatMigrationNumber(latestMigrationNumber(n))}).`});return latestMigrationNumber(n)}function formatMigrationScriptHint(e){let{migrationNumber:t,namespace:n,configPath:r,noScript:i}=e,a=namespaceMigrationArgs({subcommand:[`script`,formatMigrationNumber(t)],namespace:n,configPath:r});return i&&a.push(`--no-script`,`--reason`,`<reason>`),w({command:`tailor`,args:a})}function formatRebaselineHint(e){return formatNamespaceMigrationHint({...e,subcommand:[`rebaseline`]})}function migrationCommandContext(e){return{configPath:e.configPath,contextArgs:[...Se(e),...e.extraArgs??[]]}}function migrationContextArgs(e){let t=Ae(e.configPath);return[...t===void 0?[]:[t],...e.contextArgs??[]]}function migrationCommandArgs(e,t){return[`tailordb`,`migration`,...e,...migrationContextArgs(t)]}function namespaceMigrationArgs(e){let{subcommand:t,namespace:n,...r}=e;return migrationCommandArgs([...t,`--namespace`,n],r)}function formatNamespaceMigrationHint(e){return w({command:`tailor`,args:namespaceMigrationArgs(e)})}function formatCheckpointSyncHint(e){let{migrationNumber:t,replaceHistoryId:n,...r}=e,i=formatNamespaceMigrationHint({...r,subcommand:[`sync`,formatMigrationNumber(t),...n?[`--force`]:[]]});return n?`${i} (replaces the migration history ID)`:i}function applyDiffToSnapshot(e,t){let n=copySnapshotRecord(e.tables);for(let e of t.changes)switch(e.kind){case`table_added`:n[e.tableName]=e.after;break;case`table_removed`:delete n[e.tableName];break;case`table_modified`:{let t=n[e.tableName];if(t&&e.after){let r=e.after;n[e.tableName]={...t,...r.indexes!==void 0&&{indexes:r.indexes},...r.files!==void 0&&{files:r.files}}}break}case`table_settings_modified`:{let t=n[e.tableName];t&&(n[e.tableName]={...t,description:e.after.description,pluralForm:e.after.pluralForm,settings:e.after.settings??{}});break}case`table_scripts_modified`:{let t=n[e.tableName];if(t){let{typeHookExpr:r,typeValidateExpr:i,...a}=t;n[e.tableName]={...a,...e.after.typeHookExpr&&{typeHookExpr:e.after.typeHookExpr},...e.after.typeValidateExpr!==void 0&&{typeValidateExpr:e.after.typeValidateExpr}}}break}case`field_added`:case`field_modified`:case`field_type_modified`:{let t=n[e.tableName];if(t){let r=copySnapshotRecord(t.fields);r[e.fieldName]=e.after,n[e.tableName]={...t,fields:r}}break}case`field_removed`:{let t=n[e.tableName];if(t){let r=copySnapshotRecord(t.fields);delete r[e.fieldName],n[e.tableName]={...t,fields:r}}break}case`field_renamed`:{let t=n[e.tableName];if(t){let r=copySnapshotRecord(t.fields);delete r[e.previousFieldName],r[e.fieldName]=e.after,n[e.tableName]={...t,fields:r}}break}case`table_renamed`:delete n[e.previousTableName],n[e.tableName]=e.after;break;case`index_added`:case`index_modified`:{let t=n[e.tableName];if(t){let r=copySnapshotRecord(t.indexes);r[e.indexName]=e.after,n[e.tableName]={...t,indexes:r}}break}case`index_removed`:{let t=n[e.tableName];if(t&&t.indexes){let r=copySnapshotRecord(t.indexes);delete r[e.indexName],n[e.tableName]={...t,indexes:Object.keys(r).length>0?r:void 0}}break}case`file_added`:case`file_modified`:{let t=n[e.tableName];if(t){let r=copySnapshotRecord(t.files);r[e.fieldName]=e.after,n[e.tableName]={...t,files:r}}break}case`file_removed`:{let t=n[e.tableName];if(t&&t.files){let r=copySnapshotRecord(t.files);delete r[e.fieldName],n[e.tableName]={...t,files:Object.keys(r).length>0?r:void 0}}break}case`relationship_added`:case`relationship_modified`:{let t=n[e.tableName];if(t){let r=e.after;if((e.relationshipType??(t.forwardRelationships?.[e.relationshipName]?`forward`:t.backwardRelationships?.[e.relationshipName]?`backward`:`forward`))===`forward`){let i=copySnapshotRecord(t.forwardRelationships);i[e.relationshipName]=r,n[e.tableName]={...t,forwardRelationships:i}}else{let i=copySnapshotRecord(t.backwardRelationships);i[e.relationshipName]=r,n[e.tableName]={...t,backwardRelationships:i}}}break}case`relationship_removed`:{let t=n[e.tableName];if(t){let r=e.relationshipType??(t.forwardRelationships?.[e.relationshipName]?`forward`:t.backwardRelationships?.[e.relationshipName]?`backward`:null);if(r===`forward`&&t.forwardRelationships?.[e.relationshipName]){let r=copySnapshotRecord(t.forwardRelationships);delete r[e.relationshipName],n[e.tableName]={...t,forwardRelationships:Object.keys(r).length>0?r:void 0}}else if(r===`backward`&&t.backwardRelationships?.[e.relationshipName]){let r=copySnapshotRecord(t.backwardRelationships);delete r[e.relationshipName],n[e.tableName]={...t,backwardRelationships:Object.keys(r).length>0?r:void 0}}}break}case`permission_modified`:{let t=n[e.tableName];if(t&&e.after){let r=e.after;n[e.tableName]={...t,permissions:{record:r.recordPermission,gql:r.gqlPermission}}}break}}return normalizeSchemaSnapshot({...e,tables:n,createdAt:t.createdAt})}function reconstructSnapshotFromMigrations(e,t){let n=getMigrationFiles(e);if(n.length===0)return null;let r=n.find(e=>e.type===`schema`&&e.number===0);if(!r)throw E({code:`MIGRATION_BASELINE_NOT_FOUND`,message:`No initial schema file found in ${e}. Expected ${formatMigrationNumber(0)}/schema.json`});let i=loadSnapshot(r.path);for(let e of n)if(e.type===`diff`&&e.number>r.number){if(t!==void 0&&e.number>t)continue;let n=loadDiff(e.path);i=applyDiffToSnapshot(i,n)}return i}function validateMigrationFiles(e){let t=[];if(!W.existsSync(e))return t;let n=getMigrationArtifacts(e);if(n.length===0)return t;let r=[],i=[];for(let{number:e,fileTypes:t}of n)t.includes(`schema`)&&r.push(e),t.includes(`diff`)&&i.push(e);let a=n.map(({number:e})=>e),o=Math.max(0,...i),s=o>0;if(!r.includes(0)){let e=formatMigrationNumber(0);t.push({type:`missing_schema`,message:`Initial schema snapshot (${e}/${ts}) is missing`,suggestion:s||a.includes(0)?missingFileSuggestion(e,ts,!s):void 0,migrationNumber:0})}for(let e of r)e!==0&&t.push({type:`invalid_schema_number`,message:`Schema file found at migration ${formatMigrationNumber(e)}, but schema should only exist at ${formatMigrationNumber(0)}`,migrationNumber:e});i.includes(0)&&t.push({type:`invalid_diff_number`,message:`Migration ${formatMigrationNumber(0)} must not have ${ns}`,migrationNumber:0});for(let e of r)e!==0&&i.includes(e)&&t.push({type:`duplicate`,message:`Migration ${formatMigrationNumber(e)} has both schema and diff files`,migrationNumber:e});let c=Math.max(...a);for(let e=0;e<=c;e++)a.includes(e)||t.push({type:`gap`,message:`Migration ${formatMigrationNumber(e)} is missing (gap in sequence)`,migrationNumber:e});for(let{number:e,fileTypes:r}of n){if(e===0||r.includes(`diff`))continue;if(r.includes(`schema`)){t.push({type:`missing_diff`,message:`Migration ${formatMigrationNumber(e)} is missing diff file`,migrationNumber:e});continue}let n=formatMigrationNumber(e),i=r.map(e=>ls[e]).join(`, `);t.push({type:`missing_diff`,message:`Migration ${n} has ${i} but no ${ns}`,suggestion:missingFileSuggestion(n,ns,e>o),migrationNumber:e})}return t}function missingFileSuggestion(e,t,n){return n?`Delete migration directory ${e} if it is a leftover, or restore its ${t}.`:`Restore ${t} in migration directory ${e}.`}function assertValidMigrationFiles(e,t,n){let r=validateMigrationFiles(e);if(r.length>0){let e=r.map(e=>` - ${e.message}`).join(`
|
|
7
7
|
`),i=new Set(r.flatMap(e=>e.suggestion?[e.suggestion]:[]));if(r.some(e=>e.suggestion===void 0)){let e=formatNamespaceMigrationHint({subcommand:[`generate`,`--init`],namespace:t,configPath:n});i.add(`Restore the migration files from version control. If no workspace has been deployed with these migrations, you can instead recreate ${formatMigrationNumber(0)} from the local tables with ${e}, which deletes every migration of the namespace.`)}throw E({code:`MIGRATION_FILES_INVALID`,message:`Migration file validation failed for namespace "${t}":\n${e}`,suggestion:[...i].join(`
|
|
8
|
-
`)})}}function createSnapshotFieldConfigFromOperatorConfig(e){let t={type:e.type,required:e.required!==!1};if(e.array&&(t.array=!0),e.index&&(t.index=!0),e.unique&&(t.unique=!0),e.allowedValues&&e.allowedValues.length>0&&(t.allowedValues=e.allowedValues.map(e=>({value:e.value,...e.description&&{description:e.description}}))),e.foreignKey&&(t.foreignKey=!0,e.foreignKeyType&&(t.foreignKeyType=e.foreignKeyType),e.foreignKeyField&&(t.foreignKeyField=e.foreignKeyField)),e.description&&(t.description=e.description),e.vector&&(t.vector=!0),e.hooks&&(t.hooks={},e.hooks.create&&(t.hooks.create={expr:e.hooks.create.expr}),e.hooks.update&&(t.hooks.update={expr:e.hooks.update.expr})),e.validate&&e.validate.length>0&&(t.validate=e.validate.map(e=>({script:{expr:e.script.expr},errorMessage:e.errorMessage}))),e.serial&&(t.serial={start:e.serial.start,...e.serial.maxValue!==void 0&&{maxValue:e.serial.maxValue},...e.serial.format&&{format:e.serial.format},...e.serial.gapless&&{gapless:!0}}),e.scale!==void 0&&(t.scale=e.scale),e.default!==void 0&&(t.default=e.default),e.fields&&Object.keys(e.fields).length>0){let n=createSnapshotRecord();for(let[t,r]of Object.entries(e.fields))n[t]=createSnapshotFieldConfigFromOperatorConfig(r);t.fields=n}return normalizeSnapshotField(t)}function createSnapshotType(e){let t=createSnapshotRecord();for(let[n,r]of Object.entries(e.fields))t[n]=createSnapshotFieldConfigFromOperatorConfig(r.config);let n={name:e.name,pluralForm:e.pluralForm||
|
|
8
|
+
`)})}}function createSnapshotFieldConfigFromOperatorConfig(e){let t={type:e.type,required:e.required!==!1};if(e.array&&(t.array=!0),e.index&&(t.index=!0),e.unique&&(t.unique=!0),e.allowedValues&&e.allowedValues.length>0&&(t.allowedValues=e.allowedValues.map(e=>({value:e.value,...e.description&&{description:e.description}}))),e.foreignKey&&(t.foreignKey=!0,e.foreignKeyType&&(t.foreignKeyType=e.foreignKeyType),e.foreignKeyField&&(t.foreignKeyField=e.foreignKeyField)),e.description&&(t.description=e.description),e.vector&&(t.vector=!0),e.hooks&&(t.hooks={},e.hooks.create&&(t.hooks.create={expr:e.hooks.create.expr}),e.hooks.update&&(t.hooks.update={expr:e.hooks.update.expr})),e.validate&&e.validate.length>0&&(t.validate=e.validate.map(e=>({script:{expr:e.script.expr},errorMessage:e.errorMessage}))),e.serial&&(t.serial={start:e.serial.start,...e.serial.maxValue!==void 0&&{maxValue:e.serial.maxValue},...e.serial.format&&{format:e.serial.format},...e.serial.gapless&&{gapless:!0}}),e.scale!==void 0&&(t.scale=e.scale),e.default!==void 0&&(t.default=e.default),e.fields&&Object.keys(e.fields).length>0){let n=createSnapshotRecord();for(let[t,r]of Object.entries(e.fields))n[t]=createSnapshotFieldConfigFromOperatorConfig(r);t.fields=n}return normalizeSnapshotField(t)}function createSnapshotType(e){let t=createSnapshotRecord();for(let[n,r]of Object.entries(e.fields))t[n]=createSnapshotFieldConfigFromOperatorConfig(r.config);let n={name:e.name,pluralForm:e.pluralForm||Di.pluralize(e.name),fields:t};if(e.description&&(n.description=e.description),n.settings={},e.settings.aggregation!==void 0&&(n.settings.aggregation=e.settings.aggregation),e.settings.bulkUpsert!==void 0&&(n.settings.bulkUpsert=e.settings.bulkUpsert),e.settings.gqlOperations){let t=e.settings.gqlOperations;n.settings.gqlOperations={...t.create!==void 0&&{create:t.create},...t.update!==void 0&&{update:t.update},...t.delete!==void 0&&{delete:t.delete},...t.read!==void 0&&{read:t.read}}}if(e.settings.publishEvents!==void 0&&(n.settings.publishEvents=e.settings.publishEvents),e.indexes&&Object.keys(e.indexes).length>0){let t=createSnapshotRecord();for(let[n,r]of Object.entries(e.indexes))t[n]={fields:r.fields,unique:r.unique};n.indexes=t}if(e.files&&Object.keys(e.files).length>0&&(n.files={...e.files}),e.typeHookExpr&&(n.typeHookExpr=e.typeHookExpr),e.typeValidateExpr&&(n.typeValidateExpr=e.typeValidateExpr),Object.keys(e.forwardRelationships).length>0){let t=createSnapshotRecord();for(let[n,r]of Object.entries(e.forwardRelationships))t[n]={targetType:r.targetType,targetField:r.targetField,sourceField:r.sourceField,isArray:r.isArray,description:r.description};n.forwardRelationships=t}if(Object.keys(e.backwardRelationships).length>0){let t=createSnapshotRecord();for(let[n,r]of Object.entries(e.backwardRelationships))t[n]={targetType:r.targetType,targetField:r.targetField,sourceField:r.sourceField,isArray:r.isArray,description:r.description};n.backwardRelationships=t}return(e.permissions.record||e.permissions.gql)&&(n.permissions={},e.permissions.record&&(n.permissions.record={create:e.permissions.record.create.map(convertActionPermission),read:e.permissions.record.read.map(convertActionPermission),update:e.permissions.record.update.map(convertActionPermission),delete:e.permissions.record.delete.map(convertActionPermission)}),e.permissions.gql&&(n.permissions.gql=e.permissions.gql.map(e=>({conditions:e.conditions,actions:e.actions,permit:e.permit,...e.description&&{description:e.description}})))),normalizeSnapshotType(n)}function convertActionPermission(e){return{conditions:e.conditions,permit:e.permit,...e.description&&{description:e.description}}}function createSnapshotFromLocalTypes(e,t){let n=createSnapshotRecord();for(let[t,r]of Object.entries(e))n[t]=createSnapshotType(r);return normalizeSchemaSnapshot({version:8,namespace:t,createdAt:(/* @__PURE__ */ new Date()).toISOString(),tables:n})}const ds=`_input`,fs=`_oldRecord`,ps=`_now`,hs=/* @__PURE__ */ new Set([`datetime`,`date`,`time`]),key=e=>JSON.stringify(e);function collectFieldScriptSources(e){let t=[];for(let[n,r]of Object.entries(e).toSorted(([e],[t])=>e.localeCompare(t,`en`))){let e={};if(r.hooks?.create?.expr&&(e.hc=r.hooks.create.expr),r.hooks?.update?.expr&&(e.hu=r.hooks.update.expr),r.validate?.some(e=>e.script?.expr)&&(e.v=r.validate.filter(e=>e.script?.expr).map(e=>[e.script?.expr,e.errorMessage])),r.default!==void 0&&(e.d=r.default instanceof Date?r.default.toISOString():r.default,e.t=r.type),r.fields){let t=collectFieldScriptSources(r.fields);t.length>0&&(e.f=t,e.a=!!r.array)}Object.keys(e).length>0&&t.push([n,e])}return t}function computeSourceScriptHash(e,t){let n=collectFieldScriptSources(e);if(!(n.length>0||t?.typeHookExpr?.create||t?.typeHookExpr?.update||t?.typeValidateExpr))return;let r=[n];return t?.typeHookExpr?.create&&r.push([`thc`,t.typeHookExpr.create]),t?.typeHookExpr?.update&&r.push([`thu`,t.typeHookExpr.update]),t?.typeValidateExpr&&r.push([`tve`,t.typeValidateExpr]),gi(`sha256`).update(JSON.stringify(r)).digest(`hex`).slice(0,16)}function extractSourceScriptHash(e){return e.match(/\/\/ @sdk-source-hash:([0-9a-f]+)\s*$/)?.[1]}const isNestedType=e=>e.type===`nested`&&e.fields!==void 0;function serializeDefault(e,t){return e===`now`&&hs.has(t)?ps:e instanceof Date?`new Date(${JSON.stringify(e.toISOString())})`:JSON.stringify(e)}function buildHookObject(e,t,n,r,i=!1,a=t){let o=[];for(let[s,c]of Object.entries(e)){let e=`${t}[${key(s)}]`,l=`${n}?.[${key(s)}]`;if(isNestedType(c)&&c.fields){let t=`${a}[${key(s)}]`;if(c.array){let n=buildHookObject(c.fields,r===`update`?`(__arrInput === undefined ? {} : __el)`:`__el`,r===`update`?`(__arrInput === undefined ? __el : undefined)`:`undefined`,r,!0,`__el`);if(n!==null){let i=`${t}.map((__el) => Object.assign({}, __el, ${n}))`,a=r===`update`?`((__arrInput) => ${i})(${e})`:i;o.push(`${key(s)}: ${t} == null ? ${t} : ${a}`)}}else{let n=buildHookObject(c.fields,`(${e} || {})`,l,r,!0,`(${t} || {})`);n!==null&&o.push(`${key(s)}: ${t} == null ? ${t} : Object.assign({}, ${t}, ${n})`)}continue}let u=c.hooks?.[r];if(i&&c.default!==void 0)throw Error(`.default() cannot be used on nested inner field "${s}"`);let d=r===`create`&&c.default!==void 0;u&&d?o.push(`${key(s)}: ((_value) => (${u.expr}))(${e}) ?? ${serializeDefault(c.default,c.type)}`):u&&r===`create`?o.push(`${key(s)}: ((_value) => (${u.expr}))(${e})`):u?o.push(`${key(s)}: ((_value, _oldValue) => (${u.expr}))(${e}, ${l} ?? null)`):d&&o.push(`${key(s)}: ${e} ?? ${serializeDefault(c.default,c.type)}`)}return o.length===0?null:`{ ${o.join(`, `)} }`}function buildValidateStatements(e,t,n,r=0){let i=[];for(let[a,o]of Object.entries(e)){let e=`${t}[${key(a)}]`,s=n?`${n} + ${key(`.${a}`)}`:key(a),c=(o.validate??[]).filter(e=>e.script?.expr);if(c.length>0){let t=c.map(e=>`{ const __r = (${e.script?.expr}); if (typeof __r === "string") { __errs[${s}] = __r; } }`).join(`
|
|
9
9
|
`);i.push(`{ const _value = ${e};\n${t}\n}`)}if(isNestedType(o)&&o.fields){if(o.array){let t=r===0?`__idx`:`__idx${r}`,n=`${s} + "[" + ${t} + "]"`,a=buildValidateStatements(o.fields,`__el`,n,r+1);a.length>0&&i.push(`(${e} || []).forEach((__el, ${t}) => {\n${a.join(`
|
|
10
10
|
`)}\n});`)}else{let t=buildValidateStatements(o.fields,e,s,r);t.length>0&&i.push(`if (${e} != null) {\n${t.join(`
|
|
11
|
-
`)}\n}`)}}}return i}function principalDeclIfReferenced(...e){return e.some(e=>e?.includes(`_principal`))?` const ${
|
|
12
|
-
`)}${i}\nreturn __errs; })(typeof _invoker !== "undefined" ? _invoker : undefined)`}function buildTypeScripts(e,t){let n={},r=t?.typeHookExpr,i=t?.typeValidateExpr,a=computeSourceScriptHash(t?.sourceFields??e,t),o=a?` // @sdk-source-hash:${a}`:``,s={};for(let t of[`create`,`update`]){let n=buildHookObject(e,cs,ls,t,!1,t===`update`?`Object.assign({}, ${ls}, ${cs})`:cs),i=r?.[t],a;if(n!==null&&i){let e=principalDeclIfReferenced(n,i);a=`((_invoker) => { const ${us} = new Date();${e} const __fl = ${n}; return Object.assign({}, __fl, ((${cs}) => ${i})(Object.assign({}, ${cs}, __fl))); })(typeof _invoker !== "undefined" ? _invoker : undefined)`}else i?a=wrapHook(i):n!==null&&(a=wrapHook(n));a&&(s[t]={expr:a+o})}(s.create||s.update)&&(n.typeHook=s);let c=buildValidateStatements(e,`_newRecord`,``);if(c.length>0||i){let e=wrapValidate(c,i)+o;n.typeValidate={create:{expr:e},update:{expr:e}}}return n}function convertRemoteFieldToSnapshot(e){let t={type:e.type,required:e.required};e.array&&(t.array=!0),e.index&&(t.index=!0),e.unique&&(t.unique=!0),e.foreignKey&&(t.foreignKey=!0,e.foreignKeyType&&(t.foreignKeyType=e.foreignKeyType),e.foreignKeyField&&(t.foreignKeyField=e.foreignKeyField));let n=e.allowedValues;n.length>0&&(t.allowedValues=n.map(e=>({value:e.value,...e.description&&{description:e.description}}))),e.description&&(t.description=e.description),e.vector&&(t.vector=!0),e.hooks&&(t.hooks={},e.hooks.create?.expr&&(t.hooks.create={expr:e.hooks.create.expr}),e.hooks.update?.expr&&(t.hooks.update={expr:e.hooks.update.expr}));let r=e.validate;r.length>0&&(t.validate=r.map(e=>({script:{expr:convertRemoteValidateExpression(e.script?.expr??``,e.action)},errorMessage:e.errorMessage??``}))),e.serial&&(t.serial={start:Number(e.serial.start),...e.serial.maxValue&&{maxValue:Number(e.serial.maxValue)},...e.serial.format&&{format:e.serial.format},...e.serial.gapless&&{gapless:!0}}),e.scale!==void 0&&(t.scale=e.scale),e.optionalOnCreate&&!t.hooks?.create&&(t.optionalOnCreate=!0);let i=e.fields;if(Object.keys(i).length>0){t.fields=createSnapshotRecord();for(let[e,n]of Object.entries(i))t.fields[e]=convertRemoteFieldToSnapshot(n)}return t}function convertRemoteFieldsToSnapshot(e){let t=createSnapshotRecord(),n=e.schema?.fields??{};for(let[e,r]of Object.entries(n))t[e]=convertRemoteFieldToSnapshot(r);return t}function convertRemoteValidateExpression(e,t){return t===_r.DENY&&e.startsWith(`!`)?e.slice(1):e}function convertRemoteSettingsToSnapshot(e,t){let n={};e?.aggregation&&(n.aggregation=!0),e?.bulkUpsert&&(n.bulkUpsert=!0),e?.publishRecordEvents&&(n.publishEvents=!0);let r=e?.disableGqlOperations;if(r){let e=r.create||r.update||r.delete||r.read;(t?.gqlOperations!==void 0||e)&&(n.gqlOperations={create:!r.create,update:!r.update,delete:!r.delete,read:!r.read})}return Object.keys(n).length>0?n:void 0}function convertRemoteIndexesToSnapshot(e){let t=createSnapshotRecord();for(let[n,r]of Object.entries(e??{}))t[n]={fields:r.fieldNames,...r.unique&&{unique:!0}};return Object.keys(t).length>0?t:void 0}function convertRemoteFilesToSnapshot(e){let t=createSnapshotRecord();for(let[n,r]of Object.entries(e??{}))t[n]=r.description||``;return Object.keys(t).length>0?t:void 0}function convertRemoteRelationshipToSnapshot(e,t){return t===`forward`?{targetType:e.refType,targetField:e.srcField,sourceField:e.refField,isArray:e.array,description:e.description||``}:{targetType:e.refType,targetField:e.refField,sourceField:e.srcField,isArray:e.array,description:e.description||``}}function remoteRelationshipMatchesExpectedDirection(e,t,n){let r=convertRemoteRelationshipToSnapshot(e,n);return r.targetType===t.targetType&&r.targetField===t.targetField&&r.sourceField===t.sourceField&&r.isArray===t.isArray}function inferRemoteRelationshipDirection(e,t,n){let r=n?.forwardRelationships?.[e],i=n?.backwardRelationships?.[e];return r&&!i?`forward`:i&&!r?`backward`:r&&remoteRelationshipMatchesExpectedDirection(t,r,`forward`)?`forward`:i&&remoteRelationshipMatchesExpectedDirection(t,i,`backward`)||t.array?`backward`:`forward`}function convertRemoteRelationshipsToSnapshot(e,t){let n=createSnapshotRecord(),r=createSnapshotRecord();for(let[i,a]of Object.entries(e??{})){let e=inferRemoteRelationshipDirection(i,a,t);e===`forward`?n[i]=convertRemoteRelationshipToSnapshot(a,e):r[i]=convertRemoteRelationshipToSnapshot(a,e)}return{...Object.keys(n).length>0&&{forwardRelationships:n},...Object.keys(r).length>0&&{backwardRelationships:r}}}const fs=/* @__PURE__ */ new Map([[Pn.ALLOW,`allow`],[Pn.DENY,`deny`]]),ps=/* @__PURE__ */ new Map([[yr.EQ,`eq`],[yr.NE,`ne`],[yr.IN,`in`],[yr.NIN,`nin`],[yr.HAS_ANY,`hasAny`],[yr.NHAS_ANY,`nhasAny`]]);function convertRemotePermit(e,t){let n=fs.get(e);if(n)return n;throw b(`Unsupported ${t} permission permit: ${e}`)}function convertRemoteOperator(e,t){let n=ps.get(e);if(n)return n;throw b(`Unsupported ${t} permission operator: ${e}`)}function convertRemoteValueOperand(e){switch(e?.kind.case){case`userField`:return{user:e.kind.value};case`recordField`:return{record:e.kind.value};case`oldRecordField`:return{oldRecord:e.kind.value};case`newRecordField`:return{newRecord:e.kind.value};case`value`:return Yr(ai,e.kind.value);default:throw b(`Unsupported permission operand`)}}function convertRemoteRecordCondition(e){return[convertRemoteValueOperand(e.left),convertRemoteOperator(e.operator,`record`),convertRemoteValueOperand(e.right)]}function convertRemoteGqlCondition(e){return[convertRemoteValueOperand(e.left),convertRemoteOperator(e.operator,`GQL`),convertRemoteValueOperand(e.right)]}function convertRemoteRecordPolicy(e){return{conditions:e.conditions.map(convertRemoteRecordCondition),permit:convertRemotePermit(e.permit,`record`),...e.description&&{description:e.description}}}function convertRemoteRecordPermissionToSnapshot(e){let t={create:e?.create.map(convertRemoteRecordPolicy)??[],read:e?.read.map(convertRemoteRecordPolicy)??[],update:e?.update.map(convertRemoteRecordPolicy)??[],delete:e?.delete.map(convertRemoteRecordPolicy)??[]};return Object.values(t).some(e=>e.length>0)?t:void 0}function convertRemoteGqlAction(e){switch(e){case L.ALL:return`all`;case L.CREATE:return`create`;case L.READ:return`read`;case L.UPDATE:return`update`;case L.DELETE:return`delete`;case L.AGGREGATE:return`aggregate`;case L.BULK_UPSERT:return`bulkUpsert`;default:throw b(`Unsupported GQL permission action: ${e}`)}}function convertRemoteGqlPermissionToSnapshot(e){let t=e?.policies.map(e=>({conditions:e.conditions.map(convertRemoteGqlCondition),actions:e.actions.map(convertRemoteGqlAction),permit:convertRemotePermit(e.permit,`GQL`),...e.description&&{description:e.description}}))??[];return t.length>0?t:void 0}function convertRemoteTypeToSnapshot(e,t){let n=convertRemoteSettingsToSnapshot(e.schema?.settings,t?.settings),r=convertRemoteRelationshipsToSnapshot(e.schema?.relationships,t),i=convertRemoteRecordPermissionToSnapshot(e.schema?.permission),a={name:e.name,pluralForm:e.schema?.settings?.pluralForm||wi.pluralize(e.name),fields:convertRemoteFieldsToSnapshot(e),...n&&{settings:n},...r};e.schema?.description&&(a.description=e.schema.description);let o=convertRemoteIndexesToSnapshot(e.schema?.indexes);o&&(a.indexes=o);let s=convertRemoteFilesToSnapshot(e.schema?.files);return s&&(a.files=s),i&&(a.permissions={record:i}),a}function createSnapshotFromRemoteTypes(e,t,n=[],r){let i=createSnapshotRecord();for(let t of e)i[t.name]=convertRemoteTypeToSnapshot(t,r?.tables[t.name]);for(let e of n){let{typeName:t}=e,n=i[t];if(!n)continue;let r=convertRemoteGqlPermissionToSnapshot(e.permission);r&&(n.permissions={...n.permissions,gql:r})}return normalizeSchemaSnapshot({version:8,namespace:t,createdAt:(/* @__PURE__ */ new Date()).toISOString(),tables:i})}function fieldDifferenceValue(e){return e===void 0||e===``?`none`:String(e)}function fieldDifferenceKey(e,t){return e?`${e}.${t}`:t}function addFieldDifference(e,t,n,r,i){r!==i&&e.push(`${fieldDifferenceKey(t,n)}: remote=${fieldDifferenceValue(r)}, expected=${fieldDifferenceValue(i)}`)}function addBooleanFieldDifference(e,t,n,r,i){addFieldDifference(e,t,n,r[n]??!1,i[n]??!1)}function addAllowedValuesDifferences(e,t,n,r){let i=n.allowedValues??[],a=r.allowedValues??[];if(i.length!==a.length){e.push(`${fieldDifferenceKey(t,`allowedValues`)} count: remote=${i.length}, expected=${a.length}`);return}let o=new Map(a.map(e=>[e.value,e.description]));for(let n of i){if(!o.has(n.value)){e.push(`${fieldDifferenceKey(t,`allowedValues`)}: remote has '${n.value}' not in snapshot`);return}let r=o.get(n.value);if((n.description??``)!==(r??``)){addFieldDifference(e,t,`allowedValues.${n.value}.description`,n.description??``,r??``);return}}let s=new Set(i.map(e=>e.value));for(let n of a)if(!s.has(n.value)){e.push(`${fieldDifferenceKey(t,`allowedValues`)}: snapshot has '${n.value}' not in remote`);return}}function addHooksDifferences(e,t,n,r){addFieldDifference(e,t,`hooks.create`,n.hooks?.create?.expr??``,r.hooks?.create?.expr??``),addFieldDifference(e,t,`hooks.update`,n.hooks?.update?.expr??``,r.hooks?.update?.expr??``)}function addValidationDifferences(e,t,n,r){let i=n.validate??[],o=r.validate??[];i.length!==o.length&&e.push(`${fieldDifferenceKey(t,`validate`)} count: remote=${i.length}, expected=${o.length}`);let s=Math.min(i.length,o.length);for(let n=0;n<s;n++){let r=a(i[n],`remoteValidate missing index ${n}`),s=a(o[n],`snapshotValidate missing index ${n}`);addFieldDifference(e,t,`validate[${n}].script`,r.script?.expr??``,s.script?.expr??``),addFieldDifference(e,t,`validate[${n}].errorMessage`,r.errorMessage,s.errorMessage)}}function addSerialDifferences(e,t,n,r){addFieldDifference(e,t,`serial.start`,n.serial?.start,r.serial?.start),addFieldDifference(e,t,`serial.maxValue`,n.serial?.maxValue,r.serial?.maxValue),addFieldDifference(e,t,`serial.format`,n.serial?.format??``,r.serial?.format??``),addFieldDifference(e,t,`serial.gapless`,n.serial?.gapless??!1,r.serial?.gapless??!1)}function addNestedFieldDifferences(e,t,n,r){let i=n.fields??{},o=r.fields??{},s=Object.keys(i),c=Object.keys(o);s.length!==c.length&&e.push(`${fieldDifferenceKey(t,`fields`)} count: remote=${s.length}, expected=${c.length}`);for(let n of s){let r=i[n],s=o[n],c=fieldDifferenceKey(t,`fields.${n}`);s?addFieldDifferences(e,c,a(r,`remote field "${n}" missing`),s):e.push(`${c}: exists in remote but not snapshot`)}for(let n of c)i[n]||e.push(`${fieldDifferenceKey(t,`fields.${n}`)}: exists in snapshot but not remote`)}function addFieldDifferences(e,t,n,r){addFieldDifference(e,t,`type`,n.type,r.type),addFieldDifference(e,t,`required`,n.required,r.required);for(let i of Da)addBooleanFieldDifference(e,t,i,n,r);addFieldDifference(e,t,`foreignKeyType`,n.foreignKeyType,r.foreignKeyType),addFieldDifference(e,t,`foreignKeyField`,n.foreignKeyField,r.foreignKeyField),addFieldDifference(e,t,`description`,n.description??``,r.description??``),addAllowedValuesDifferences(e,t,n,r),addHooksDifferences(e,t,n,r),addValidationDifferences(e,t,n,r),addSerialDifferences(e,t,n,r),addFieldDifference(e,t,`scale`,n.scale,r.scale),addNestedFieldDifferences(e,t,n,r)}function compareFields(e,t,n,r){let i=[];return addFieldDifferences(i,``,n,r),i.length>0?{tableName:e,kind:`field_mismatch`,fieldName:t,details:i.join(`; `)}:null}const hs=/* @__PURE__ */ new Set([`id`]),gs=[`bulkUpsert`,`gqlOperations`,`publishEvents`];function isMigrationRestricted(e){let t=e?.disableGqlOperations;return e?.publishRecordEvents!==!0&&e?.bulkUpsert!==!0&&t?.create===!0&&t.update===!0&&t.delete===!0}function withoutSettings(e,t,n){if(t.length===0||n?.size===0)return e;let r=createSnapshotRecord();for(let[i,a]of Object.entries(e.tables)){if(!a.settings||n&&!n.has(i)){r[i]=a;continue}let e={...a.settings};for(let n of t)delete e[n];let{settings:o,...s}=a;r[i]=Object.keys(e).length>0?{...s,settings:e}:s}return{...e,tables:r}}function compareRemoteWithSnapshot(e,t,n=[],r=[],i){let a=compareNormalizedRemoteWithSnapshot(createRemoteComparableSnapshot(withoutSettings(createSnapshotFromRemoteTypes(e,t.namespace,n,t),r,i)),createRemoteComparableSnapshot(withoutSettings(t,r,i))),o=compareScriptHashes(e,t);return[...a,...o]}function extractRemoteScriptHashState(e){let t=[e.schema?.typeHook?.create?.expr,e.schema?.typeHook?.update?.expr,e.schema?.typeValidate?.create?.expr,e.schema?.typeValidate?.update?.expr],n;for(let e of t){if(!e)continue;let t=extractSourceScriptHash(e);if(t){if(n&&n!==t)return{kind:`conflicting`};n=t}}return n?{kind:`hash`,hash:n}:{kind:`absent`}}function remoteHasScripts(e){return!!(e.schema?.typeHook?.create?.expr||e.schema?.typeHook?.update?.expr||e.schema?.typeValidate?.create?.expr||e.schema?.typeValidate?.update?.expr)}const _s=`has no script hash on remote`;function compareScriptHashes(e,t){let n=[],r=new Map(e.map(e=>[e.name,e]));for(let[e,i]of Object.entries(t.tables)){let t=computeSourceScriptHash(i.fields,{typeHookExpr:i.typeHookExpr,typeValidateExpr:i.typeValidateExpr}),a=r.get(e);if(a){if(t){let r=extractRemoteScriptHashState(a);if(t!==(r.kind===`hash`?r.hash:void 0)){let t=r.kind===`hash`?`Table '${e}' scripts differ between remote and snapshot`:r.kind===`conflicting`?`Table '${e}' has conflicting script hashes on remote`:remoteHasScripts(a)?`Table '${e}' ${_s}`:`Table '${e}' has scripts in snapshot but not on remote`;n.push({tableName:e,kind:`script_mismatch`,details:t})}}else remoteHasScripts(a)&&n.push({tableName:e,kind:`script_mismatch`,details:`Table '${e}' has scripts on remote but not in snapshot`})}}return n}function stripFieldScriptProps(e){let{hooks:t,validate:n,default:r,optionalOnCreate:i,...a}=e;if(a.fields){let e=createSnapshotRecord();for(let[t,n]of Object.entries(a.fields))e[t]=stripFieldScriptProps(n);return{...a,fields:e}}return a}function createRemoteComparableSnapshot(e){let t=createSnapshotRecord();for(let[n,r]of Object.entries(e.tables)){let e=createSnapshotRecord();for(let[t,n]of Object.entries(r.fields))hs.has(t)||(e[t]=stripFieldScriptProps(n));let{typeHookExpr:i,typeValidateExpr:a,...o}=r;t[n]={...o,fields:e}}return normalizeSchemaSnapshot({...e,tables:t})}function fieldDriftFromChange(e){return compareFields(e.tableName,e.fieldName,e.before,e.after)??{tableName:e.tableName,kind:`field_mismatch`,fieldName:e.fieldName,details:`Field '${e.fieldName}' differs between remote and snapshot`}}function schemaDriftFromDiffChange(e){switch(e.kind){case`table_added`:return{tableName:e.tableName,kind:`type_missing_remote`,details:`Table '${e.tableName}' exists in snapshot but not in remote`};case`table_removed`:return{tableName:e.tableName,kind:`type_missing_local`,details:`Table '${e.tableName}' exists in remote but not in snapshot`};case`table_renamed`:return{tableName:e.tableName,kind:`type_settings_mismatch`,details:`Table '${e.previousTableName}' was renamed to '${e.tableName}'`};case`table_settings_modified`:case`table_modified`:return{tableName:e.tableName,kind:`type_settings_mismatch`,details:e.reason??`Table settings differ between remote and snapshot`};case`field_added`:return{tableName:e.tableName,kind:`field_missing_remote`,fieldName:e.fieldName,details:`Field '${e.fieldName}' exists in snapshot but not in remote`};case`field_removed`:return{tableName:e.tableName,kind:`field_missing_local`,fieldName:e.fieldName,details:`Field '${e.fieldName}' exists in remote but not in snapshot`};case`field_modified`:case`field_type_modified`:return fieldDriftFromChange(e);case`field_renamed`:return{tableName:e.tableName,kind:`field_mismatch`,fieldName:e.fieldName,details:`Field '${e.previousFieldName}' was renamed to '${e.fieldName}'`};case`index_added`:return{tableName:e.tableName,kind:`index_missing_remote`,indexName:e.indexName,details:`Index '${e.indexName}' exists in snapshot but not in remote`};case`index_removed`:return{tableName:e.tableName,kind:`index_missing_local`,indexName:e.indexName,details:`Index '${e.indexName}' exists in remote but not in snapshot`};case`index_modified`:return{tableName:e.tableName,kind:`index_mismatch`,indexName:e.indexName,details:e.reason??`Index '${e.indexName}' differs between remote and snapshot`};case`file_added`:return{tableName:e.tableName,kind:`file_missing_remote`,fileName:e.fieldName,details:`File '${e.fieldName}' exists in snapshot but not in remote`};case`file_removed`:return{tableName:e.tableName,kind:`file_missing_local`,fileName:e.fieldName,details:`File '${e.fieldName}' exists in remote but not in snapshot`};case`file_modified`:return{tableName:e.tableName,kind:`file_mismatch`,fileName:e.fieldName,details:e.reason??`File '${e.fieldName}' differs between remote and snapshot`};case`relationship_added`:return{tableName:e.tableName,kind:`relationship_missing_remote`,relationshipName:e.relationshipName,relationshipType:e.relationshipType,details:`Relationship '${e.relationshipName}' exists in snapshot but not in remote`};case`relationship_removed`:return{tableName:e.tableName,kind:`relationship_missing_local`,relationshipName:e.relationshipName,relationshipType:e.relationshipType,details:`Relationship '${e.relationshipName}' exists in remote but not in snapshot`};case`relationship_modified`:return{tableName:e.tableName,kind:`relationship_mismatch`,relationshipName:e.relationshipName,relationshipType:e.relationshipType,details:e.reason??`Relationship '${e.relationshipName}' differs between remote and snapshot`};case`permission_modified`:return{tableName:e.tableName,kind:`permission_mismatch`,details:e.reason??`Permissions differ between remote and snapshot`};case`table_scripts_modified`:return{tableName:e.tableName,kind:`script_mismatch`,details:e.reason??`Table-level scripts differ between remote and snapshot`};default:throw b(`Unsupported diff change`)}}function compareNormalizedRemoteWithSnapshot(e,t){return compareSnapshots(e,t).changes.map(schemaDriftFromDiffChange)}function formatSchemaDrifts(e){if(e.length===0)return`No schema drifts detected.`;let t=[],n=/* @__PURE__ */ new Map;for(let t of e){let e=n.get(t.tableName)??[];e.push(t),n.set(t.tableName,e)}for(let[e,r]of n){t.push(` Table '${e}':`);for(let e of r)if(e.fieldName)t.push(` - Field '${e.fieldName}': ${e.details}`);else if(e.indexName)t.push(` - Index '${e.indexName}': ${e.details}`);else if(e.fileName)t.push(` - File '${e.fileName}': ${e.details}`);else if(e.relationshipName){let n=e.relationshipType?` (${e.relationshipType})`:``;t.push(` - Relationship${n} '${e.relationshipName}': ${e.details}`)}else t.push(` - ${e.details}`)}return t.join(`
|
|
13
|
-
`)}function updateHashWithDirectory(e,t,n=``,r=/* @__PURE__ */ new Set){let i=W.realpathSync(t);if(r.has(i)){e.update(`directory-cycle\0${n}\0${i}\0`);return}r.add(i);let a=W.readdirSync(t,{withFileTypes:!0}).toSorted((e,t)=>e.name.localeCompare(t.name));try{for(let i of a){let a=n?`${n}/${i.name}`:i.name,o=H.join(t,i.name);if(i.isDirectory())e.update(`directory\0${a}\0`),updateHashWithDirectory(e,o,a,r);else if(i.isFile())e.update(`file\0${a}\0`),e.update(W.readFileSync(o)),e.update(`\0`);else if(i.isSymbolicLink()){e.update(`symlink\0${a}\0${W.readlinkSync(o)}\0`);try{let t=W.statSync(o);t.isDirectory()?(e.update(`target-directory\0`),updateHashWithDirectory(e,o,`${a}@target`,r)):t.isFile()?(e.update(`target-file\0`),e.update(W.readFileSync(o)),e.update(`\0`)):e.update(`target-other\0`)}catch(t){if(t.code!==`ENOENT`)throw t;e.update(`target-missing\0`)}}else e.update(`other\0${a}\0`)}}finally{r.delete(i)}}function captureFileState(e){let t=
|
|
14
|
-
`),suggestion:"Set a different `migration.directory` for each namespace in tailor.config.ts.",context:{conflicts:r}});return n}function selectTargetNamespace(e,t){if(e.length===0)throw migrationConfigNotFoundError();if(t){let n=e.find(e=>e.namespace===t);if(!n)throw E({code:`TAILORDB_NAMESPACE_NOT_FOUND`,message:`Namespace "${t}" not found or does not have migrations configured`});return n}if(e.length>1)throw E({code:`MIGRATION_NAMESPACE_REQUIRED`,message:`Multiple TailorDB services found. Please specify namespace with --namespace flag: ${e.map(e=>e.namespace).join(`, `)}`});return a(e[0],`namespace with migrations missing`)}function migrationConfigNotFoundError(){return E({code:`MIGRATION_CONFIG_NOT_FOUND`,message:`No TailorDB services with migrations configuration found`,suggestion:"Configure `migration` on the TailorDB service in tailor.config.ts."})}function usesLegacyData(e){return e.includes(`_data`)&&Le(`(${e}\n);`,{includeGuardedReferences:!0}).has(`_data`)}function normalizeValidations(e,t){let n=[],r,i=[];function flushLegacy(){r?.script&&(n.push({...r,script:{...r.script,expr:
|
|
15
|
-
`)} })(${t})`,`legacy migration validator`)}}),r=void 0,i=[])}for(let t of e)t.script&&usesLegacyData(t.script.expr)?(r??=t,i.push(`if (!(${t.script.expr}\n)) return ${JSON.stringify(t.errorMessage)};`)):(flushLegacy(),n.push(t));return flushLegacy(),n}function normalizeField(e,t,n,r,i){let a={...e};if(e.fields){let o=e.array?`__el`:`${t}?.[${JSON.stringify(i)}]`,s=e.array?`__el`:`${n}?.[${JSON.stringify(i)}]`,c=e.array?`__el`:`${r}?.[${JSON.stringify(i)}]`;a.fields=Object.fromEntries(Object.entries(e.fields).map(([e,t])=>[e,normalizeField(t,o,s,c,e)]))}if(e.hooks){a.hooks={...e.hooks};for(let r of[`create`,`update`]){let i=e.hooks[r];if(i&&usesLegacyData(i.expr)){let e=r===`update`?n:t;a.hooks[r]={...i,expr:We(`((_data) => (${i.expr}\n))(${e})`,`legacy migration hook`)}}}}return e.validate&&(a.validate=normalizeValidations(e.validate,r)),a}function normalizeTableScriptCompatibility(e){return{...e,fields:Object.fromEntries(Object.entries(e.fields).map(([e,t])=>[e,normalizeField(t,`_input`,`Object.assign({}, _oldRecord, _input)`,`_newRecord`,e)]))}}function publishesRecordEvents(e,t){return resolvePublishEvents({explicit:e.settings?.publishEvents,subscribed:t,conflict:Ca.tailorDBType(e.name)})}function generateTailorDBTypeManifestFromSnapshot(e,t={}){let n=wi.camelize(e.pluralForm,!0),r={aggregation:e.settings?.aggregation??!1,bulkUpsert:t.suppressGqlMutations===!0?!1:e.settings?.bulkUpsert??!1,draft:!1,defaultQueryLimitSize:100n,maxBulkUpsertSize:1000n,pluralForm:n,publishRecordEvents:t.suppressRecordEvents!==!0&&publishesRecordEvents(e,t.subscribed??!1)},i=e.settings?.gqlOperations??t.namespaceGqlOperations;(i||t.suppressGqlMutations===!0)&&(r.disableGqlOperations={create:t.suppressGqlMutations===!0||i?.create===!1,update:t.suppressGqlMutations===!0||i?.update===!1,delete:t.suppressGqlMutations===!0||i?.delete===!1,read:i?.read===!1});let a=Object.fromEntries(Object.entries(e.fields).filter(([e])=>e!==`id`).map(([e,t])=>[e,convertFieldConfigToProto(t)])),o=/* @__PURE__ */ new Map;if(e.forwardRelationships)for(let[t,n]of Object.entries(e.forwardRelationships))o.set(t,convertRelationshipToProto(n,`forward`));if(e.backwardRelationships)for(let[t,n]of Object.entries(e.backwardRelationships))o.set(t,convertRelationshipToProto(n,`backward`));let s=/* @__PURE__ */ new Map;if(e.indexes)for(let[t,n]of Object.entries(e.indexes))s.set(t,convertIndexToProto(n));let c=/* @__PURE__ */ new Map;if(e.files)for(let[t,n]of Object.entries(e.files))c.set(t,{description:n||``});let l=e.permissions?.record?convertRecordPermissionToProto(e.permissions.record):{create:[],read:[],update:[],delete:[]},{typeHook:u,typeValidate:d}=buildTypeScripts(normalizeTableScriptCompatibility(e).fields,{sourceFields:e.fields,typeHookExpr:e.typeHookExpr,typeValidateExpr:e.typeValidateExpr});return{name:e.name,schema:{description:e.description||``,fields:a,relationships:Object.fromEntries(o),settings:r,extends:!1,directives:[],indexes:Object.fromEntries(s),files:Object.fromEntries(c),permission:l,...u&&{typeHook:u},...d&&{typeValidate:d}}}}function optionalOnCreate(e){return e.hooks?.create||e.default!==void 0?{optionalOnCreate:!0}:{}}function convertFieldConfigToProto(e){let t={type:e.type,allowedValues:e.type===`enum`?e.allowedValues?.map(e=>({...e}))??[]:[],description:e.description||``,array:e.array??!1,index:e.index??!1,unique:e.unique??!1,foreignKey:e.foreignKey??!1,foreignKeyType:e.foreignKeyType,foreignKeyField:e.foreignKeyField,required:e.required,vector:e.vector??!1,...optionalOnCreate(e),...e.serial&&{serial:{start:BigInt(e.serial.start),...e.serial.maxValue!==void 0&&{maxValue:BigInt(e.serial.maxValue)},...e.serial.format&&{format:e.serial.format},...e.serial.gapless&&{gapless:!0}}},...e.scale!==void 0&&{scale:e.scale}};return e.type===`nested`&&e.fields&&(t.fields=processNestedFieldsFromSnapshot(e.fields)),t}function processNestedFieldsFromSnapshot(e){let t=/* @__PURE__ */ new Map;for(let[n,r]of Object.entries(e))if(r.type===`nested`&&r.fields){let e=processNestedFieldsFromSnapshot(r.fields);t.set(n,{type:`nested`,allowedValues:r.allowedValues?.map(e=>({...e}))??[],description:r.description||``,required:r.required,array:r.array??!1,index:!1,unique:!1,foreignKey:!1,vector:!1,fields:e,...r.scale!==void 0&&{scale:r.scale}})}else t.set(n,{type:r.type,allowedValues:r.type===`enum`?r.allowedValues?.map(e=>({...e}))??[]:[],description:r.description||``,required:r.required,array:r.array??!1,index:(r.index??!1)||(r.unique??!1),unique:r.unique??!1,foreignKey:r.foreignKey??!1,foreignKeyType:r.foreignKeyType,foreignKeyField:r.foreignKeyField,vector:!1,...optionalOnCreate(r),...r.serial&&{serial:{start:BigInt(r.serial.start),...r.serial.maxValue!==void 0&&{maxValue:BigInt(r.serial.maxValue)},...r.serial.format&&{format:r.serial.format}}},...r.scale!==void 0&&{scale:r.scale}});return Object.fromEntries(t)}function convertRelationshipToProto(e,t){return t===`forward`?{refType:e.targetType,refField:e.sourceField,srcField:e.targetField,array:e.isArray,description:e.description}:{refType:e.targetType,refField:e.targetField,srcField:e.sourceField,array:e.isArray,description:e.description}}function convertIndexToProto(e){return{fieldNames:e.fields,unique:e.unique??!1}}function convertRecordPermissionToProto(e){return{create:e.create.map(convertActionPermissionToProto),read:e.read.map(convertActionPermissionToProto),update:e.update.map(convertActionPermissionToProto),delete:e.delete.map(convertActionPermissionToProto)}}function convertActionPermissionToProto(e){let t;switch(e.permit){case`allow`:t=Pn.ALLOW;break;case`deny`:t=Pn.DENY;break;default:throw b(`Unknown permission: ${e.permit}`)}return{conditions:e.conditions.map(convertConditionToProto),permit:t,description:e.description}}function convertConditionToProto(e){let[t,n,r]=e,i=convertOperandToProto(t),a=convertOperandToProto(r),o;switch(n){case`eq`:o=yr.EQ;break;case`ne`:o=yr.NE;break;case`in`:o=yr.IN;break;case`nin`:o=yr.NIN;break;case`hasAny`:o=yr.HAS_ANY;break;case`nhasAny`:o=yr.NHAS_ANY;break;default:throw b(`Unknown operator: ${n}`)}return{left:i,operator:o,right:a}}function convertOperandToProto(e){if(isSnapshotFieldRefOperand(e)){if(`user`in e)return{kind:{case:`userField`,value:e.user}};if(`record`in e)return{kind:{case:`recordField`,value:e.record}};if(`newRecord`in e)return{kind:{case:`newRecordField`,value:e.newRecord}};if(`oldRecord`in e)return{kind:{case:`oldRecordField`,value:e.oldRecord}};throw b(`Unknown field-ref operand shape: ${JSON.stringify(e)}`)}return{kind:{case:`value`,value:Jr(ai,e)}}}function generateAllTypeManifestsFromSnapshot(e,t={}){let n=/* @__PURE__ */ new Map,{executorUsedTables:r,...i}=t;for(let[t,a]of Object.entries(e.tables)){let e={...i,subscribed:r?.has(t)??!1};n.set(t,generateTailorDBTypeManifestFromSnapshot(a,e))}return n}function compareSnapshotWithRemote(e,t){let n=new Set(Object.keys(e.tables)),r=[],i=[],a=[];for(let e of n)t.has(e)?i.push(e):r.push(e);for(let e of t)n.has(e)||a.push(e);return{creates:r,updates:i,deletes:a}}function protoGqlPermission(e){return{policies:e.map(e=>protoGqlPolicy(e))}}function protoGqlPolicy(e){let t=[];for(let n of e.actions)switch(n){case`all`:t.push(L.ALL);break;case`create`:t.push(L.CREATE);break;case`read`:t.push(L.READ);break;case`update`:t.push(L.UPDATE);break;case`delete`:t.push(L.DELETE);break;case`aggregate`:t.push(L.AGGREGATE);break;case`bulkUpsert`:t.push(L.BULK_UPSERT);break;default:throw b(`Unknown action: ${n}`)}let n;switch(e.permit){case`allow`:n=jn.ALLOW;break;case`deny`:n=jn.DENY;break;default:throw b(`Unknown permission: ${e.permit}`)}return{conditions:e.conditions.map(e=>protoGqlCondition(e)),actions:t,permit:n,description:e.description}}function protoGqlCondition(e){let[t,n,r]=e,i=protoGqlOperand(t),a=protoGqlOperand(r),o;switch(n){case`eq`:o=Un.EQ;break;case`ne`:o=Un.NE;break;case`in`:o=Un.IN;break;case`nin`:o=Un.NIN;break;case`hasAny`:o=Un.HAS_ANY;break;case`nhasAny`:o=Un.NHAS_ANY;break;default:throw b(`Unknown operator: ${n}`)}return{left:i,operator:o,right:a}}function protoGqlOperand(e){if(isSnapshotFieldRefOperand(e)){if(`user`in e)return{kind:{case:`userField`,value:e.user}};throw E({code:`TAILORDB_PERMISSION_OPERAND_UNSUPPORTED`,message:`Unsupported field-ref operand in GQL permission: ${JSON.stringify(e)}.`,suggestion:`GQL permissions only support { user } field references.`})}return{kind:{case:`value`,value:Jr(ai,e)}}}function defineRecordEntry(e,t,n){Object.defineProperty(e,t,{value:n,enumerable:!0,writable:!0,configurable:!0})}const vs=/* @__PURE__ */ new Set([`field_added`,`field_modified`,`field_type_modified`,`field_removed`,`field_renamed`]);function isPreMigrationFieldChange(e){return vs.has(e.kind)}function createPreMigrationSnapshotType(e,t,n){let r=structuredClone(e.fields),i=!1;for(let[e,n]of t)n.kind===`field_type_modified`&&(i=!0,defineRecordEntry(r,e,structuredClone(n.before)));let a={...e,fields:r};if(!i||!n)return a;let{typeHookExpr:o,typeValidateExpr:s,...c}=a;return{...c,...n.before.typeHookExpr&&{typeHookExpr:structuredClone(n.before.typeHookExpr)},...n.before.typeValidateExpr!==void 0&&{typeValidateExpr:n.before.typeValidateExpr}}}function buildPreMigrationChangesMap(e){return buildPreMigrationChangesMapFromDiffs(e.map(e=>e.diff))}function buildPreMigrationChangesMapFromDiffs(e){let t=/* @__PURE__ */ new Map;for(let n of e)for(let e of n.changes){if(!isPreMigrationFieldChange(e)||!e.fieldName)continue;let n=t.get(e.tableName)??/* @__PURE__ */ new Map;n.set(e.fieldName,e),t.set(e.tableName,n)}return t}function applyPreMigrationFieldAdjustments(e,t){relaxFieldsForPreMigration(e,t,{toField:convertFieldConfigToProto,adjustNestedMembers:(e,t)=>{restoreRemovedNestedMembers(e,t.before,t.after),relaxRenamedNestedMembers(e,t.memberRenames??[])}})}function applyPreMigrationFieldAdjustmentsToSnapshot(e,t){relaxFieldsForPreMigration(e,t,{toField:e=>structuredClone(e),adjustNestedMembers:(e,t)=>{for(let n of collectNestedMemberChanges(t.before,t.after)){if(n.kind!==`removed`)continue;let t=getNestedMember(e,n.path.slice(0,-1))?.fields,r=n.path.at(-1);if(!t||r===void 0)continue;let i=structuredClone(n.before);relaxMemberUnique(i),defineRecordEntry(t,r,i)}for(let n of t.memberRenames??[]){let t=getNestedMember(e,n.path);t?.required&&(t.required=!1),t&&relaxMemberUnique(t)}}})}function relaxMemberUnique(e){e.unique&&=!1,relaxNestedUnique(e)}function relaxNestedUnique(e){for(let t of Object.values(e.fields??{}))t.unique&&=!1,relaxNestedUnique(t)}function relaxFieldsForPreMigration(e,t,n){let restoreField=e=>{let t=n.toField(e);return relaxNestedUnique(t),t};for(let[r,i]of t){if(i.kind===`field_removed`){defineRecordEntry(e,r,restoreField(i.before));continue}if(i.kind===`field_renamed`){defineRecordEntry(e,i.previousFieldName,restoreField(i.before));let t=e[r];t&&(i.after.required&&(t.required=!1),(i.after.unique??!1)&&(t.unique=!1),relaxNestedUnique(t));continue}let t=e[r];if(!t)continue;let a=t;if(i.kind===`field_added`){i.after.required&&(a.required=!1);continue}if(i.kind===`field_type_modified`){defineRecordEntry(e,r,restoreField(i.before));continue}let{before:o,after:s}=i;n.adjustNestedMembers?.(t,i);for(let e of collectNestedMemberChanges(o,s)){if(e.kind===`removed`)continue;let n=e.path.reduce((e,t)=>e?.fields?.[t],t);n&&(e.kind===`added`?e.after.required&&(n.required=!1):relaxModifiedFieldConstraints(n,e.before,e.after))}relaxModifiedFieldConstraints(a,o,s),addsForeignKey(o,s)&&(delete a.foreignKey,delete a.foreignKeyType,delete a.foreignKeyField)}}function relaxModifiedFieldConstraints(e,t,n){!t.required&&n.required&&(e.required=!1),!(t.unique??!1)&&(n.unique??!1)&&(e.unique=!1);let r=t.allowedValues??[],i=n.allowedValues??[],a=new Set(i.map(e=>e.value));if(r.filter(e=>!a.has(e.value)).length>0){let t=/* @__PURE__ */ new Map;for(let e of r)t.set(e.value,e.description??``);for(let e of i)t.has(e.value)||t.set(e.value,e.description??``);e.allowedValues=Array.from(t.entries()).map(([e,t])=>({value:e,description:t}))}}function getProtoNestedMember(e,t){return t.reduce((e,t)=>e?.fields?.[t],e)}function restoreRemovedNestedMembers(e,t,n){for(let r of collectNestedMemberChanges(t,n)){if(r.kind!==`removed`)continue;let t=r.path.join(`.`),n=a(getProtoNestedMember(e,r.path.slice(0,-1))?.fields,`parent of removed nested member "${t}" missing from the Pre-phase field`),i=a(r.path.at(-1),`removed nested member path is empty`),o=a(processNestedFieldsFromSnapshot({[i]:r.before})[i],`restored nested member "${t}" missing`);relaxMemberUnique(o),defineRecordEntry(n,i,o)}}function relaxRenamedNestedMembers(e,t){for(let n of t){let t=getProtoNestedMember(e,n.path);t?.required&&(t.required=!1),t&&relaxMemberUnique(t)}}function buildPreMigrationIndexChangesMap(e){return buildPreMigrationIndexChangesMapFromDiffs(e.map(e=>e.diff))}function buildPreMigrationIndexChangesMapFromDiffs(e){let t=/* @__PURE__ */ new Map;for(let n of e)for(let e of n.changes){if(e.kind!==`index_added`&&e.kind!==`index_modified`)continue;let n=e.kind===`index_modified`?e.before:void 0;if(!isBreakingIndexChange(e.tableName,e.indexName,n,e.after))continue;let r=t.get(e.tableName)??/* @__PURE__ */ new Map;r.set(e.indexName,e),t.set(e.tableName,r)}return t}function applyPreMigrationIndexAdjustments(e,t){relaxIndexesForPreMigration(e,t,convertIndexToProto)}function applyPreMigrationIndexAdjustmentsToSnapshot(e,t){relaxIndexesForPreMigration(e,t,e=>structuredClone(e))}function relaxIndexesForPreMigration(e,t,n){for(let[r,i]of t)i.kind===`index_added`?delete e[r]:i.kind===`index_modified`&&defineRecordEntry(e,r,n(i.before))}function buildPreMigrationSnapshot(e,t){let n=applyDiffToSnapshot(e,t),r=buildPreMigrationChangesMapFromDiffs([t]),i=buildPreMigrationIndexChangesMapFromDiffs([t]),a=createSnapshotRecord();for(let e of Object.values(n.tables)){let n=r.get(e.name),o=n?createPreMigrationSnapshotType(e,n,t.changes.find(t=>t.kind===`table_scripts_modified`&&t.tableName===e.name)):e,s=copySnapshotRecord(o.fields);n&&applyPreMigrationFieldAdjustmentsToSnapshot(s,n);let c={...o,fields:s},l=i.get(e.name);if(e.indexes&&l){let t=copySnapshotRecord(e.indexes);applyPreMigrationIndexAdjustmentsToSnapshot(t,l),c.indexes=t}a[e.name]=c}return includeTablesDeletedAfterCheckpoint({...n,tables:a},t)}function tablesDeletedAfterCheckpoint(e){return e.changes.flatMap(e=>e.kind===`table_removed`?[{name:e.tableName,before:e.before}]:e.kind===`table_renamed`?[{name:e.previousTableName,before:e.before}]:[])}function getTablesDeletedAfterCheckpoint(e){return new Set(tablesDeletedAfterCheckpoint(e).map(e=>e.name))}function includeTablesDeletedAfterCheckpoint(e,t){let n=copySnapshotRecord(e.tables);for(let{name:e,before:r}of tablesDeletedAfterCheckpoint(t))n[e]=r;return{...e,tables:n}}function parseInProgress(e){let t=e[qa],n=e[Ya];if(t===void 0)return{inProgress:null,inProgressInvalid:n!==void 0};let r=parseInProgressLabel(t),i=n===void 0?void 0:parseExecutionLabel(n);return r===null||i===null?{inProgress:null,inProgressInvalid:!0}:{inProgress:{number:r.number,...i===void 0?{}:{executionId:i},kind:r.kind},inProgressInvalid:!1}}async function fetchRemoteMigrationState(e,t){let n=await P(async()=>{let{metadata:n}=await e.getMetadata({trn:t});return n});if(!n)return{metadataExists:!1,number:null,historyId:null,historyIdInvalid:!1,inProgress:null,inProgressInvalid:!1,maintenanceModeCheckpoint:null,cleanupCheckpoint:null};let r=n.labels[Ga],i=n.labels[Xa],a=n.labels[Za],o=n.labels[Ka],s=o?parseMigrationHistoryId(o):null;return{metadataExists:!0,number:r?parseMigrationLabelNumber(r):null,historyId:s,historyIdInvalid:o!==void 0&&s===null,...parseInProgress(n.labels),maintenanceModeCheckpoint:i?parseMigrationLabelNumber(i):null,cleanupCheckpoint:a?parseMigrationLabelNumber(a):null}}function isCheckpointStillOwned(e,t){return e.number===t.number&&!e.historyIdInvalid&&e.historyId===t.historyId}function matchesLocalMigrationHistory(e,t){return e.historyIdInvalid?!1:e.number===null&&e.historyId===null||e.historyId===t}function describeMigrationHistoryId(e){return e.historyIdInvalid?`<invalid>`:e.historyId??`<unset>`}function migrationHistoryMismatchError(e){let{state:t,localHistoryId:n,namespace:r,code:i,suggestion:a}=e;return E({code:i,message:`The migration history of namespace "${r}" on the workspace does not match the local migration history.`,details:`The workspace records migration history ID ${describeMigrationHistoryId(t)}; the local migration history has ${n??`<unset>`}.`,suggestion:a,context:{namespace:r,remoteHistoryId:t.historyId,remoteHistoryIdInvalid:t.historyIdInvalid,localHistoryId:n}})}function assertLocalMigrationHistory(e){let{force:t,...n}=e,{state:r,localHistoryId:i}=n;if(!matchesLocalMigrationHistory(r,i)){if(!t)throw migrationHistoryMismatchError({...n,suggestion:`Run the command from a checkout of the migration history that was deployed to the workspace, or pass --force to replace it with the local migration history.`});return`Overwriting the migration history ID ${describeMigrationHistoryId(r)} with ${i??`<unset>`} (--force).`}}function describeMigrationCheckpoint(e){return e==null?`<unset>`:formatMigrationNumber(e)}function isStaleMigrationInProgress(e){return e.inProgress!==null&&e.number!==null&&e.inProgress.number<=e.number}function migrationResolveArgs(e,t,n){return namespaceMigrationArgs({...n,subcommand:[`resolve`,`--${e}`],namespace:t})}function formatMigrationResolveHint(e,t,n){return w({command:`tailor`,args:migrationResolveArgs(e,t,n)})}function describeMainRunSettlement(e,t){return`Settle it with ${formatMigrationResolveHint(`complete`,e,t)} if its run succeeded, or with ${formatMigrationResolveHint(`rollback`,e,t)} otherwise; the command shows the outcome of the run before it changes anything.`}function inProgressMigrationActions(e){let{state:t,namespace:n,...r}=e,i=t.inProgress;if(!i||i.number!==(t.number??0)+1)return[];let a=formatMigrationNumber(i.number),o=formatMigrationNumber(i.number-1),settleAction=(e,t)=>({action:e,description:t,command:`tailor`,args:migrationResolveArgs(e,n,r)});return i.kind===`main`?[settleAction(`complete`,`applies the schema of migration ${a} without running its script again; use it when the run succeeded`),settleAction(`rollback`,`returns to the schema of migration ${o}, and the next deploy runs its script again; use it when the run did not succeed`)]:[{action:`resume`,description:`steps that already completed do not run again`,command:`tailor`,args:[`deploy`,...migrationContextArgs(r)]},settleAction(`rollback`,`returns to the schema of migration ${o}, and the next deploy runs every step again`),settleAction(`complete`,`applies the schema of migration ${a} without running its script again`)]}const ys={resume:`Resume`,rollback:`Roll back`,complete:`Complete`};function formatInProgressMigrationAction(e){return`${ys[e.action]}: ${w(e)} (${e.description})`}function assertNoMigrationInProgress(e,t,n){if(!e.inProgress&&!e.inProgressInvalid)return;let r=e.inProgress?`${t}/${formatMigrationNumber(e.inProgress.number)}`:void 0,i=inProgressMigrationActions({...n,state:e,namespace:t});throw E({code:`MIGRATION_IN_PROGRESS`,message:e.inProgress?e.inProgress.kind===`main`?`The outcome of the run of migration ${r} that an earlier deploy started is not settled.`:`Migration ${r} is partially applied by an earlier deploy.`:`Namespace "${t}" records a partially applied migration that cannot be read.`,suggestion:i.length>0?[`Continue or settle the migration first with one of these commands:`,...i.map(e=>`- ${formatInProgressMigrationAction(e)}`)].join(`
|
|
16
|
-
`):e.inProgress?.kind===`main`?describeMainRunSettlement(t,n):`Finish the migration with a deploy first; steps that already completed do not run again.`})}function toTailorDBDeployInput(e){let t={};for(let[n,r]of Object.entries(e.types))t[n]=createSnapshotType(r);return{namespace:e.namespace,config:e.config,types:t}}async function fetchRemoteTypes(e,t,n){return F(async(r,i)=>{let{tailordbTypes:a,nextPageToken:o}=await e.listTailorDBTypes({workspaceId:t,namespaceName:n,pageToken:r,pageSize:i});return[a,o]})}async function fetchRemoteGqlPermissions(e,t,n){return F(async(r,i)=>{let{permissions:a,nextPageToken:o}=await e.listTailorDBGQLPermissions({workspaceId:t,namespaceName:n,pageToken:r,pageSize:i});return[a,o]})}async function fetchRemoteSchema(e,t,n){let[r,i]=await Promise.all([fetchRemoteTypes(e,t,n),fetchRemoteGqlPermissions(e,t,n)]);return{types:r,gqlPermissions:i}}async function fetchRemoteSchemaSnapshot(e,t,n){let{types:r,gqlPermissions:i}=await fetchRemoteSchema(e,t,n);return createSnapshotFromRemoteTypes(r,n,i)}function definedWhenNotEmpty(e){return Object.keys(e).length>0?e:void 0}function namespaceConfig(e,t,n){return t.find(e=>e.namespace===n)?.config??e.db?.[n]}function namespaceGqlOperations(e,t,n){return namespaceConfig(e,t,n)?.gqlOperations}const bs=[`create`,`update`,`delete`,`read`];function configuredDisabledGqlOperations(e){if(!e)return;if(e===`query`)return{create:!1,update:!1,delete:!1};let t={};for(let n of bs)e[n]===!1&&(t[n]=!1);return definedWhenNotEmpty(t)}function appliedConfiguredDisabledGqlOperations(e,t){if(!e||!t)return;let n={};for(let r of bs)t[r]===!1&&e[r]&&(n[r]=!1);return definedWhenNotEmpty(n)}function deployComparableSnapshot(e,t,n){let r=new Map(t.map(e=>[e.name,e])),i=configuredDisabledGqlOperations(n),a={};for(let[t,n]of Object.entries(e.tables)){let e={...n.settings},o=r.get(t)?.schema?.settings;if(n.settings?.publishEvents===void 0&&o?.publishRecordEvents&&(e.publishEvents=!0),n.settings?.gqlOperations===void 0){let t=appliedConfiguredDisabledGqlOperations(o?.disableGqlOperations,i);t&&(e.gqlOperations=t)}let s={...n},c=definedWhenNotEmpty(e);c?s.settings=c:delete s.settings,a[t]=s}return{...e,tables:a}}function buildInProgressSnapshot(e,t){let n=buildPreMigrationSnapshot(e,t);for(let e of t.changes){let t=n.tables[e.tableName]?.fields;if(t){if(e.kind===`field_removed`)stripKeptFieldScripts(t,e.fieldName);else if(e.kind===`field_renamed`)stripKeptFieldScripts(t,e.previousFieldName);else if(e.kind===`field_modified`)for(let n of collectNestedMemberChanges(e.before,e.after)){if(n.kind!==`removed`)continue;let r=getNestedMember(t[e.fieldName],n.path.slice(0,-1))?.fields,i=n.path.at(-1);r&&i!==void 0&&stripKeptFieldScripts(r,i)}}}return n}function stripKeptFieldScripts(e,t){let n=Object.hasOwn(e,t)?e[t]:void 0;n&&(e[t]=stripFieldScriptProps(n))}function loadMigrationDiff(e,t){let n=getMigrationFilePath(e,t,`diff`);return W.existsSync(n)?loadDiff(n):null}function reconstructPreMigrationSnapshot(e,t){let n=reconstructSnapshotFromMigrations(e,t-1),r=loadMigrationDiff(e,t);return!n||!r?null:buildInProgressSnapshot(n,r)}function reconstructExpectedRemoteSchema(e,t,n){if(!n){let n=reconstructSnapshotFromMigrations(e,t);return n&&{snapshot:n}}let r=reconstructSnapshotFromMigrations(e,n.number-1),i=loadMigrationDiff(e,n.number);return!r||!i?null:{snapshot:buildInProgressSnapshot(r,i),...n.kind===`steps`&&{postPhase:includeTablesDeletedAfterCheckpoint(applyDiffToSnapshot(r,i),i)}}}function compareRemoteSchemaWithSnapshot(e,t,n,r,i,a=[],o=`all`){let s=deployComparableSnapshot(n,e.types,namespaceGqlOperations(r,i,t));return compareRemoteWithSnapshot(e.types,s,e.gqlPermissions,a,o===`maintenance-mode`?new Set(e.types.filter(e=>isMigrationRestricted(e.schema?.settings)).map(e=>e.name)):void 0)}function locateRemoteCheckpoint(e,t,n){let r=e.number,i=getLatestMigrationNumber(t),a=getMigrationFiles(t).length>0?i:null,o=!matchesLocalMigrationHistory(e,n?.historyId??null);if(e.historyIdInvalid||r===null&&e.historyId!==null)return{kind:`outside`,number:r??0,localLatestMigration:a,historyIdMismatch:o};if(r===null)return{kind:`unset`};let s=n?e.historyId===n.historyId:e.historyId===null,c=n?e.historyId===n.replacedHistoryId:!1,l=n&&c&&r===n.replacedLatestMigration?{from:r,to:0,fromHistoryId:e.historyId,toHistoryId:n.historyId}:void 0;if(!s&&!l||r>i&&!l){let e=n&&c&&r<n.replacedLatestMigration?{replacedLatestMigration:n.replacedLatestMigration}:void 0;return{kind:`outside`,number:r,localLatestMigration:a,historyIdMismatch:o,...e?{rebaselinePending:e}:{}}}return{kind:`inside`,number:r,...l?{checkpointRepair:l}:{}}}function findUnfinishedRemovals(e,t,n){let r=getMigrationFilePath(e,t,`diff`);if(!W.existsSync(r))return[];let i=getTablesDeletedAfterCheckpoint(loadDiff(r)),a=reconstructSnapshotFromMigrations(e)?.tables??{};return n.map(e=>e.name).filter(e=>i.has(e)&&!Object.hasOwn(a,e)).toSorted()}function withGqlPermissionsOf(e,t){let n=createSnapshotRecord();for(let[r,i]of Object.entries(e.tables)){let{permissions:e,...a}=i,{gql:o,...s}=e??{},c=t.tables[r]?.permissions?.gql,l=c?{...s,gql:c}:s;n[r]=Object.keys(l).length>0?{...a,permissions:l}:a}return{...e,tables:n}}function findInterruptedMigration(e){let{remote:t,namespace:n,migrationsDir:r,checkpoint:i,checkpointSnapshot:a,config:o,tailorDBInputs:s}=e,c=i+1,l=reconstructPreMigrationSnapshot(r,c);if(!l)return;let u=o.maintenanceMode!==!1,compare=e=>compareRemoteSchemaWithSnapshot(t,n,e,o,s,u?gs:[],`maintenance-mode`),d=new Set(t.types.filter(e=>isMigrationRestricted(e.schema?.settings)).map(e=>e.name)),f=loadMigrationDiff(r,i),p=f?getTablesDeletedAfterCheckpoint(f):/* @__PURE__ */ new Set,driftedTables=e=>new Set(compare(e).map(e=>e.tableName)),m=driftedTables(l).intersection(driftedTables(withGqlPermissionsOf(l,a)));return compare(a).every(e=>!m.has(e.tableName)&&!p.has(e.tableName)&&(!u||d.has(e.tableName)))?c:void 0}function notDeployedResult(e){return{namespace:e,remoteMigrationNumber:0,drifts:[],hasDrift:!1,skipped:`not_deployed`}}async function verifyRemoteSchema(e,t,n,r,i,a={}){let o=[];for(let{namespace:s,migrationsDir:c}of n){let n=await fetchRemoteMigrationState(e,resourceTrn(t,`tailordb`,s));a.remoteStates?.set(s,n);let l=locateRemoteCheckpoint(n,c,reconstructSnapshotFromMigrations(c,0)?.rebaseline);if(l.kind===`outside`){o.push({namespace:s,remoteMigrationNumber:l.number,drifts:[],hasDrift:!1,checkpointMissingLocal:!0,localLatestMigration:l.localLatestMigration,historyIdMismatch:l.historyIdMismatch,...l.rebaselinePending?{rebaselinePending:l.rebaselinePending}:{}});continue}let u=l.kind===`unset`;if(u&&!n.metadataExists){o.push(notDeployedResult(s));continue}let d=l.kind===`inside`?l.number:0,f=l.kind===`inside`?l.checkpointRepair:void 0,p=f?.to??d,m=!f&&n.inProgress?.number===d+1?n.inProgress:void 0,h=reconstructExpectedRemoteSchema(c,p,m);if(!h){o.push({namespace:s,remoteMigrationNumber:d,drifts:[],hasDrift:!1,skipped:`no_snapshot`});continue}let g=await fetchRemoteSchema(e,t,s);if(u&&g.types.length===0){o.push(notDeployedResult(s));continue}let _=a.acceptUnfinishedRemovals&&!f&&n.cleanupCheckpoint===d?findUnfinishedRemovals(c,d,g.types):void 0,v=m===void 0&&n.maintenanceModeCheckpoint===d,y=_?.length?{...g,types:g.types.filter(e=>!_.includes(e.name))}:g,compareWith=e=>compareRemoteSchemaWithSnapshot(y,s,e,r,i,m!==void 0||v?gs:[],v?`maintenance-mode`:`all`),b=compareWith(h.snapshot);if(b.length>0&&h.postPhase){let e=new Set(compareWith(h.postPhase).map(e=>e.tableName));b=b.filter(t=>e.has(t.tableName))}let x=!n.inProgressInvalid&&(n.inProgress===null||isStaleMigrationInProgress(n)),S=b.length>0&&a.acceptInterruptedMigration&&x&&!f?findInterruptedMigration({remote:y,namespace:s,migrationsDir:c,checkpoint:d,checkpointSnapshot:h.snapshot,config:r,tailorDBInputs:i}):void 0;o.push({namespace:s,remoteMigrationNumber:d,...S===void 0?{drifts:b,hasDrift:b.length>0}:{drifts:[],hasDrift:!1,interruptedMigration:S},...v?{leftInMaintenanceMode:v}:{},...u?{checkpointUnset:u}:{},...f&&b.length===0?{checkpointRepair:f}:{},...n.inProgress?{migrationInProgress:n.inProgress}:{},...n.inProgressInvalid?{migrationInProgressInvalid:!0}:{},..._?{unfinishedRemovals:_}:{}})}return o}function isMissingRemoteScriptHashDrift(e){return e.kind===`script_mismatch`&&e.details.endsWith(`has no script hash on remote`)}function isLikelyPreV2ScriptHashDrift(e){let t=e.filter(e=>e.hasDrift);return t.length>0&&t.every(e=>e.drifts.length>0&&e.drifts.every(isMissingRemoteScriptHashDrift))}function logRemoteDriftGuidance(e,t){let n=t?.filter(e=>e.hasDrift)??[];if(n.length>0&&n.every(e=>e.checkpointUnset))return;let r=w({command:`tailor`,args:migrationCommandArgs([`status`],e)});C.info(`This may indicate:`),C.info(` - Another developer applied different migrations`,{mode:`plain`}),C.info(` - Manual schema changes were made directly`,{mode:`plain`}),C.info(` - Migration history is out of sync`,{mode:`plain`}),C.newline(),C.info(`To resolve:`),C.info(` - Run ${r} to compare local vs remote.`,{mode:`plain`}),C.info(` - If remote is correct, update local tables and run 'migration generate'.`,{mode:`plain`}),C.info(` - If local migration history is correct, run 'migration sync <N>' to overwrite remote.`,{mode:`plain`}),C.info(` - If remote already matches another migration, run 'migration sync <N>' with that migration to move only the checkpoint.`,{mode:`plain`}),t&&isLikelyPreV2ScriptHashDrift(t)&&(C.newline(),C.info(`Every listed drift is '${_s}'. Run 'migration sync <N>' above to add the missing hashes.`))}function unsetCheckpointDriftHints(e,t){return e.filter(e=>e.checkpointUnset&&e.hasDrift).map(({namespace:e})=>`Namespace "${e}" has no migration checkpoint yet, so its tables must match migration 0000. Run ${formatNamespaceMigrationHint({...t,subcommand:[`sync`,formatMigrationNumber(0)],namespace:e})} to rewrite them to 0000, which deletes the tables and fields that 0000 does not have together with their data. To keep the tables instead, update the local tables to match them and recreate 0000 with ${formatNamespaceMigrationHint({subcommand:[`generate`,`--init`],namespace:e,configPath:t.configPath})}, which deletes every migration of the namespace, so only while no workspace has been deployed with them.`)}function hasRebaselinePending(e){return e.rebaselinePending!==void 0}const xs=`Pull the latest migration files if this checkout is behind.`;function missingCheckpointRecoveryHints(e,t){let n=e.filter(e=>!e.rebaselinePending);if(n.length===0)return[];let r=n.flatMap(({namespace:e,localLatestMigration:n,historyIdMismatch:r})=>n===null?[]:[` ${formatCheckpointSyncHint({...t,namespace:e,migrationNumber:n,replaceHistoryId:r})}`]);return[xs,...n.some(e=>e.historyIdMismatch&&e.localLatestMigration!==null)?[`For a namespace that records another migration history, work from a checkout of that history instead; run its --force command below only if the local migration history should replace it.`]:[],...r.length>0?[`To move the checkpoint back to the local history on purpose, run the following, then deploy. Each command rewrites the tables to that migration, removing the fields it does not have and deleting the tables it does not have together with their data:`,...r]:[]]}function logRebaselinePendingGuidance(e){let t=e.filter(hasRebaselinePending);if(t.length>0){for(let e of t){let t=formatMigrationNumber(e.rebaselinePending.replacedLatestMigration),n=formatMigrationNumber(e.remoteMigrationNumber);C.info(`${e.namespace} fell behind before 'migration rebaseline' ran: every environment was required to already be at migration ${t} before the rebaseline, but this environment is at ${n}.`)}C.newline(),C.info(`To recover:`),C.info(` 1. Restore the pre-rebaseline migrations/ directory from git history (the commit before 'migration rebaseline' ran; rebaseline preserves committed files there).`,{mode:`plain`}),C.info(` 2. Deploy this environment against that restored history until its checkpoint reaches the migration named above, running any migrate.ts scripts it still needs.`,{mode:`plain`}),C.info(` 3. Switch back to the current migration files and deploy again — the automatic checkpoint reset to the new baseline then applies.`,{mode:`plain`})}}function formatRemoteVerificationResults(e){let t=[];for(let n of e)n.hasDrift&&(t.push(`Namespace: ${n.namespace}`),t.push(` Remote migration: ${describeMigrationCheckpoint(n.checkpointUnset?null:n.remoteMigrationNumber)}`),t.push(` Differences:`),t.push(formatSchemaDrifts(n.drifts)),t.push(``));return t.join(`
|
|
11
|
+
`)}\n}`)}}}return i}function principalDeclIfReferenced(...e){return e.some(e=>e?.includes(`_principal`))?` const ${Ue} = (${He});`:``}function wrapHook(e){return`((_invoker) => { const ${ps} = new Date();${principalDeclIfReferenced(e)} return ${e}; })(typeof _invoker !== "undefined" ? _invoker : undefined)`}function wrapValidate(e,t){let n=t?` const __issues = (f, m) => { __errs[f] = m; };`:``,r=principalDeclIfReferenced(t,...e),i=t?` ${t};`:``;return`((_invoker) => { const __errs = {};${n}${r}\n${e.join(`
|
|
12
|
+
`)}${i}\nreturn __errs; })(typeof _invoker !== "undefined" ? _invoker : undefined)`}function buildTypeScripts(e,t){let n={},r=t?.typeHookExpr,i=t?.typeValidateExpr,a=computeSourceScriptHash(t?.sourceFields??e,t),o=a?` // @sdk-source-hash:${a}`:``,s={};for(let t of[`create`,`update`]){let n=buildHookObject(e,ds,fs,t,!1,t===`update`?`Object.assign({}, ${fs}, ${ds})`:ds),i=r?.[t],a;if(n!==null&&i){let e=principalDeclIfReferenced(n,i);a=`((_invoker) => { const ${ps} = new Date();${e} const __fl = ${n}; return Object.assign({}, __fl, ((${ds}) => ${i})(Object.assign({}, ${ds}, __fl))); })(typeof _invoker !== "undefined" ? _invoker : undefined)`}else i?a=wrapHook(i):n!==null&&(a=wrapHook(n));a&&(s[t]={expr:a+o})}(s.create||s.update)&&(n.typeHook=s);let c=buildValidateStatements(e,`_newRecord`,``);if(c.length>0||i){let e=wrapValidate(c,i)+o;n.typeValidate={create:{expr:e},update:{expr:e}}}return n}function convertRemoteFieldToSnapshot(e){let t={type:e.type,required:e.required};e.array&&(t.array=!0),e.index&&(t.index=!0),e.unique&&(t.unique=!0),e.foreignKey&&(t.foreignKey=!0,e.foreignKeyType&&(t.foreignKeyType=e.foreignKeyType),e.foreignKeyField&&(t.foreignKeyField=e.foreignKeyField));let n=e.allowedValues;n.length>0&&(t.allowedValues=n.map(e=>({value:e.value,...e.description&&{description:e.description}}))),e.description&&(t.description=e.description),e.vector&&(t.vector=!0),e.hooks&&(t.hooks={},e.hooks.create?.expr&&(t.hooks.create={expr:e.hooks.create.expr}),e.hooks.update?.expr&&(t.hooks.update={expr:e.hooks.update.expr}));let r=e.validate;r.length>0&&(t.validate=r.map(e=>({script:{expr:convertRemoteValidateExpression(e.script?.expr??``,e.action)},errorMessage:e.errorMessage??``}))),e.serial&&(t.serial={start:Number(e.serial.start),...e.serial.maxValue&&{maxValue:Number(e.serial.maxValue)},...e.serial.format&&{format:e.serial.format},...e.serial.gapless&&{gapless:!0}}),e.scale!==void 0&&(t.scale=e.scale),e.optionalOnCreate&&!t.hooks?.create&&(t.optionalOnCreate=!0);let i=e.fields;if(Object.keys(i).length>0){t.fields=createSnapshotRecord();for(let[e,n]of Object.entries(i))t.fields[e]=convertRemoteFieldToSnapshot(n)}return t}function convertRemoteFieldsToSnapshot(e){let t=createSnapshotRecord(),n=e.schema?.fields??{};for(let[e,r]of Object.entries(n))t[e]=convertRemoteFieldToSnapshot(r);return t}function convertRemoteValidateExpression(e,t){return t===br.DENY&&e.startsWith(`!`)?e.slice(1):e}function convertRemoteSettingsToSnapshot(e,t){let n={};e?.aggregation&&(n.aggregation=!0),e?.bulkUpsert&&(n.bulkUpsert=!0),e?.publishRecordEvents&&(n.publishEvents=!0);let r=e?.disableGqlOperations;if(r){let e=r.create||r.update||r.delete||r.read;(t?.gqlOperations!==void 0||e)&&(n.gqlOperations={create:!r.create,update:!r.update,delete:!r.delete,read:!r.read})}return Object.keys(n).length>0?n:void 0}function convertRemoteIndexesToSnapshot(e){let t=createSnapshotRecord();for(let[n,r]of Object.entries(e??{}))t[n]={fields:r.fieldNames,...r.unique&&{unique:!0}};return Object.keys(t).length>0?t:void 0}function convertRemoteFilesToSnapshot(e){let t=createSnapshotRecord();for(let[n,r]of Object.entries(e??{}))t[n]=r.description||``;return Object.keys(t).length>0?t:void 0}function convertRemoteRelationshipToSnapshot(e,t){return t===`forward`?{targetType:e.refType,targetField:e.srcField,sourceField:e.refField,isArray:e.array,description:e.description||``}:{targetType:e.refType,targetField:e.refField,sourceField:e.srcField,isArray:e.array,description:e.description||``}}function remoteRelationshipMatchesExpectedDirection(e,t,n){let r=convertRemoteRelationshipToSnapshot(e,n);return r.targetType===t.targetType&&r.targetField===t.targetField&&r.sourceField===t.sourceField&&r.isArray===t.isArray}function inferRemoteRelationshipDirection(e,t,n){let r=n?.forwardRelationships?.[e],i=n?.backwardRelationships?.[e];return r&&!i?`forward`:i&&!r?`backward`:r&&remoteRelationshipMatchesExpectedDirection(t,r,`forward`)?`forward`:i&&remoteRelationshipMatchesExpectedDirection(t,i,`backward`)||t.array?`backward`:`forward`}function convertRemoteRelationshipsToSnapshot(e,t){let n=createSnapshotRecord(),r=createSnapshotRecord();for(let[i,a]of Object.entries(e??{})){let e=inferRemoteRelationshipDirection(i,a,t);e===`forward`?n[i]=convertRemoteRelationshipToSnapshot(a,e):r[i]=convertRemoteRelationshipToSnapshot(a,e)}return{...Object.keys(n).length>0&&{forwardRelationships:n},...Object.keys(r).length>0&&{backwardRelationships:r}}}const gs=/* @__PURE__ */ new Map([[Ln.ALLOW,`allow`],[Ln.DENY,`deny`]]),_s=/* @__PURE__ */ new Map([[Sr.EQ,`eq`],[Sr.NE,`ne`],[Sr.IN,`in`],[Sr.NIN,`nin`],[Sr.HAS_ANY,`hasAny`],[Sr.NHAS_ANY,`nhasAny`]]);function convertRemotePermit(e,t){let n=gs.get(e);if(n)return n;throw b(`Unsupported ${t} permission permit: ${e}`)}function convertRemoteOperator(e,t){let n=_s.get(e);if(n)return n;throw b(`Unsupported ${t} permission operator: ${e}`)}function convertRemoteValueOperand(e){switch(e?.kind.case){case`userField`:return{user:e.kind.value};case`recordField`:return{record:e.kind.value};case`oldRecordField`:return{oldRecord:e.kind.value};case`newRecordField`:return{newRecord:e.kind.value};case`value`:return Qr(ci,e.kind.value);default:throw b(`Unsupported permission operand`)}}function convertRemoteRecordCondition(e){return[convertRemoteValueOperand(e.left),convertRemoteOperator(e.operator,`record`),convertRemoteValueOperand(e.right)]}function convertRemoteGqlCondition(e){return[convertRemoteValueOperand(e.left),convertRemoteOperator(e.operator,`GQL`),convertRemoteValueOperand(e.right)]}function convertRemoteRecordPolicy(e){return{conditions:e.conditions.map(convertRemoteRecordCondition),permit:convertRemotePermit(e.permit,`record`),...e.description&&{description:e.description}}}function convertRemoteRecordPermissionToSnapshot(e){let t={create:e?.create.map(convertRemoteRecordPolicy)??[],read:e?.read.map(convertRemoteRecordPolicy)??[],update:e?.update.map(convertRemoteRecordPolicy)??[],delete:e?.delete.map(convertRemoteRecordPolicy)??[]};return Object.values(t).some(e=>e.length>0)?t:void 0}function convertRemoteGqlAction(e){switch(e){case L.ALL:return`all`;case L.CREATE:return`create`;case L.READ:return`read`;case L.UPDATE:return`update`;case L.DELETE:return`delete`;case L.AGGREGATE:return`aggregate`;case L.BULK_UPSERT:return`bulkUpsert`;default:throw b(`Unsupported GQL permission action: ${e}`)}}function convertRemoteGqlPermissionToSnapshot(e){let t=e?.policies.map(e=>({conditions:e.conditions.map(convertRemoteGqlCondition),actions:e.actions.map(convertRemoteGqlAction),permit:convertRemotePermit(e.permit,`GQL`),...e.description&&{description:e.description}}))??[];return t.length>0?t:void 0}function convertRemoteTypeToSnapshot(e,t){let n=convertRemoteSettingsToSnapshot(e.schema?.settings,t?.settings),r=convertRemoteRelationshipsToSnapshot(e.schema?.relationships,t),i=convertRemoteRecordPermissionToSnapshot(e.schema?.permission),a={name:e.name,pluralForm:e.schema?.settings?.pluralForm||Di.pluralize(e.name),fields:convertRemoteFieldsToSnapshot(e),...n&&{settings:n},...r};e.schema?.description&&(a.description=e.schema.description);let o=convertRemoteIndexesToSnapshot(e.schema?.indexes);o&&(a.indexes=o);let s=convertRemoteFilesToSnapshot(e.schema?.files);return s&&(a.files=s),i&&(a.permissions={record:i}),a}function createSnapshotFromRemoteTypes(e,t,n=[],r){let i=createSnapshotRecord();for(let t of e)i[t.name]=convertRemoteTypeToSnapshot(t,r?.tables[t.name]);for(let e of n){let{typeName:t}=e,n=i[t];if(!n)continue;let r=convertRemoteGqlPermissionToSnapshot(e.permission);r&&(n.permissions={...n.permissions,gql:r})}return normalizeSchemaSnapshot({version:8,namespace:t,createdAt:(/* @__PURE__ */ new Date()).toISOString(),tables:i})}function fieldDifferenceValue(e){return e===void 0||e===``?`none`:String(e)}function fieldDifferenceKey(e,t){return e?`${e}.${t}`:t}function addFieldDifference(e,t,n,r,i){r!==i&&e.push(`${fieldDifferenceKey(t,n)}: remote=${fieldDifferenceValue(r)}, expected=${fieldDifferenceValue(i)}`)}function addBooleanFieldDifference(e,t,n,r,i){addFieldDifference(e,t,n,r[n]??!1,i[n]??!1)}function addAllowedValuesDifferences(e,t,n,r){let i=n.allowedValues??[],a=r.allowedValues??[];if(i.length!==a.length){e.push(`${fieldDifferenceKey(t,`allowedValues`)} count: remote=${i.length}, expected=${a.length}`);return}let o=new Map(a.map(e=>[e.value,e.description]));for(let n of i){if(!o.has(n.value)){e.push(`${fieldDifferenceKey(t,`allowedValues`)}: remote has '${n.value}' not in snapshot`);return}let r=o.get(n.value);if((n.description??``)!==(r??``)){addFieldDifference(e,t,`allowedValues.${n.value}.description`,n.description??``,r??``);return}}let s=new Set(i.map(e=>e.value));for(let n of a)if(!s.has(n.value)){e.push(`${fieldDifferenceKey(t,`allowedValues`)}: snapshot has '${n.value}' not in remote`);return}}function addHooksDifferences(e,t,n,r){addFieldDifference(e,t,`hooks.create`,n.hooks?.create?.expr??``,r.hooks?.create?.expr??``),addFieldDifference(e,t,`hooks.update`,n.hooks?.update?.expr??``,r.hooks?.update?.expr??``)}function addValidationDifferences(e,t,n,r){let i=n.validate??[],o=r.validate??[];i.length!==o.length&&e.push(`${fieldDifferenceKey(t,`validate`)} count: remote=${i.length}, expected=${o.length}`);let s=Math.min(i.length,o.length);for(let n=0;n<s;n++){let r=a(i[n],`remoteValidate missing index ${n}`),s=a(o[n],`snapshotValidate missing index ${n}`);addFieldDifference(e,t,`validate[${n}].script`,r.script?.expr??``,s.script?.expr??``),addFieldDifference(e,t,`validate[${n}].errorMessage`,r.errorMessage,s.errorMessage)}}function addSerialDifferences(e,t,n,r){addFieldDifference(e,t,`serial.start`,n.serial?.start,r.serial?.start),addFieldDifference(e,t,`serial.maxValue`,n.serial?.maxValue,r.serial?.maxValue),addFieldDifference(e,t,`serial.format`,n.serial?.format??``,r.serial?.format??``),addFieldDifference(e,t,`serial.gapless`,n.serial?.gapless??!1,r.serial?.gapless??!1)}function addNestedFieldDifferences(e,t,n,r){let i=n.fields??{},o=r.fields??{},s=Object.keys(i),c=Object.keys(o);s.length!==c.length&&e.push(`${fieldDifferenceKey(t,`fields`)} count: remote=${s.length}, expected=${c.length}`);for(let n of s){let r=i[n],s=o[n],c=fieldDifferenceKey(t,`fields.${n}`);s?addFieldDifferences(e,c,a(r,`remote field "${n}" missing`),s):e.push(`${c}: exists in remote but not snapshot`)}for(let n of c)i[n]||e.push(`${fieldDifferenceKey(t,`fields.${n}`)}: exists in snapshot but not remote`)}function addFieldDifferences(e,t,n,r){addFieldDifference(e,t,`type`,n.type,r.type),addFieldDifference(e,t,`required`,n.required,r.required);for(let i of Aa)addBooleanFieldDifference(e,t,i,n,r);addFieldDifference(e,t,`foreignKeyType`,n.foreignKeyType,r.foreignKeyType),addFieldDifference(e,t,`foreignKeyField`,n.foreignKeyField,r.foreignKeyField),addFieldDifference(e,t,`description`,n.description??``,r.description??``),addAllowedValuesDifferences(e,t,n,r),addHooksDifferences(e,t,n,r),addValidationDifferences(e,t,n,r),addSerialDifferences(e,t,n,r),addFieldDifference(e,t,`scale`,n.scale,r.scale),addNestedFieldDifferences(e,t,n,r)}function compareFields(e,t,n,r){let i=[];return addFieldDifferences(i,``,n,r),i.length>0?{tableName:e,kind:`field_mismatch`,fieldName:t,details:i.join(`; `)}:null}const vs=/* @__PURE__ */ new Set([`id`]),ys=[`bulkUpsert`,`gqlOperations`,`publishEvents`];function isMigrationRestricted(e){let t=e?.disableGqlOperations;return e?.publishRecordEvents!==!0&&e?.bulkUpsert!==!0&&t?.create===!0&&t.update===!0&&t.delete===!0}function withoutSettings(e,t,n){if(t.length===0||n?.size===0)return e;let r=createSnapshotRecord();for(let[i,a]of Object.entries(e.tables)){if(!a.settings||n&&!n.has(i)){r[i]=a;continue}let e={...a.settings};for(let n of t)delete e[n];let{settings:o,...s}=a;r[i]=Object.keys(e).length>0?{...s,settings:e}:s}return{...e,tables:r}}function compareRemoteWithSnapshot(e,t,n=[],r=[],i){let a=compareNormalizedRemoteWithSnapshot(createRemoteComparableSnapshot(withoutSettings(createSnapshotFromRemoteTypes(e,t.namespace,n,t),r,i)),createRemoteComparableSnapshot(withoutSettings(t,r,i))),o=compareScriptHashes(e,t);return[...a,...o]}function extractRemoteScriptHashState(e){let t=[e.schema?.typeHook?.create?.expr,e.schema?.typeHook?.update?.expr,e.schema?.typeValidate?.create?.expr,e.schema?.typeValidate?.update?.expr],n;for(let e of t){if(!e)continue;let t=extractSourceScriptHash(e);if(t){if(n&&n!==t)return{kind:`conflicting`};n=t}}return n?{kind:`hash`,hash:n}:{kind:`absent`}}function remoteHasScripts(e){return!!(e.schema?.typeHook?.create?.expr||e.schema?.typeHook?.update?.expr||e.schema?.typeValidate?.create?.expr||e.schema?.typeValidate?.update?.expr)}const bs=`has no script hash on remote`;function compareScriptHashes(e,t){let n=[],r=new Map(e.map(e=>[e.name,e]));for(let[e,i]of Object.entries(t.tables)){let t=computeSourceScriptHash(i.fields,{typeHookExpr:i.typeHookExpr,typeValidateExpr:i.typeValidateExpr}),a=r.get(e);if(a){if(t){let r=extractRemoteScriptHashState(a);if(t!==(r.kind===`hash`?r.hash:void 0)){let t=r.kind===`hash`?`Table '${e}' scripts differ between remote and snapshot`:r.kind===`conflicting`?`Table '${e}' has conflicting script hashes on remote`:remoteHasScripts(a)?`Table '${e}' ${bs}`:`Table '${e}' has scripts in snapshot but not on remote`;n.push({tableName:e,kind:`script_mismatch`,details:t})}}else remoteHasScripts(a)&&n.push({tableName:e,kind:`script_mismatch`,details:`Table '${e}' has scripts on remote but not in snapshot`})}}return n}function stripFieldScriptProps(e){let{hooks:t,validate:n,default:r,optionalOnCreate:i,...a}=e;if(a.fields){let e=createSnapshotRecord();for(let[t,n]of Object.entries(a.fields))e[t]=stripFieldScriptProps(n);return{...a,fields:e}}return a}function createRemoteComparableSnapshot(e){let t=createSnapshotRecord();for(let[n,r]of Object.entries(e.tables)){let e=createSnapshotRecord();for(let[t,n]of Object.entries(r.fields))vs.has(t)||(e[t]=stripFieldScriptProps(n));let{typeHookExpr:i,typeValidateExpr:a,...o}=r;t[n]={...o,fields:e}}return normalizeSchemaSnapshot({...e,tables:t})}function fieldDriftFromChange(e){return compareFields(e.tableName,e.fieldName,e.before,e.after)??{tableName:e.tableName,kind:`field_mismatch`,fieldName:e.fieldName,details:`Field '${e.fieldName}' differs between remote and snapshot`}}function schemaDriftFromDiffChange(e){switch(e.kind){case`table_added`:return{tableName:e.tableName,kind:`type_missing_remote`,details:`Table '${e.tableName}' exists in snapshot but not in remote`};case`table_removed`:return{tableName:e.tableName,kind:`type_missing_local`,details:`Table '${e.tableName}' exists in remote but not in snapshot`};case`table_renamed`:return{tableName:e.tableName,kind:`type_settings_mismatch`,details:`Table '${e.previousTableName}' was renamed to '${e.tableName}'`};case`table_settings_modified`:case`table_modified`:return{tableName:e.tableName,kind:`type_settings_mismatch`,details:e.reason??`Table settings differ between remote and snapshot`};case`field_added`:return{tableName:e.tableName,kind:`field_missing_remote`,fieldName:e.fieldName,details:`Field '${e.fieldName}' exists in snapshot but not in remote`};case`field_removed`:return{tableName:e.tableName,kind:`field_missing_local`,fieldName:e.fieldName,details:`Field '${e.fieldName}' exists in remote but not in snapshot`};case`field_modified`:case`field_type_modified`:return fieldDriftFromChange(e);case`field_renamed`:return{tableName:e.tableName,kind:`field_mismatch`,fieldName:e.fieldName,details:`Field '${e.previousFieldName}' was renamed to '${e.fieldName}'`};case`index_added`:return{tableName:e.tableName,kind:`index_missing_remote`,indexName:e.indexName,details:`Index '${e.indexName}' exists in snapshot but not in remote`};case`index_removed`:return{tableName:e.tableName,kind:`index_missing_local`,indexName:e.indexName,details:`Index '${e.indexName}' exists in remote but not in snapshot`};case`index_modified`:return{tableName:e.tableName,kind:`index_mismatch`,indexName:e.indexName,details:e.reason??`Index '${e.indexName}' differs between remote and snapshot`};case`file_added`:return{tableName:e.tableName,kind:`file_missing_remote`,fileName:e.fieldName,details:`File '${e.fieldName}' exists in snapshot but not in remote`};case`file_removed`:return{tableName:e.tableName,kind:`file_missing_local`,fileName:e.fieldName,details:`File '${e.fieldName}' exists in remote but not in snapshot`};case`file_modified`:return{tableName:e.tableName,kind:`file_mismatch`,fileName:e.fieldName,details:e.reason??`File '${e.fieldName}' differs between remote and snapshot`};case`relationship_added`:return{tableName:e.tableName,kind:`relationship_missing_remote`,relationshipName:e.relationshipName,relationshipType:e.relationshipType,details:`Relationship '${e.relationshipName}' exists in snapshot but not in remote`};case`relationship_removed`:return{tableName:e.tableName,kind:`relationship_missing_local`,relationshipName:e.relationshipName,relationshipType:e.relationshipType,details:`Relationship '${e.relationshipName}' exists in remote but not in snapshot`};case`relationship_modified`:return{tableName:e.tableName,kind:`relationship_mismatch`,relationshipName:e.relationshipName,relationshipType:e.relationshipType,details:e.reason??`Relationship '${e.relationshipName}' differs between remote and snapshot`};case`permission_modified`:return{tableName:e.tableName,kind:`permission_mismatch`,details:e.reason??`Permissions differ between remote and snapshot`};case`table_scripts_modified`:return{tableName:e.tableName,kind:`script_mismatch`,details:e.reason??`Table-level scripts differ between remote and snapshot`};default:throw b(`Unsupported diff change`)}}function compareNormalizedRemoteWithSnapshot(e,t){return compareSnapshots(e,t).changes.map(schemaDriftFromDiffChange)}function formatSchemaDrifts(e){if(e.length===0)return`No schema drifts detected.`;let t=[],n=/* @__PURE__ */ new Map;for(let t of e){let e=n.get(t.tableName)??[];e.push(t),n.set(t.tableName,e)}for(let[e,r]of n){t.push(` Table '${e}':`);for(let e of r)if(e.fieldName)t.push(` - Field '${e.fieldName}': ${e.details}`);else if(e.indexName)t.push(` - Index '${e.indexName}': ${e.details}`);else if(e.fileName)t.push(` - File '${e.fileName}': ${e.details}`);else if(e.relationshipName){let n=e.relationshipType?` (${e.relationshipType})`:``;t.push(` - Relationship${n} '${e.relationshipName}': ${e.details}`)}else t.push(` - ${e.details}`)}return t.join(`
|
|
13
|
+
`)}function updateHashWithDirectory(e,t,n=``,r=/* @__PURE__ */ new Set){let i=W.realpathSync(t);if(r.has(i)){e.update(`directory-cycle\0${n}\0${i}\0`);return}r.add(i);let a=W.readdirSync(t,{withFileTypes:!0}).toSorted((e,t)=>e.name.localeCompare(t.name));try{for(let i of a){let a=n?`${n}/${i.name}`:i.name,o=H.join(t,i.name);if(i.isDirectory())e.update(`directory\0${a}\0`),updateHashWithDirectory(e,o,a,r);else if(i.isFile())e.update(`file\0${a}\0`),e.update(W.readFileSync(o)),e.update(`\0`);else if(i.isSymbolicLink()){e.update(`symlink\0${a}\0${W.readlinkSync(o)}\0`);try{let t=W.statSync(o);t.isDirectory()?(e.update(`target-directory\0`),updateHashWithDirectory(e,o,`${a}@target`,r)):t.isFile()?(e.update(`target-file\0`),e.update(W.readFileSync(o)),e.update(`\0`)):e.update(`target-other\0`)}catch(t){if(t.code!==`ENOENT`)throw t;e.update(`target-missing\0`)}}else e.update(`other\0${a}\0`)}}finally{r.delete(i)}}function captureFileState(e){let t=gi(`sha256`);for(let n of[...new Set(e)].toSorted())t.update(n),t.update(`\0`),W.existsSync(n)?t.update(W.readFileSync(n)):t.update(`<missing>`),t.update(`\0`);return t.digest(`hex`)}function captureMigrationFileState(e){let t=Object.create(null);for(let{namespace:n,migrationsDir:r}of e.toSorted((e,t)=>e.namespace.localeCompare(t.namespace))){let e=gi(`sha256`);for(let{number:t}of getMigrationArtifacts(r)){let n=formatMigrationNumber(t);e.update(`migration\0${n}\0`),updateHashWithDirectory(e,H.join(r,n))}t[n]=e.digest(`hex`)}return t}function hasMigrationConfig(e){if(typeof e!=`object`||!e||!(`migration`in e))return!1;let t=e.migration;return typeof t!=`object`||!t||!(`directory`in t)?!1:typeof t.directory==`string`}function getNamespacesWithMigrations(e,t){let n=[];for(let r of Object.keys(e.db??{})){let i=e.db?.[r];if(!hasMigrationConfig(i))continue;let a=H.resolve(t,i.migration.directory);n.push({namespace:r,migrationsDir:a})}let r=[...Map.groupBy(n,e=>e.migrationsDir)].filter(([,e])=>e.length>1).map(([e,t])=>({directory:e,namespaces:t.map(e=>e.namespace)}));if(r.length>0)throw E({code:`MIGRATION_DIRECTORY_CONFLICT`,message:r.map(({directory:e,namespaces:t})=>`TailorDB namespaces ${t.map(e=>`"${e}"`).join(`, `)} share the migration directory ${e}`).join(`
|
|
14
|
+
`),suggestion:"Set a different `migration.directory` for each namespace in tailor.config.ts.",context:{conflicts:r}});return n}function selectTargetNamespace(e,t){if(e.length===0)throw migrationConfigNotFoundError();if(t){let n=e.find(e=>e.namespace===t);if(!n)throw E({code:`TAILORDB_NAMESPACE_NOT_FOUND`,message:`Namespace "${t}" not found or does not have migrations configured`});return n}if(e.length>1)throw E({code:`MIGRATION_NAMESPACE_REQUIRED`,message:`Multiple TailorDB services found. Please specify namespace with --namespace flag: ${e.map(e=>e.namespace).join(`, `)}`});return a(e[0],`namespace with migrations missing`)}function migrationConfigNotFoundError(){return E({code:`MIGRATION_CONFIG_NOT_FOUND`,message:`No TailorDB services with migrations configuration found`,suggestion:"Configure `migration` on the TailorDB service in tailor.config.ts."})}function usesLegacyData(e){return e.includes(`_data`)&&Le(`(${e}\n);`,{includeGuardedReferences:!0}).has(`_data`)}function normalizeValidations(e,t){let n=[],r,i=[];function flushLegacy(){r?.script&&(n.push({...r,script:{...r.script,expr:Ge(`((_data) => { ${i.join(`
|
|
15
|
+
`)} })(${t})`,`legacy migration validator`)}}),r=void 0,i=[])}for(let t of e)t.script&&usesLegacyData(t.script.expr)?(r??=t,i.push(`if (!(${t.script.expr}\n)) return ${JSON.stringify(t.errorMessage)};`)):(flushLegacy(),n.push(t));return flushLegacy(),n}function normalizeField(e,t,n,r,i){let a={...e};if(e.fields){let o=e.array?`__el`:`${t}?.[${JSON.stringify(i)}]`,s=e.array?`__el`:`${n}?.[${JSON.stringify(i)}]`,c=e.array?`__el`:`${r}?.[${JSON.stringify(i)}]`;a.fields=Object.fromEntries(Object.entries(e.fields).map(([e,t])=>[e,normalizeField(t,o,s,c,e)]))}if(e.hooks){a.hooks={...e.hooks};for(let r of[`create`,`update`]){let i=e.hooks[r];if(i&&usesLegacyData(i.expr)){let e=r===`update`?n:t;a.hooks[r]={...i,expr:Ge(`((_data) => (${i.expr}\n))(${e})`,`legacy migration hook`)}}}}return e.validate&&(a.validate=normalizeValidations(e.validate,r)),a}function normalizeTableScriptCompatibility(e){return{...e,fields:Object.fromEntries(Object.entries(e.fields).map(([e,t])=>[e,normalizeField(t,`_input`,`Object.assign({}, _oldRecord, _input)`,`_newRecord`,e)]))}}function publishesRecordEvents(e,t){return resolvePublishEvents({explicit:e.settings?.publishEvents,subscribed:t,conflict:Ea.tailorDBType(e.name)})}function generateTailorDBTypeManifestFromSnapshot(e,t={}){let n=Di.camelize(e.pluralForm,!0),r={aggregation:e.settings?.aggregation??!1,bulkUpsert:t.suppressGqlMutations===!0?!1:e.settings?.bulkUpsert??!1,draft:!1,defaultQueryLimitSize:100n,maxBulkUpsertSize:1000n,pluralForm:n,publishRecordEvents:t.suppressRecordEvents!==!0&&publishesRecordEvents(e,t.subscribed??!1)},i=e.settings?.gqlOperations??t.namespaceGqlOperations;(i||t.suppressGqlMutations===!0)&&(r.disableGqlOperations={create:t.suppressGqlMutations===!0||i?.create===!1,update:t.suppressGqlMutations===!0||i?.update===!1,delete:t.suppressGqlMutations===!0||i?.delete===!1,read:i?.read===!1});let a=Object.fromEntries(Object.entries(e.fields).filter(([e])=>e!==`id`).map(([e,t])=>[e,convertFieldConfigToProto(t)])),o=/* @__PURE__ */ new Map;if(e.forwardRelationships)for(let[t,n]of Object.entries(e.forwardRelationships))o.set(t,convertRelationshipToProto(n,`forward`));if(e.backwardRelationships)for(let[t,n]of Object.entries(e.backwardRelationships))o.set(t,convertRelationshipToProto(n,`backward`));let s=/* @__PURE__ */ new Map;if(e.indexes)for(let[t,n]of Object.entries(e.indexes))s.set(t,convertIndexToProto(n));let c=/* @__PURE__ */ new Map;if(e.files)for(let[t,n]of Object.entries(e.files))c.set(t,{description:n||``});let l=e.permissions?.record?convertRecordPermissionToProto(e.permissions.record):{create:[],read:[],update:[],delete:[]},{typeHook:u,typeValidate:d}=buildTypeScripts(normalizeTableScriptCompatibility(e).fields,{sourceFields:e.fields,typeHookExpr:e.typeHookExpr,typeValidateExpr:e.typeValidateExpr});return{name:e.name,schema:{description:e.description||``,fields:a,relationships:Object.fromEntries(o),settings:r,extends:!1,directives:[],indexes:Object.fromEntries(s),files:Object.fromEntries(c),permission:l,...u&&{typeHook:u},...d&&{typeValidate:d}}}}function optionalOnCreate(e){return e.hooks?.create||e.default!==void 0?{optionalOnCreate:!0}:{}}function convertFieldConfigToProto(e){let t={type:e.type,allowedValues:e.type===`enum`?e.allowedValues?.map(e=>({...e}))??[]:[],description:e.description||``,array:e.array??!1,index:e.index??!1,unique:e.unique??!1,foreignKey:e.foreignKey??!1,foreignKeyType:e.foreignKeyType,foreignKeyField:e.foreignKeyField,required:e.required,vector:e.vector??!1,...optionalOnCreate(e),...e.serial&&{serial:{start:BigInt(e.serial.start),...e.serial.maxValue!==void 0&&{maxValue:BigInt(e.serial.maxValue)},...e.serial.format&&{format:e.serial.format},...e.serial.gapless&&{gapless:!0}}},...e.scale!==void 0&&{scale:e.scale}};return e.type===`nested`&&e.fields&&(t.fields=processNestedFieldsFromSnapshot(e.fields)),t}function processNestedFieldsFromSnapshot(e){let t=/* @__PURE__ */ new Map;for(let[n,r]of Object.entries(e))if(r.type===`nested`&&r.fields){let e=processNestedFieldsFromSnapshot(r.fields);t.set(n,{type:`nested`,allowedValues:r.allowedValues?.map(e=>({...e}))??[],description:r.description||``,required:r.required,array:r.array??!1,index:!1,unique:!1,foreignKey:!1,vector:!1,fields:e,...r.scale!==void 0&&{scale:r.scale}})}else t.set(n,{type:r.type,allowedValues:r.type===`enum`?r.allowedValues?.map(e=>({...e}))??[]:[],description:r.description||``,required:r.required,array:r.array??!1,index:(r.index??!1)||(r.unique??!1),unique:r.unique??!1,foreignKey:r.foreignKey??!1,foreignKeyType:r.foreignKeyType,foreignKeyField:r.foreignKeyField,vector:!1,...optionalOnCreate(r),...r.serial&&{serial:{start:BigInt(r.serial.start),...r.serial.maxValue!==void 0&&{maxValue:BigInt(r.serial.maxValue)},...r.serial.format&&{format:r.serial.format}}},...r.scale!==void 0&&{scale:r.scale}});return Object.fromEntries(t)}function convertRelationshipToProto(e,t){return t===`forward`?{refType:e.targetType,refField:e.sourceField,srcField:e.targetField,array:e.isArray,description:e.description}:{refType:e.targetType,refField:e.targetField,srcField:e.sourceField,array:e.isArray,description:e.description}}function convertIndexToProto(e){return{fieldNames:e.fields,unique:e.unique??!1}}function convertRecordPermissionToProto(e){return{create:e.create.map(convertActionPermissionToProto),read:e.read.map(convertActionPermissionToProto),update:e.update.map(convertActionPermissionToProto),delete:e.delete.map(convertActionPermissionToProto)}}function convertActionPermissionToProto(e){let t;switch(e.permit){case`allow`:t=Ln.ALLOW;break;case`deny`:t=Ln.DENY;break;default:throw b(`Unknown permission: ${e.permit}`)}return{conditions:e.conditions.map(convertConditionToProto),permit:t,description:e.description}}function convertConditionToProto(e){let[t,n,r]=e,i=convertOperandToProto(t),a=convertOperandToProto(r),o;switch(n){case`eq`:o=Sr.EQ;break;case`ne`:o=Sr.NE;break;case`in`:o=Sr.IN;break;case`nin`:o=Sr.NIN;break;case`hasAny`:o=Sr.HAS_ANY;break;case`nhasAny`:o=Sr.NHAS_ANY;break;default:throw b(`Unknown operator: ${n}`)}return{left:i,operator:o,right:a}}function convertOperandToProto(e){if(isSnapshotFieldRefOperand(e)){if(`user`in e)return{kind:{case:`userField`,value:e.user}};if(`record`in e)return{kind:{case:`recordField`,value:e.record}};if(`newRecord`in e)return{kind:{case:`newRecordField`,value:e.newRecord}};if(`oldRecord`in e)return{kind:{case:`oldRecordField`,value:e.oldRecord}};throw b(`Unknown field-ref operand shape: ${JSON.stringify(e)}`)}return{kind:{case:`value`,value:Zr(ci,e)}}}function generateAllTypeManifestsFromSnapshot(e,t={}){let n=/* @__PURE__ */ new Map,{executorUsedTables:r,...i}=t;for(let[t,a]of Object.entries(e.tables)){let e={...i,subscribed:r?.has(t)??!1};n.set(t,generateTailorDBTypeManifestFromSnapshot(a,e))}return n}function compareSnapshotWithRemote(e,t){let n=new Set(Object.keys(e.tables)),r=[],i=[],a=[];for(let e of n)t.has(e)?i.push(e):r.push(e);for(let e of t)n.has(e)||a.push(e);return{creates:r,updates:i,deletes:a}}function protoGqlPermission(e){return{policies:e.map(e=>protoGqlPolicy(e))}}function protoGqlPolicy(e){let t=[];for(let n of e.actions)switch(n){case`all`:t.push(L.ALL);break;case`create`:t.push(L.CREATE);break;case`read`:t.push(L.READ);break;case`update`:t.push(L.UPDATE);break;case`delete`:t.push(L.DELETE);break;case`aggregate`:t.push(L.AGGREGATE);break;case`bulkUpsert`:t.push(L.BULK_UPSERT);break;default:throw b(`Unknown action: ${n}`)}let n;switch(e.permit){case`allow`:n=Pn.ALLOW;break;case`deny`:n=Pn.DENY;break;default:throw b(`Unknown permission: ${e.permit}`)}return{conditions:e.conditions.map(e=>protoGqlCondition(e)),actions:t,permit:n,description:e.description}}function protoGqlCondition(e){let[t,n,r]=e,i=protoGqlOperand(t),a=protoGqlOperand(r),o;switch(n){case`eq`:o=Kn.EQ;break;case`ne`:o=Kn.NE;break;case`in`:o=Kn.IN;break;case`nin`:o=Kn.NIN;break;case`hasAny`:o=Kn.HAS_ANY;break;case`nhasAny`:o=Kn.NHAS_ANY;break;default:throw b(`Unknown operator: ${n}`)}return{left:i,operator:o,right:a}}function protoGqlOperand(e){if(isSnapshotFieldRefOperand(e)){if(`user`in e)return{kind:{case:`userField`,value:e.user}};throw E({code:`TAILORDB_PERMISSION_OPERAND_UNSUPPORTED`,message:`Unsupported field-ref operand in GQL permission: ${JSON.stringify(e)}.`,suggestion:`GQL permissions only support { user } field references.`})}return{kind:{case:`value`,value:Zr(ci,e)}}}function defineRecordEntry(e,t,n){Object.defineProperty(e,t,{value:n,enumerable:!0,writable:!0,configurable:!0})}const xs=/* @__PURE__ */ new Set([`field_added`,`field_modified`,`field_type_modified`,`field_removed`,`field_renamed`]);function isPreMigrationFieldChange(e){return xs.has(e.kind)}function createPreMigrationSnapshotType(e,t,n){let r=structuredClone(e.fields),i=!1;for(let[e,n]of t)n.kind===`field_type_modified`&&(i=!0,defineRecordEntry(r,e,structuredClone(n.before)));let a={...e,fields:r};if(!i||!n)return a;let{typeHookExpr:o,typeValidateExpr:s,...c}=a;return{...c,...n.before.typeHookExpr&&{typeHookExpr:structuredClone(n.before.typeHookExpr)},...n.before.typeValidateExpr!==void 0&&{typeValidateExpr:n.before.typeValidateExpr}}}function buildPreMigrationChangesMap(e){return buildPreMigrationChangesMapFromDiffs(e.map(e=>e.diff))}function buildPreMigrationChangesMapFromDiffs(e){let t=/* @__PURE__ */ new Map;for(let n of e)for(let e of n.changes){if(!isPreMigrationFieldChange(e)||!e.fieldName)continue;let n=t.get(e.tableName)??/* @__PURE__ */ new Map;n.set(e.fieldName,e),t.set(e.tableName,n)}return t}function applyPreMigrationFieldAdjustments(e,t){relaxFieldsForPreMigration(e,t,{toField:convertFieldConfigToProto,adjustNestedMembers:(e,t)=>{restoreRemovedNestedMembers(e,t.before,t.after),relaxRenamedNestedMembers(e,t.memberRenames??[])}})}function applyPreMigrationFieldAdjustmentsToSnapshot(e,t){relaxFieldsForPreMigration(e,t,{toField:e=>structuredClone(e),adjustNestedMembers:(e,t)=>{for(let n of collectNestedMemberChanges(t.before,t.after)){if(n.kind!==`removed`)continue;let t=getNestedMember(e,n.path.slice(0,-1))?.fields,r=n.path.at(-1);if(!t||r===void 0)continue;let i=structuredClone(n.before);relaxMemberUnique(i),defineRecordEntry(t,r,i)}for(let n of t.memberRenames??[]){let t=getNestedMember(e,n.path);t?.required&&(t.required=!1),t&&relaxMemberUnique(t)}}})}function relaxMemberUnique(e){e.unique&&=!1,relaxNestedUnique(e)}function relaxNestedUnique(e){for(let t of Object.values(e.fields??{}))t.unique&&=!1,relaxNestedUnique(t)}function relaxFieldsForPreMigration(e,t,n){let restoreField=e=>{let t=n.toField(e);return relaxNestedUnique(t),t};for(let[r,i]of t){if(i.kind===`field_removed`){defineRecordEntry(e,r,restoreField(i.before));continue}if(i.kind===`field_renamed`){defineRecordEntry(e,i.previousFieldName,restoreField(i.before));let t=e[r];t&&(i.after.required&&(t.required=!1),(i.after.unique??!1)&&(t.unique=!1),relaxNestedUnique(t));continue}let t=e[r];if(!t)continue;let a=t;if(i.kind===`field_added`){i.after.required&&(a.required=!1);continue}if(i.kind===`field_type_modified`){defineRecordEntry(e,r,restoreField(i.before));continue}let{before:o,after:s}=i;n.adjustNestedMembers?.(t,i);for(let e of collectNestedMemberChanges(o,s)){if(e.kind===`removed`)continue;let n=e.path.reduce((e,t)=>e?.fields?.[t],t);n&&(e.kind===`added`?e.after.required&&(n.required=!1):relaxModifiedFieldConstraints(n,e.before,e.after))}relaxModifiedFieldConstraints(a,o,s),addsForeignKey(o,s)&&(delete a.foreignKey,delete a.foreignKeyType,delete a.foreignKeyField)}}function relaxModifiedFieldConstraints(e,t,n){!t.required&&n.required&&(e.required=!1),!(t.unique??!1)&&(n.unique??!1)&&(e.unique=!1);let r=t.allowedValues??[],i=n.allowedValues??[],a=new Set(i.map(e=>e.value));if(r.filter(e=>!a.has(e.value)).length>0){let t=/* @__PURE__ */ new Map;for(let e of r)t.set(e.value,e.description??``);for(let e of i)t.has(e.value)||t.set(e.value,e.description??``);e.allowedValues=Array.from(t.entries()).map(([e,t])=>({value:e,description:t}))}}function getProtoNestedMember(e,t){return t.reduce((e,t)=>e?.fields?.[t],e)}function restoreRemovedNestedMembers(e,t,n){for(let r of collectNestedMemberChanges(t,n)){if(r.kind!==`removed`)continue;let t=r.path.join(`.`),n=a(getProtoNestedMember(e,r.path.slice(0,-1))?.fields,`parent of removed nested member "${t}" missing from the Pre-phase field`),i=a(r.path.at(-1),`removed nested member path is empty`),o=a(processNestedFieldsFromSnapshot({[i]:r.before})[i],`restored nested member "${t}" missing`);relaxMemberUnique(o),defineRecordEntry(n,i,o)}}function relaxRenamedNestedMembers(e,t){for(let n of t){let t=getProtoNestedMember(e,n.path);t?.required&&(t.required=!1),t&&relaxMemberUnique(t)}}function buildPreMigrationIndexChangesMap(e){return buildPreMigrationIndexChangesMapFromDiffs(e.map(e=>e.diff))}function buildPreMigrationIndexChangesMapFromDiffs(e){let t=/* @__PURE__ */ new Map;for(let n of e)for(let e of n.changes){if(e.kind!==`index_added`&&e.kind!==`index_modified`)continue;let n=e.kind===`index_modified`?e.before:void 0;if(!isBreakingIndexChange(e.tableName,e.indexName,n,e.after))continue;let r=t.get(e.tableName)??/* @__PURE__ */ new Map;r.set(e.indexName,e),t.set(e.tableName,r)}return t}function applyPreMigrationIndexAdjustments(e,t){relaxIndexesForPreMigration(e,t,convertIndexToProto)}function applyPreMigrationIndexAdjustmentsToSnapshot(e,t){relaxIndexesForPreMigration(e,t,e=>structuredClone(e))}function relaxIndexesForPreMigration(e,t,n){for(let[r,i]of t)i.kind===`index_added`?delete e[r]:i.kind===`index_modified`&&defineRecordEntry(e,r,n(i.before))}function buildPreMigrationSnapshot(e,t){let n=applyDiffToSnapshot(e,t),r=buildPreMigrationChangesMapFromDiffs([t]),i=buildPreMigrationIndexChangesMapFromDiffs([t]),a=createSnapshotRecord();for(let e of Object.values(n.tables)){let n=r.get(e.name),o=n?createPreMigrationSnapshotType(e,n,t.changes.find(t=>t.kind===`table_scripts_modified`&&t.tableName===e.name)):e,s=copySnapshotRecord(o.fields);n&&applyPreMigrationFieldAdjustmentsToSnapshot(s,n);let c={...o,fields:s},l=i.get(e.name);if(e.indexes&&l){let t=copySnapshotRecord(e.indexes);applyPreMigrationIndexAdjustmentsToSnapshot(t,l),c.indexes=t}a[e.name]=c}return includeTablesDeletedAfterCheckpoint({...n,tables:a},t)}function tablesDeletedAfterCheckpoint(e){return e.changes.flatMap(e=>e.kind===`table_removed`?[{name:e.tableName,before:e.before}]:e.kind===`table_renamed`?[{name:e.previousTableName,before:e.before}]:[])}function getTablesDeletedAfterCheckpoint(e){return new Set(tablesDeletedAfterCheckpoint(e).map(e=>e.name))}function includeTablesDeletedAfterCheckpoint(e,t){let n=copySnapshotRecord(e.tables);for(let{name:e,before:r}of tablesDeletedAfterCheckpoint(t))n[e]=r;return{...e,tables:n}}function parseInProgress(e){let t=e[Xa],n=e[Qa];if(t===void 0)return{inProgress:null,inProgressInvalid:n!==void 0};let r=parseInProgressLabel(t),i=n===void 0?void 0:parseExecutionLabel(n);return r===null||i===null?{inProgress:null,inProgressInvalid:!0}:{inProgress:{number:r.number,...i===void 0?{}:{executionId:i},kind:r.kind},inProgressInvalid:!1}}async function fetchRemoteMigrationState(e,t){let n=await P(async()=>{let{metadata:n}=await e.getMetadata({trn:t});return n});if(!n)return{metadataExists:!1,number:null,historyId:null,historyIdInvalid:!1,inProgress:null,inProgressInvalid:!1,maintenanceModeCheckpoint:null,cleanupCheckpoint:null};let r=n.labels[Ja],i=n.labels[$a],a=n.labels[eo],o=n.labels[Ya],s=o?parseMigrationHistoryId(o):null;return{metadataExists:!0,number:r?parseMigrationLabelNumber(r):null,historyId:s,historyIdInvalid:o!==void 0&&s===null,...parseInProgress(n.labels),maintenanceModeCheckpoint:i?parseMigrationLabelNumber(i):null,cleanupCheckpoint:a?parseMigrationLabelNumber(a):null}}function isCheckpointStillOwned(e,t){return e.number===t.number&&!e.historyIdInvalid&&e.historyId===t.historyId}function matchesLocalMigrationHistory(e,t){return e.historyIdInvalid?!1:e.number===null&&e.historyId===null||e.historyId===t}function describeMigrationHistoryId(e){return e.historyIdInvalid?`<invalid>`:e.historyId??`<unset>`}function migrationHistoryMismatchError(e){let{state:t,localHistoryId:n,namespace:r,code:i,suggestion:a}=e;return E({code:i,message:`The migration history of namespace "${r}" on the workspace does not match the local migration history.`,details:`The workspace records migration history ID ${describeMigrationHistoryId(t)}; the local migration history has ${n??`<unset>`}.`,suggestion:a,context:{namespace:r,remoteHistoryId:t.historyId,remoteHistoryIdInvalid:t.historyIdInvalid,localHistoryId:n}})}function assertLocalMigrationHistory(e){let{force:t,...n}=e,{state:r,localHistoryId:i}=n;if(!matchesLocalMigrationHistory(r,i)){if(!t)throw migrationHistoryMismatchError({...n,suggestion:`Run the command from a checkout of the migration history that was deployed to the workspace, or pass --force to replace it with the local migration history.`});return`Overwriting the migration history ID ${describeMigrationHistoryId(r)} with ${i??`<unset>`} (--force).`}}function describeMigrationCheckpoint(e){return e==null?`<unset>`:formatMigrationNumber(e)}function isStaleMigrationInProgress(e){return e.inProgress!==null&&e.number!==null&&e.inProgress.number<=e.number}function migrationResolveArgs(e,t,n){return namespaceMigrationArgs({...n,subcommand:[`resolve`,`--${e}`],namespace:t})}function formatMigrationResolveHint(e,t,n){return w({command:`tailor`,args:migrationResolveArgs(e,t,n)})}function describeMainRunSettlement(e,t){return`Settle it with ${formatMigrationResolveHint(`complete`,e,t)} if its run succeeded, or with ${formatMigrationResolveHint(`rollback`,e,t)} otherwise; the command shows the outcome of the run before it changes anything.`}function inProgressMigrationActions(e){let{state:t,namespace:n,...r}=e,i=t.inProgress;if(!i||i.number!==(t.number??0)+1)return[];let a=formatMigrationNumber(i.number),o=formatMigrationNumber(i.number-1),settleAction=(e,t)=>({action:e,description:t,command:`tailor`,args:migrationResolveArgs(e,n,r)});return i.kind===`main`?[settleAction(`complete`,`applies the schema of migration ${a} without running its script again; use it when the run succeeded`),settleAction(`rollback`,`returns to the schema of migration ${o}, and the next deploy runs its script again; use it when the run did not succeed`)]:[{action:`resume`,description:`steps that already completed do not run again`,command:`tailor`,args:[`deploy`,...migrationContextArgs(r)]},settleAction(`rollback`,`returns to the schema of migration ${o}, and the next deploy runs every step again`),settleAction(`complete`,`applies the schema of migration ${a} without running its script again`)]}const Ss={resume:`Resume`,rollback:`Roll back`,complete:`Complete`};function formatInProgressMigrationAction(e){return`${Ss[e.action]}: ${w(e)} (${e.description})`}function assertNoMigrationInProgress(e,t,n){if(!e.inProgress&&!e.inProgressInvalid)return;let r=e.inProgress?`${t}/${formatMigrationNumber(e.inProgress.number)}`:void 0,i=inProgressMigrationActions({...n,state:e,namespace:t});throw E({code:`MIGRATION_IN_PROGRESS`,message:e.inProgress?e.inProgress.kind===`main`?`The outcome of the run of migration ${r} that an earlier deploy started is not settled.`:`Migration ${r} is partially applied by an earlier deploy.`:`Namespace "${t}" records a partially applied migration that cannot be read.`,suggestion:i.length>0?[`Continue or settle the migration first with one of these commands:`,...i.map(e=>`- ${formatInProgressMigrationAction(e)}`)].join(`
|
|
16
|
+
`):e.inProgress?.kind===`main`?describeMainRunSettlement(t,n):`Finish the migration with a deploy first; steps that already completed do not run again.`})}function toTailorDBDeployInput(e){let t={};for(let[n,r]of Object.entries(e.types))t[n]=createSnapshotType(r);return{namespace:e.namespace,config:e.config,types:t}}async function fetchRemoteTypes(e,t,n){return F(async(r,i)=>{let{tailordbTypes:a,nextPageToken:o}=await e.listTailorDBTypes({workspaceId:t,namespaceName:n,pageToken:r,pageSize:i});return[a,o]})}async function fetchRemoteGqlPermissions(e,t,n){return F(async(r,i)=>{let{permissions:a,nextPageToken:o}=await e.listTailorDBGQLPermissions({workspaceId:t,namespaceName:n,pageToken:r,pageSize:i});return[a,o]})}async function fetchRemoteSchema(e,t,n){let[r,i]=await Promise.all([fetchRemoteTypes(e,t,n),fetchRemoteGqlPermissions(e,t,n)]);return{types:r,gqlPermissions:i}}async function fetchRemoteSchemaSnapshot(e,t,n){let{types:r,gqlPermissions:i}=await fetchRemoteSchema(e,t,n);return createSnapshotFromRemoteTypes(r,n,i)}function definedWhenNotEmpty(e){return Object.keys(e).length>0?e:void 0}function namespaceConfig(e,t,n){return t.find(e=>e.namespace===n)?.config??e.db?.[n]}function namespaceGqlOperations(e,t,n){return namespaceConfig(e,t,n)?.gqlOperations}const Cs=[`create`,`update`,`delete`,`read`];function configuredDisabledGqlOperations(e){if(!e)return;if(e===`query`)return{create:!1,update:!1,delete:!1};let t={};for(let n of Cs)e[n]===!1&&(t[n]=!1);return definedWhenNotEmpty(t)}function appliedConfiguredDisabledGqlOperations(e,t){if(!e||!t)return;let n={};for(let r of Cs)t[r]===!1&&e[r]&&(n[r]=!1);return definedWhenNotEmpty(n)}function deployComparableSnapshot(e,t,n){let r=new Map(t.map(e=>[e.name,e])),i=configuredDisabledGqlOperations(n),a={};for(let[t,n]of Object.entries(e.tables)){let e={...n.settings},o=r.get(t)?.schema?.settings;if(n.settings?.publishEvents===void 0&&o?.publishRecordEvents&&(e.publishEvents=!0),n.settings?.gqlOperations===void 0){let t=appliedConfiguredDisabledGqlOperations(o?.disableGqlOperations,i);t&&(e.gqlOperations=t)}let s={...n},c=definedWhenNotEmpty(e);c?s.settings=c:delete s.settings,a[t]=s}return{...e,tables:a}}function buildInProgressSnapshot(e,t){let n=buildPreMigrationSnapshot(e,t);for(let e of t.changes){let t=n.tables[e.tableName]?.fields;if(t){if(e.kind===`field_removed`)stripKeptFieldScripts(t,e.fieldName);else if(e.kind===`field_renamed`)stripKeptFieldScripts(t,e.previousFieldName);else if(e.kind===`field_modified`)for(let n of collectNestedMemberChanges(e.before,e.after)){if(n.kind!==`removed`)continue;let r=getNestedMember(t[e.fieldName],n.path.slice(0,-1))?.fields,i=n.path.at(-1);r&&i!==void 0&&stripKeptFieldScripts(r,i)}}}return n}function stripKeptFieldScripts(e,t){let n=Object.hasOwn(e,t)?e[t]:void 0;n&&(e[t]=stripFieldScriptProps(n))}function loadMigrationDiff(e,t){let n=getMigrationFilePath(e,t,`diff`);return W.existsSync(n)?loadDiff(n):null}function reconstructPreMigrationSnapshot(e,t){let n=reconstructSnapshotFromMigrations(e,t-1),r=loadMigrationDiff(e,t);return!n||!r?null:buildInProgressSnapshot(n,r)}function reconstructExpectedRemoteSchema(e,t,n){if(!n){let n=reconstructSnapshotFromMigrations(e,t);return n&&{snapshot:n}}let r=reconstructSnapshotFromMigrations(e,n.number-1),i=loadMigrationDiff(e,n.number);return!r||!i?null:{snapshot:buildInProgressSnapshot(r,i),...n.kind===`steps`&&{postPhase:includeTablesDeletedAfterCheckpoint(applyDiffToSnapshot(r,i),i)}}}function compareRemoteSchemaWithSnapshot(e,t,n,r,i,a=[],o=`all`){let s=deployComparableSnapshot(n,e.types,namespaceGqlOperations(r,i,t));return compareRemoteWithSnapshot(e.types,s,e.gqlPermissions,a,o===`maintenance-mode`?new Set(e.types.filter(e=>isMigrationRestricted(e.schema?.settings)).map(e=>e.name)):void 0)}function locateRemoteCheckpoint(e,t,n){let r=e.number,i=getLatestMigrationNumber(t),a=getMigrationFiles(t).length>0?i:null,o=!matchesLocalMigrationHistory(e,n?.historyId??null);if(e.historyIdInvalid||r===null&&e.historyId!==null)return{kind:`outside`,number:r??0,localLatestMigration:a,historyIdMismatch:o};if(r===null)return{kind:`unset`};let s=n?e.historyId===n.historyId:e.historyId===null,c=n?e.historyId===n.replacedHistoryId:!1,l=n&&c&&r===n.replacedLatestMigration?{from:r,to:0,fromHistoryId:e.historyId,toHistoryId:n.historyId}:void 0;if(!s&&!l||r>i&&!l){let e=n&&c&&r<n.replacedLatestMigration?{replacedLatestMigration:n.replacedLatestMigration}:void 0;return{kind:`outside`,number:r,localLatestMigration:a,historyIdMismatch:o,...e?{rebaselinePending:e}:{}}}return{kind:`inside`,number:r,...l?{checkpointRepair:l}:{}}}function findUnfinishedRemovals(e,t,n){let r=getMigrationFilePath(e,t,`diff`);if(!W.existsSync(r))return[];let i=getTablesDeletedAfterCheckpoint(loadDiff(r)),a=reconstructSnapshotFromMigrations(e)?.tables??{};return n.map(e=>e.name).filter(e=>i.has(e)&&!Object.hasOwn(a,e)).toSorted()}function withGqlPermissionsOf(e,t){let n=createSnapshotRecord();for(let[r,i]of Object.entries(e.tables)){let{permissions:e,...a}=i,{gql:o,...s}=e??{},c=t.tables[r]?.permissions?.gql,l=c?{...s,gql:c}:s;n[r]=Object.keys(l).length>0?{...a,permissions:l}:a}return{...e,tables:n}}function findInterruptedMigration(e){let{remote:t,namespace:n,migrationsDir:r,checkpoint:i,checkpointSnapshot:a,config:o,tailorDBInputs:s}=e,c=i+1,l=reconstructPreMigrationSnapshot(r,c);if(!l)return;let u=o.maintenanceMode!==!1,compare=e=>compareRemoteSchemaWithSnapshot(t,n,e,o,s,u?ys:[],`maintenance-mode`),d=new Set(t.types.filter(e=>isMigrationRestricted(e.schema?.settings)).map(e=>e.name)),f=loadMigrationDiff(r,i),p=f?getTablesDeletedAfterCheckpoint(f):/* @__PURE__ */ new Set,driftedTables=e=>new Set(compare(e).map(e=>e.tableName)),m=driftedTables(l).intersection(driftedTables(withGqlPermissionsOf(l,a)));return compare(a).every(e=>!m.has(e.tableName)&&!p.has(e.tableName)&&(!u||d.has(e.tableName)))?c:void 0}function notDeployedResult(e){return{namespace:e,remoteMigrationNumber:0,drifts:[],hasDrift:!1,skipped:`not_deployed`}}async function verifyRemoteSchema(e,t,n,r,i,a={}){let o=[];for(let{namespace:s,migrationsDir:c}of n){let n=await fetchRemoteMigrationState(e,resourceTrn(t,`tailordb`,s));a.remoteStates?.set(s,n);let l=locateRemoteCheckpoint(n,c,reconstructSnapshotFromMigrations(c,0)?.rebaseline);if(l.kind===`outside`){o.push({namespace:s,remoteMigrationNumber:l.number,drifts:[],hasDrift:!1,checkpointMissingLocal:!0,localLatestMigration:l.localLatestMigration,historyIdMismatch:l.historyIdMismatch,...l.rebaselinePending?{rebaselinePending:l.rebaselinePending}:{}});continue}let u=l.kind===`unset`;if(u&&!n.metadataExists){o.push(notDeployedResult(s));continue}let d=l.kind===`inside`?l.number:0,f=l.kind===`inside`?l.checkpointRepair:void 0,p=f?.to??d,m=!f&&n.inProgress?.number===d+1?n.inProgress:void 0,h=reconstructExpectedRemoteSchema(c,p,m);if(!h){o.push({namespace:s,remoteMigrationNumber:d,drifts:[],hasDrift:!1,skipped:`no_snapshot`});continue}let g=await fetchRemoteSchema(e,t,s);if(u&&g.types.length===0){o.push(notDeployedResult(s));continue}let _=a.acceptUnfinishedRemovals&&!f&&n.cleanupCheckpoint===d?findUnfinishedRemovals(c,d,g.types):void 0,v=m===void 0&&n.maintenanceModeCheckpoint===d,y=_?.length?{...g,types:g.types.filter(e=>!_.includes(e.name))}:g,compareWith=e=>compareRemoteSchemaWithSnapshot(y,s,e,r,i,m!==void 0||v?ys:[],v?`maintenance-mode`:`all`),b=compareWith(h.snapshot);if(b.length>0&&h.postPhase){let e=new Set(compareWith(h.postPhase).map(e=>e.tableName));b=b.filter(t=>e.has(t.tableName))}let x=!n.inProgressInvalid&&(n.inProgress===null||isStaleMigrationInProgress(n)),S=b.length>0&&a.acceptInterruptedMigration&&x&&!f?findInterruptedMigration({remote:y,namespace:s,migrationsDir:c,checkpoint:d,checkpointSnapshot:h.snapshot,config:r,tailorDBInputs:i}):void 0;o.push({namespace:s,remoteMigrationNumber:d,...S===void 0?{drifts:b,hasDrift:b.length>0}:{drifts:[],hasDrift:!1,interruptedMigration:S},...v?{leftInMaintenanceMode:v}:{},...u?{checkpointUnset:u}:{},...f&&b.length===0?{checkpointRepair:f}:{},...n.inProgress?{migrationInProgress:n.inProgress}:{},...n.inProgressInvalid?{migrationInProgressInvalid:!0}:{},..._?{unfinishedRemovals:_}:{}})}return o}function isMissingRemoteScriptHashDrift(e){return e.kind===`script_mismatch`&&e.details.endsWith(`has no script hash on remote`)}function isLikelyPreV2ScriptHashDrift(e){let t=e.filter(e=>e.hasDrift);return t.length>0&&t.every(e=>e.drifts.length>0&&e.drifts.every(isMissingRemoteScriptHashDrift))}function logRemoteDriftGuidance(e,t){let n=t?.filter(e=>e.hasDrift)??[];if(n.length>0&&n.every(e=>e.checkpointUnset))return;let r=w({command:`tailor`,args:migrationCommandArgs([`status`],e)});C.info(`This may indicate:`),C.info(` - Another developer applied different migrations`,{mode:`plain`}),C.info(` - Manual schema changes were made directly`,{mode:`plain`}),C.info(` - Migration history is out of sync`,{mode:`plain`}),C.newline(),C.info(`To resolve:`),C.info(` - Run ${r} to compare local vs remote.`,{mode:`plain`}),C.info(` - If remote is correct, update local tables and run 'migration generate'.`,{mode:`plain`}),C.info(` - If local migration history is correct, run 'migration sync <N>' to overwrite remote.`,{mode:`plain`}),C.info(` - If remote already matches another migration, run 'migration sync <N>' with that migration to move only the checkpoint.`,{mode:`plain`}),t&&isLikelyPreV2ScriptHashDrift(t)&&(C.newline(),C.info(`Every listed drift is '${bs}'. Run 'migration sync <N>' above to add the missing hashes.`))}function unsetCheckpointDriftHints(e,t){return e.filter(e=>e.checkpointUnset&&e.hasDrift).map(({namespace:e})=>`Namespace "${e}" has no migration checkpoint yet, so its tables must match migration 0000. Run ${formatNamespaceMigrationHint({...t,subcommand:[`sync`,formatMigrationNumber(0)],namespace:e})} to rewrite them to 0000, which deletes the tables and fields that 0000 does not have together with their data. To keep the tables instead, update the local tables to match them and recreate 0000 with ${formatNamespaceMigrationHint({subcommand:[`generate`,`--init`],namespace:e,configPath:t.configPath})}, which deletes every migration of the namespace, so only while no workspace has been deployed with them.`)}function hasRebaselinePending(e){return e.rebaselinePending!==void 0}const ws=`Pull the latest migration files if this checkout is behind.`;function missingCheckpointRecoveryHints(e,t){let n=e.filter(e=>!e.rebaselinePending);if(n.length===0)return[];let r=n.flatMap(({namespace:e,localLatestMigration:n,historyIdMismatch:r})=>n===null?[]:[` ${formatCheckpointSyncHint({...t,namespace:e,migrationNumber:n,replaceHistoryId:r})}`]);return[ws,...n.some(e=>e.historyIdMismatch&&e.localLatestMigration!==null)?[`For a namespace that records another migration history, work from a checkout of that history instead; run its --force command below only if the local migration history should replace it.`]:[],...r.length>0?[`To move the checkpoint back to the local history on purpose, run the following, then deploy. Each command rewrites the tables to that migration, removing the fields it does not have and deleting the tables it does not have together with their data:`,...r]:[]]}function logRebaselinePendingGuidance(e){let t=e.filter(hasRebaselinePending);if(t.length>0){for(let e of t){let t=formatMigrationNumber(e.rebaselinePending.replacedLatestMigration),n=formatMigrationNumber(e.remoteMigrationNumber);C.info(`${e.namespace} fell behind before 'migration rebaseline' ran: every environment was required to already be at migration ${t} before the rebaseline, but this environment is at ${n}.`)}C.newline(),C.info(`To recover:`),C.info(` 1. Restore the pre-rebaseline migrations/ directory from git history (the commit before 'migration rebaseline' ran; rebaseline preserves committed files there).`,{mode:`plain`}),C.info(` 2. Deploy this environment against that restored history until its checkpoint reaches the migration named above, running any migrate.ts scripts it still needs.`,{mode:`plain`}),C.info(` 3. Switch back to the current migration files and deploy again — the automatic checkpoint reset to the new baseline then applies.`,{mode:`plain`})}}function formatRemoteVerificationResults(e){let t=[];for(let n of e)n.hasDrift&&(t.push(`Namespace: ${n.namespace}`),t.push(` Remote migration: ${describeMigrationCheckpoint(n.checkpointUnset?null:n.remoteMigrationNumber)}`),t.push(` Differences:`),t.push(formatSchemaDrifts(n.drifts)),t.push(``));return t.join(`
|
|
17
17
|
`)}async function checkMigrationDiffs(e,t){let n=[];for(let{namespace:r,migrationsDir:i}of t){let t=e.get(r);if(!t)continue;let a=reconstructSnapshotFromMigrations(i);if(!a){n.push({namespace:r,migrationsDir:i,hasDiff:!0,diff:void 0});continue}let o=compareLocalTypesWithSnapshot(a,t,r);n.push({namespace:r,migrationsDir:i,hasDiff:hasChanges(o),diff:hasChanges(o)?o:void 0})}return n}function formatMigrationCheckResults(e){let t=[];for(let n of e)n.hasDiff&&(t.push(`Namespace: ${n.namespace}`),n.diff?(t.push(` ${formatDiffSummary(n.diff)}`),t.push(``),t.push(formatMigrationDiff(n.diff))):t.push(` No migration snapshot found. Run 'tailor tailordb migration generate' first.`),t.push(``));return t.join(`
|
|
18
|
-
`)}const Ss=/* @__PURE__ */ new Set([`run`,`dependsOn`]);function usesStepRunner(e,t){return e?.kind===`steps`&&(e.order.length>1||t)}function invalidScript(e,t){return E({code:`MIGRATION_SCRIPT_INVALID`,message:`Invalid migration script ${e}: ${t}`})}function unwrapExpression(e){let t=e;for(;t.type===`TSSatisfiesExpression`||t.type===`TSAsExpression`||t.type===`ParenthesizedExpression`;)t=t.expression;return t}function propertyName(e){if(e.type===`Identifier`)return e.name;if(e.type===`Literal`&&typeof e.value==`string`)return e.value}function boundNames(e){switch(e.type){case`Identifier`:return[e.name];case`AssignmentPattern`:return boundNames(e.left);case`RestElement`:return boundNames(e.argument);case`ObjectPattern`:return e.properties.flatMap(e=>boundNames(e.type===`RestElement`?e:e.value));case`ArrayPattern`:return e.elements.flatMap(e=>e?boundNames(e):[])}}function collectExports(e){let t={hasMain:!1,stepsInit:void 0,stepsExportedIndirectly:!1,onFailureInit:void 0,onFailureExportedIndirectly:!1,hasUnreadableExports:!1};for(let n of e.body){if(n.type===`ExportAllDeclaration`){if(n.exportKind===`type`)continue;n.exported?propertyName(n.exported)===`main`?t.hasMain=!0:propertyName(n.exported)===`onFailure`&&(t.onFailureExportedIndirectly=!0):t.hasUnreadableExports=!0;continue}if(n.type!==`ExportNamedDeclaration`||n.exportKind===`type`)continue;let e=n.declaration;if(e?.type===`FunctionDeclaration`&&e.id?.name===`main`&&(t.hasMain=!0),e?.type===`TSModuleDeclaration`&&e.id.type===`Identifier`&&e.id.name===`onFailure`&&(t.onFailureExportedIndirectly=!0),(e?.type===`FunctionDeclaration`||e?.type===`ClassDeclaration`||e?.type===`TSEnumDeclaration`)&&e.id?.name===`onFailure`&&(t.onFailureExportedIndirectly=!0),e?.type===`VariableDeclaration`)for(let n of e.declarations)if(n.id.type!==`Identifier`){let e=boundNames(n.id);e.includes(`main`)&&(t.hasMain=!0),e.includes(`steps`)&&(t.stepsExportedIndirectly=!0),e.includes(`onFailure`)&&(t.onFailureExportedIndirectly=!0)}else n.id.name===`main`&&(t.hasMain=!0),n.id.name===`steps`&&(t.stepsInit=e.kind===`const`?n.init:null),n.id.name===`onFailure`&&(t.onFailureInit=e.kind===`const`?n.init:null);for(let e of n.specifiers){if(e.exportKind===`type`)continue;let n=propertyName(e.exported);n===`main`&&(t.hasMain=!0),n===`steps`&&(t.stepsExportedIndirectly=!0),n===`onFailure`&&(t.onFailureExportedIndirectly=!0)}}return t}function readSteps(e,t){let n=[];for(let r of t.properties){if(r.type===`SpreadElement`)throw invalidScript(e,"`steps` cannot use spread properties.");let t=r.computed?void 0:propertyName(r.key);if(t===void 0)throw invalidScript(e,"step names must be written literally in `steps`.");let i=unwrapExpression(r.value);if(r.method||r.kind!==`init`||i.type!==`ObjectExpression`)throw invalidScript(e,`Step "${t}" must be an object literal with a \`run\` function, written inside \`steps\`.`);let a=!1,o=[];for(let n of i.properties){let r=n.type===`SpreadElement`||n.computed?void 0:propertyName(n.key);if(n.type===`SpreadElement`||r===void 0||!Ss.has(r))throw invalidScript(e,`Step "${t}" has unknown key ${r===void 0?`(spread or computed)`:`"${r}"`}.`);if(r===`run`){a=!0;continue}let i=unwrapExpression(n.value),s=(i.type===`ArrayExpression`?i.elements:void 0)?.map(e=>e?.type===`Literal`&&typeof e.value==`string`?e.value:null);if(!s||s.some(e=>e===null))throw invalidScript(e,`Step "${t}" must list \`dependsOn\` as an array of string literals.`);o=s}if(!a)throw invalidScript(e,`Step "${t}" is missing \`run\`.`);n.push({name:t,dependsOn:o})}return n}function readRollbackOnFailure(e,t){let n=invalidScript(e,'declare `onFailure` as `export const onFailure = "resume"` or `"rollback"`.');if(t.onFailureExportedIndirectly)throw n;if(t.onFailureInit===void 0)return!1;let r=t.onFailureInit?unwrapExpression(t.onFailureInit):void 0;if(r?.type!==`Literal`||r.value!==`resume`&&r.value!==`rollback`)throw n;return r.value===`rollback`}function analyzeMigrationScriptSource(e,t){let{program:n,errors:r}=Ci(t,e,{sourceType:`module`,lang:`ts`});if(r.length>0)throw E({code:`MIGRATION_SCRIPT_INVALID`,message:`Failed to parse ${t}: ${r.map(e=>e.message).join(`; `)}`});let i=collectExports(n),a=i.stepsInit!==void 0||i.stepsExportedIndirectly;if(i.hasMain||i.hasUnreadableExports)return a?{kind:`main`,ignoredSteps:!0}:{kind:`main`};if(!a)throw invalidScript(t,"it must export either `main` or `steps`.");if(i.stepsExportedIndirectly)throw invalidScript(t,"declare `steps` directly as `export const steps = { ... }`.");let o=i.stepsInit?unwrapExpression(i.stepsInit):void 0;if(o?.type!==`ObjectExpression`)throw invalidScript(t,"`steps` must be an object literal declared with `const`.");let s=readSteps(t,o),c=readRollbackOnFailure(t,i);try{let e=Bt(s);return c?{kind:`steps`,order:e,rollbackOnFailure:c}:{kind:`steps`,order:e}}catch(e){throw invalidScript(t,e instanceof Error?e.message:String(e))}}function analyzeMigrationScript(e){return analyzeMigrationScriptSource(W.readFileSync(e,`utf-8`),e)}const Cs=`TODO(tailor-migration-review)`,ws=`Replace each TODO() call with the value or logic it asks for, then remove the TODO import from ./db. For the ${Cs} comment that earlier versions generated, review the code it marks, then remove the comment and the \`never\` annotation next to it.`;function collectTodoBindings(e){let t=/* @__PURE__ */ new Set,n=/* @__PURE__ */ new Set;for(let r of e.body)if(r.type===`ImportDeclaration`&&r.source.value===`./db`)for(let e of r.specifiers)e.type===`ImportNamespaceSpecifier`?n.add(e.local.name):e.type===`ImportSpecifier`&&(e.imported.type===`Identifier`?e.imported.name:String(e.imported.value))===`TODO`&&t.add(e.local.name);return{names:t,namespaces:n}}function countUnresolvedTodos(e,t){let{program:n,comments:r,errors:i}=Ci(t,e,{sourceType:`module`,lang:`ts`});if(i.length>0)throw E({code:`MIGRATION_SCRIPT_INVALID`,message:`Failed to parse ${t}: ${i.map(e=>e.message).join(`; `)}`});let{names:a,namespaces:o}=collectTodoBindings(n),s=0;new Si({CallExpression(e){let{callee:t}=e;(t.type===`Identifier`&&a.has(t.name)||t.type===`MemberExpression`&&!t.computed&&t.object.type===`Identifier`&&o.has(t.object.name)&&t.property.type===`Identifier`&&t.property.name===`TODO`)&&s++}}).visit(n);let c=r.filter(e=>e.value.includes(Cs)).length;return s+c}function countUnresolvedTodosInFile(e){return countUnresolvedTodos(W.readFileSync(e,`utf-8`),e)}function ignoredStepsWarning(e){return`Migration ${e}: migrate.ts exports \`steps\` next to \`main\` (or an \`export *\` that may provide it), so \`main\` runs and \`steps\` is ignored. Remove the export you do not use.`}function normalizeComparableTailorDBService(e){return normalizeProtoConfig({namespace:e.namespace,defaultTimezone:e.defaultTimezone||`UTC`})}function areTailorDBServicesEqual(e,t){return areNormalizedEqual(normalizeComparableTailorDBService({namespace:e.namespace?.name,defaultTimezone:e.defaultTimezone}),normalizeComparableTailorDBService({namespace:t.namespace,defaultTimezone:`UTC`}))}function isPlainObject$2(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}const Ts={disableGqlOperations:{create:!1,update:!1,delete:!1,read:!1},emptyExpression:``,numericStringPaths:/* @__PURE__ */ new Set([`schema.fields.*.serial.start`,`schema.fields.*.serial.maxValue`,`schema.settings.defaultQueryLimitSize`,`schema.settings.maxBulkUpsertSize`])};function normalizeComparableTailorDBType(e){let t=normalizeProtoConfig(toComparableProtoJson(pr,e));return normalizeTailorDBCompareValue({name:t?.name??``,schema:{description:t?.schema?.description??``,fields:t?.schema?.fields??{},relationships:t?.schema?.relationships??{},settings:t?.schema?.settings??{},indexes:t?.schema?.indexes??{},files:t?.schema?.files??{},permission:t?.schema?.permission??{},typeHook:t?.schema?.typeHook??{},typeValidate:t?.schema?.typeValidate??{}}},[])}function isPermissionPolicyArrayPath(e){return e.length===3&&e[0]===`schema`&&e[1]===`permission`&&(e[2]===`create`||e[2]===`read`||e[2]===`update`||e[2]===`delete`)}function normalizeTailorDBCompareValue(e,t){if(e==null)return e;if(typeof e==`boolean`)return t.at(-1)===`optionalOnCreate`&&e===!1?void 0:e;if(typeof e==`number`||typeof e==`bigint`||typeof e==`string`)return matchesNumericStringPath(t)&&isNumericLikeValue(e)?String(e):(t.at(-1)===`expr`||t.at(-1)===`description`)&&e===Ts.emptyExpression?void 0:e;if(Array.isArray(e)){let n=e.map((e,n)=>normalizeTailorDBCompareValue(e,[...t,n])).filter(e=>e!==void 0);return n.length===0&&t.at(-1)===`validate`?void 0:isPermissionPolicyArrayPath(t)?n.toSorted((e,t)=>JSON.stringify(e)<JSON.stringify(t)?-1:1):n}if(!isPlainObject$2(e))return e;let n=Object.entries(e).map(([e,n])=>[e,normalizeTailorDBCompareValue(n,[...t,e])]).filter(([,e])=>e!==void 0),r=Object.fromEntries(n);if((t.at(-1)!==`fields`||Object.keys(r).length!==0)&&(t.at(-1)!==`disableGqlOperations`||Object.keys(r).length!==0&&!areNormalizedEqual(r,Ts.disableGqlOperations)))return r}function matchesNumericStringPath(e){let t=e.map(e=>String(e)).join(`.`);return[...Ts.numericStringPaths].some(e=>{let n=e.split(`.`),r=t.split(`.`);return n.length===r.length&&n.every((e,t)=>e===`*`||e===r[t])})}function isNumericLikeValue(e){return typeof e==`number`||typeof e==`bigint`||/^-?\d+$/.test(e)}function normalizeComparableGqlPermission(e){return{policies:(normalizeProtoConfig(e)?.policies??[]).map(e=>({...e,actions:(e.actions??[]).toSorted((e,t)=>e-t)}))}}async function buildEntry(e,t,n,r){W.writeFileSync(e,t);let i=await Ie(n),a=Be({tsconfig:i}),o=await xi.build({plugins:[ze(e,n),Ye(),Ne(void 0,r)],input:e,write:!1,output:{format:`esm`,sourcemap:!1,minify:!1,codeSplitting:!1,globals:{tailordb:`tailordb`}},external:[`tailordb`],resolve:{conditionNames:[`node`,`import`]},tsconfig:i,treeshake:{moduleSideEffects:!1,annotations:!0,unknownGlobalSideEffects:!1},...a.options});return a.assertAllResolved(),o.output[0].code}async function bundleMigrationScript(e,t,n,r={},i,a=!1,o=`legacy`){let s=H.resolve(Ze(),`migrations`);W.mkdirSync(s,{recursive:!0});let c=H.join(s,`migration_${t}_${n}.entry.js`),l=H.resolve(e).replace(/\\/g,`/`);return{namespace:t,migrationNumber:n,bundledCode:await buildEntry(c,M`
|
|
18
|
+
`)}const Ts=/* @__PURE__ */ new Set([`run`,`dependsOn`]);function usesStepRunner(e,t){return e?.kind===`steps`&&(e.order.length>1||t)}function invalidScript(e,t){return E({code:`MIGRATION_SCRIPT_INVALID`,message:`Invalid migration script ${e}: ${t}`})}function unwrapExpression(e){let t=e;for(;t.type===`TSSatisfiesExpression`||t.type===`TSAsExpression`||t.type===`ParenthesizedExpression`;)t=t.expression;return t}function propertyName(e){if(e.type===`Identifier`)return e.name;if(e.type===`Literal`&&typeof e.value==`string`)return e.value}function boundNames(e){switch(e.type){case`Identifier`:return[e.name];case`AssignmentPattern`:return boundNames(e.left);case`RestElement`:return boundNames(e.argument);case`ObjectPattern`:return e.properties.flatMap(e=>boundNames(e.type===`RestElement`?e:e.value));case`ArrayPattern`:return e.elements.flatMap(e=>e?boundNames(e):[])}}function collectExports(e){let t={hasMain:!1,stepsInit:void 0,stepsExportedIndirectly:!1,onFailureInit:void 0,onFailureExportedIndirectly:!1,hasUnreadableExports:!1};for(let n of e.body){if(n.type===`ExportAllDeclaration`){if(n.exportKind===`type`)continue;n.exported?propertyName(n.exported)===`main`?t.hasMain=!0:propertyName(n.exported)===`onFailure`&&(t.onFailureExportedIndirectly=!0):t.hasUnreadableExports=!0;continue}if(n.type!==`ExportNamedDeclaration`||n.exportKind===`type`)continue;let e=n.declaration;if(e?.type===`FunctionDeclaration`&&e.id?.name===`main`&&(t.hasMain=!0),e?.type===`TSModuleDeclaration`&&e.id.type===`Identifier`&&e.id.name===`onFailure`&&(t.onFailureExportedIndirectly=!0),(e?.type===`FunctionDeclaration`||e?.type===`ClassDeclaration`||e?.type===`TSEnumDeclaration`)&&e.id?.name===`onFailure`&&(t.onFailureExportedIndirectly=!0),e?.type===`VariableDeclaration`)for(let n of e.declarations)if(n.id.type!==`Identifier`){let e=boundNames(n.id);e.includes(`main`)&&(t.hasMain=!0),e.includes(`steps`)&&(t.stepsExportedIndirectly=!0),e.includes(`onFailure`)&&(t.onFailureExportedIndirectly=!0)}else n.id.name===`main`&&(t.hasMain=!0),n.id.name===`steps`&&(t.stepsInit=e.kind===`const`?n.init:null),n.id.name===`onFailure`&&(t.onFailureInit=e.kind===`const`?n.init:null);for(let e of n.specifiers){if(e.exportKind===`type`)continue;let n=propertyName(e.exported);n===`main`&&(t.hasMain=!0),n===`steps`&&(t.stepsExportedIndirectly=!0),n===`onFailure`&&(t.onFailureExportedIndirectly=!0)}}return t}function readSteps(e,t){let n=[];for(let r of t.properties){if(r.type===`SpreadElement`)throw invalidScript(e,"`steps` cannot use spread properties.");let t=r.computed?void 0:propertyName(r.key);if(t===void 0)throw invalidScript(e,"step names must be written literally in `steps`.");let i=unwrapExpression(r.value);if(r.method||r.kind!==`init`||i.type!==`ObjectExpression`)throw invalidScript(e,`Step "${t}" must be an object literal with a \`run\` function, written inside \`steps\`.`);let a=!1,o=[];for(let n of i.properties){let r=n.type===`SpreadElement`||n.computed?void 0:propertyName(n.key);if(n.type===`SpreadElement`||r===void 0||!Ts.has(r))throw invalidScript(e,`Step "${t}" has unknown key ${r===void 0?`(spread or computed)`:`"${r}"`}.`);if(r===`run`){a=!0;continue}let i=unwrapExpression(n.value),s=(i.type===`ArrayExpression`?i.elements:void 0)?.map(e=>e?.type===`Literal`&&typeof e.value==`string`?e.value:null);if(!s||s.some(e=>e===null))throw invalidScript(e,`Step "${t}" must list \`dependsOn\` as an array of string literals.`);o=s}if(!a)throw invalidScript(e,`Step "${t}" is missing \`run\`.`);n.push({name:t,dependsOn:o})}return n}function readRollbackOnFailure(e,t){let n=invalidScript(e,'declare `onFailure` as `export const onFailure = "resume"` or `"rollback"`.');if(t.onFailureExportedIndirectly)throw n;if(t.onFailureInit===void 0)return!1;let r=t.onFailureInit?unwrapExpression(t.onFailureInit):void 0;if(r?.type!==`Literal`||r.value!==`resume`&&r.value!==`rollback`)throw n;return r.value===`rollback`}function analyzeMigrationScriptSource(e,t){let{program:n,errors:r}=Ei(t,e,{sourceType:`module`,lang:`ts`});if(r.length>0)throw E({code:`MIGRATION_SCRIPT_INVALID`,message:`Failed to parse ${t}: ${r.map(e=>e.message).join(`; `)}`});let i=collectExports(n),a=i.stepsInit!==void 0||i.stepsExportedIndirectly;if(i.hasMain||i.hasUnreadableExports)return a?{kind:`main`,ignoredSteps:!0}:{kind:`main`};if(!a)throw invalidScript(t,"it must export either `main` or `steps`.");if(i.stepsExportedIndirectly)throw invalidScript(t,"declare `steps` directly as `export const steps = { ... }`.");let o=i.stepsInit?unwrapExpression(i.stepsInit):void 0;if(o?.type!==`ObjectExpression`)throw invalidScript(t,"`steps` must be an object literal declared with `const`.");let s=readSteps(t,o),c=readRollbackOnFailure(t,i);try{let e=Ut(s);return c?{kind:`steps`,order:e,rollbackOnFailure:c}:{kind:`steps`,order:e}}catch(e){throw invalidScript(t,e instanceof Error?e.message:String(e))}}function analyzeMigrationScript(e){return analyzeMigrationScriptSource(W.readFileSync(e,`utf-8`),e)}const Es=`TODO(tailor-migration-review)`,Ds=`Replace each TODO() call with the value or logic it asks for, then remove the TODO import from ./db. For the ${Es} comment that earlier versions generated, review the code it marks, then remove the comment and the \`never\` annotation next to it.`;function collectTodoBindings(e){let t=/* @__PURE__ */ new Set,n=/* @__PURE__ */ new Set;for(let r of e.body)if(r.type===`ImportDeclaration`&&r.source.value===`./db`)for(let e of r.specifiers)e.type===`ImportNamespaceSpecifier`?n.add(e.local.name):e.type===`ImportSpecifier`&&(e.imported.type===`Identifier`?e.imported.name:String(e.imported.value))===`TODO`&&t.add(e.local.name);return{names:t,namespaces:n}}function countUnresolvedTodos(e,t){let{program:n,comments:r,errors:i}=Ei(t,e,{sourceType:`module`,lang:`ts`});if(i.length>0)throw E({code:`MIGRATION_SCRIPT_INVALID`,message:`Failed to parse ${t}: ${i.map(e=>e.message).join(`; `)}`});let{names:a,namespaces:o}=collectTodoBindings(n),s=0;new Ti({CallExpression(e){let{callee:t}=e;(t.type===`Identifier`&&a.has(t.name)||t.type===`MemberExpression`&&!t.computed&&t.object.type===`Identifier`&&o.has(t.object.name)&&t.property.type===`Identifier`&&t.property.name===`TODO`)&&s++}}).visit(n);let c=r.filter(e=>e.value.includes(Es)).length;return s+c}function countUnresolvedTodosInFile(e){return countUnresolvedTodos(W.readFileSync(e,`utf-8`),e)}function ignoredStepsWarning(e){return`Migration ${e}: migrate.ts exports \`steps\` next to \`main\` (or an \`export *\` that may provide it), so \`main\` runs and \`steps\` is ignored. Remove the export you do not use.`}function normalizeComparableTailorDBService(e){return normalizeProtoConfig({namespace:e.namespace,defaultTimezone:e.defaultTimezone||`UTC`})}function areTailorDBServicesEqual(e,t){return areNormalizedEqual(normalizeComparableTailorDBService({namespace:e.namespace?.name,defaultTimezone:e.defaultTimezone}),normalizeComparableTailorDBService({namespace:t.namespace,defaultTimezone:`UTC`}))}function isPlainObject$2(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}const Os={disableGqlOperations:{create:!1,update:!1,delete:!1,read:!1},emptyExpression:``,numericStringPaths:/* @__PURE__ */ new Set([`schema.fields.*.serial.start`,`schema.fields.*.serial.maxValue`,`schema.settings.defaultQueryLimitSize`,`schema.settings.maxBulkUpsertSize`])};function normalizeComparableTailorDBType(e){let t=normalizeProtoConfig(toComparableProtoJson(gr,e));return normalizeTailorDBCompareValue({name:t?.name??``,schema:{description:t?.schema?.description??``,fields:t?.schema?.fields??{},relationships:t?.schema?.relationships??{},settings:t?.schema?.settings??{},indexes:t?.schema?.indexes??{},files:t?.schema?.files??{},permission:t?.schema?.permission??{},typeHook:t?.schema?.typeHook??{},typeValidate:t?.schema?.typeValidate??{}}},[])}function isPermissionPolicyArrayPath(e){return e.length===3&&e[0]===`schema`&&e[1]===`permission`&&(e[2]===`create`||e[2]===`read`||e[2]===`update`||e[2]===`delete`)}function normalizeTailorDBCompareValue(e,t){if(e==null)return e;if(typeof e==`boolean`)return t.at(-1)===`optionalOnCreate`&&e===!1?void 0:e;if(typeof e==`number`||typeof e==`bigint`||typeof e==`string`)return matchesNumericStringPath(t)&&isNumericLikeValue(e)?String(e):(t.at(-1)===`expr`||t.at(-1)===`description`)&&e===Os.emptyExpression?void 0:e;if(Array.isArray(e)){let n=e.map((e,n)=>normalizeTailorDBCompareValue(e,[...t,n])).filter(e=>e!==void 0);return n.length===0&&t.at(-1)===`validate`?void 0:isPermissionPolicyArrayPath(t)?n.toSorted((e,t)=>JSON.stringify(e)<JSON.stringify(t)?-1:1):n}if(!isPlainObject$2(e))return e;let n=Object.entries(e).map(([e,n])=>[e,normalizeTailorDBCompareValue(n,[...t,e])]).filter(([,e])=>e!==void 0),r=Object.fromEntries(n);if((t.at(-1)!==`fields`||Object.keys(r).length!==0)&&(t.at(-1)!==`disableGqlOperations`||Object.keys(r).length!==0&&!areNormalizedEqual(r,Os.disableGqlOperations)))return r}function matchesNumericStringPath(e){let t=e.map(e=>String(e)).join(`.`);return[...Os.numericStringPaths].some(e=>{let n=e.split(`.`),r=t.split(`.`);return n.length===r.length&&n.every((e,t)=>e===`*`||e===r[t])})}function isNumericLikeValue(e){return typeof e==`number`||typeof e==`bigint`||/^-?\d+$/.test(e)}function normalizeComparableGqlPermission(e){return{policies:(normalizeProtoConfig(e)?.policies??[]).map(e=>({...e,actions:(e.actions??[]).toSorted((e,t)=>e-t)}))}}async function buildEntry(e,t,n,r){W.writeFileSync(e,t);let i=await Ie(n),a=Be({tsconfig:i}),o=await wi.build({plugins:[ze(e,n),Xe(),Ne(void 0,r)],input:e,write:!1,output:{format:`esm`,sourcemap:!1,minify:!1,codeSplitting:!1,globals:{tailordb:`tailordb`}},external:[`tailordb`],resolve:{conditionNames:[`node`,`import`]},tsconfig:i,treeshake:{moduleSideEffects:!1,annotations:!0,unknownGlobalSideEffects:!1},...a.options});return a.assertAllResolved(),o.output[0].code}async function bundleMigrationScript(e,t,n,r={},i,a=!1,o=`legacy`){let s=H.resolve(Qe(),`migrations`);W.mkdirSync(s,{recursive:!0});let c=H.join(s,`migration_${t}_${n}.entry.js`),l=H.resolve(e).replace(/\\/g,`/`);return{namespace:t,migrationNumber:n,bundledCode:await buildEntry(c,M`
|
|
19
19
|
import { main as _migrationMain } from "${l}";
|
|
20
20
|
import { Kysely, TailordbDialect } from "@tailor-platform/sdk/kysely";
|
|
21
21
|
|
|
@@ -34,7 +34,7 @@ If a value is genuinely safe to keep in 'env', allow it where it is defined: ${a
|
|
|
34
34
|
});
|
|
35
35
|
return { success: true };
|
|
36
36
|
}
|
|
37
|
-
`,i??H.dirname(l),o)}}async function bundleSingleStepMigration(e){let{sourceFile:t,namespace:n,migrationNumber:r,env:i,step:a,temporal:o=!1,dateDefault:s=`legacy`}=e,c=H.resolve(
|
|
37
|
+
`,i??H.dirname(l),o)}}async function bundleSingleStepMigration(e){let{sourceFile:t,namespace:n,migrationNumber:r,env:i,step:a,temporal:o=!1,dateDefault:s=`legacy`}=e,c=H.resolve(Qe(),`migrations`);W.mkdirSync(c,{recursive:!0});let l=H.join(c,`migration_${n}_${r}.single-step.entry.js`),u=H.resolve(t).replace(/\\/g,`/`);return{namespace:n,migrationNumber:r,bundledCode:await buildEntry(l,M`
|
|
38
38
|
import { steps as _migrationSteps } from ${JSON.stringify(u)};
|
|
39
39
|
import { Kysely, TailordbDialect } from "@tailor-platform/sdk/kysely";
|
|
40
40
|
|
|
@@ -53,7 +53,7 @@ If a value is genuinely safe to keep in 'env', allow it where it is defined: ${a
|
|
|
53
53
|
});
|
|
54
54
|
return { success: true };
|
|
55
55
|
}
|
|
56
|
-
`,e.baseDir??H.dirname(u),s)}}async function bundleMigrationSteps(e){let{sourceFile:t,namespace:n,migrationNumber:r,env:i,order:a,runnerJobFunctionName:o,skipSteps:s=[],temporal:c=!1,dateDefault:l=`legacy`}=e,u=H.resolve(
|
|
56
|
+
`,e.baseDir??H.dirname(u),s)}}async function bundleMigrationSteps(e){let{sourceFile:t,namespace:n,migrationNumber:r,env:i,order:a,runnerJobFunctionName:o,skipSteps:s=[],temporal:c=!1,dateDefault:l=`legacy`}=e,u=H.resolve(Qe(),`migrations`);W.mkdirSync(u,{recursive:!0});let d=H.join(u,`migration_${n}_${r}.steps.entry.js`),f=H.resolve(t).replace(/\\/g,`/`);return{namespace:n,migrationNumber:r,bundledCode:await buildEntry(d,M`
|
|
57
57
|
import { steps as _migrationSteps } from ${JSON.stringify(f)};
|
|
58
58
|
import { Kysely, TailordbDialect } from "@tailor-platform/sdk/kysely";
|
|
59
59
|
|
|
@@ -89,20 +89,20 @@ If a value is genuinely safe to keep in 'env', allow it where it is defined: ${a
|
|
|
89
89
|
});
|
|
90
90
|
return { step };
|
|
91
91
|
}
|
|
92
|
-
`,e.baseDir??H.dirname(f),l)}}function protoEnumName(e,t){let n=e[t];return typeof n==`string`?n:void 0}function protoEnumNames(e){return Object.keys(e).filter(t=>typeof e[t]==`number`)}function parseProtoEnumName(e,t,n=[]){let r=e[t.toUpperCase()];if(!(typeof r!=`number`||n.includes(r)))return r}function protoEnumLookup(e,t,n){let r=e;return Object.hasOwn(r,t)?r[t]:n}const
|
|
92
|
+
`,e.baseDir??H.dirname(f),l)}}function protoEnumName(e,t){let n=e[t];return typeof n==`string`?n:void 0}function protoEnumNames(e){return Object.keys(e).filter(t=>typeof e[t]==`number`)}function parseProtoEnumName(e,t,n=[]){let r=e[t.toUpperCase()];if(!(typeof r!=`number`||n.includes(r)))return r}function protoEnumLookup(e,t,n){let r=e;return Object.hasOwn(r,t)?r[t]:n}const ks=[`⠋`,`⠙`,`⠹`,`⠸`,`⠼`,`⠴`,`⠦`,`⠧`,`⠇`,`⠏`],As=`\x1B[?25h`,js=`\x1B[2K`,Ms=/\u001B\[[0-9;]*[a-zA-Z]/g;function visibleLength(e){return e.replace(Ms,``).length}const Ns=/* @__PURE__ */ new Set;let Ps=!1,Fs=!1;function installExitHook(){Ps||(Ps=!0,process.on(`exit`,()=>{for(let e of Ns)e.cleanupOnExit()}))}function installSignalHook(){if(Fs)return;Fs=!0;let handler=()=>{for(let e of Ns)e.stop()};process.prependListener(`SIGINT`,handler),process.prependListener(`SIGTERM`,handler)}var Spinner=class{text;#e;#t;#n;#r=0;#i;#a=0;#o=!1;constructor(e={}){this.text=``,this.#e=e.indent??0,this.#t=e.stream??process.stderr,this.#n=!!this.#t.isTTY}start(e){return e!==void 0&&(this.text=e),this.#n?(this.#o||(installExitHook(),installSignalHook(),Ns.add(this),this.#o=!0,this.#t.write(`\x1B[?25l`),this.#c(),this.#i=setInterval(()=>this.#c(),80),typeof this.#i.unref==`function`&&this.#i.unref()),this):(this.#u(`- ${this.text}`),this)}stop(){return this.#o&&(this.#o=!1,this.#i&&=(clearInterval(this.#i),void 0),this.#n&&(this.#l(),this.#t.write(As)),Ns.delete(this)),this}succeed(e){return this.#s(D.success,e)}fail(e){return this.#s(D.error,e)}warn(e){return this.#s(D.warning,e)}cleanupOnExit(){this.#i&&=(clearInterval(this.#i),void 0),this.#n&&this.#t.write(As)}#s(e,t){return t!==void 0&&(this.text=t),this.#o&&(this.#o=!1,this.#i&&=(clearInterval(this.#i),void 0),this.#n&&(this.#l(),this.#t.write(As)),Ns.delete(this)),this.#u(`${e} ${this.text}`),this}#c(){this.#t.write(`\x1B[?2026h`),this.#l();let e=h.info(ks[this.#r]??a(ks[0],`spinner frames empty`));this.#r=(this.#r+1)%ks.length;let t=` `.repeat(this.#e),n=v(this.#t,`${t}${e} ${this.text}`);this.#t.write(n),this.#t.write(`\x1B[?2026l`);let r=this.#t.columns||80;this.#a=Math.max(1,Math.ceil(visibleLength(n)/r))}#l(){if(this.#a!==0){this.#t.write(`\r`),this.#t.write(js);for(let e=1;e<this.#a;e++)this.#t.write(`\x1B[1A`),this.#t.write(js);this.#a=0}}#u(e){let t=` `.repeat(this.#e);this.#t.write(v(this.#t,`${t}${e}\n`))}};function spinner(e){return new Spinner(e)}function functionExecutionStatusToString(e){return protoEnumName(jn,e)??`UNSPECIFIED`}function colorizeFunctionExecutionStatus(e){switch(e){case`RUNNING`:return h.info(e);case`SUCCESS`:return h.success(e);case`FAILED`:return h.error(e);default:return e}}const Is={[jn.UNSPECIFIED]:!1,[jn.RUNNING]:!1,[jn.SUCCESS]:!0,[jn.FAILED]:!0,[jn.SUSPEND]:!1,[jn.CANCELING]:!1,[jn.CANCELED]:!0};function isFunctionExecutionTerminalStatus(e){return protoEnumLookup(Is,e,!1)}function functionLogSeverityToString(e){return protoEnumName(Nn,e)??`UNSPECIFIED`}function functionLogSourceToString(e){return protoEnumName(vn,e)??`UNSPECIFIED`}function toFunctionLogEntryInfo(e){return{message:e.message,severity:functionLogSeverityToString(e.severity),timestamp:e.timestamp?G(e.timestamp):null,source:functionLogSourceToString(e.source)}}function colorizeLogSeverity(e){let t=`[${e}]`;switch(e){case`ERROR`:return h.error(t);case`WARNING`:return h.warning(t);case`DEBUG`:return h.dim(t);default:return t}}function markedMessage(e){if(e.source!==`PLATFORM`)return e.message;let t=h.info(`[PLATFORM]`);return e.message.split(`
|
|
93
93
|
`).map(e=>`${t} ${e}`).join(`
|
|
94
94
|
`)}function formatFunctionLogEntry(e){let t=e.timestamp?e.timestamp.toISOString():`N/A`;return`${h.dim(t)} ${colorizeLogSeverity(e.severity)} ${markedMessage(e)}`}function formatFunctionLogLines(e){return e?e.map(formatFunctionLogEntry):[]}function formatFunctionLogMessages(e){return e?e.map(markedMessage).join(`
|
|
95
95
|
`):``}function joinFunctionLogMessages(e){return e.map(e=>e.message).join(`
|
|
96
|
-
`)}function collectFunctionExecutionLogs(e){return{logs:joinFunctionLogMessages(e)||void 0,logEntries:e.length>0?e.map(toFunctionLogEntryInfo):void 0}}function formatWaitError(e){return e instanceof Error?e.message:String(e)}function isRetryableWaitError(e){return e instanceof q?e.code===K.Aborted||e.code===K.ResourceExhausted||e.code===K.Unavailable:!1}const Is=65536,Ls=3e3,Rs=`[tailor-sdk] migration script started`;function migrationWorkflowResourceName(e,t){return`tailordb-migration--${e}--${formatMigrationNumber(t)}`}function formatMigrationExecutionsHint(e,t,n){return w({command:`tailor`,args:[`workflow`,`executions`,`--workflow-name`,migrationWorkflowResourceName(e,t),...n.contextArgs??[]]})}async function uploadMigrationFunction(e,t,n,r,i,a,o=`create`){let s=`globalThis.console.log(${JSON.stringify(Rs)});\n${r}`,c=Buffer.from(s,`utf-8`),l={workspaceId:t,name:n,description:`Temporary function for a TailorDB migration`,sizeBytes:BigInt(c.length),contentHash:fi.createHash(`sha256`).update(s,`utf-8`).digest(`hex`)};async function*stream(){yield{payload:{case:`info`,value:l}};for(let e=0;e<c.length;e+=Is)yield{payload:{case:`chunk`,value:c.subarray(e,Math.min(e+Is,c.length))}}}o===`create`?await e.createFunctionRegistry(stream()):await e.updateFunctionRegistry(stream()),await writeMetadataLabelsDirect(e,await buildMetaRequest({trn:resourceTrn(t,`function_registry`,n),appName:i,appId:a}))}async function teardown(e,t,n,r,i=[n]){let a=[];r&&a.push([`workflow`,n,()=>e.deleteWorkflow({workspaceId:t,workflowId:r})]);for(let n of i)a.push([`job function`,n,()=>e.deleteWorkflowJobFunction({workspaceId:t,jobFunctionName:n})]);a.push([`function`,n,()=>e.deleteFunctionRegistry({workspaceId:t,name:n})]);for(let[e,t,n]of a)try{await n()}catch(n){if(Ot(n))continue;C.warn(`Could not remove the temporary migration ${e} '${t}': ${n instanceof Error?n.message:String(n)}. It is labeled as owned by this app and can be removed by a later deploy.`)}}async function reclaimLeftovers(e,t,n,r=[n]){await teardown(e,t,n,await findMigrationWorkflowId(e,t,n),r)}async function findMigrationWorkflowId(e,t,n){return(await P(()=>e.getWorkflowByName({workspaceId:t,workflowName:n})))?.workflow?.id}async function createMigrationWorkflow(e,t){let{client:n,workspaceId:r,name:i,appName:a,appId:o}=e,s={};for(let t of e.jobFunctionNames){let{jobFunction:e}=await n.createWorkflowJobFunction({workspaceId:r,jobFunctionName:t,scriptRef:i,publishExecutionEvents:!1});await writeMetadataLabelsDirect(n,await buildMetaRequest({trn:resourceTrn(r,`workflow_job_function`,t),appName:a,appId:o}));let c=e?.version;if(c===void 0)throw b(`Temporary migration job function '${t}' was created without a version.`);s[t]=c}let{workflow:c}=await n.createWorkflow({workspaceId:r,workflowName:i,mainJobFunctionName:i,jobFunctions:s}),l=c?.id;if(!l)throw b(`Temporary migration workflow '${i}' was created without an id.`);return t.workflowId=l,await writeMetadataLabelsDirect(n,await buildMetaRequest({trn:resourceTrn(r,`workflow`,i),appName:a,appId:o,...e.workflowLabels?{metadata:e.workflowLabels}:{}})),l}async function executeMigrationAsWorkflow(e){let{client:t,workspaceId:n,code:r,namespace:i,migrationNumber:a,invoker:o,appName:s,appId:c}=e,l=migrationWorkflowResourceName(i,a),u=`${i}/${formatMigrationNumber(a)}`,d=e.pollIntervalMs??Ls;await assertNoActiveExecution(t,n,l,u,{active:(t,n)=>outcomeUnknownError(e,t,{executionId:n,recorded:!1}),lookupFailed:t=>outcomeUnknownError(e,`Could not check for an earlier run of migration ${u}: ${formatWaitError(t)}`,{cause:t,recorded:!1})}),await reclaimLeftovers(t,n,l),await e.onBeforeStart();let f={},p,m;try{await uploadMigrationFunction(t,n,l,r,s,c),p=await createMigrationWorkflow({client:t,workspaceId:n,name:l,jobFunctionNames:[l],appName:s,appId:c},f),m=new Set((await listMigrationExecutions(t,n,l)).map(e=>e.id))}catch(e){throw await teardown(t,n,l,f.workflowId),e}let h;try{({executionId:h}=await t.startWorkflow({workspaceId:n,workflowId:p,authInvoker:o}))}catch(r){if(isStartRefused(r))throw await teardown(t,n,l,p),r;let i,a=``;try{i=await findStartedExecution(t,n,l,m,d)}catch(e){a=`\nListing its executions failed: ${formatWaitError(e)}`}if(!i)throw outcomeUnknownError(e,`Could not confirm whether migration ${u} started: ${formatWaitError(r)}${a}`,{cause:r,recorded:!0});C.debug(`Start of migration workflow '${l}' failed (${formatWaitError(r)}), but execution '${i.id}' was created; waiting for it.`),h=i.id}try{await e.onExecutionStarted(h)}catch(t){throw outcomeUnknownError(e,`Could not record the run of migration ${u}: ${formatWaitError(t)}`,{cause:t,executionId:h,recorded:!0})}try{return await waitForMigrationWorkflow(e,h)}catch(t){throw outcomeUnknownError(e,`Lost track of migration ${u} while it ran: ${formatWaitError(t)}`,{cause:t,executionId:h,recorded:!0})}}async function findStartedExecution(e,t,n,r,i){for(let a=1;a<=5;a++){a>1&&await new Promise(e=>setTimeout(e,i));try{let i=(await listMigrationExecutions(e,t,n)).find(e=>!r.has(e.id));if(i)return i}catch(e){if(a===5||isStartRefused(e))throw e}}}function outcomeUnknownError(e,t,n){let{namespace:r,migrationNumber:i,commandContext:a}=e,o=migrationWorkflowResourceName(r,i),s=formatMigrationExecutionsHint(r,i,a),syncHint=e=>formatNamespaceMigrationHint({...a,subcommand:[`sync`,formatMigrationNumber(e)],namespace:r}),resolveHint=e=>formatMigrationResolveHint(e,r,a),c=n.recorded?`If the execution succeeded, run ${resolveHint(`complete`)}; otherwise run ${resolveHint(`rollback`)}. Deploys stop before changing anything until then.`:`If the execution succeeded, run ${syncHint(i)}; otherwise run ${syncHint(i-1)}. Then deploy again. Do not deploy before running sync, even with \`--no-schema-check\` to skip the drift check: the deploy may run the \`main\` script again even if the execution succeeded.`;return E({code:`MIGRATION_OUTCOME_UNKNOWN`,message:t,suggestion:`Run ${s} until its execution has finished or none is listed. ${c}`+(e.maintenanceMode?` Until then, the tables of namespace '${r}' stay in maintenance mode.`:``),context:{namespace:r,migrationNumber:i,workflowName:o,...n.executionId?{executionId:n.executionId}:{}},cause:n.cause})}async function pollUntilTerminal(e,t,n,r,i={}){for(;;){let a;try{({execution:a}=await e.getWorkflowExecution({workspaceId:t,executionId:n}))}catch(e){if(!isRetryableWaitError(e))throw e;i.onPollFailed?.(),await new Promise(e=>setTimeout(e,r));continue}if(!a)throw E({code:`WORKFLOW_EXECUTION_NOT_FOUND`,message:`Migration workflow execution '${n}' not found.`});if(!isExecutionActive(a))return a;await i.onActive?.(a),await new Promise(e=>setTimeout(e,r))}}async function hasLoggedScriptStart(e,t,n){try{let{execution:r}=await e.getFunctionExecution({workspaceId:t,executionId:n});return r?.logEntries.some(e=>e.message===Rs)}catch(e){C.debug(`Could not read the logs of migration job execution '${n}': ${e instanceof Error?e.message:String(e)}`);return}}async function observeRun(e,t,n){let{client:r,workspaceId:i,onRunEvent:a}=e,o=e.pollIntervalMs??Ls,s=/* @__PURE__ */ new Set,c=`waiting`,report=e=>{e!==c&&(c=e,a?.({type:e,at:performance.now()}))};a?.({type:`waiting`,at:performance.now()});let l=await pollUntilTerminal(r,i,t,o,{onPollFailed:()=>report(`unknown`),onActive:async e=>{let t=`waiting`;for(let a of e.jobExecutions){if(a.status!==z.RUNNING||!n.runsScript(a))continue;let e=a.executionId;if(!s.has(e)){let n=e?await hasLoggedScriptStart(r,i,e):void 0;n?s.add(e):n===void 0&&(t=`unknown`)}if(s.has(e)){t=`running`;break}}report(t),a?.({type:`polled`,at:performance.now(),execution:e}),await n.onActive?.(e)}}),u=performance.now(),d=await collectJobOutcomes(r,i,l,n),startLogPending=()=>s.size===0&&!d.scriptStarted&&l.status===R.SUCCESS;for(let e=0;e<2&&startLogPending();e++)await new Promise(e=>setTimeout(e,Math.min(o,1e3))),d=await collectJobOutcomes(r,i,l,n);return a?.({type:`finished`,at:u,scriptStarted:s.size>0||d.scriptStarted}),{execution:l,outcomes:d}}async function waitForMigrationWorkflow(e,t){let{execution:n,outcomes:r}=await observeRun(e,t,{runsScript:()=>!0});return n.status===R.SUCCESS?{success:!0,logs:r.logs}:n.status===R.CANCELED?{success:!1,logs:r.logs,error:`Migration workflow execution was canceled.`}:{success:!1,logs:r.logs,error:extractFailureMessage(r)}}async function collectJobOutcomes(e,t,n,r){let{labelJob=()=>void 0,reportsFailure=()=>!0,runsScript:i}=r,a=await Promise.all(n.jobExecutions.map(async n=>{let r=labelJob(n);if(n.executionId)try{let{execution:a}=await e.getFunctionExecution({workspaceId:t,executionId:n.executionId});if(!a)return;let o=reportsFailure(n)&&(a.error?.message.trim()||a.result.trim())||``,s=a.logEntries.filter(e=>e.message!==Rs),c=joinFunctionLogMessages(s);return{logs:r&&c?prefixLines(c,`[${r}] `):c,failure:o,scriptStarted:i(n)&&s.length<a.logEntries.length}}catch{return}}));return{logs:a.map(e=>e?.logs).filter(Boolean).join(`
|
|
96
|
+
`)}function collectFunctionExecutionLogs(e){return{logs:joinFunctionLogMessages(e)||void 0,logEntries:e.length>0?e.map(toFunctionLogEntryInfo):void 0}}const Ls={[R.UNSPECIFIED]:`transient`,[R.PENDING]:`transient`,[R.PENDING_RESUME]:`suspended`,[R.RUNNING]:`transient`,[R.SUCCESS]:`success`,[R.FAILED]:`failure`,[R.PENDING_RETRY]:`transient`,[R.WAITING]:`suspended`,[R.CANCELED]:`failure`};function classifyStatus(e){return protoEnumLookup(Ls,e,`transient`)}const Rs={[z.UNSPECIFIED]:!1,[z.RUNNING]:!1,[z.SUSPEND]:!0,[z.SUCCESS]:!1,[z.FAILED]:!1,[z.WAITING]:!0,[z.CANCELED]:!1};function isWorkflowJobExecutionSuspendedStatus(e){return protoEnumLookup(Rs,e,!1)}function isWorkflowExecutionSuspendedStatus(e){return classifyStatus(e)===`suspended`}function isWorkflowExecutionFailureStatus(e){return classifyStatus(e)===`failure`}function classifyWorkflowExecutionStatus(e){let t=classifyStatus(e.status);return t===`transient`?e.jobExecutions.some(e=>isWorkflowJobExecutionSuspendedStatus(e.status))?{statusClass:`suspended`,status:e.status}:{statusClass:`transient`,status:e.status}:{statusClass:t,status:e.status}}function hasReachedWorkflowWaitTarget(e,t){switch(t){case`success`:return e.statusClass===`success`;case`suspended`:return e.statusClass===`suspended`;case`terminal`:return e.statusClass===`success`||e.statusClass===`failure`||e.statusClass===`suspended`}}function formatWaitError(e){return e instanceof Error?e.message:String(e)}function isRetryableWaitError(e){return e instanceof q?e.code===K.Aborted||e.code===K.ResourceExhausted||e.code===K.Unavailable:!1}const zs=65536;async function uploadTemporaryFunction(e){let{client:t,workspaceId:n,name:r,code:i,description:a,appName:o,appId:s,mode:c=`create`}=e,l=`${e.prelude??``}${i}`,u=Buffer.from(l,`utf-8`),d={workspaceId:n,name:r,description:a,sizeBytes:BigInt(u.length),contentHash:hi.createHash(`sha256`).update(l,`utf-8`).digest(`hex`)};async function*stream(){yield{payload:{case:`info`,value:d}};for(let e=0;e<u.length;e+=zs)yield{payload:{case:`chunk`,value:u.subarray(e,Math.min(e+zs,u.length))}}}c===`create`?await t.createFunctionRegistry(stream()):await t.updateFunctionRegistry(stream()),await writeMetadataLabelsDirect(t,await buildMetaRequest({trn:resourceTrn(n,`function_registry`,r),appName:o,appId:s}))}async function teardownTemporaryWorkflow(e){let{client:t,workspaceId:n,name:r,workflowId:i,subject:a,leftoverNote:o}=e,s=e.jobFunctionNames??[r],c=[];i&&c.push([`workflow`,r,()=>t.deleteWorkflow({workspaceId:n,workflowId:i})]);for(let e of s)c.push([`job function`,e,()=>t.deleteWorkflowJobFunction({workspaceId:n,jobFunctionName:e})]);c.push([`function`,r,()=>t.deleteFunctionRegistry({workspaceId:n,name:r})]);for(let[e,t,n]of c)try{await n()}catch(n){if(At(n))continue;C.warn(`Could not remove the temporary ${a} ${e} '${t}': ${n instanceof Error?n.message:String(n)}. ${o}`)}}async function findTemporaryWorkflowId(e,t,n){return(await P(()=>e.getWorkflowByName({workspaceId:t,workflowName:n})))?.workflow?.id}async function listTemporaryWorkflowExecutions(e,n,r){return(await P(()=>e.listWorkflowExecutions({workspaceId:n,workflowName:r,pageSize:20,pageDirection:t.DESC})))?.executions??[]}async function reclaimTemporaryWorkflow(e){let t=await findTemporaryWorkflowId(e.client,e.workspaceId,e.name);await teardownTemporaryWorkflow({...e,workflowId:t})}async function createTemporaryWorkflow(e,t){let{client:n,workspaceId:r,name:i,appName:a,appId:o,subject:s}=e,c={};for(let t of e.jobFunctionNames){let{jobFunction:e}=await n.createWorkflowJobFunction({workspaceId:r,jobFunctionName:t,scriptRef:i,publishExecutionEvents:!1});await writeMetadataLabelsDirect(n,await buildMetaRequest({trn:resourceTrn(r,`workflow_job_function`,t),appName:a,appId:o}));let l=e?.version;if(l===void 0)throw b(`Temporary ${s} job function '${t}' was created without a version.`);c[t]=l}let{workflow:l}=await n.createWorkflow({workspaceId:r,workflowName:i,mainJobFunctionName:i,jobFunctions:c}),u=l?.id;if(!u)throw b(`Temporary ${s} workflow '${i}' was created without an id.`);return t.workflowId=u,await writeMetadataLabelsDirect(n,await buildMetaRequest({trn:resourceTrn(r,`workflow`,i),appName:a,appId:o,...e.workflowLabels?{metadata:e.workflowLabels}:{}})),u}async function pollUntilTerminal$1(e){let{client:t,workspaceId:n,executionId:r,pollInterval:i,subject:a,options:o={}}=e;for(;;){let e;try{({execution:e}=await t.getWorkflowExecution({workspaceId:n,executionId:r}))}catch(e){if(!isRetryableWaitError(e))throw e;o.onPollFailed?.(),await new Promise(e=>setTimeout(e,i));continue}if(!e)throw E({code:`WORKFLOW_EXECUTION_NOT_FOUND`,message:`${a} workflow execution '${r}' not found.`});if(!isExecutionActive(e))return e;await o.onActive?.(e),await new Promise(e=>setTimeout(e,i))}}function isExecutionActive(e){return e.status!==R.SUCCESS&&!isWorkflowExecutionFailureStatus(e.status)}const Bs=/* @__PURE__ */ new Set([K.InvalidArgument,K.NotFound,K.PermissionDenied,K.Unauthenticated]);function isStartRefused(e){return e instanceof q&&Bs.has(e.code)}const Vs=3e3,Hs=`[tailor-sdk] migration script started`,Us=`migration`,Ws=`It is labeled as owned by this app and can be removed by a later deploy.`;function formatMigrationExecutionsHint(e,t,n){return w({command:`tailor`,args:[`workflow`,`executions`,`--workflow-name`,migrationWorkflowResourceName(e,t),...n.contextArgs??[]]})}async function uploadMigrationFunction(e,t,n,r,i,a,o=`create`){await uploadTemporaryFunction({client:e,workspaceId:t,name:n,code:r,appName:i,appId:a,mode:o,description:`Temporary function for a TailorDB migration`,prelude:`globalThis.console.log(${JSON.stringify(Hs)});\n`})}async function teardown(e,t,n,r,i=[n]){await teardownTemporaryWorkflow({client:e,workspaceId:t,name:n,workflowId:r,jobFunctionNames:i,subject:Us,leftoverNote:Ws})}async function reclaimLeftovers(e,t,n,r=[n]){await reclaimTemporaryWorkflow({client:e,workspaceId:t,name:n,jobFunctionNames:r,subject:Us,leftoverNote:Ws})}async function createMigrationWorkflow(e,t){return await createTemporaryWorkflow({...e,subject:Us},t)}async function pollUntilTerminal(e,t,n,r,i={}){return await pollUntilTerminal$1({client:e,workspaceId:t,executionId:n,pollInterval:r,subject:`Migration`,options:i})}function migrationWorkflowResourceName(e,t){return`tailordb-migration--${e}--${formatMigrationNumber(t)}`}async function executeMigrationAsWorkflow(e){let{client:t,workspaceId:n,code:r,namespace:i,migrationNumber:a,invoker:o,appName:s,appId:c}=e,l=migrationWorkflowResourceName(i,a),u=`${i}/${formatMigrationNumber(a)}`,d=e.pollIntervalMs??Vs;await assertNoActiveExecution(t,n,l,u,{active:(t,n)=>outcomeUnknownError(e,t,{executionId:n,recorded:!1}),lookupFailed:t=>outcomeUnknownError(e,`Could not check for an earlier run of migration ${u}: ${formatWaitError(t)}`,{cause:t,recorded:!1})}),await reclaimLeftovers(t,n,l),await e.onBeforeStart();let f={},p,m;try{await uploadMigrationFunction(t,n,l,r,s,c),p=await createMigrationWorkflow({client:t,workspaceId:n,name:l,jobFunctionNames:[l],appName:s,appId:c},f),m=new Set((await listTemporaryWorkflowExecutions(t,n,l)).map(e=>e.id))}catch(e){throw await teardown(t,n,l,f.workflowId),e}let h;try{({executionId:h}=await t.startWorkflow({workspaceId:n,workflowId:p,authInvoker:o}))}catch(r){if(isStartRefused(r))throw await teardown(t,n,l,p),r;let i,a=``;try{i=await findStartedExecution(t,n,l,m,d)}catch(e){a=`\nListing its executions failed: ${formatWaitError(e)}`}if(!i)throw outcomeUnknownError(e,`Could not confirm whether migration ${u} started: ${formatWaitError(r)}${a}`,{cause:r,recorded:!0});C.debug(`Start of migration workflow '${l}' failed (${formatWaitError(r)}), but execution '${i.id}' was created; waiting for it.`),h=i.id}try{await e.onExecutionStarted(h)}catch(t){throw outcomeUnknownError(e,`Could not record the run of migration ${u}: ${formatWaitError(t)}`,{cause:t,executionId:h,recorded:!0})}try{return await waitForMigrationWorkflow(e,h)}catch(t){throw outcomeUnknownError(e,`Lost track of migration ${u} while it ran: ${formatWaitError(t)}`,{cause:t,executionId:h,recorded:!0})}}async function findStartedExecution(e,t,n,r,i){for(let a=1;a<=5;a++){a>1&&await new Promise(e=>setTimeout(e,i));try{let i=(await listTemporaryWorkflowExecutions(e,t,n)).find(e=>!r.has(e.id));if(i)return i}catch(e){if(a===5||isStartRefused(e))throw e}}}function outcomeUnknownError(e,t,n){let{namespace:r,migrationNumber:i,commandContext:a}=e,o=migrationWorkflowResourceName(r,i),s=formatMigrationExecutionsHint(r,i,a),syncHint=e=>formatNamespaceMigrationHint({...a,subcommand:[`sync`,formatMigrationNumber(e)],namespace:r}),resolveHint=e=>formatMigrationResolveHint(e,r,a),c=n.recorded?`If the execution succeeded, run ${resolveHint(`complete`)}; otherwise run ${resolveHint(`rollback`)}. Deploys stop before changing anything until then.`:`If the execution succeeded, run ${syncHint(i)}; otherwise run ${syncHint(i-1)}. Then deploy again. Do not deploy before running sync, even with \`--no-schema-check\` to skip the drift check: the deploy may run the \`main\` script again even if the execution succeeded.`;return E({code:`MIGRATION_OUTCOME_UNKNOWN`,message:t,suggestion:`Run ${s} until its execution has finished or none is listed. ${c}`+(e.maintenanceMode?` Until then, the tables of namespace '${r}' stay in maintenance mode.`:``),context:{namespace:r,migrationNumber:i,workflowName:o,...n.executionId?{executionId:n.executionId}:{}},cause:n.cause})}async function hasLoggedScriptStart(e,t,n){try{let{execution:r}=await e.getFunctionExecution({workspaceId:t,executionId:n});return r?.logEntries.some(e=>e.message===Hs)}catch(e){C.debug(`Could not read the logs of migration job execution '${n}': ${e instanceof Error?e.message:String(e)}`);return}}async function observeRun(e,t,n){let{client:r,workspaceId:i,onRunEvent:a}=e,o=e.pollIntervalMs??Vs,s=/* @__PURE__ */ new Set,c=`waiting`,report=e=>{e!==c&&(c=e,a?.({type:e,at:performance.now()}))};a?.({type:`waiting`,at:performance.now()});let l=await pollUntilTerminal(r,i,t,o,{onPollFailed:()=>report(`unknown`),onActive:async e=>{let t=`waiting`;for(let a of e.jobExecutions){if(a.status!==z.RUNNING||!n.runsScript(a))continue;let e=a.executionId;if(!s.has(e)){let n=e?await hasLoggedScriptStart(r,i,e):void 0;n?s.add(e):n===void 0&&(t=`unknown`)}if(s.has(e)){t=`running`;break}}report(t),a?.({type:`polled`,at:performance.now(),execution:e}),await n.onActive?.(e)}}),u=performance.now(),d=await collectJobOutcomes(r,i,l,n),startLogPending=()=>s.size===0&&!d.scriptStarted&&l.status===R.SUCCESS;for(let e=0;e<2&&startLogPending();e++)await new Promise(e=>setTimeout(e,Math.min(o,1e3))),d=await collectJobOutcomes(r,i,l,n);return a?.({type:`finished`,at:u,scriptStarted:s.size>0||d.scriptStarted}),{execution:l,outcomes:d}}async function waitForMigrationWorkflow(e,t){let{execution:n,outcomes:r}=await observeRun(e,t,{runsScript:()=>!0});return n.status===R.SUCCESS?{success:!0,logs:r.logs}:n.status===R.CANCELED?{success:!1,logs:r.logs,error:`Migration workflow execution was canceled.`}:{success:!1,logs:r.logs,error:extractFailureMessage(r)}}async function collectJobOutcomes(e,t,n,r){let{labelJob=()=>void 0,reportsFailure=()=>!0,runsScript:i}=r,a=await Promise.all(n.jobExecutions.map(async n=>{let r=labelJob(n);if(n.executionId)try{let{execution:a}=await e.getFunctionExecution({workspaceId:t,executionId:n.executionId});if(!a)return;let o=reportsFailure(n)&&(a.error?.message.trim()||a.result.trim())||``,s=a.logEntries.filter(e=>e.message!==Hs),c=joinFunctionLogMessages(s);return{logs:r&&c?prefixLines(c,`[${r}] `):c,failure:o,scriptStarted:i(n)&&s.length<a.logEntries.length}}catch{return}}));return{logs:a.map(e=>e?.logs).filter(Boolean).join(`
|
|
97
97
|
`),failures:a.map(e=>e?.failure).filter(e=>!!e),scriptStarted:a.some(e=>e?.scriptStarted)}}function extractFailureMessage(e){return e.failures.at(-1)||e.logs.split(`
|
|
98
98
|
`).filter(e=>/error/i.test(e)).at(-1)?.trim()||`Migration workflow execution failed.`}function prefixLines(e,t){return e.split(`
|
|
99
99
|
`).map(e=>`${t}${e}`).join(`
|
|
100
|
-
`)}const zs=`sdk-migration-plan`;function isExecutionActive(e){return e.status!==R.SUCCESS&&!isWorkflowExecutionFailureStatus(e.status)}const Bs=/* @__PURE__ */ new Set([K.InvalidArgument,K.NotFound,K.PermissionDenied,K.Unauthenticated]);function isStartRefused(e){return e instanceof q&&Bs.has(e.code)}function migrationStepRunnerName(e){return`${e}--step`}function migrationPlanFingerprint(e){return`p${fi.createHash(`sha256`).update(JSON.stringify(e),`utf-8`).digest(`hex`).slice(0,40)}`}function classifySteps(e,t,n){let r=/* @__PURE__ */ new Map;for(let n of e.jobExecutions){if(n.kind.case!==`jobFunction`||n.kind.value.name!==t)continue;let e=n.position?.callIndex;if(e===void 0)continue;let i=r.get(e)??/* @__PURE__ */ new Set;i.add(n.status),r.set(e,i)}let i=n.filter((e,t)=>r.get(t)?.has(z.SUCCESS));return{completed:i,failed:n.filter((e,t)=>{let n=r.get(t);return!i.includes(e)&&(n?.has(z.FAILED)||n?.has(z.CANCELED))})}}async function readSucceededStepNames(e,t,n,r){let i=n.jobExecutions.filter(e=>e.kind.case===`jobFunction`&&e.kind.value.name===r&&e.status===z.SUCCESS&&e.executionId).toSorted((e,t)=>(e.position?.callIndex??0)-(t.position?.callIndex??0)),a=await Promise.all(i.map(async n=>{try{let{execution:r}=await e.getFunctionExecution({workspaceId:t,executionId:n.executionId}),i=JSON.parse(r?.result??``)?.step;return typeof i==`string`?i:void 0}catch{return}}));return{steps:[...new Set(a.filter(e=>e!==void 0))],unreadable:a.filter(e=>e===void 0).length}}const Vs={unknown_step:`is not a step of this migration`,no_earlier_run:`has no earlier run to have succeeded in`,not_succeeded:`did not succeed in the earlier run`,unverified:`could not be verified because the earlier run's step results could not be read`};function skipSuggestion(e,t){let n=e.filter(e=>t.includes(e));return n.length>0?`Skip only steps that succeeded in the earlier run and are still steps of this migration: ${n.join(`, `)}.`:e.length>0?`None of the steps that succeeded in the earlier run is still a step of this migration, so there is nothing to skip. Remove --migration-skip-steps for this migration.`:`Skipping applies only to a migration that an earlier deploy left partially applied, and only to its steps that succeeded. Remove --migration-skip-steps for this migration.`}async function assertSkippableSteps(e){let{client:t,workspaceId:n,namespace:r,migrationNumber:i,order:a,inProgress:o,requested:s}=e,c=migrationWorkflowResourceName(r,i),l=o?await findRecordedExecution(t,n,c,o.executionId):void 0,{steps:u,unreadable:d}=l?await readSucceededStepNames(t,n,l,migrationStepRunnerName(c)):{steps:[],unreadable:0},f=s.flatMap(e=>{let t=a.includes(e)?l?u.includes(e)?void 0:d>0?`unverified`:`not_succeeded`:`no_earlier_run`:`unknown_step`;return t?[{step:e,reason:t}]:[]});if(f.length===0)return;let p=`${r}/${formatMigrationNumber(i)}`,m=f.every(({reason:e})=>e===`unverified`);throw E({code:m?`MIGRATION_SKIP_STEPS_UNVERIFIED`:`MIGRATION_SKIP_STEPS_INVALID`,message:`Cannot skip steps of migration ${p}: `+f.map(({step:e,reason:t})=>`'${e}' ${Vs[t]}`).join(`; `)+`.`,suggestion:m?`Run the command again to retry reading the earlier run; if it keeps failing, check connectivity to the platform.`:skipSuggestion(u,a),context:{namespace:r,migrationNumber:i,requested:[...s],invalid:f,succeededSteps:u,unreadableSteps:d}})}function describeRerun(e){let{migrationLabel:t,namespace:n,reason:r,succeeded:i,order:a,skipped:o}=e,s=`Migration ${t} cannot be resumed because ${r}`,c=i.unreadable>0?` The results of ${i.unreadable} succeeded step job${i.unreadable===1?``:`s`} could not be read, so steps that succeeded may be missing from this list.`:``,skipOption=e=>`--migration-skip-steps ${e.map(e=>`${n}/${e}`).join(`,`)}`,l=i.steps.filter(e=>!o.includes(e)),u=l.filter(e=>a.includes(e));if(o.length>0){let e=l.length>0?` ${l.join(`, `)} already succeeded but ${l.length===1?`runs`:`run`} again.`:``;return{message:`${s}; starting it again and skipping ${o.join(`, `)}.${e}${c}`,suggestion:`Every other step runs again, so each must be safe to run twice.`+(u.length>0?` To skip ${u.join(`, `)} as well, pass ${skipOption([...o,...u])} on a deploy that changes the steps.`:``)}}let d=i.steps.length===0?`${s}; every step runs again.${c}`:`${s}; every step runs again, including ${i.steps.join(`, `)}, which already succeeded.${c}`;return u.length===0?{message:d,suggestion:`A step that had already committed would run a second time, so each step must be safe to run twice.`}:{message:d,suggestion:`A step that is not safe to run twice breaks on its second run, and this deploy starts the run without waiting. To skip succeeded steps on a deploy that changes the steps of a migration in progress, pass ${skipOption(u)}. A renamed step cannot be skipped.`}}async function listMigrationExecutions(e,n,r){return(await P(()=>e.listWorkflowExecutions({workspaceId:n,workflowName:r,pageSize:20,pageDirection:t.DESC})))?.executions??[]}const Hs={active:(e,t)=>E({code:`MIGRATION_EXECUTION_ACTIVE`,message:e,suggestion:`Wait for it to finish, or check that no other deploy is running against this workspace, then deploy again.`,context:{executionId:t}})};async function assertNoActiveExecution(e,t,n,r,i=Hs){let a;try{a=await listMigrationExecutions(e,t,n)}catch(e){throw i.lookupFailed?.(e)??e}let o=a.find(isExecutionActive);if(o)throw i.active(`Migration ${r} has an execution that is still running (${o.id}).`,o.id)}function retryCommandActiveError(e,t){return E({code:`MIGRATION_EXECUTION_ACTIVE`,message:e,suggestion:`Wait for it to finish, then run the command again.`,...t?{context:{executionId:t}}:{}})}const Us={active:retryCommandActiveError};async function assertNoActiveMigrationExecution(e,t,n,r){await assertNoActiveExecution(e,t,migrationWorkflowResourceName(n,r),`${n}/${formatMigrationNumber(r)}`,Us)}async function findRecordedExecution(e,t,n,r){return r===void 0?(await listMigrationExecutions(e,t,n))[0]:(await P(()=>e.getWorkflowExecution({workspaceId:t,executionId:r})))?.execution}async function readMigrationRunStatus(e,t,n,r){let i=migrationWorkflowResourceName(n,r.number);try{let n=await findRecordedExecution(e,t,i,r.executionId);return n?isExecutionActive(n)?`running`:n.status===R.SUCCESS?`succeeded`:n.status===R.CANCELED?`canceled`:`failed`:r.executionId===void 0?`not_started`:`unknown`}catch(e){return C.debug(`Could not read the run of migration ${n}/${formatMigrationNumber(r.number)}: ${formatWaitError(e)}`),`unknown`}}function settlingResolution(e){if(e===`succeeded`)return`complete`;if(e!==`running`&&e!==`unknown`)return`rollback`}async function readWorkflowPlan(e,t,n){return(await P(()=>e.getMetadata({trn:resourceTrn(t,`workflow`,n)})))?.metadata?.labels[zs]}function stepJobOptions(e,t){let runsScript=t=>t.kind.case===`jobFunction`&&t.kind.value.name===e;return{runsScript,labelJob:e=>{if(!runsScript(e))return;let n=e.position?.callIndex;return n===void 0?void 0:t[n]},reportsFailure:e=>e.status===z.FAILED||e.status===z.CANCELED}}async function summarizeSteps(e,t,n,r,i,a){let o=classifySteps(n,r,i),s=a??await collectJobOutcomes(e,t,n,stepJobOptions(r,i)),c={logs:s.logs,executionId:n.id,completedSteps:o.completed,failedSteps:o.failed,stepsMayHaveCommitted:n.jobExecutions.some(e=>e.status===z.SUCCESS),runEnded:!0};return n.status===R.SUCCESS?{success:!0,...c}:{success:!1,error:n.status===R.CANCELED?`Migration workflow execution was canceled.`:extractFailureMessage(s),...c}}async function waitForSteps(e,t){let{client:n,workspaceId:r,order:i}=e,a=migrationStepRunnerName(migrationWorkflowResourceName(e.namespace,e.migrationNumber));try{let{execution:o,outcomes:s}=await observeRun(e,t,{...stepJobOptions(a,i),onActive:t=>e.onProgress?.(classifySteps(t,a,i).completed.length,i.length)});return await summarizeSteps(n,r,o,a,i,s)}catch(e){return{success:!1,logs:``,error:`Lost track of migration workflow execution '${t}': ${e instanceof Error?e.message:String(e)}`,executionId:t,completedSteps:[],failedSteps:[],stepsMayHaveCommitted:!0,runEnded:!1}}}async function executeMigrationStepsAsWorkflow(e){let{client:t,workspaceId:n,code:r,namespace:i,migrationNumber:a,invoker:o,appName:s,appId:c,order:l}=e,u=migrationWorkflowResourceName(i,a),d=migrationStepRunnerName(u),f=[d,u],p=`${i}/${formatMigrationNumber(a)}`,m=migrationPlanFingerprint(l),{notify:h}=e;if(e.inProgress){let a=!1,o=await findRecordedExecution(t,n,u,e.inProgress.executionId),f=await findMigrationWorkflowId(t,n,u),g=f!==void 0&&await readWorkflowPlan(t,n,u)===m;if(o&&isExecutionActive(o)){h(`info`,`Migration ${p} is still running from an earlier deploy; waiting.`);let t=await waitForSteps(e,o.id);if(a=!0,g)return t}else if(o?.status===R.SUCCESS&&g)return await summarizeSteps(t,n,o,d,l);if(o?.status===R.FAILED&&g)return await uploadMigrationFunction(t,n,u,r,s,c,`update`),await t.resumeWorkflowExecution({workspaceId:n,executionId:o.id}),h(`info`,`Resuming migration ${p} from the steps that have not completed.`),await waitForSteps(e,o.id);let _=!o||f===void 0?`its earlier run is no longer available`:o.status===R.CANCELED?`its earlier run was canceled`:`its steps changed since its earlier run`,v=o&&a?await findRecordedExecution(t,n,u,o.id):o,{message:y,suggestion:b}=describeRerun({migrationLabel:p,namespace:i,reason:_,succeeded:v?await readSucceededStepNames(t,n,v,d):{steps:[],unreadable:0},order:l,skipped:e.skipSteps??[]});h(`warn`,y,b)}await assertNoActiveExecution(t,n,u,p),await e.onBeforeStart(),await reclaimLeftovers(t,n,u,f);let g={},_;try{await uploadMigrationFunction(t,n,u,r,s,c),_=await createMigrationWorkflow({client:t,workspaceId:n,name:u,jobFunctionNames:f,appName:s,appId:c,workflowLabels:{[zs]:m}},g)}catch(e){throw await teardown(t,n,u,g.workflowId,f),e}let v;try{({executionId:v}=await t.startWorkflow({workspaceId:n,workflowId:_,authInvoker:o}))}catch(e){throw isStartRefused(e)?(await teardown(t,n,u,_,f),e):E({code:`MIGRATION_START_UNCONFIRMED`,message:`Could not confirm whether migration ${p} started: ${e instanceof Error?e.message:String(e)}`,suggestion:`Deploy again; the next deploy checks whether the migration started and continues from what it finds.`,cause:e})}await e.onExecutionStarted(v);let y=await waitForSteps(e,v);return y.success||y.stepsMayHaveCommitted||e.inProgress||await teardown(t,n,u,g.workflowId,f),y}async function removeMigrationWorkflowResources(e,t,n,r){let i=migrationWorkflowResourceName(n,r);await reclaimLeftovers(e,t,i,[i,migrationStepRunnerName(i)])}function parseMigrationSkipSteps(e){let t=/* @__PURE__ */ new Map;if(e===void 0)return t;for(let n of e.split(`,`)){let e=n.indexOf(`/`),r=n.slice(0,e),i=n.slice(e+1);if(e<=0||i===``)throw E({code:`MIGRATION_SKIP_STEPS_FORMAT_INVALID`,message:`'${n}' is not a step to skip.`,suggestion:`Write each step as <namespace>/<step> and separate entries with commas, e.g. --migration-skip-steps main-db/backfillUser,main-db/backfillInvoice.`,context:{entry:n}});let a=t.get(r)??[];a.includes(i)||a.push(i),t.set(r,a)}return t}function formatMigrationSkipSteps(e){let t=[...e??[]].flatMap(([e,t])=>t.map(t=>`${e}/${t}`));return t.length>0?t.join(`,`):void 0}function selectSkipStepsOfNamespaces(e,t){let n=new Set(t);return new Map([...e??[]].filter(([e])=>n.has(e)))}function noStepsToSkipError(e,t){return E({code:`MIGRATION_SKIP_STEPS_INVALID`,message:`Cannot skip steps in namespace '${e}': no multi-step migration of it is partially applied by an earlier deploy.`,suggestion:`Skipping applies only to a multi-step migration that an earlier deploy left partially applied. Remove these entries from --migration-skip-steps.`,context:{namespace:e,requested:[...t]}})}async function assertMigrationSkipSteps(e){let{client:t,workspaceId:n,requested:r,pendingMigrations:i,inProgressByNamespace:a}=e;for(let[e,o]of r){let r=a[e],s=i.find(t=>t.namespace===e&&t.number===r?.number&&t.scriptForm?.kind===`steps`);if(!r||s?.scriptForm?.kind!==`steps`)throw noStepsToSkipError(e,o);await assertSkippableSteps({client:t,workspaceId:n,namespace:e,migrationNumber:s.number,order:s.scriptForm.order,inProgress:r,requested:o})}}function assertSkipNamespacesKnown(e,t){for(let[n,r]of e){if(t.has(n))continue;let e=[...t];throw E({code:`MIGRATION_SKIP_STEPS_INVALID`,message:`Cannot skip steps in namespace '${n}': no deployed config defines a TailorDB namespace with that name.`,suggestion:e.length>0?`Use one of the TailorDB namespaces: ${e.join(`, `)}.`:`The deployed config defines no TailorDB namespace. Remove --migration-skip-steps.`,context:{namespace:n,requested:[...r],namespaces:e}})}}const Ws={restrict:`restrict`,preMigration:`pre-migration`,jobSetup:`job setup`,waitingToStart:`waiting to start`,running:`running`,waitingOrRunning:`waiting to start or running`,jobCleanup:`job cleanup`,postMigration:`post-migration`,remainingDeploy:`remaining deploy`,restore:`restore`},Gs=Object.keys(Ws);function formatDuration(e){if(e<9950)return`${(e/1e3).toFixed(1)}s`;let t=Math.round(e/1e3),n=Math.floor(t/3600),r=Math.floor(t%3600/60),i=t%60,pad=e=>String(e).padStart(2,`0`);return n>0?`${n}h${pad(r)}m${pad(i)}s`:r>0?`${r}m${pad(i)}s`:`${i}s`}function sumDurations(e,t){let n=/* @__PURE__ */ new Map;return e.forEach((r,i)=>{let a=e[i+1]?.at??t;n.set(r.phase,(n.get(r.phase)??0)+(a-r.at))}),n}var ScriptRunTimer=class{namespace;migrationNumber;#e;constructor(e,t,n=performance.now()){this.namespace=e,this.migrationNumber=t,this.#e=[{phase:`jobSetup`,at:n}]}get phase(){return this.#t.phase}get phaseStartedAt(){return this.#t.at}get waitedMs(){return this.#r(`waitingToStart`)}get ranMs(){return this.#r(`running`)}get unobservedMs(){return this.#r(`waitingOrRunning`)}get startObserved(){return this.#e.some(e=>e.phase===`running`)}get#t(){return a(this.#e.at(-1),`A script run always has a phase.`)}waiting(e){this.#i(`waitingToStart`,e)}running(e){this.#i(`running`,e)}unknown(e){this.#i(`waitingOrRunning`,e)}finished(e,t){t&&!this.#n()&&this.#i(`running`,e),this.#i(`jobCleanup`,e)}marks(){let e=0,t=this.#e.map(t=>t.phase===`jobCleanup`?e++:e),n=new Set(this.#e.flatMap((e,n)=>e.phase===`running`?[t[n]]:[]));return this.#e.map((e,r)=>e.phase===`waitingToStart`&&!n.has(t[r])?{...e,phase:`waitingOrRunning`}:e)}#n(){for(let e of this.#e.toReversed()){if(e.phase===`running`)return!0;if(e.phase===`jobCleanup`)return!1}return!1}#r(e){return sumDurations(this.marks().slice(0,-1),this.#t.at).get(e)??0}#i(e,t){this.phase!==e&&this.#e.push({phase:e,at:t})}},MaintenanceTimeline=class{#e=[];#t=[];#n;enter(e,t=performance.now()){this.#r(t),this.#e.push({phase:e,at:t})}recordScript(e,t=performance.now()){let n=e.marks();for(let e of n)this.enter(e.phase,e.at);let r=sumDurations(n,t),ms=e=>Math.round(r.get(e)??0);this.#t.push({namespace:e.namespace,migrationNumber:e.migrationNumber,startObserved:e.startObserved,waitingToStartMs:ms(`waitingToStart`),runningMs:ms(`running`),waitingOrRunningMs:ms(`waitingOrRunning`)})}finish(e=performance.now()){this.#n===void 0&&(this.#r(e),this.#n=e)}report(e){let t=a(this.#n,`A maintenance window is reported once it has finished.`),n=sumDurations(this.#e,t),r=Object.fromEntries(Gs.map(e=>[e,Math.round(n.get(e)??0)]));return{namespaces:[...e],maintenanceMs:Object.values(r).reduce((e,t)=>e+t,0),phases:r,migrations:[...this.#t]}}#r(e){let t=this.#e.at(-1);t&&C.debug(`Maintenance phase "${Ws[t.phase]}" took ${formatDuration(e-t.at)}.`)}};function formatMaintenanceSummary(e){let t=e.namespaces.length===1?`namespace ${e.namespaces[0]}`:`namespaces ${e.namespaces.join(`, `)}`,n=Gs.filter(t=>e.phases[t]>0).map(t=>`${Ws[t]} ${formatDuration(e.phases[t])}`).join(`, `);return`Tables of ${t} were in maintenance mode for ${formatDuration(e.maintenanceMs)}${n?` (${n})`:``}.`}async function getCurrentMigrationNumber(e,t,n,r){let i=await fetchRemoteMigrationState(e,resourceTrn(t,`tailordb`,n));return r?.set(n,i),i.number??0}function migrationNumbersAfter(e,t){return getMigrationFiles(e).filter(e=>e.type===`diff`&&e.number>t).map(e=>e.number)}function readPendingMigration(e,t,n){let r=getMigrationFilePath(t,n,`diff`),i=getMigrationFilePath(t,n,`migrate`);return{number:n,scriptPath:i,hasScript:W.existsSync(i),diffPath:r,namespace:e,migrationsDir:t,diff:loadDiff(r)}}function withScriptForm(e){return{...e,scriptForm:e.hasScript?analyzeMigrationScript(e.scriptPath):null}}function pendingMigrationsAfter(e,t,n){return migrationNumbersAfter(t,n).map(n=>withScriptForm(readPendingMigration(e,t,n)))}async function detectPendingMigrations(e,t,n,r,i,a){let o=[];for(let{namespace:s,migrationsDir:c}of n){let n=i?.get(s)??await getCurrentMigrationNumber(e,t,s,a);for(let e of migrationNumbersAfter(c,n)){let t=readPendingMigration(s,c,e),{diff:n,scriptPath:i,hasScript:a}=t;if(n.requiresMigrationScript&&!a&&!n.scriptSkipped){let t={migrationNumber:e,namespace:s,configPath:r};throw E({code:`MIGRATION_SCRIPT_REQUIRED`,message:`Migration ${s}/${formatMigrationNumber(e)} requires a migration script but migrate.ts was not found.`,suggestion:`Add a script: ${formatMigrationScriptHint(t)}\nOr record that no script is needed: ${formatMigrationScriptHint({...t,noScript:!0})}`})}if(n.scriptSkipped){let t=`${s}/${formatMigrationNumber(e)}`;if(a)throw E({code:`MIGRATION_SCRIPT_SKIP_CONFLICT`,message:`Migration ${t} has both a --no-script skip acknowledgment and migrate.ts.`,suggestion:`Keep the script and clear the stale acknowledgment: ${formatMigrationScriptHint({migrationNumber:e,namespace:s,configPath:r})}\nOr keep the skip: delete migrate.ts`});C.info(`Migration ${t} runs without a script (skip acknowledged at ${n.scriptSkipped.acknowledgedAt}: ${n.scriptSkipped.reason})`)}if(a&&countUnresolvedTodosInFile(i)>0)throw E({code:`MIGRATION_SCRIPT_REVIEW_REQUIRED`,message:`Migration ${s}/${formatMigrationNumber(e)} still has a TODO() call or review marker in migrate.ts, where the generated script leaves a value or logic for you to decide.`,suggestion:ws});let l=withScriptForm(t),{scriptForm:u}=l;u?.kind===`main`&&u.ignoredSteps&&C.warn(ignoredStepsWarning(`${s}/${formatMigrationNumber(e)}`)),o.push(l)}}return o.toSorted((e,t)=>e.namespace===t.namespace?e.number-t.number:e.namespace.localeCompare(t.namespace))}function describeRunStatus(e){let t=e.jobExecutions.map(e=>`${e.kind.case===`jobFunction`?e.kind.value.name:e.kind.case??`job`}=${protoEnumName(z,e.status)??e.status}`);return`workflow execution ${protoEnumName(R,e.status)??e.status}, ${t.length>0?`jobs ${t.join(`, `)}`:`no jobs yet`}`}function displayMigrationRun(e,t,n){let r=``,i,aside=e=>{n.stop(),e(),n.start()},debug=e=>{C.verbose&&aside(()=>C.debug(e))},render=i=>{let a=`(${r}${formatDuration(i-t.phaseStartedAt)})`;n.text=t.phase===`running`?`Running migration ${e} ${a}...`:t.phase===`waitingOrRunning`?`Executing migration ${e} ${a}...`:`Waiting for a job of migration ${e} to start ${a}...`};return{onRunEvent:n=>{if(n.type===`finished`){t.finished(n.at,n.scriptStarted),t.startObserved||debug(`Could not observe when migration ${e} started running, so its run is not split into waiting and running.`);return}let r=n.type===`running`&&!t.startObserved;if(n.type===`waiting`&&t.waiting(n.at),n.type===`running`&&t.running(n.at),n.type===`unknown`&&t.unknown(n.at),render(n.at),n.type===`unknown`&&debug(`Migration ${e}: could not tell whether its script is running.`),r&&aside(()=>C.info(`Migration ${e} started running after waiting ${formatDuration(t.waitedMs)} for its job to start.`,{mode:`stream`})),n.type===`polled`&&C.verbose){let t=describeRunStatus(n.execution);t!==i&&debug(`Migration ${e}: ${t}.`),i=t}},onProgress:(e,t)=>{r=`${e}/${t} steps completed, `,render(performance.now())}}}const Ks=`MIGRATION_SCRIPT_BUNDLE_FAILED`;function isScriptBundleFailure(e){return e instanceof Error&&s(e).code===Ks}async function bundlePendingMigration(e,t){let{env:n,configDir:r,resumed:i,skipSteps:o}=t,s=e.scriptForm,c=e.diff.temporal??!1,u=e.diff.dateRepresentation??`legacy`;try{if(s?.kind!==`steps`)return await bundleMigrationScript(e.scriptPath,e.namespace,e.number,n,r,c,u);let t={sourceFile:e.scriptPath,namespace:e.namespace,migrationNumber:e.number,env:n,baseDir:r,temporal:c,dateDefault:u};return usesStepRunner(s,i)?await bundleMigrationSteps({...t,order:s.order,skipSteps:o,runnerJobFunctionName:migrationStepRunnerName(migrationWorkflowResourceName(e.namespace,e.number))}):await bundleSingleStepMigration({...t,step:a(s.order[0],`a steps script has at least one step`)})}catch(t){throw t instanceof Error&&!m(t)&&l(t,{code:Ks,context:{namespace:e.namespace,migrationNumber:e.number}}),t}}async function assertMigrationScriptsBundle(e,t,n,r){for(let i of e)i.hasScript&&await bundlePendingMigration(i,{env:n,configDir:r,resumed:inProgressRecordOf(i,t)!==void 0})}function inProgressRecordOf(e,t){let n=t[e.namespace];return n?.number===e.number?n:void 0}async function executeSingleMigration(e,t,n,r,i){let{client:a,workspaceId:o,invoker:s,env:c,configDir:l,appName:u,appId:d}=e,f=t.scriptForm;if(f?.kind===`steps`&&usesStepRunner(f,n!==void 0))return executeStepsMigration(e,t,f,n,r,i);let p=await bundlePendingMigration(t,{env:c,configDir:l,resumed:n!==void 0}),m=notifyAround(r),h={mayBeRecorded:!1},g;try{g=await executeMigrationAsWorkflow({client:a,workspaceId:o,code:p.bundledCode,namespace:t.namespace,migrationNumber:t.number,invoker:s,appName:u,appId:d,maintenanceMode:e.maintenanceMode,commandContext:e.commandContext,onBeforeStart:async()=>{await assertCheckpointUnchanged(e,t),h.mayBeRecorded=!0,await writeMigrationInProgress(a,o,t.namespace,{number:t.number,kind:`main`})},onExecutionStarted:e=>writeMigrationInProgress(a,o,t.namespace,{number:t.number,executionId:e,kind:`main`}),onRunEvent:i.onRunEvent})}catch(n){throw(h.mayBeRecorded&&!isMigrationOutcomeUnknown(n)?await releaseMigrationInProgress(e,t,n,m,`main`):void 0)??n}let _={namespace:t.namespace,migrationNumber:t.number,success:g.success,logs:g.logs,error:g.error};if(g.success)return _;let v=h.mayBeRecorded?await releaseMigrationInProgress(e,t,g.error??`Migration failed`,m,`main`):void 0;return v?{..._,failure:v}:(await removeRunResources(a,o,t.namespace,t.number),_)}function notifyAround(e){return(t,n,r)=>{e.stop(),C[t](n),r&&C.log(r),e.start()}}async function removeRunResources(e,t,n,r){try{await removeMigrationWorkflowResources(e,t,n,r)}catch(e){C.warn(`Could not remove the temporary resources of migration ${n}/${formatMigrationNumber(r)}: ${e instanceof Error?e.message:String(e)}. A later deploy removes them.`)}}async function updateMigrationLabel(e,t,n,r,i,a=!1,o=!1){return writeMetadataLabelsDirect(e,{trn:resourceTrn(t,`tailordb`,n),labels:{[Ga]:sanitizeMigrationLabel(r),...i?{[Ka]:i}:{},...a?{[Xa]:sanitizeMigrationLabel(r)}:{},...o?{[Za]:sanitizeMigrationLabel(r)}:{}},remove:[...i?[]:[Ka],...o?[]:[Za],qa,Ya]})}async function assertCheckpointUnchanged(e,t){let n=a(e.checkpoints.get(t.namespace),`every namespace with a migration to run has an expected checkpoint`),{namespace:r}=t,i;try{i=await fetchRemoteMigrationState(e.client,resourceTrn(e.workspaceId,`tailordb`,r))}catch(e){throw E({code:`MIGRATION_CHECKPOINT_UNVERIFIED`,message:`Could not confirm migration checkpoint ${r}/${describeMigrationCheckpoint(n.number)} before migration ${r}/${formatMigrationNumber(t.number)} started: `+(e instanceof Error?e.message:String(e)),suggestion:`Deploy again.`,cause:e})}if(isCheckpointStillOwned(i,n))return;let o=!matchesLocalMigrationHistory(i,e.localHistoryId),s=i.historyIdInvalid?` with a migration history label that cannot be read`:o?` in a different migration history`:``,command=t=>formatNamespaceMigrationHint({...e.commandContext,subcommand:t,namespace:r}),c=command([`sync`,formatMigrationNumber(n.number??0),...o?[`--force`]:[]]);throw E({code:`MIGRATION_CHECKPOINT_CONFLICT`,message:`Migration checkpoint ${r}/${describeMigrationCheckpoint(n.number)} changed to ${describeMigrationCheckpoint(i.number)}${s} before migration ${r}/${formatMigrationNumber(t.number)} started.`,suggestion:`Another deploy or a 'tailor tailordb migration' command changed it while this deploy ran. Run ${command([`status`])} to see it. `+(o?`If another deploy is running, wait for it to finish. To keep the migration history deployed to the workspace, deploy from a checkout of that history instead; to replace it with the local migration history on purpose, run ${c}, then deploy again.`:`If another deploy is running, wait for it to finish; otherwise return the namespace to the checkpoint with ${c}. Then deploy again.`),context:{namespace:r,migrationNumber:t.number,expectedCheckpoint:n.number,remoteCheckpoint:i.number,expectedHistoryId:n.historyId,remoteHistoryId:i.historyId,remoteHistoryIdInvalid:i.historyIdInvalid,localHistoryId:e.localHistoryId,historyIdMismatch:o}})}async function writeMigrationInProgress(e,t,n,r){let{executionId:i}=r;await writeMetadataLabelsDirect(e,{trn:resourceTrn(t,`tailordb`,n),labels:{[qa]:inProgressLabel(r.number,r.kind),...i?{[Ya]:executionIdToLabel(i)}:{}},remove:i?void 0:[Ya]})}async function clearMigrationInProgress(e,t,n){await writeMetadataLabelsDirect(e,{trn:resourceTrn(t,`tailordb`,n),labels:{},remove:[qa,Ya]})}async function clearMigrationCleanupRecord(e,t,n){await writeMetadataLabelsDirect(e,{trn:resourceTrn(t,`tailordb`,n),labels:{},remove:[Za]})}async function clearMaintenanceModeRecord(e,t,n){await writeMetadataLabelsDirect(e,{trn:resourceTrn(t,`tailordb`,n),labels:{},remove:[Xa]})}function isMigrationPartiallyApplied(e){return m(e)&&e.code===`MIGRATION_PARTIALLY_APPLIED`}function isMigrationOutcomeUnknown(e){return m(e)&&e.code===`MIGRATION_OUTCOME_UNKNOWN`}function isMigrationStartRefused(e){return m(e)&&(e.code===`MIGRATION_CHECKPOINT_CONFLICT`||e.code===`MIGRATION_CHECKPOINT_UNVERIFIED`)}function isMigrationRunEnded(e){return m(e)&&e.code===`MIGRATION_PARTIALLY_APPLIED`&&e.context?.runEnded===!0}function withMaintenanceModeNote(e,t,n,r=`Until the migration completes`){if(!n)return e;let i=`${r}, the tables of namespace '${t}' stay in maintenance mode, as during the migration.`;return e?`${e} ${i}`:i}function partiallyAppliedError(e,t,n,r){let i=`${e.namespace}/${formatMigrationNumber(e.number)}`,a=t.failedSteps.length>0?` at ${t.failedSteps.join(`, `)}`:``,o=t.completedSteps.length>0?` after ${t.completedSteps.join(`, `)} completed`:` after some steps may have completed`;return E({code:`MIGRATION_PARTIALLY_APPLIED`,message:`Migration ${i} failed${a}${o}: ${n instanceof Error?n.message:String(n)}`,suggestion:withMaintenanceModeNote(m(n)&&n.suggestion?n.suggestion:`Fix the failing step in migrate.ts and deploy again; steps that already completed do not run again.`,e.namespace,r),context:{namespace:e.namespace,migrationNumber:e.number,completedSteps:t.completedSteps,failedSteps:t.failedSteps,...t.executionId?{executionId:t.executionId}:{},...t.runEnded?{runEnded:!0}:{}},cause:n})}function rolledBackError(e,t){let{namespace:n}=e,r=formatMigrationNumber(e.number-1),i=t instanceof Error&&!m(t)?s(t).suggestion:void 0;return E({code:`MIGRATION_ROLLED_BACK`,message:t instanceof Error?t.message:String(t),suggestion:`Migration ${n}/${formatMigrationNumber(e.number)} was rolled back to migration ${r} and is no longer in progress; any table the rollback could not revert is listed in a warning above. Fix the failure in migrate.ts and deploy again: the next deploy runs every step again from the beginning.`+(i?` ${i}`:``),context:{namespace:n,migrationNumber:e.number},cause:t})}function rollbackSkippedError(e,t,n,r,i){let{namespace:a}=e,resolveHint=e=>formatMigrationResolveHint(e,a,i),o=r.kind===`main`?`Its in-progress record could not be cleared, so its schema was not rolled back, and deploys stop before changing anything until the migration is settled. Once the data meets the migration's schema, run ${resolveHint(`complete`)} to keep what its script wrote; or run ${resolveHint(`rollback`)} to return to migration ${formatMigrationNumber(e.number-1)}.`:`Its in-progress record could not be cleared, so its schema was not rolled back and the migration stays in progress. Deploy again to resume it, or run ${resolveHint(`rollback`)} to roll it back without deploying.`;return E({code:`MIGRATION_PARTIALLY_APPLIED`,message:t instanceof Error?t.message:String(t),suggestion:withMaintenanceModeNote(o,a,n,`Until then`),context:{namespace:a,migrationNumber:e.number,rollbackSkipped:!0,...r.confirmed?{recordConfirmed:!0}:{}},cause:t})}function isRollbackSkippedWithRecord(e){return m(e)&&e.code===`MIGRATION_PARTIALLY_APPLIED`&&e.context?.rollbackSkipped===!0&&e.context.recordConfirmed===!0}function unreleasedRecordError(e,t,n,r,i){let{namespace:a}=e,o=formatMigrationNumber(e.number),s=formatMigrationNumber(e.number-1),command=e=>formatNamespaceMigrationHint({...i,subcommand:e,namespace:a}),c=formatMigrationResolveHint(`rollback`,a,i),l=n.confirmed?n.kind===`main`?`Its in-progress record could not be cleared, so its pre-migration schema stays in place, and deploys stop before changing anything until the record is cleared. Run ${c} to clear it, then fix the failure and deploy again.`:`Its in-progress record could not be cleared, so its pre-migration schema stays in place and the next deploy runs every step again. Fix the failure and deploy again, or run ${c} to clear the record without deploying.`:`Whether it is still recorded as in progress could not be confirmed, so its pre-migration schema stays in place. Run ${command([`status`])}: if it reports migration ${o} in progress, `+(n.kind===`main`?`run ${c} to clear the record, then fix the failure and deploy again; `:`fix the failure and deploy again, or run ${c} to clear the record without deploying; `)+`otherwise run ${command([`sync`,s])} to return the schema to migration ${s}, then deploy again.`,u=t instanceof Error?t.message:String(t);return E({code:`MIGRATION_PARTIALLY_APPLIED`,message:n.kind===`main`?`Migration ${a}/${o} failed: ${u}`:`Migration ${a}/${o} failed before any step completed: ${u}`,suggestion:withMaintenanceModeNote(l,a,r,`Until then`),context:{namespace:a,migrationNumber:e.number,...n.kind===`main`?{}:{completedSteps:[],failedSteps:[]}},cause:t})}function unconfirmedStartError(e,t,n){return E({code:`MIGRATION_PARTIALLY_APPLIED`,message:t.message,suggestion:withMaintenanceModeNote(t.suggestion,e.namespace,n),context:{namespace:e.namespace,migrationNumber:e.number,completedSteps:[],failedSteps:[]},cause:t})}async function releaseMigrationInProgress(e,t,n,r,i){try{await clearMigrationInProgress(e.client,e.workspaceId,t.namespace);return}catch(a){let o;try{o=await fetchRemoteMigrationState(e.client,resourceTrn(e.workspaceId,`tailordb`,t.namespace))}catch{return unreleasedRecordError(t,n,{confirmed:!1,kind:i},e.maintenanceMode,e.commandContext)}return!o.inProgressInvalid&&o.inProgress?.number!==t.number?void 0:(r(`warn`,`Could not clear the in-progress record of migration ${t.namespace}/${formatMigrationNumber(t.number)}: ${a instanceof Error?a.message:String(a)}.`),unreleasedRecordError(t,n,{confirmed:!0,kind:i},e.maintenanceMode,e.commandContext))}}async function executeStepsMigration(e,t,n,r,i,a){let{client:o,workspaceId:s,invoker:c,env:l,configDir:u,appName:d,appId:f}=e,p=r&&e.skipSteps?.get(t.namespace)||[],h=await bundlePendingMigration(t,{env:l,configDir:u,resumed:r!==void 0,skipSteps:p}),g=notifyAround(i),_=r!==void 0,v=r!==void 0,y;try{y=await executeMigrationStepsAsWorkflow({client:o,workspaceId:s,code:h.bundledCode,namespace:t.namespace,migrationNumber:t.number,invoker:c,appName:d,appId:f,maintenanceMode:e.maintenanceMode,order:n.order,skipSteps:p,inProgress:r,notify:g,onBeforeStart:async()=>{await assertCheckpointUnchanged(e,t),_=!0,await writeMigrationInProgress(o,s,t.namespace,{number:t.number,kind:`steps`})},onExecutionStarted:async e=>{v=!0,await writeMigrationInProgress(o,s,t.namespace,{number:t.number,executionId:e,kind:`steps`})},onProgress:a.onProgress,onRunEvent:a.onRunEvent})}catch(n){if(m(n)&&n.code===`MIGRATION_START_UNCONFIRMED`)throw unconfirmedStartError(t,n,e.maintenanceMode);if(isMigrationStartRefused(n))throw n;let r=m(n)&&n.code===`MIGRATION_EXECUTION_ACTIVE`;throw v||r?partiallyAppliedError(t,{completedSteps:[],failedSteps:[]},n,e.maintenanceMode):(_?await releaseMigrationInProgress(e,t,n,g,`steps`):void 0)??n}if(y.success)return{namespace:t.namespace,migrationNumber:t.number,success:!0,logs:y.logs};let b={namespace:t.namespace,migrationNumber:t.number,success:!1,logs:y.logs,error:y.error};if(y.stepsMayHaveCommitted||r)return{...b,failure:partiallyAppliedError(t,y,y.error??`Migration failed`,e.maintenanceMode)};let x=await releaseMigrationInProgress(e,t,y.error??`Migration failed`,g,`steps`);return x?{...b,failure:x}:b}async function executeMigrations(e,t,n,r={},i){let o=t.filter(e=>e.hasScript);if(o.length===0)return;let s=groupMigrationsByNamespace(o);for(let[t,o]of s){let s=a(e.machineUserByNamespace.get(t),`machine user for namespace '${t}' was not resolved`),c=Kr(un,{namespace:e.authNamespace,machineUserName:s}),l={client:e.client,workspaceId:e.workspaceId,invoker:c,env:e.env,configDir:H.dirname(e.configPath),appName:e.appName,appId:e.appId,maintenanceMode:e.maintenanceMode,skipSteps:e.skipSteps,checkpoints:n,localHistoryId:e.migrationHistoryIds[t]??null,commandContext:migrationCommandContext({workspaceId:e.workspaceId,configPath:e.configPath,extraArgs:e.migrationRecoveryArgs})};C.info(`Using machine user: ${h.bold(s)} for namespace '${t}'`);for(let e of o){let t=`${e.namespace}/${formatMigrationNumber(e.number)}`,n=new ScriptRunTimer(e.namespace,e.number),a=spinner().start(`Executing migration ${t}...`),o;try{o=await executeSingleMigration(l,e,inProgressRecordOf(e,r),a,displayMigrationRun(t,n,a))}catch(e){throw a.fail(isMigrationOutcomeUnknown(e)?`Could not confirm the outcome of migration ${t}`:isMigrationStartRefused(e)?`Migration ${t} did not start`:`Migration ${t} failed`),e}finally{a.stop(),i?.recordScript(n)}if(o.success){let e=[...n.startObserved?[`waiting to start ${formatDuration(n.waitedMs)}`,`running ${formatDuration(n.ranMs)}`]:[],...n.unobservedMs>0?[`waiting to start or running ${formatDuration(n.unobservedMs)}`]:[]].join(`, `);a.succeed(`Migration ${t} completed successfully${e?` (${e})`:``}`),o.logs&&o.logs.trim()&&C.log(`Logs:\n${o.logs}`)}else throw a.fail(`Migration ${t} failed`),o.logs&&C.error(`Logs:\n${o.logs}`),o.failure??E({code:`MIGRATION_FAILED`,message:o.error??`Migration failed`})}}}function getMigrationMachineUser(e,t){if(e?.machineUser)return e.machineUser;if(t&&t.length>0)return t[0]}function resolveMigrationMachineUsers(e,t){let n=new Set(t.filter(e=>e.hasScript).map(({namespace:e})=>e));if(n.size===0)return;let r=e.application.authService;if(!r)throw E({code:`AUTH_CONFIG_REQUIRED`,message:`Auth configuration is required to execute migration scripts.`,suggestion:`Define auth with machine users in this config; migration scripts run as one of them.`});let i=Object.keys(r.config.machineUsers??{}),a=/* @__PURE__ */ new Map,o=[];for(let t of n){let n=e.config.db?.[t]?.migration,r=e.migrationMachineUserOverride??getMigrationMachineUser(n,i);r===void 0?o.push(t):a.set(t,r)}if(o.length>0)throw E({code:`MACHINE_USER_REQUIRED`,message:`No machine user available for migration execution in ${describeNamespaces(o)}.`,suggestion:`Either configure 'migration.machineUser' in db config or define machine users in auth config.`,context:{namespaces:o}});let s=r.config.name,c=[...a].filter(([,e])=>!i.includes(e)).map(([e,t])=>({namespace:e,machineUser:t}));if(c.length>0)throw E({code:`MACHINE_USER_NOT_FOUND`,message:`Machine user for migration execution is not defined in auth '${s}': ${c.map(({namespace:e,machineUser:t})=>`'${t}' (namespace '${e}')`).join(`, `)}.`,suggestion:undefinedMachineUserSuggestion(i,e.migrationMachineUserOverride),context:{authNamespace:s,machineUsers:c}});return{authNamespace:s,byNamespace:a}}function undefinedMachineUserSuggestion(e,t){return t===void 0?e.length>0?`Add the machine user to auth.machineUsers, or use one that is defined: ${e.join(`, `)}.`:`Add the machine user to auth.machineUsers.`:e.length>0?`Pass a machine user defined in auth.machineUsers to --machine-user (${e.join(`, `)}), or add '${t}' to auth.machineUsers.`:`Add '${t}' to auth.machineUsers.`}function describeNamespaces(e){let t=e.map(e=>`'${e}'`).join(`, `);return`${e.length===1?`namespace`:`namespaces`} ${t}`}async function assertPendingMigrationsRunnable(e){let{pendingMigrations:t,inProgressByNamespace:n,source:r}=e;await assertMigrationSkipSteps(e);let i=resolveMigrationMachineUsers(r,t);return await assertMigrationScriptsBundle(t,n,r.application.env,H.dirname(r.config.path)),i}function groupMigrationsByNamespace(e){let t=/* @__PURE__ */ new Map;for(let n of e){let e=t.get(n.namespace)??[];e.push(n),t.set(n.namespace,e)}return t}async function captureMigrationRestrictionState(e,t,n){let r=/* @__PURE__ */ new Map;for(let i of n){let n=await F(async(n,r)=>{let{tailordbTypes:a,nextPageToken:o}=await e.listTailorDBTypes({workspaceId:t,namespaceName:i,pageToken:n,pageSize:r});return[a,o]}),a=/* @__PURE__ */ new Map;for(let e of n){let t=e.schema?.settings;e.name&&a.set(e.name,{bulkUpsert:t?.bulkUpsert??!1,publishRecordEvents:t?.publishRecordEvents??!1,...t?.disableGqlOperations&&{disableGqlOperations:{create:t.disableGqlOperations.create??!1,update:t.disableGqlOperations.update??!1,delete:t.disableGqlOperations.delete??!1,read:t.disableGqlOperations.read??!1}},tailordbType:structuredClone(e)})}r.set(i,a)}return r}function getAffectedTableNames(e){let t=/* @__PURE__ */ new Set;for(let n of e.diff.changes)t.add(n.tableName);return t}function getPreMigrationTargetTableNames(e){let t=Js.load(e).tables;return new Set([...getAffectedTableNames(e)].filter(e=>e in t))}function namespacedTableKey(e,t){return`${e}/${t}`}function entriesOfNamespace(e,t){return e.filter(e=>e.request.namespaceName===t)}const qs={created:/* @__PURE__ */ new Set,updated:/* @__PURE__ */ new Set,gqlPermissionsProcessed:/* @__PURE__ */ new Set,reset(){this.created.clear(),this.updated.clear(),this.gqlPermissionsProcessed.clear()}},Js={cache:/* @__PURE__ */ new Map,reset(){this.cache.clear()},load(e){let t=`${e.namespace}/${e.number}`,n=this.cache.get(t);if(!n){let r=reconstructSnapshotFromMigrations(e.migrationsDir,e.number);if(!r)throw E({code:`MIGRATION_HISTORY_INVALID`,message:`Cannot reconstruct snapshot for ${e.namespace} migration ${e.number}: no migrations found in ${e.migrationsDir}`});n=r,this.cache.set(t,n)}return n}};function generateMigrationPhaseManifest(e,t,n){let r=n.tailorDBInputs.find(e=>e.namespace===t)?.config.gqlOperations;return n.restricted?generateTailorDBTypeManifestFromSnapshot(e,{suppressRecordEvents:!0,suppressGqlMutations:!0,namespaceGqlOperations:r}):generateTailorDBTypeManifestFromSnapshot(e,{subscribed:e.settings?.publishEvents!==!1&&n.executorUsedTables.has(e.name),namespaceGqlOperations:r})}function buildSnapshotTypeManifest(e,t,n,r){let i=Js.load(e).tables[t];if(!i)return;let a=e.diff.changes.find(e=>e.kind===`table_scripts_modified`&&e.tableName===t);return generateMigrationPhaseManifest(r?createPreMigrationSnapshotType(i,r,a):i,e.namespace,n)}async function awaitAllSettledOrThrow(e){let t=(await Promise.allSettled(e.filter(e=>e!==void 0))).find(e=>e.status===`rejected`);if(t)throw t.reason}async function executeSingleMigrationPrePhase(e,t,n,r,i,a){let o=buildPreMigrationChangesMap([n]),s=buildPreMigrationIndexChangesMap([n]),c=getAffectedTableNames(n),tableKey=e=>namespacedTableKey(n.namespace,e),l=entriesOfNamespace(t.type.creates,n.namespace),u=entriesOfNamespace(t.type.updates,n.namespace),d=new Set(qs.created);for(let t of l){let a=t.request.tailordbType?.name;if(!a||!c.has(a)||d.has(tableKey(a)))continue;let l=o.get(a),u=buildSnapshotTypeManifest(n,a,r,l);if(!u)continue;let f=structuredClone(t.request);f.tailordbType=u,l&&l.size>0&&f.tailordbType.schema?.fields&&applyPreMigrationFieldAdjustments(f.tailordbType.schema.fields,l);let p=s.get(a);p&&p.size>0&&f.tailordbType.schema?.indexes&&applyPreMigrationIndexAdjustments(f.tailordbType.schema.indexes,p),qs.created.add(tableKey(a)),i.add(a),await e.createTailorDBType(f)}for(let t of l){let a=t.request.tailordbType?.name;if(!a||!c.has(a)||!d.has(tableKey(a)))continue;let l=o.get(a),u=buildSnapshotTypeManifest(n,a,r,l);if(!u)continue;let f=structuredClone(u);l&&l.size>0&&f.schema?.fields&&applyPreMigrationFieldAdjustments(f.schema.fields,l);let p=s.get(a);p&&p.size>0&&f.schema?.indexes&&applyPreMigrationIndexAdjustments(f.schema.indexes,p),qs.updated.add(tableKey(a)),i.add(a),await e.updateTailorDBType({workspaceId:t.request.workspaceId,namespaceName:t.request.namespaceName,tailordbType:f})}for(let t of u){let a=t.request.tailordbType?.name;if(!a||!c.has(a))continue;let l=o.get(a),u=buildSnapshotTypeManifest(n,a,r,l);if(!u)continue;let d=structuredClone(t.request);d.tailordbType=u,l&&l.size>0&&d.tailordbType.schema?.fields&&applyPreMigrationFieldAdjustments(d.tailordbType.schema.fields,l);let f=s.get(a);f&&f.size>0&&d.tailordbType.schema?.indexes&&applyPreMigrationIndexAdjustments(d.tailordbType.schema.indexes,f),qs.updated.add(tableKey(a)),i.add(a),await e.updateTailorDBType(d)}let f=new Set(Object.keys(Js.load(n).tables)),p=entriesOfNamespace(t.gqlPermission.creates,n.namespace).filter(e=>f.has(e.name)&&!qs.gqlPermissionsProcessed.has(tableKey(e.name))),m=entriesOfNamespace(t.gqlPermission.updates,n.namespace).filter(e=>f.has(e.name)&&!qs.gqlPermissionsProcessed.has(tableKey(e.name)));if(p.length+m.length>0){let t=new Set(p.map(e=>e.name)),o=l.filter(e=>{let n=e.request.tailordbType?.name;return n&&t.has(n)&&!qs.created.has(tableKey(n))});if(o.length>0)for(let t of o){let a=t.request.tailordbType?.name;if(!a)continue;let o=buildSnapshotTypeManifest(n,a,r);if(!o)continue;qs.created.add(tableKey(a)),i.add(a);let s=structuredClone(t.request);s.tailordbType=o,await e.createTailorDBType(s)}for(let e of p)a.set(e.name,{});for(let e of m)e.previousPermission&&a.set(e.name,{previous:e.previousPermission});await awaitAllSettledOrThrow([...p.map(t=>e.createTailorDBGQLPermission(t.request)),...m.map(t=>e.updateTailorDBGQLPermission(t.request))]);for(let e of[...p.map(e=>e.name),...m.map(e=>e.name)])qs.gqlPermissionsProcessed.add(tableKey(e))}}const Ys={types:/* @__PURE__ */ new Set,gqlPermissions:/* @__PURE__ */ new Set,reset(){this.types.clear(),this.gqlPermissions.clear()}};function gqlPermissionUndoFromSnapshots(e,t=e,n){let r=/* @__PURE__ */ new Map;if(e.number<=0)return r;let i=reconstructSnapshotFromMigrations(e.migrationsDir,e.number-1);if(!i)return r;let a=Js.load(e).tables,o=Js.load(t).tables;for(let[e,t]of Object.entries(i.tables)){let i=a[e];if(!i)continue;let s=o[e]??i,c=ii(t.permissions?.gql,s.permissions?.gql),l=n===void 0||ii(t.permissions?.gql,i.permissions?.gql);c&&l&&!n?.has(e)||r.set(e,t.permissions?.gql?{previous:protoGqlPermission(t.permissions.gql)}:{})}return r}async function rollbackSingleMigrationAfterFailure(e,t,n,r,i,a){let o=`${t.namespace}/${formatMigrationNumber(t.number)}`,s;try{s=await rollbackSingleMigrationPrePhase(e,t,n,r,i,a)}catch(e){C.warn(`Failed to roll back migration ${o}: ${e instanceof Error?e.message:String(e)}`),s={tables:[...i],permissions:[...a.keys()]}}return s}async function executeSingleMigrationPostPhase(e,t,n,r,i){let a=buildPreMigrationChangesMap([n]),o=buildPreMigrationIndexChangesMap([n]),s=/* @__PURE__ */ new Set([...a.keys(),...o.keys()]),c=getAffectedTableNames(n);try{for(let a of entriesOfNamespace(t.type.creates,n.namespace)){let t=a.request.tailordbType?.name;if(!t||!c.has(t)||!s.has(t))continue;let o=buildSnapshotTypeManifest(n,t,r);o&&(i.add(t),await e.updateTailorDBType({workspaceId:a.request.workspaceId,namespaceName:a.request.namespaceName,tailordbType:o}))}for(let a of entriesOfNamespace(t.type.updates,n.namespace)){let t=a.request.tailordbType?.name;if(!t||!c.has(t)||!s.has(t))continue;let o=buildSnapshotTypeManifest(n,t,r);o&&(i.add(t),await e.updateTailorDBType({workspaceId:a.request.workspaceId,namespaceName:a.request.namespaceName,tailordbType:o}))}}catch(e){handleOptionalToRequiredError(e,[`This error occurred during post-migration phase. Please check your migration script.`,`Ensure all existing records have values for fields being changed to required.`])}}function acceptsMigrationWrites(e){let t=e.disableGqlOperations;return e.publishRecordEvents||e.bulkUpsert||t?.create!==!0||t.update!==!0||t.delete!==!0}const Xs=`the GraphQL create, update, and delete operations and bulk upsert are disabled, and record events are not published`,Zs=`Deploy again: once it finishes, the deploy writes the tables' configured settings back.`,Qs=`Deploy again to run the migration again: a table left with the migration's pre-migration schema does not stop it. If that deploy stops with remote schema drift on these tables, check them in the workspace and delete or repair them by hand.`;function warnTablesLeftRestricted(e,t,n={}){let{recovery:r=Zs,namesUnknown:i=!1}=n,a=t.filter(e=>e.tables.length>0);a.length===0?(C.warn(e),i&&C.log(r)):(C.warn(`${e} Still restricted (${Xs}): ${a.map(e=>`namespace '${e.namespace}': ${e.tables.join(`, `)}`).join(`; `)}.`),C.log(r))}async function rewriteRestrictedTables(e,t){let{workspaceId:n,namespaceName:r,snapshot:i,input:a,executorUsedTables:o,settingsState:s,restricted:c,continueOnError:l=!1}=t,u={tailorDBInputs:[a],executorUsedTables:o,restricted:c},d,f=[],p=/* @__PURE__ */ new Set([...Object.keys(i.tables),...s?.keys()??[]]);for(let t of p)try{let a=i.tables[t],o=s?.get(t);if(s&&!o||c&&(!o||isMigrationRestricted(o)))continue;let l=a?generateMigrationPhaseManifest(a,r,u):o?.tailordbType?structuredClone(o.tailordbType):void 0;if(!l?.schema)continue;l.schema.settings??={};let d=l.schema.settings;c&&(d.bulkUpsert=!1,d.publishRecordEvents=!1,d.disableGqlOperations={create:!0,update:!0,delete:!0,read:o?.disableGqlOperations?.read??!1}),!c&&o&&(d.bulkUpsert=o.bulkUpsert,d.publishRecordEvents=o.publishRecordEvents,d.disableGqlOperations=o.disableGqlOperations?{...o.disableGqlOperations}:void 0),await e.updateTailorDBType({workspaceId:n,namespaceName:r,tailordbType:l})}catch(e){if(!l)throw e;f.push(t),d??=e instanceof Error?e:T(e)}return{failedTables:f,firstError:d}}function resolveMigrationSnapshotSettings(e,t,n){let r=/* @__PURE__ */ new Map;for(let[i,a]of Object.entries(e.tables)){let e=generateTailorDBTypeManifestFromSnapshot(a,{subscribed:!1,namespaceGqlOperations:t.config.gqlOperations}).schema?.settings;e&&r.set(i,{bulkUpsert:e.bulkUpsert??!1,publishRecordEvents:a.settings?.publishEvents??n.has(i),...e.disableGqlOperations&&{disableGqlOperations:{create:e.disableGqlOperations.create??!1,update:e.disableGqlOperations.update??!1,delete:e.disableGqlOperations.delete??!1,read:e.disableGqlOperations.read??!1}}})}return r}function releaseRecordedMaintenanceMode(e,t,n,r){let i=resolveMigrationSnapshotSettings(t,n,r);return new Map([...e].map(([e,t])=>{let n=i.get(e);return[e,n&&isMigrationRestricted(t)?n:t]}))}async function applyMigrationRestrictions(e,t,n,r,i,a){for(let[o,s]of t){let t=r.find(e=>e.namespace===o);t&&await rewriteRestrictedTables(e,{workspaceId:a,namespaceName:o,snapshot:s,input:t,executorUsedTables:i,settingsState:n.get(o)??/* @__PURE__ */ new Map,restricted:!0})}}async function restoreMigrationRestrictions(e,t,n,r,i,a,o){let c,u=[];for(let[o,s]of t){let t=r.find(e=>e.namespace===o);if(t)try{let r=await rewriteRestrictedTables(e,{workspaceId:a,namespaceName:o,snapshot:s,input:t,executorUsedTables:i,settingsState:n?.get(o),restricted:!1,continueOnError:!0});r.firstError&&(c??=r.firstError,u.push({namespace:o,tables:r.failedTables}))}catch(e){c??=e instanceof Error?e:T(e),u.push({namespace:o,tables:[]})}}if(c!==void 0){let e=s(c);throw l(c,{code:`MIGRATION_RESTORE_FAILED`,suggestion:[o?`${Zs} Tables that stay restricted: ${describeUnrestored(u)}.`:`Tables whose settings could not be restored: ${describeUnrestored(u)}. Check these tables in the workspace and repair their settings before retrying the deployment.`,e.suggestion].filter(Boolean).join(` `),context:{...e.context,unrestored:u}})}}function readUnrestoredTables(e){if(!(e instanceof Error))return[];let t=s(e).context?.unrestored;return Array.isArray(t)?t:[]}function describeUnrestored(e){return e.map(e=>`namespace '${e.namespace}': ${e.tables.join(`, `)||`(unknown)`}`).join(`; `)}async function deletePlannedTables(e,t,n,r){let tableKey=e=>namespacedTableKey(n,e),i=entriesOfNamespace(t.gqlPermission.deletes,n).filter(e=>r.has(e.name)&&!Ys.gqlPermissions.has(tableKey(e.name)));for(let t of i)await e.deleteTailorDBGQLPermission(t.request),Ys.gqlPermissions.add(tableKey(t.name));let a=entriesOfNamespace(t.type.deletes,n).filter(e=>r.has(e.name)&&!Ys.types.has(tableKey(e.name)));for(let t of a)await e.deleteTailorDBType(t.request),Ys.types.add(tableKey(t.name))}async function rollbackSingleMigrationPrePhase(e,t,n,r,i,a){if(t.number<=0)return{tables:[...i],permissions:[]};if(i.size===0&&a.size===0)return{tables:[],permissions:[]};let o=reconstructSnapshotFromMigrations(t.migrationsDir,t.number-1);if(!o)return C.warn(`Cannot roll back migration ${t.namespace}/${formatMigrationNumber(t.number)}: prior snapshot (migration ${formatMigrationNumber(t.number-1)}) could not be reconstructed. Leaving schema as-is; manual repair may be required.`),{tables:[...i],permissions:[...a.keys()]};C.warn(`Migration ${t.namespace}/${formatMigrationNumber(t.number)} failed; rolling back its pre-migration schema changes.`);let s=[...i].flatMap(e=>{let t=o.tables[e];return t?[{tableName:e,priorTable:t}]:[]}),c=[...i].filter(e=>!o.tables[e]),l=[],u=[];for(let{tableName:i,priorTable:a}of s)try{let i=generateMigrationPhaseManifest(a,t.namespace,r);await e.updateTailorDBType({workspaceId:n,namespaceName:t.namespace,tailordbType:i})}catch(e){l.push(i),C.warn(`Failed to roll back table '${i}' in namespace '${t.namespace}': ${e instanceof Error?e.message:String(e)}`)}for(let[r,i]of a)if(o.tables[r])try{await restoreGqlPermission(e,n,t.namespace,r,i)}catch(e){u.push(r),C.warn(`Failed to roll back the GraphQL permission of table '${r}' in namespace '${t.namespace}': ${e instanceof Error?e.message:String(e)}`)}for(let r of c)try{await e.deleteTailorDBGQLPermission({workspaceId:n,namespaceName:t.namespace,typeName:r}).catch(()=>void 0),await e.deleteTailorDBType({workspaceId:n,namespaceName:t.namespace,tailordbTypeName:r})}catch(e){if(Ot(e))continue;l.push(r),C.warn(`Failed to roll back table '${r}' in namespace '${t.namespace}': ${e instanceof Error?e.message:String(e)}`)}return{tables:[...new Set(l)],permissions:[...new Set(u)]}}async function restoreGqlPermission(e,t,n,r,i){let a={workspaceId:t,namespaceName:n,typeName:r};if(!i.previous)await e.deleteTailorDBGQLPermission(a).catch(e=>{if(!Ot(e))throw e});else try{await e.updateTailorDBGQLPermission({...a,permission:i.previous})}catch(t){if(!Ot(t))throw t;await e.createTailorDBGQLPermission({...a,permission:i.previous})}}function migrationFileStatesEqual(e,t){let n=Object.keys(e).toSorted(),r=Object.keys(t).toSorted();return n.length===r.length&&n.every((n,i)=>n===r[i]&&e[n]===t[n])}const $s={running:`its run is still running`,succeeded:`its run succeeded`,failed:`its run failed`,canceled:`its run was canceled`,not_started:`its run did not start`,unknown:`whether its run succeeded could not be confirmed`};async function assertMainRunSettled(e,t,n,r,i){let a=r.inProgress;if(a?.kind!==`main`||isStaleMigrationInProgress(r))return;let o=await readMigrationRunStatus(e,t,n,a),s=`${n}/${formatMigrationNumber(a.number)}`,c=migrationWorkflowResourceName(n,a.number),l=formatMigrationExecutionsHint(n,a.number,i),u=settlingResolution(o),d=u===`complete`?`Run ${formatMigrationResolveHint(u,n,i)} to apply the migration's schema without running its script again, then deploy again.`:u===`rollback`?`Run ${formatMigrationResolveHint(u,n,i)} to return to migration ${formatMigrationNumber(a.number-1)}, then deploy again to run the migration again.`:o===`running`?`Wait until ${l} shows that the run finished, then deploy again to see how to settle it.`:`Check the run with ${l}. ${describeMainRunSettlement(n,i)}`;throw E({code:`MIGRATION_OUTCOME_UNSETTLED`,message:`An earlier deploy did not settle the run of migration ${s}: ${$s[o]}.`,suggestion:d,...u?{next:{command:`tailor`,args:migrationResolveArgs(u,n,i)}}:{},context:{namespace:n,migrationNumber:a.number,workflowName:c,...a.executionId?{executionId:a.executionId}:{},runStatus:o}})}function checkpointRepairInProgressError(e){return E({code:`MIGRATION_IN_PROGRESS_CONFLICT`,message:`A migration is in progress in namespace "${e}", so its checkpoint cannot be repaired.`,suggestion:`From a checkout of the migration history that started the migration, finish a multi-step migration with a deploy, or settle the migration with 'tailor tailordb migration resolve' first.`})}async function checkMigrationInProgress(e){let{client:t,workspaceId:n,namespace:r,state:i,next:a,commandContext:o}=e;if(i.inProgressInvalid)throw E({code:`MIGRATION_IN_PROGRESS_INVALID`,message:`The in-progress migration recorded for namespace "${r}" cannot be read.`,suggestion:`The namespace metadata was edited outside the SDK. Restore the in-progress labels it recorded before deploying again.`});let s=i.inProgress;if(!s)return{kind:`none`};if(isStaleMigrationInProgress(i))return{kind:`stale`,migrationNumber:s.number};let c=`${r}/${formatMigrationNumber(s.number)}`;if(await assertMainRunSettled(t,n,r,i,o),a?.number!==s.number)throw E({code:`MIGRATION_IN_PROGRESS_INVALID`,message:`Migration ${c} is in progress, but the next pending migration is ${a?formatMigrationNumber(a.number):`none`}.`,suggestion:`Deploy the migration history that started the migration and let it complete first.`});if(a.scriptForm?.kind!==`steps`)throw E({code:`MIGRATION_IN_PROGRESS_INVALID`,message:`Migration ${c} was partially applied by its steps, but its migrate.ts no longer exports \`steps\`.`,suggestion:"Keep the migration as `steps` so the deploy can finish it; steps that already completed do not run again."});return{kind:`resume`,inProgress:s}}async function validateMigrationsInProgress(e,t,n,r,i,a){let o=r[0];if(o!==void 0)throw checkpointRepairInProgressError(o);let s={inProgressMigrations:{},staleInProgress:[]};for(let[r,o]of n){let n=await checkMigrationInProgress({client:e,workspaceId:t,namespace:r,state:o,next:i.find(e=>e.namespace===r),commandContext:a});n.kind===`stale`&&s.staleInProgress.push({namespace:r,migrationNumber:n.migrationNumber}),n.kind===`resume`&&(s.inProgressMigrations[r]=n.inProgress)}return s}function assertCheckpointsInLocalHistory(e,t){if(e.length!==0){C.error(`Remote migration checkpoint is not in the local migration history:`);for(let t of e)C.log(` ${t.namespace}: ${formatMigrationNumber(t.remoteMigrationNumber)}`);throw C.newline(),logRebaselinePendingGuidance(e),E({code:`MIGRATION_CHECKPOINT_UNKNOWN`,message:`Remote migration checkpoint verification failed`,suggestion:[...missingCheckpointRecoveryHints(e,t),...e.some(e=>e.rebaselinePending)?[`For a namespace that fell behind before 'migration rebaseline' ran, follow the recovery steps above.`]:[]].join(`
|
|
100
|
+
`)}const Gs=`sdk-migration-plan`;function migrationStepRunnerName(e){return`${e}--step`}function migrationPlanFingerprint(e){return`p${hi.createHash(`sha256`).update(JSON.stringify(e),`utf-8`).digest(`hex`).slice(0,40)}`}function classifySteps(e,t,n){let r=/* @__PURE__ */ new Map;for(let n of e.jobExecutions){if(n.kind.case!==`jobFunction`||n.kind.value.name!==t)continue;let e=n.position?.callIndex;if(e===void 0)continue;let i=r.get(e)??/* @__PURE__ */ new Set;i.add(n.status),r.set(e,i)}let i=n.filter((e,t)=>r.get(t)?.has(z.SUCCESS));return{completed:i,failed:n.filter((e,t)=>{let n=r.get(t);return!i.includes(e)&&(n?.has(z.FAILED)||n?.has(z.CANCELED))})}}async function readSucceededStepNames(e,t,n,r){let i=n.jobExecutions.filter(e=>e.kind.case===`jobFunction`&&e.kind.value.name===r&&e.status===z.SUCCESS&&e.executionId).toSorted((e,t)=>(e.position?.callIndex??0)-(t.position?.callIndex??0)),a=await Promise.all(i.map(async n=>{try{let{execution:r}=await e.getFunctionExecution({workspaceId:t,executionId:n.executionId}),i=JSON.parse(r?.result??``)?.step;return typeof i==`string`?i:void 0}catch{return}}));return{steps:[...new Set(a.filter(e=>e!==void 0))],unreadable:a.filter(e=>e===void 0).length}}const Ks={unknown_step:`is not a step of this migration`,no_earlier_run:`has no earlier run to have succeeded in`,not_succeeded:`did not succeed in the earlier run`,unverified:`could not be verified because the earlier run's step results could not be read`};function skipSuggestion(e,t){let n=e.filter(e=>t.includes(e));return n.length>0?`Skip only steps that succeeded in the earlier run and are still steps of this migration: ${n.join(`, `)}.`:e.length>0?`None of the steps that succeeded in the earlier run is still a step of this migration, so there is nothing to skip. Remove --migration-skip-steps for this migration.`:`Skipping applies only to a migration that an earlier deploy left partially applied, and only to its steps that succeeded. Remove --migration-skip-steps for this migration.`}async function assertSkippableSteps(e){let{client:t,workspaceId:n,namespace:r,migrationNumber:i,order:a,inProgress:o,requested:s}=e,c=migrationWorkflowResourceName(r,i),l=o?await findRecordedExecution(t,n,c,o.executionId):void 0,{steps:u,unreadable:d}=l?await readSucceededStepNames(t,n,l,migrationStepRunnerName(c)):{steps:[],unreadable:0},f=s.flatMap(e=>{let t=a.includes(e)?l?u.includes(e)?void 0:d>0?`unverified`:`not_succeeded`:`no_earlier_run`:`unknown_step`;return t?[{step:e,reason:t}]:[]});if(f.length===0)return;let p=`${r}/${formatMigrationNumber(i)}`,m=f.every(({reason:e})=>e===`unverified`);throw E({code:m?`MIGRATION_SKIP_STEPS_UNVERIFIED`:`MIGRATION_SKIP_STEPS_INVALID`,message:`Cannot skip steps of migration ${p}: `+f.map(({step:e,reason:t})=>`'${e}' ${Ks[t]}`).join(`; `)+`.`,suggestion:m?`Run the command again to retry reading the earlier run; if it keeps failing, check connectivity to the platform.`:skipSuggestion(u,a),context:{namespace:r,migrationNumber:i,requested:[...s],invalid:f,succeededSteps:u,unreadableSteps:d}})}function describeRerun(e){let{migrationLabel:t,namespace:n,reason:r,succeeded:i,order:a,skipped:o}=e,s=`Migration ${t} cannot be resumed because ${r}`,c=i.unreadable>0?` The results of ${i.unreadable} succeeded step job${i.unreadable===1?``:`s`} could not be read, so steps that succeeded may be missing from this list.`:``,skipOption=e=>`--migration-skip-steps ${e.map(e=>`${n}/${e}`).join(`,`)}`,l=i.steps.filter(e=>!o.includes(e)),u=l.filter(e=>a.includes(e));if(o.length>0){let e=l.length>0?` ${l.join(`, `)} already succeeded but ${l.length===1?`runs`:`run`} again.`:``;return{message:`${s}; starting it again and skipping ${o.join(`, `)}.${e}${c}`,suggestion:`Every other step runs again, so each must be safe to run twice.`+(u.length>0?` To skip ${u.join(`, `)} as well, pass ${skipOption([...o,...u])} on a deploy that changes the steps.`:``)}}let d=i.steps.length===0?`${s}; every step runs again.${c}`:`${s}; every step runs again, including ${i.steps.join(`, `)}, which already succeeded.${c}`;return u.length===0?{message:d,suggestion:`A step that had already committed would run a second time, so each step must be safe to run twice.`}:{message:d,suggestion:`A step that is not safe to run twice breaks on its second run, and this deploy starts the run without waiting. To skip succeeded steps on a deploy that changes the steps of a migration in progress, pass ${skipOption(u)}. A renamed step cannot be skipped.`}}const qs={active:(e,t)=>E({code:`MIGRATION_EXECUTION_ACTIVE`,message:e,suggestion:`Wait for it to finish, or check that no other deploy is running against this workspace, then deploy again.`,context:{executionId:t}})};async function assertNoActiveExecution(e,t,n,r,i=qs){let a;try{a=await listTemporaryWorkflowExecutions(e,t,n)}catch(e){throw i.lookupFailed?.(e)??e}let o=a.find(isExecutionActive);if(o)throw i.active(`Migration ${r} has an execution that is still running (${o.id}).`,o.id)}function retryCommandActiveError(e,t){return E({code:`MIGRATION_EXECUTION_ACTIVE`,message:e,suggestion:`Wait for it to finish, then run the command again.`,...t?{context:{executionId:t}}:{}})}const Js={active:retryCommandActiveError};async function assertNoActiveMigrationExecution(e,t,n,r){await assertNoActiveExecution(e,t,migrationWorkflowResourceName(n,r),`${n}/${formatMigrationNumber(r)}`,Js)}async function findRecordedExecution(e,t,n,r){return r===void 0?(await listTemporaryWorkflowExecutions(e,t,n))[0]:(await P(()=>e.getWorkflowExecution({workspaceId:t,executionId:r})))?.execution}async function readMigrationRunStatus(e,t,n,r){let i=migrationWorkflowResourceName(n,r.number);try{let n=await findRecordedExecution(e,t,i,r.executionId);return n?isExecutionActive(n)?`running`:n.status===R.SUCCESS?`succeeded`:n.status===R.CANCELED?`canceled`:`failed`:r.executionId===void 0?`not_started`:`unknown`}catch(e){return C.debug(`Could not read the run of migration ${n}/${formatMigrationNumber(r.number)}: ${formatWaitError(e)}`),`unknown`}}function settlingResolution(e){if(e===`succeeded`)return`complete`;if(e!==`running`&&e!==`unknown`)return`rollback`}async function readWorkflowPlan(e,t,n){return(await P(()=>e.getMetadata({trn:resourceTrn(t,`workflow`,n)})))?.metadata?.labels[Gs]}function stepJobOptions(e,t){let runsScript=t=>t.kind.case===`jobFunction`&&t.kind.value.name===e;return{runsScript,labelJob:e=>{if(!runsScript(e))return;let n=e.position?.callIndex;return n===void 0?void 0:t[n]},reportsFailure:e=>e.status===z.FAILED||e.status===z.CANCELED}}async function summarizeSteps(e,t,n,r,i,a){let o=classifySteps(n,r,i),s=a??await collectJobOutcomes(e,t,n,stepJobOptions(r,i)),c={logs:s.logs,executionId:n.id,completedSteps:o.completed,failedSteps:o.failed,stepsMayHaveCommitted:n.jobExecutions.some(e=>e.status===z.SUCCESS),runEnded:!0};return n.status===R.SUCCESS?{success:!0,...c}:{success:!1,error:n.status===R.CANCELED?`Migration workflow execution was canceled.`:extractFailureMessage(s),...c}}async function waitForSteps(e,t){let{client:n,workspaceId:r,order:i}=e,a=migrationStepRunnerName(migrationWorkflowResourceName(e.namespace,e.migrationNumber));try{let{execution:o,outcomes:s}=await observeRun(e,t,{...stepJobOptions(a,i),onActive:t=>e.onProgress?.(classifySteps(t,a,i).completed.length,i.length)});return await summarizeSteps(n,r,o,a,i,s)}catch(e){return{success:!1,logs:``,error:`Lost track of migration workflow execution '${t}': ${e instanceof Error?e.message:String(e)}`,executionId:t,completedSteps:[],failedSteps:[],stepsMayHaveCommitted:!0,runEnded:!1}}}async function executeMigrationStepsAsWorkflow(e){let{client:t,workspaceId:n,code:r,namespace:i,migrationNumber:a,invoker:o,appName:s,appId:c,order:l}=e,u=migrationWorkflowResourceName(i,a),d=migrationStepRunnerName(u),f=[d,u],p=`${i}/${formatMigrationNumber(a)}`,m=migrationPlanFingerprint(l),{notify:h}=e;if(e.inProgress){let a=!1,o=await findRecordedExecution(t,n,u,e.inProgress.executionId),f=await findTemporaryWorkflowId(t,n,u),g=f!==void 0&&await readWorkflowPlan(t,n,u)===m;if(o&&isExecutionActive(o)){h(`info`,`Migration ${p} is still running from an earlier deploy; waiting.`);let t=await waitForSteps(e,o.id);if(a=!0,g)return t}else if(o?.status===R.SUCCESS&&g)return await summarizeSteps(t,n,o,d,l);if(o?.status===R.FAILED&&g)return await uploadMigrationFunction(t,n,u,r,s,c,`update`),await t.resumeWorkflowExecution({workspaceId:n,executionId:o.id}),h(`info`,`Resuming migration ${p} from the steps that have not completed.`),await waitForSteps(e,o.id);let _=!o||f===void 0?`its earlier run is no longer available`:o.status===R.CANCELED?`its earlier run was canceled`:`its steps changed since its earlier run`,v=o&&a?await findRecordedExecution(t,n,u,o.id):o,{message:y,suggestion:b}=describeRerun({migrationLabel:p,namespace:i,reason:_,succeeded:v?await readSucceededStepNames(t,n,v,d):{steps:[],unreadable:0},order:l,skipped:e.skipSteps??[]});h(`warn`,y,b)}await assertNoActiveExecution(t,n,u,p),await e.onBeforeStart(),await reclaimLeftovers(t,n,u,f);let g={},_;try{await uploadMigrationFunction(t,n,u,r,s,c),_=await createMigrationWorkflow({client:t,workspaceId:n,name:u,jobFunctionNames:f,appName:s,appId:c,workflowLabels:{[Gs]:m}},g)}catch(e){throw await teardown(t,n,u,g.workflowId,f),e}let v;try{({executionId:v}=await t.startWorkflow({workspaceId:n,workflowId:_,authInvoker:o}))}catch(e){throw isStartRefused(e)?(await teardown(t,n,u,_,f),e):E({code:`MIGRATION_START_UNCONFIRMED`,message:`Could not confirm whether migration ${p} started: ${e instanceof Error?e.message:String(e)}`,suggestion:`Deploy again; the next deploy checks whether the migration started and continues from what it finds.`,cause:e})}await e.onExecutionStarted(v);let y=await waitForSteps(e,v);return y.success||y.stepsMayHaveCommitted||e.inProgress||await teardown(t,n,u,g.workflowId,f),y}async function removeMigrationWorkflowResources(e,t,n,r){let i=migrationWorkflowResourceName(n,r);await reclaimLeftovers(e,t,i,[i,migrationStepRunnerName(i)])}function parseMigrationSkipSteps(e){let t=/* @__PURE__ */ new Map;if(e===void 0)return t;for(let n of e.split(`,`)){let e=n.indexOf(`/`),r=n.slice(0,e),i=n.slice(e+1);if(e<=0||i===``)throw E({code:`MIGRATION_SKIP_STEPS_FORMAT_INVALID`,message:`'${n}' is not a step to skip.`,suggestion:`Write each step as <namespace>/<step> and separate entries with commas, e.g. --migration-skip-steps main-db/backfillUser,main-db/backfillInvoice.`,context:{entry:n}});let a=t.get(r)??[];a.includes(i)||a.push(i),t.set(r,a)}return t}function formatMigrationSkipSteps(e){let t=[...e??[]].flatMap(([e,t])=>t.map(t=>`${e}/${t}`));return t.length>0?t.join(`,`):void 0}function selectSkipStepsOfNamespaces(e,t){let n=new Set(t);return new Map([...e??[]].filter(([e])=>n.has(e)))}function noStepsToSkipError(e,t){return E({code:`MIGRATION_SKIP_STEPS_INVALID`,message:`Cannot skip steps in namespace '${e}': no multi-step migration of it is partially applied by an earlier deploy.`,suggestion:`Skipping applies only to a multi-step migration that an earlier deploy left partially applied. Remove these entries from --migration-skip-steps.`,context:{namespace:e,requested:[...t]}})}async function assertMigrationSkipSteps(e){let{client:t,workspaceId:n,requested:r,pendingMigrations:i,inProgressByNamespace:a}=e;for(let[e,o]of r){let r=a[e],s=i.find(t=>t.namespace===e&&t.number===r?.number&&t.scriptForm?.kind===`steps`);if(!r||s?.scriptForm?.kind!==`steps`)throw noStepsToSkipError(e,o);await assertSkippableSteps({client:t,workspaceId:n,namespace:e,migrationNumber:s.number,order:s.scriptForm.order,inProgress:r,requested:o})}}function assertSkipNamespacesKnown(e,t){for(let[n,r]of e){if(t.has(n))continue;let e=[...t];throw E({code:`MIGRATION_SKIP_STEPS_INVALID`,message:`Cannot skip steps in namespace '${n}': no deployed config defines a TailorDB namespace with that name.`,suggestion:e.length>0?`Use one of the TailorDB namespaces: ${e.join(`, `)}.`:`The deployed config defines no TailorDB namespace. Remove --migration-skip-steps.`,context:{namespace:n,requested:[...r],namespaces:e}})}}const Ys={restrict:`restrict`,preMigration:`pre-migration`,jobSetup:`job setup`,waitingToStart:`waiting to start`,running:`running`,waitingOrRunning:`waiting to start or running`,jobCleanup:`job cleanup`,postMigration:`post-migration`,remainingDeploy:`remaining deploy`,restore:`restore`},Xs=Object.keys(Ys);function formatDuration(e){if(e<9950)return`${(e/1e3).toFixed(1)}s`;let t=Math.round(e/1e3),n=Math.floor(t/3600),r=Math.floor(t%3600/60),i=t%60,pad=e=>String(e).padStart(2,`0`);return n>0?`${n}h${pad(r)}m${pad(i)}s`:r>0?`${r}m${pad(i)}s`:`${i}s`}function sumDurations(e,t){let n=/* @__PURE__ */ new Map;return e.forEach((r,i)=>{let a=e[i+1]?.at??t;n.set(r.phase,(n.get(r.phase)??0)+(a-r.at))}),n}var ScriptRunTimer=class{namespace;migrationNumber;#e;constructor(e,t,n=performance.now()){this.namespace=e,this.migrationNumber=t,this.#e=[{phase:`jobSetup`,at:n}]}get phase(){return this.#t.phase}get phaseStartedAt(){return this.#t.at}get waitedMs(){return this.#r(`waitingToStart`)}get ranMs(){return this.#r(`running`)}get unobservedMs(){return this.#r(`waitingOrRunning`)}get startObserved(){return this.#e.some(e=>e.phase===`running`)}get#t(){return a(this.#e.at(-1),`A script run always has a phase.`)}waiting(e){this.#i(`waitingToStart`,e)}running(e){this.#i(`running`,e)}unknown(e){this.#i(`waitingOrRunning`,e)}finished(e,t){t&&!this.#n()&&this.#i(`running`,e),this.#i(`jobCleanup`,e)}marks(){let e=0,t=this.#e.map(t=>t.phase===`jobCleanup`?e++:e),n=new Set(this.#e.flatMap((e,n)=>e.phase===`running`?[t[n]]:[]));return this.#e.map((e,r)=>e.phase===`waitingToStart`&&!n.has(t[r])?{...e,phase:`waitingOrRunning`}:e)}#n(){for(let e of this.#e.toReversed()){if(e.phase===`running`)return!0;if(e.phase===`jobCleanup`)return!1}return!1}#r(e){return sumDurations(this.marks().slice(0,-1),this.#t.at).get(e)??0}#i(e,t){this.phase!==e&&this.#e.push({phase:e,at:t})}},MaintenanceTimeline=class{#e=[];#t=[];#n;enter(e,t=performance.now()){this.#r(t),this.#e.push({phase:e,at:t})}recordScript(e,t=performance.now()){let n=e.marks();for(let e of n)this.enter(e.phase,e.at);let r=sumDurations(n,t),ms=e=>Math.round(r.get(e)??0);this.#t.push({namespace:e.namespace,migrationNumber:e.migrationNumber,startObserved:e.startObserved,waitingToStartMs:ms(`waitingToStart`),runningMs:ms(`running`),waitingOrRunningMs:ms(`waitingOrRunning`)})}finish(e=performance.now()){this.#n===void 0&&(this.#r(e),this.#n=e)}report(e){let t=a(this.#n,`A maintenance window is reported once it has finished.`),n=sumDurations(this.#e,t),r=Object.fromEntries(Xs.map(e=>[e,Math.round(n.get(e)??0)]));return{namespaces:[...e],maintenanceMs:Object.values(r).reduce((e,t)=>e+t,0),phases:r,migrations:[...this.#t]}}#r(e){let t=this.#e.at(-1);t&&C.debug(`Maintenance phase "${Ys[t.phase]}" took ${formatDuration(e-t.at)}.`)}};function formatMaintenanceSummary(e){let t=e.namespaces.length===1?`namespace ${e.namespaces[0]}`:`namespaces ${e.namespaces.join(`, `)}`,n=Xs.filter(t=>e.phases[t]>0).map(t=>`${Ys[t]} ${formatDuration(e.phases[t])}`).join(`, `);return`Tables of ${t} were in maintenance mode for ${formatDuration(e.maintenanceMs)}${n?` (${n})`:``}.`}async function getCurrentMigrationNumber(e,t,n,r){let i=await fetchRemoteMigrationState(e,resourceTrn(t,`tailordb`,n));return r?.set(n,i),i.number??0}function migrationNumbersAfter(e,t){return getMigrationFiles(e).filter(e=>e.type===`diff`&&e.number>t).map(e=>e.number)}function readPendingMigration(e,t,n){let r=getMigrationFilePath(t,n,`diff`),i=getMigrationFilePath(t,n,`migrate`);return{number:n,scriptPath:i,hasScript:W.existsSync(i),diffPath:r,namespace:e,migrationsDir:t,diff:loadDiff(r)}}function withScriptForm(e){return{...e,scriptForm:e.hasScript?analyzeMigrationScript(e.scriptPath):null}}function pendingMigrationsAfter(e,t,n){return migrationNumbersAfter(t,n).map(n=>withScriptForm(readPendingMigration(e,t,n)))}async function detectPendingMigrations(e,t,n,r,i,a){let o=[];for(let{namespace:s,migrationsDir:c}of n){let n=i?.get(s)??await getCurrentMigrationNumber(e,t,s,a);for(let e of migrationNumbersAfter(c,n)){let t=readPendingMigration(s,c,e),{diff:n,scriptPath:i,hasScript:a}=t;if(n.requiresMigrationScript&&!a&&!n.scriptSkipped){let t={migrationNumber:e,namespace:s,configPath:r};throw E({code:`MIGRATION_SCRIPT_REQUIRED`,message:`Migration ${s}/${formatMigrationNumber(e)} requires a migration script but migrate.ts was not found.`,suggestion:`Add a script: ${formatMigrationScriptHint(t)}\nOr record that no script is needed: ${formatMigrationScriptHint({...t,noScript:!0})}`})}if(n.scriptSkipped&&a)throw E({code:`MIGRATION_SCRIPT_SKIP_CONFLICT`,message:`Migration ${s}/${formatMigrationNumber(e)} has both a --no-script skip acknowledgment and migrate.ts.`,suggestion:`Keep the script and clear the stale acknowledgment: ${formatMigrationScriptHint({migrationNumber:e,namespace:s,configPath:r})}\nOr keep the skip: delete migrate.ts`});if(a&&countUnresolvedTodosInFile(i)>0)throw E({code:`MIGRATION_SCRIPT_REVIEW_REQUIRED`,message:`Migration ${s}/${formatMigrationNumber(e)} still has a TODO() call or review marker in migrate.ts, where the generated script leaves a value or logic for you to decide.`,suggestion:Ds});o.push(withScriptForm(t))}}return o.toSorted((e,t)=>e.namespace===t.namespace?e.number-t.number:e.namespace.localeCompare(t.namespace))}function describeRunStatus(e){let t=e.jobExecutions.map(e=>`${e.kind.case===`jobFunction`?e.kind.value.name:e.kind.case??`job`}=${protoEnumName(z,e.status)??e.status}`);return`workflow execution ${protoEnumName(R,e.status)??e.status}, ${t.length>0?`jobs ${t.join(`, `)}`:`no jobs yet`}`}function displayMigrationRun(e,t,n){let r=``,i,aside=e=>{n.stop(),e(),n.start()},debug=e=>{C.verbose&&aside(()=>C.debug(e))},render=i=>{let a=`(${r}${formatDuration(i-t.phaseStartedAt)})`;n.text=t.phase===`running`?`Running migration ${e} ${a}...`:t.phase===`waitingOrRunning`?`Executing migration ${e} ${a}...`:`Waiting for a job of migration ${e} to start ${a}...`};return{onRunEvent:n=>{if(n.type===`finished`){t.finished(n.at,n.scriptStarted),t.startObserved||debug(`Could not observe when migration ${e} started running, so its run is not split into waiting and running.`);return}let r=n.type===`running`&&!t.startObserved;if(n.type===`waiting`&&t.waiting(n.at),n.type===`running`&&t.running(n.at),n.type===`unknown`&&t.unknown(n.at),render(n.at),n.type===`unknown`&&debug(`Migration ${e}: could not tell whether its script is running.`),r&&aside(()=>C.info(`Migration ${e} started running after waiting ${formatDuration(t.waitedMs)} for its job to start.`,{mode:`stream`})),n.type===`polled`&&C.verbose){let t=describeRunStatus(n.execution);t!==i&&debug(`Migration ${e}: ${t}.`),i=t}},onProgress:(e,t)=>{r=`${e}/${t} steps completed, `,render(performance.now())}}}const Zs=`MIGRATION_SCRIPT_BUNDLE_FAILED`;function isScriptBundleFailure(e){return e instanceof Error&&s(e).code===Zs}async function bundlePendingMigration(e,t){let{env:n,configDir:r,resumed:i,skipSteps:o}=t,s=e.scriptForm,c=e.diff.temporal??!1,u=e.diff.dateRepresentation??`legacy`;try{if(s?.kind!==`steps`)return await bundleMigrationScript(e.scriptPath,e.namespace,e.number,n,r,c,u);let t={sourceFile:e.scriptPath,namespace:e.namespace,migrationNumber:e.number,env:n,baseDir:r,temporal:c,dateDefault:u};return usesStepRunner(s,i)?await bundleMigrationSteps({...t,order:s.order,skipSteps:o,runnerJobFunctionName:migrationStepRunnerName(migrationWorkflowResourceName(e.namespace,e.number))}):await bundleSingleStepMigration({...t,step:a(s.order[0],`a steps script has at least one step`)})}catch(t){throw t instanceof Error&&!m(t)&&l(t,{code:Zs,context:{namespace:e.namespace,migrationNumber:e.number}}),t}}async function assertMigrationScriptsBundle(e,t,n,r){for(let i of e)i.hasScript&&await bundlePendingMigration(i,{env:n,configDir:r,resumed:inProgressRecordOf(i,t)!==void 0})}function inProgressRecordOf(e,t){let n=t[e.namespace];return n?.number===e.number?n:void 0}async function executeSingleMigration(e,t,n,r,i){let{client:a,workspaceId:o,invoker:s,env:c,configDir:l,appName:u,appId:d}=e,f=t.scriptForm;if(f?.kind===`steps`&&usesStepRunner(f,n!==void 0))return executeStepsMigration(e,t,f,n,r,i);let p=await bundlePendingMigration(t,{env:c,configDir:l,resumed:n!==void 0}),m=notifyAround(r),h={mayBeRecorded:!1},g;try{g=await executeMigrationAsWorkflow({client:a,workspaceId:o,code:p.bundledCode,namespace:t.namespace,migrationNumber:t.number,invoker:s,appName:u,appId:d,maintenanceMode:e.maintenanceMode,commandContext:e.commandContext,onBeforeStart:async()=>{await assertCheckpointUnchanged(e,t),h.mayBeRecorded=!0,await writeMigrationInProgress(a,o,t.namespace,{number:t.number,kind:`main`})},onExecutionStarted:e=>writeMigrationInProgress(a,o,t.namespace,{number:t.number,executionId:e,kind:`main`}),onRunEvent:i.onRunEvent})}catch(n){throw(h.mayBeRecorded&&!isMigrationOutcomeUnknown(n)?await releaseMigrationInProgress(e,t,n,m,`main`):void 0)??n}let _={namespace:t.namespace,migrationNumber:t.number,success:g.success,logs:g.logs,error:g.error};if(g.success)return _;let v=h.mayBeRecorded?await releaseMigrationInProgress(e,t,g.error??`Migration failed`,m,`main`):void 0;return v?{..._,failure:v}:(await removeRunResources(a,o,t.namespace,t.number),_)}function notifyAround(e){return(t,n,r)=>{e.stop(),C[t](n),r&&C.log(r),e.start()}}async function removeRunResources(e,t,n,r){try{await removeMigrationWorkflowResources(e,t,n,r)}catch(e){C.warn(`Could not remove the temporary resources of migration ${n}/${formatMigrationNumber(r)}: ${e instanceof Error?e.message:String(e)}. A later deploy removes them.`)}}async function updateMigrationLabel(e,t,n,r,i,a=!1,o=!1){return writeMetadataLabelsDirect(e,{trn:resourceTrn(t,`tailordb`,n),labels:{[Ja]:sanitizeMigrationLabel(r),...i?{[Ya]:i}:{},...a?{[$a]:sanitizeMigrationLabel(r)}:{},...o?{[eo]:sanitizeMigrationLabel(r)}:{}},remove:[...i?[]:[Ya],...o?[]:[eo],Xa,Qa]})}async function assertCheckpointUnchanged(e,t){let n=a(e.checkpoints.get(t.namespace),`every namespace with a migration to run has an expected checkpoint`),{namespace:r}=t,i;try{i=await fetchRemoteMigrationState(e.client,resourceTrn(e.workspaceId,`tailordb`,r))}catch(e){throw E({code:`MIGRATION_CHECKPOINT_UNVERIFIED`,message:`Could not confirm migration checkpoint ${r}/${describeMigrationCheckpoint(n.number)} before migration ${r}/${formatMigrationNumber(t.number)} started: `+(e instanceof Error?e.message:String(e)),suggestion:`Deploy again.`,cause:e})}if(isCheckpointStillOwned(i,n))return;let o=!matchesLocalMigrationHistory(i,e.localHistoryId),s=i.historyIdInvalid?` with a migration history label that cannot be read`:o?` in a different migration history`:``,command=t=>formatNamespaceMigrationHint({...e.commandContext,subcommand:t,namespace:r}),c=command([`sync`,formatMigrationNumber(n.number??0),...o?[`--force`]:[]]);throw E({code:`MIGRATION_CHECKPOINT_CONFLICT`,message:`Migration checkpoint ${r}/${describeMigrationCheckpoint(n.number)} changed to ${describeMigrationCheckpoint(i.number)}${s} before migration ${r}/${formatMigrationNumber(t.number)} started.`,suggestion:`Another deploy or a 'tailor tailordb migration' command changed it while this deploy ran. Run ${command([`status`])} to see it. `+(o?`If another deploy is running, wait for it to finish. To keep the migration history deployed to the workspace, deploy from a checkout of that history instead; to replace it with the local migration history on purpose, run ${c}, then deploy again.`:`If another deploy is running, wait for it to finish; otherwise return the namespace to the checkpoint with ${c}. Then deploy again.`),context:{namespace:r,migrationNumber:t.number,expectedCheckpoint:n.number,remoteCheckpoint:i.number,expectedHistoryId:n.historyId,remoteHistoryId:i.historyId,remoteHistoryIdInvalid:i.historyIdInvalid,localHistoryId:e.localHistoryId,historyIdMismatch:o}})}async function writeMigrationInProgress(e,t,n,r){let{executionId:i}=r;await writeMetadataLabelsDirect(e,{trn:resourceTrn(t,`tailordb`,n),labels:{[Xa]:inProgressLabel(r.number,r.kind),...i?{[Qa]:executionIdToLabel(i)}:{}},remove:i?void 0:[Qa]})}async function clearMigrationInProgress(e,t,n){await writeMetadataLabelsDirect(e,{trn:resourceTrn(t,`tailordb`,n),labels:{},remove:[Xa,Qa]})}async function clearMigrationCleanupRecord(e,t,n){await writeMetadataLabelsDirect(e,{trn:resourceTrn(t,`tailordb`,n),labels:{},remove:[eo]})}async function clearMaintenanceModeRecord(e,t,n){await writeMetadataLabelsDirect(e,{trn:resourceTrn(t,`tailordb`,n),labels:{},remove:[$a]})}function isMigrationPartiallyApplied(e){return m(e)&&e.code===`MIGRATION_PARTIALLY_APPLIED`}function isMigrationOutcomeUnknown(e){return m(e)&&e.code===`MIGRATION_OUTCOME_UNKNOWN`}function isMigrationStartRefused(e){return m(e)&&(e.code===`MIGRATION_CHECKPOINT_CONFLICT`||e.code===`MIGRATION_CHECKPOINT_UNVERIFIED`)}function isMigrationRunEnded(e){return m(e)&&e.code===`MIGRATION_PARTIALLY_APPLIED`&&e.context?.runEnded===!0}function withMaintenanceModeNote(e,t,n,r=`Until the migration completes`){if(!n)return e;let i=`${r}, the tables of namespace '${t}' stay in maintenance mode, as during the migration.`;return e?`${e} ${i}`:i}function partiallyAppliedError(e,t,n,r){let i=`${e.namespace}/${formatMigrationNumber(e.number)}`,a=t.failedSteps.length>0?` at ${t.failedSteps.join(`, `)}`:``,o=t.completedSteps.length>0?` after ${t.completedSteps.join(`, `)} completed`:` after some steps may have completed`;return E({code:`MIGRATION_PARTIALLY_APPLIED`,message:`Migration ${i} failed${a}${o}: ${n instanceof Error?n.message:String(n)}`,suggestion:withMaintenanceModeNote(m(n)&&n.suggestion?n.suggestion:`Fix the failing step in migrate.ts and deploy again; steps that already completed do not run again.`,e.namespace,r),context:{namespace:e.namespace,migrationNumber:e.number,completedSteps:t.completedSteps,failedSteps:t.failedSteps,...t.executionId?{executionId:t.executionId}:{},...t.runEnded?{runEnded:!0}:{}},cause:n})}function rolledBackError(e,t){let{namespace:n}=e,r=formatMigrationNumber(e.number-1),i=t instanceof Error&&!m(t)?s(t).suggestion:void 0;return E({code:`MIGRATION_ROLLED_BACK`,message:t instanceof Error?t.message:String(t),suggestion:`Migration ${n}/${formatMigrationNumber(e.number)} was rolled back to migration ${r} and is no longer in progress; any table the rollback could not revert is listed in a warning above. Fix the failure in migrate.ts and deploy again: the next deploy runs every step again from the beginning.`+(i?` ${i}`:``),context:{namespace:n,migrationNumber:e.number},cause:t})}function rollbackSkippedError(e,t,n,r,i){let{namespace:a}=e,resolveHint=e=>formatMigrationResolveHint(e,a,i),o=r.kind===`main`?`Its in-progress record could not be cleared, so its schema was not rolled back, and deploys stop before changing anything until the migration is settled. Once the data meets the migration's schema, run ${resolveHint(`complete`)} to keep what its script wrote; or run ${resolveHint(`rollback`)} to return to migration ${formatMigrationNumber(e.number-1)}.`:`Its in-progress record could not be cleared, so its schema was not rolled back and the migration stays in progress. Deploy again to resume it, or run ${resolveHint(`rollback`)} to roll it back without deploying.`;return E({code:`MIGRATION_PARTIALLY_APPLIED`,message:t instanceof Error?t.message:String(t),suggestion:withMaintenanceModeNote(o,a,n,`Until then`),context:{namespace:a,migrationNumber:e.number,rollbackSkipped:!0,...r.confirmed?{recordConfirmed:!0}:{}},cause:t})}function isRollbackSkippedWithRecord(e){return m(e)&&e.code===`MIGRATION_PARTIALLY_APPLIED`&&e.context?.rollbackSkipped===!0&&e.context.recordConfirmed===!0}function unreleasedRecordError(e,t,n,r,i){let{namespace:a}=e,o=formatMigrationNumber(e.number),s=formatMigrationNumber(e.number-1),command=e=>formatNamespaceMigrationHint({...i,subcommand:e,namespace:a}),c=formatMigrationResolveHint(`rollback`,a,i),l=n.confirmed?n.kind===`main`?`Its in-progress record could not be cleared, so its pre-migration schema stays in place, and deploys stop before changing anything until the record is cleared. Run ${c} to clear it, then fix the failure and deploy again.`:`Its in-progress record could not be cleared, so its pre-migration schema stays in place and the next deploy runs every step again. Fix the failure and deploy again, or run ${c} to clear the record without deploying.`:`Whether it is still recorded as in progress could not be confirmed, so its pre-migration schema stays in place. Run ${command([`status`])}: if it reports migration ${o} in progress, `+(n.kind===`main`?`run ${c} to clear the record, then fix the failure and deploy again; `:`fix the failure and deploy again, or run ${c} to clear the record without deploying; `)+`otherwise run ${command([`sync`,s])} to return the schema to migration ${s}, then deploy again.`,u=t instanceof Error?t.message:String(t);return E({code:`MIGRATION_PARTIALLY_APPLIED`,message:n.kind===`main`?`Migration ${a}/${o} failed: ${u}`:`Migration ${a}/${o} failed before any step completed: ${u}`,suggestion:withMaintenanceModeNote(l,a,r,`Until then`),context:{namespace:a,migrationNumber:e.number,...n.kind===`main`?{}:{completedSteps:[],failedSteps:[]}},cause:t})}function unconfirmedStartError(e,t,n){return E({code:`MIGRATION_PARTIALLY_APPLIED`,message:t.message,suggestion:withMaintenanceModeNote(t.suggestion,e.namespace,n),context:{namespace:e.namespace,migrationNumber:e.number,completedSteps:[],failedSteps:[]},cause:t})}async function releaseMigrationInProgress(e,t,n,r,i){try{await clearMigrationInProgress(e.client,e.workspaceId,t.namespace);return}catch(a){let o;try{o=await fetchRemoteMigrationState(e.client,resourceTrn(e.workspaceId,`tailordb`,t.namespace))}catch{return unreleasedRecordError(t,n,{confirmed:!1,kind:i},e.maintenanceMode,e.commandContext)}return!o.inProgressInvalid&&o.inProgress?.number!==t.number?void 0:(r(`warn`,`Could not clear the in-progress record of migration ${t.namespace}/${formatMigrationNumber(t.number)}: ${a instanceof Error?a.message:String(a)}.`),unreleasedRecordError(t,n,{confirmed:!0,kind:i},e.maintenanceMode,e.commandContext))}}async function executeStepsMigration(e,t,n,r,i,a){let{client:o,workspaceId:s,invoker:c,env:l,configDir:u,appName:d,appId:f}=e,p=r&&e.skipSteps?.get(t.namespace)||[],h=await bundlePendingMigration(t,{env:l,configDir:u,resumed:r!==void 0,skipSteps:p}),g=notifyAround(i),_=r!==void 0,v=r!==void 0,y;try{y=await executeMigrationStepsAsWorkflow({client:o,workspaceId:s,code:h.bundledCode,namespace:t.namespace,migrationNumber:t.number,invoker:c,appName:d,appId:f,maintenanceMode:e.maintenanceMode,order:n.order,skipSteps:p,inProgress:r,notify:g,onBeforeStart:async()=>{await assertCheckpointUnchanged(e,t),_=!0,await writeMigrationInProgress(o,s,t.namespace,{number:t.number,kind:`steps`})},onExecutionStarted:async e=>{v=!0,await writeMigrationInProgress(o,s,t.namespace,{number:t.number,executionId:e,kind:`steps`})},onProgress:a.onProgress,onRunEvent:a.onRunEvent})}catch(n){if(m(n)&&n.code===`MIGRATION_START_UNCONFIRMED`)throw unconfirmedStartError(t,n,e.maintenanceMode);if(isMigrationStartRefused(n))throw n;let r=m(n)&&n.code===`MIGRATION_EXECUTION_ACTIVE`;throw v||r?partiallyAppliedError(t,{completedSteps:[],failedSteps:[]},n,e.maintenanceMode):(_?await releaseMigrationInProgress(e,t,n,g,`steps`):void 0)??n}if(y.success)return{namespace:t.namespace,migrationNumber:t.number,success:!0,logs:y.logs};let b={namespace:t.namespace,migrationNumber:t.number,success:!1,logs:y.logs,error:y.error};if(y.stepsMayHaveCommitted||r)return{...b,failure:partiallyAppliedError(t,y,y.error??`Migration failed`,e.maintenanceMode)};let x=await releaseMigrationInProgress(e,t,y.error??`Migration failed`,g,`steps`);return x?{...b,failure:x}:b}async function executeMigrations(e,t,n,r={},i){let o=t.filter(e=>e.hasScript);if(o.length===0)return;let s=groupMigrationsByNamespace(o);for(let[t,o]of s){let s=a(e.machineUserByNamespace.get(t),`machine user for namespace '${t}' was not resolved`),c=Yr(pn,{namespace:e.authNamespace,machineUserName:s}),l={client:e.client,workspaceId:e.workspaceId,invoker:c,env:e.env,configDir:H.dirname(e.configPath),appName:e.appName,appId:e.appId,maintenanceMode:e.maintenanceMode,skipSteps:e.skipSteps,checkpoints:n,localHistoryId:e.migrationHistoryIds[t]??null,commandContext:migrationCommandContext({workspaceId:e.workspaceId,configPath:e.configPath,extraArgs:e.migrationRecoveryArgs})};C.info(`Using machine user: ${h.bold(s)} for namespace '${t}'`);for(let e of o){let t=`${e.namespace}/${formatMigrationNumber(e.number)}`,n=new ScriptRunTimer(e.namespace,e.number),a=spinner().start(`Executing migration ${t}...`),o;try{o=await executeSingleMigration(l,e,inProgressRecordOf(e,r),a,displayMigrationRun(t,n,a))}catch(e){throw a.fail(isMigrationOutcomeUnknown(e)?`Could not confirm the outcome of migration ${t}`:isMigrationStartRefused(e)?`Migration ${t} did not start`:`Migration ${t} failed`),e}finally{a.stop(),i?.recordScript(n)}if(o.success){let e=[...n.startObserved?[`waiting to start ${formatDuration(n.waitedMs)}`,`running ${formatDuration(n.ranMs)}`]:[],...n.unobservedMs>0?[`waiting to start or running ${formatDuration(n.unobservedMs)}`]:[]].join(`, `);a.succeed(`Migration ${t} completed successfully${e?` (${e})`:``}`),o.logs&&o.logs.trim()&&C.log(`Logs:\n${o.logs}`)}else throw a.fail(`Migration ${t} failed`),o.logs&&C.error(`Logs:\n${o.logs}`),o.failure??E({code:`MIGRATION_FAILED`,message:o.error??`Migration failed`})}}}function getMigrationMachineUser(e,t){if(e?.machineUser)return e.machineUser;if(t&&t.length>0)return t[0]}function resolveMigrationMachineUsers(e,t){let n=new Set(t.filter(e=>e.hasScript).map(({namespace:e})=>e));if(n.size===0)return;let r=e.application.authService;if(!r)throw E({code:`AUTH_CONFIG_REQUIRED`,message:`Auth configuration is required to execute migration scripts.`,suggestion:`Define auth with machine users in this config; migration scripts run as one of them.`});let i=Object.keys(r.config.machineUsers??{}),a=/* @__PURE__ */ new Map,o=[];for(let t of n){let n=e.config.db?.[t]?.migration,r=e.migrationMachineUserOverride??getMigrationMachineUser(n,i);r===void 0?o.push(t):a.set(t,r)}if(o.length>0)throw E({code:`MACHINE_USER_REQUIRED`,message:`No machine user available for migration execution in ${describeNamespaces(o)}.`,suggestion:`Either configure 'migration.machineUser' in db config or define machine users in auth config.`,context:{namespaces:o}});let s=r.config.name,c=[...a].filter(([,e])=>!i.includes(e)).map(([e,t])=>({namespace:e,machineUser:t}));if(c.length>0)throw E({code:`MACHINE_USER_NOT_FOUND`,message:`Machine user for migration execution is not defined in auth '${s}': ${c.map(({namespace:e,machineUser:t})=>`'${t}' (namespace '${e}')`).join(`, `)}.`,suggestion:undefinedMachineUserSuggestion(i,e.migrationMachineUserOverride),context:{authNamespace:s,machineUsers:c}});return{authNamespace:s,byNamespace:a}}function undefinedMachineUserSuggestion(e,t){return t===void 0?e.length>0?`Add the machine user to auth.machineUsers, or use one that is defined: ${e.join(`, `)}.`:`Add the machine user to auth.machineUsers.`:e.length>0?`Pass a machine user defined in auth.machineUsers to --machine-user (${e.join(`, `)}), or add '${t}' to auth.machineUsers.`:`Add '${t}' to auth.machineUsers.`}function describeNamespaces(e){let t=e.map(e=>`'${e}'`).join(`, `);return`${e.length===1?`namespace`:`namespaces`} ${t}`}async function assertPendingMigrationsRunnable(e){let{pendingMigrations:t,inProgressByNamespace:n,source:r}=e;await assertMigrationSkipSteps(e);let i=resolveMigrationMachineUsers(r,t);return await assertMigrationScriptsBundle(t,n,r.application.env,H.dirname(r.config.path)),i}function groupMigrationsByNamespace(e){let t=/* @__PURE__ */ new Map;for(let n of e){let e=t.get(n.namespace)??[];e.push(n),t.set(n.namespace,e)}return t}async function captureMigrationRestrictionState(e,t,n){let r=/* @__PURE__ */ new Map;for(let i of n){let n=await F(async(n,r)=>{let{tailordbTypes:a,nextPageToken:o}=await e.listTailorDBTypes({workspaceId:t,namespaceName:i,pageToken:n,pageSize:r});return[a,o]}),a=/* @__PURE__ */ new Map;for(let e of n){let t=e.schema?.settings;e.name&&a.set(e.name,{bulkUpsert:t?.bulkUpsert??!1,publishRecordEvents:t?.publishRecordEvents??!1,...t?.disableGqlOperations&&{disableGqlOperations:{create:t.disableGqlOperations.create??!1,update:t.disableGqlOperations.update??!1,delete:t.disableGqlOperations.delete??!1,read:t.disableGqlOperations.read??!1}},tailordbType:structuredClone(e)})}r.set(i,a)}return r}function getAffectedTableNames(e){let t=/* @__PURE__ */ new Set;for(let n of e.diff.changes)t.add(n.tableName);return t}function getPreMigrationTargetTableNames(e){let t=$s.load(e).tables;return new Set([...getAffectedTableNames(e)].filter(e=>e in t))}function namespacedTableKey(e,t){return`${e}/${t}`}function entriesOfNamespace(e,t){return e.filter(e=>e.request.namespaceName===t)}const Qs={created:/* @__PURE__ */ new Set,updated:/* @__PURE__ */ new Set,gqlPermissionsProcessed:/* @__PURE__ */ new Set,reset(){this.created.clear(),this.updated.clear(),this.gqlPermissionsProcessed.clear()}},$s={cache:/* @__PURE__ */ new Map,reset(){this.cache.clear()},load(e){let t=`${e.namespace}/${e.number}`,n=this.cache.get(t);if(!n){let r=reconstructSnapshotFromMigrations(e.migrationsDir,e.number);if(!r)throw E({code:`MIGRATION_HISTORY_INVALID`,message:`Cannot reconstruct snapshot for ${e.namespace} migration ${e.number}: no migrations found in ${e.migrationsDir}`});n=r,this.cache.set(t,n)}return n}};function generateMigrationPhaseManifest(e,t,n){let r=n.tailorDBInputs.find(e=>e.namespace===t)?.config.gqlOperations;return n.restricted?generateTailorDBTypeManifestFromSnapshot(e,{suppressRecordEvents:!0,suppressGqlMutations:!0,namespaceGqlOperations:r}):generateTailorDBTypeManifestFromSnapshot(e,{subscribed:e.settings?.publishEvents!==!1&&n.executorUsedTables.has(e.name),namespaceGqlOperations:r})}function buildSnapshotTypeManifest(e,t,n,r){let i=$s.load(e).tables[t];if(!i)return;let a=e.diff.changes.find(e=>e.kind===`table_scripts_modified`&&e.tableName===t);return generateMigrationPhaseManifest(r?createPreMigrationSnapshotType(i,r,a):i,e.namespace,n)}async function awaitAllSettledOrThrow(e){let t=(await Promise.allSettled(e.filter(e=>e!==void 0))).find(e=>e.status===`rejected`);if(t)throw t.reason}async function executeSingleMigrationPrePhase(e,t,n,r,i,a){let o=buildPreMigrationChangesMap([n]),s=buildPreMigrationIndexChangesMap([n]),c=getAffectedTableNames(n),tableKey=e=>namespacedTableKey(n.namespace,e),l=entriesOfNamespace(t.type.creates,n.namespace),u=entriesOfNamespace(t.type.updates,n.namespace),d=new Set(Qs.created);for(let t of l){let a=t.request.tailordbType?.name;if(!a||!c.has(a)||d.has(tableKey(a)))continue;let l=o.get(a),u=buildSnapshotTypeManifest(n,a,r,l);if(!u)continue;let f=structuredClone(t.request);f.tailordbType=u,l&&l.size>0&&f.tailordbType.schema?.fields&&applyPreMigrationFieldAdjustments(f.tailordbType.schema.fields,l);let p=s.get(a);p&&p.size>0&&f.tailordbType.schema?.indexes&&applyPreMigrationIndexAdjustments(f.tailordbType.schema.indexes,p),Qs.created.add(tableKey(a)),i.add(a),await e.createTailorDBType(f)}for(let t of l){let a=t.request.tailordbType?.name;if(!a||!c.has(a)||!d.has(tableKey(a)))continue;let l=o.get(a),u=buildSnapshotTypeManifest(n,a,r,l);if(!u)continue;let f=structuredClone(u);l&&l.size>0&&f.schema?.fields&&applyPreMigrationFieldAdjustments(f.schema.fields,l);let p=s.get(a);p&&p.size>0&&f.schema?.indexes&&applyPreMigrationIndexAdjustments(f.schema.indexes,p),Qs.updated.add(tableKey(a)),i.add(a),await e.updateTailorDBType({workspaceId:t.request.workspaceId,namespaceName:t.request.namespaceName,tailordbType:f})}for(let t of u){let a=t.request.tailordbType?.name;if(!a||!c.has(a))continue;let l=o.get(a),u=buildSnapshotTypeManifest(n,a,r,l);if(!u)continue;let d=structuredClone(t.request);d.tailordbType=u,l&&l.size>0&&d.tailordbType.schema?.fields&&applyPreMigrationFieldAdjustments(d.tailordbType.schema.fields,l);let f=s.get(a);f&&f.size>0&&d.tailordbType.schema?.indexes&&applyPreMigrationIndexAdjustments(d.tailordbType.schema.indexes,f),Qs.updated.add(tableKey(a)),i.add(a),await e.updateTailorDBType(d)}let f=new Set(Object.keys($s.load(n).tables)),p=entriesOfNamespace(t.gqlPermission.creates,n.namespace).filter(e=>f.has(e.name)&&!Qs.gqlPermissionsProcessed.has(tableKey(e.name))),m=entriesOfNamespace(t.gqlPermission.updates,n.namespace).filter(e=>f.has(e.name)&&!Qs.gqlPermissionsProcessed.has(tableKey(e.name)));if(p.length+m.length>0){let t=new Set(p.map(e=>e.name)),o=l.filter(e=>{let n=e.request.tailordbType?.name;return n&&t.has(n)&&!Qs.created.has(tableKey(n))});if(o.length>0)for(let t of o){let a=t.request.tailordbType?.name;if(!a)continue;let o=buildSnapshotTypeManifest(n,a,r);if(!o)continue;Qs.created.add(tableKey(a)),i.add(a);let s=structuredClone(t.request);s.tailordbType=o,await e.createTailorDBType(s)}for(let e of p)a.set(e.name,{});for(let e of m)e.previousPermission&&a.set(e.name,{previous:e.previousPermission});await awaitAllSettledOrThrow([...p.map(t=>e.createTailorDBGQLPermission(t.request)),...m.map(t=>e.updateTailorDBGQLPermission(t.request))]);for(let e of[...p.map(e=>e.name),...m.map(e=>e.name)])Qs.gqlPermissionsProcessed.add(tableKey(e))}}const ec={types:/* @__PURE__ */ new Set,gqlPermissions:/* @__PURE__ */ new Set,reset(){this.types.clear(),this.gqlPermissions.clear()}};function gqlPermissionUndoFromSnapshots(e,t=e,n){let r=/* @__PURE__ */ new Map;if(e.number<=0)return r;let i=reconstructSnapshotFromMigrations(e.migrationsDir,e.number-1);if(!i)return r;let a=$s.load(e).tables,o=$s.load(t).tables;for(let[e,t]of Object.entries(i.tables)){let i=a[e];if(!i)continue;let s=o[e]??i,c=si(t.permissions?.gql,s.permissions?.gql),l=n===void 0||si(t.permissions?.gql,i.permissions?.gql);c&&l&&!n?.has(e)||r.set(e,t.permissions?.gql?{previous:protoGqlPermission(t.permissions.gql)}:{})}return r}async function rollbackSingleMigrationAfterFailure(e,t,n,r,i,a){let o=`${t.namespace}/${formatMigrationNumber(t.number)}`,s;try{s=await rollbackSingleMigrationPrePhase(e,t,n,r,i,a)}catch(e){C.warn(`Failed to roll back migration ${o}: ${e instanceof Error?e.message:String(e)}`),s={tables:[...i],permissions:[...a.keys()]}}return s}async function executeSingleMigrationPostPhase(e,t,n,r,i){let a=buildPreMigrationChangesMap([n]),o=buildPreMigrationIndexChangesMap([n]),s=/* @__PURE__ */ new Set([...a.keys(),...o.keys()]),c=getAffectedTableNames(n);try{for(let a of entriesOfNamespace(t.type.creates,n.namespace)){let t=a.request.tailordbType?.name;if(!t||!c.has(t)||!s.has(t))continue;let o=buildSnapshotTypeManifest(n,t,r);o&&(i.add(t),await e.updateTailorDBType({workspaceId:a.request.workspaceId,namespaceName:a.request.namespaceName,tailordbType:o}))}for(let a of entriesOfNamespace(t.type.updates,n.namespace)){let t=a.request.tailordbType?.name;if(!t||!c.has(t)||!s.has(t))continue;let o=buildSnapshotTypeManifest(n,t,r);o&&(i.add(t),await e.updateTailorDBType({workspaceId:a.request.workspaceId,namespaceName:a.request.namespaceName,tailordbType:o}))}}catch(e){handleOptionalToRequiredError(e,[`This error occurred during post-migration phase. Please check your migration script.`,`Ensure all existing records have values for fields being changed to required.`])}}function acceptsMigrationWrites(e){let t=e.disableGqlOperations;return e.publishRecordEvents||e.bulkUpsert||t?.create!==!0||t.update!==!0||t.delete!==!0}const tc=`the GraphQL create, update, and delete operations and bulk upsert are disabled, and record events are not published`,nc=`Deploy again: once it finishes, the deploy writes the tables' configured settings back.`,rc=`Deploy again to run the migration again: a table left with the migration's pre-migration schema does not stop it. If that deploy stops with remote schema drift on these tables, check them in the workspace and delete or repair them by hand.`;function warnTablesLeftRestricted(e,t,n={}){let{recovery:r=nc,namesUnknown:i=!1}=n,a=t.filter(e=>e.tables.length>0);a.length===0?(C.warn(e),i&&C.log(r)):(C.warn(`${e} Still restricted (${tc}): ${a.map(e=>`namespace '${e.namespace}': ${e.tables.join(`, `)}`).join(`; `)}.`),C.log(r))}async function rewriteRestrictedTables(e,t){let{workspaceId:n,namespaceName:r,snapshot:i,input:a,executorUsedTables:o,settingsState:s,restricted:c,continueOnError:l=!1}=t,u={tailorDBInputs:[a],executorUsedTables:o,restricted:c},d,f=[],p=/* @__PURE__ */ new Set([...Object.keys(i.tables),...s?.keys()??[]]);for(let t of p)try{let a=i.tables[t],o=s?.get(t);if(s&&!o||c&&(!o||isMigrationRestricted(o)))continue;let l=a?generateMigrationPhaseManifest(a,r,u):o?.tailordbType?structuredClone(o.tailordbType):void 0;if(!l?.schema)continue;l.schema.settings??={};let d=l.schema.settings;c&&(d.bulkUpsert=!1,d.publishRecordEvents=!1,d.disableGqlOperations={create:!0,update:!0,delete:!0,read:o?.disableGqlOperations?.read??!1}),!c&&o&&(d.bulkUpsert=o.bulkUpsert,d.publishRecordEvents=o.publishRecordEvents,d.disableGqlOperations=o.disableGqlOperations?{...o.disableGqlOperations}:void 0),await e.updateTailorDBType({workspaceId:n,namespaceName:r,tailordbType:l})}catch(e){if(!l)throw e;f.push(t),d??=e instanceof Error?e:T(e)}return{failedTables:f,firstError:d}}function resolveMigrationSnapshotSettings(e,t,n){let r=/* @__PURE__ */ new Map;for(let[i,a]of Object.entries(e.tables)){let e=generateTailorDBTypeManifestFromSnapshot(a,{subscribed:!1,namespaceGqlOperations:t.config.gqlOperations}).schema?.settings;e&&r.set(i,{bulkUpsert:e.bulkUpsert??!1,publishRecordEvents:a.settings?.publishEvents??n.has(i),...e.disableGqlOperations&&{disableGqlOperations:{create:e.disableGqlOperations.create??!1,update:e.disableGqlOperations.update??!1,delete:e.disableGqlOperations.delete??!1,read:e.disableGqlOperations.read??!1}}})}return r}function releaseRecordedMaintenanceMode(e,t,n,r){let i=resolveMigrationSnapshotSettings(t,n,r);return new Map([...e].map(([e,t])=>{let n=i.get(e);return[e,n&&isMigrationRestricted(t)?n:t]}))}async function applyMigrationRestrictions(e,t,n,r,i,a){for(let[o,s]of t){let t=r.find(e=>e.namespace===o);t&&await rewriteRestrictedTables(e,{workspaceId:a,namespaceName:o,snapshot:s,input:t,executorUsedTables:i,settingsState:n.get(o)??/* @__PURE__ */ new Map,restricted:!0})}}async function restoreMigrationRestrictions(e,t,n,r,i,a,o){let c,u=[];for(let[o,s]of t){let t=r.find(e=>e.namespace===o);if(t)try{let r=await rewriteRestrictedTables(e,{workspaceId:a,namespaceName:o,snapshot:s,input:t,executorUsedTables:i,settingsState:n?.get(o),restricted:!1,continueOnError:!0});r.firstError&&(c??=r.firstError,u.push({namespace:o,tables:r.failedTables}))}catch(e){c??=e instanceof Error?e:T(e),u.push({namespace:o,tables:[]})}}if(c!==void 0){let e=s(c);throw l(c,{code:`MIGRATION_RESTORE_FAILED`,suggestion:[o?`${nc} Tables that stay restricted: ${describeUnrestored(u)}.`:`Tables whose settings could not be restored: ${describeUnrestored(u)}. Check these tables in the workspace and repair their settings before retrying the deployment.`,e.suggestion].filter(Boolean).join(` `),context:{...e.context,unrestored:u}})}}function readUnrestoredTables(e){if(!(e instanceof Error))return[];let t=s(e).context?.unrestored;return Array.isArray(t)?t:[]}function describeUnrestored(e){return e.map(e=>`namespace '${e.namespace}': ${e.tables.join(`, `)||`(unknown)`}`).join(`; `)}async function deletePlannedTables(e,t,n,r){let tableKey=e=>namespacedTableKey(n,e),i=entriesOfNamespace(t.gqlPermission.deletes,n).filter(e=>r.has(e.name)&&!ec.gqlPermissions.has(tableKey(e.name)));for(let t of i)await e.deleteTailorDBGQLPermission(t.request),ec.gqlPermissions.add(tableKey(t.name));let a=entriesOfNamespace(t.type.deletes,n).filter(e=>r.has(e.name)&&!ec.types.has(tableKey(e.name)));for(let t of a)await e.deleteTailorDBType(t.request),ec.types.add(tableKey(t.name))}async function rollbackSingleMigrationPrePhase(e,t,n,r,i,a){if(t.number<=0)return{tables:[...i],permissions:[]};if(i.size===0&&a.size===0)return{tables:[],permissions:[]};let o=reconstructSnapshotFromMigrations(t.migrationsDir,t.number-1);if(!o)return C.warn(`Cannot roll back migration ${t.namespace}/${formatMigrationNumber(t.number)}: prior snapshot (migration ${formatMigrationNumber(t.number-1)}) could not be reconstructed. Leaving schema as-is; manual repair may be required.`),{tables:[...i],permissions:[...a.keys()]};C.warn(`Migration ${t.namespace}/${formatMigrationNumber(t.number)} failed; rolling back its pre-migration schema changes.`);let s=[...i].flatMap(e=>{let t=o.tables[e];return t?[{tableName:e,priorTable:t}]:[]}),c=[...i].filter(e=>!o.tables[e]),l=[],u=[];for(let{tableName:i,priorTable:a}of s)try{let i=generateMigrationPhaseManifest(a,t.namespace,r);await e.updateTailorDBType({workspaceId:n,namespaceName:t.namespace,tailordbType:i})}catch(e){l.push(i),C.warn(`Failed to roll back table '${i}' in namespace '${t.namespace}': ${e instanceof Error?e.message:String(e)}`)}for(let[r,i]of a)if(o.tables[r])try{await restoreGqlPermission(e,n,t.namespace,r,i)}catch(e){u.push(r),C.warn(`Failed to roll back the GraphQL permission of table '${r}' in namespace '${t.namespace}': ${e instanceof Error?e.message:String(e)}`)}for(let r of c)try{await e.deleteTailorDBGQLPermission({workspaceId:n,namespaceName:t.namespace,typeName:r}).catch(()=>void 0),await e.deleteTailorDBType({workspaceId:n,namespaceName:t.namespace,tailordbTypeName:r})}catch(e){if(At(e))continue;l.push(r),C.warn(`Failed to roll back table '${r}' in namespace '${t.namespace}': ${e instanceof Error?e.message:String(e)}`)}return{tables:[...new Set(l)],permissions:[...new Set(u)]}}async function restoreGqlPermission(e,t,n,r,i){let a={workspaceId:t,namespaceName:n,typeName:r};if(!i.previous)await e.deleteTailorDBGQLPermission(a).catch(e=>{if(!At(e))throw e});else try{await e.updateTailorDBGQLPermission({...a,permission:i.previous})}catch(t){if(!At(t))throw t;await e.createTailorDBGQLPermission({...a,permission:i.previous})}}function migrationFileStatesEqual(e,t){let n=Object.keys(e).toSorted(),r=Object.keys(t).toSorted();return n.length===r.length&&n.every((n,i)=>n===r[i]&&e[n]===t[n])}const ic={running:`its run is still running`,succeeded:`its run succeeded`,failed:`its run failed`,canceled:`its run was canceled`,not_started:`its run did not start`,unknown:`whether its run succeeded could not be confirmed`};async function assertMainRunSettled(e,t,n,r,i){let a=r.inProgress;if(a?.kind!==`main`||isStaleMigrationInProgress(r))return;let o=await readMigrationRunStatus(e,t,n,a),s=`${n}/${formatMigrationNumber(a.number)}`,c=migrationWorkflowResourceName(n,a.number),l=formatMigrationExecutionsHint(n,a.number,i),u=settlingResolution(o),d=u===`complete`?`Run ${formatMigrationResolveHint(u,n,i)} to apply the migration's schema without running its script again, then deploy again.`:u===`rollback`?`Run ${formatMigrationResolveHint(u,n,i)} to return to migration ${formatMigrationNumber(a.number-1)}, then deploy again to run the migration again.`:o===`running`?`Wait until ${l} shows that the run finished, then deploy again to see how to settle it.`:`Check the run with ${l}. ${describeMainRunSettlement(n,i)}`;throw E({code:`MIGRATION_OUTCOME_UNSETTLED`,message:`An earlier deploy did not settle the run of migration ${s}: ${ic[o]}.`,suggestion:d,...u?{next:{command:`tailor`,args:migrationResolveArgs(u,n,i)}}:{},context:{namespace:n,migrationNumber:a.number,workflowName:c,...a.executionId?{executionId:a.executionId}:{},runStatus:o}})}function checkpointRepairInProgressError(e){return E({code:`MIGRATION_IN_PROGRESS_CONFLICT`,message:`A migration is in progress in namespace "${e}", so its checkpoint cannot be repaired.`,suggestion:`From a checkout of the migration history that started the migration, finish a multi-step migration with a deploy, or settle the migration with 'tailor tailordb migration resolve' first.`})}async function checkMigrationInProgress(e){let{client:t,workspaceId:n,namespace:r,state:i,next:a,commandContext:o}=e;if(i.inProgressInvalid)throw E({code:`MIGRATION_IN_PROGRESS_INVALID`,message:`The in-progress migration recorded for namespace "${r}" cannot be read.`,suggestion:`The namespace metadata was edited outside the SDK. Restore the in-progress labels it recorded before deploying again.`});let s=i.inProgress;if(!s)return{kind:`none`};if(isStaleMigrationInProgress(i))return{kind:`stale`,migrationNumber:s.number};let c=`${r}/${formatMigrationNumber(s.number)}`;if(await assertMainRunSettled(t,n,r,i,o),a?.number!==s.number)throw E({code:`MIGRATION_IN_PROGRESS_INVALID`,message:`Migration ${c} is in progress, but the next pending migration is ${a?formatMigrationNumber(a.number):`none`}.`,suggestion:`Deploy the migration history that started the migration and let it complete first.`});if(a.scriptForm?.kind!==`steps`)throw E({code:`MIGRATION_IN_PROGRESS_INVALID`,message:`Migration ${c} was partially applied by its steps, but its migrate.ts no longer exports \`steps\`.`,suggestion:"Keep the migration as `steps` so the deploy can finish it; steps that already completed do not run again."});return{kind:`resume`,inProgress:s}}async function validateMigrationsInProgress(e,t,n,r,i,a){let o=r[0];if(o!==void 0)throw checkpointRepairInProgressError(o);let s={inProgressMigrations:{},staleInProgress:[]};for(let[r,o]of n){let n=await checkMigrationInProgress({client:e,workspaceId:t,namespace:r,state:o,next:i.find(e=>e.namespace===r),commandContext:a});n.kind===`stale`&&s.staleInProgress.push({namespace:r,migrationNumber:n.migrationNumber}),n.kind===`resume`&&(s.inProgressMigrations[r]=n.inProgress)}return s}function assertCheckpointsInLocalHistory(e,t){if(e.length!==0){C.error(`Remote migration checkpoint is not in the local migration history:`);for(let t of e)C.log(` ${t.namespace}: ${formatMigrationNumber(t.remoteMigrationNumber)}`);throw C.newline(),logRebaselinePendingGuidance(e),E({code:`MIGRATION_CHECKPOINT_UNKNOWN`,message:`Remote migration checkpoint verification failed`,suggestion:[...missingCheckpointRecoveryHints(e,t),...e.some(e=>e.rebaselinePending)?[`For a namespace that fell behind before 'migration rebaseline' ran, follow the recovery steps above.`]:[]].join(`
|
|
101
101
|
`),context:{namespaces:e.map(({namespace:e,remoteMigrationNumber:t,rebaselinePending:n,localLatestMigration:r,historyIdMismatch:i})=>({namespace:e,remoteCheckpoint:t,localLatestMigration:r,historyIdMismatch:i,...n&&{replacedLatestMigration:n.replacedLatestMigration}}))}})}}async function validateAndDetectMigrations(e,t,n,r,i,o,s){let c=H.dirname(r.path),l=migrationCommandContext({workspaceId:t,configPath:r.path,extraArgs:s}),u=getNamespacesWithMigrations(r,c),d=new Map(u.map(({namespace:e,migrationsDir:t})=>[e,t])),f=[],p=[],m={inProgressMigrations:{},staleInProgress:[]},h=[],g=Object.create(null),_=/* @__PURE__ */ new Map,v=/* @__PURE__ */ new Map,y=Object.create(null),b=/* @__PURE__ */ new Map,x=Object.create(null);if(u.length>0){for(let{namespace:e,migrationsDir:t}of u){assertValidMigrationFiles(t,e,r.path);let n=reconstructSnapshotFromMigrations(t)?.rebaseline;_.set(e,n),g[e]=n?.historyId??null}if(!i){let i=await checkMigrationDiffs(n,u);if(i.some(e=>e.hasDiff))throw C.error(`Schema changes detected that are not in migration files:`),C.log(formatMigrationCheckResults(i)),C.newline(),C.info(`Run 'tailor tailordb migration generate' to create migration files.`),C.info(`Or use '--no-schema-check' to skip this check.`),E({code:`MIGRATION_SCHEMA_CHECK_FAILED`,message:`Schema migration check failed`,suggestion:`Run 'tailor tailordb migration generate' to create migration files, or use --no-schema-check to skip this check.`});let a=await verifyRemoteSchema(e,t,u,r,o,{acceptUnfinishedRemovals:!0,acceptInterruptedMigration:!0});if(p=a.flatMap(e=>e.checkpointRepair?[{namespace:e.namespace,...e.checkpointRepair}]:[]),h=a.filter(e=>e.checkpointRepair&&(e.migrationInProgress||e.migrationInProgressInvalid)).map(e=>e.namespace),assertCheckpointsInLocalHistory(a.flatMap(e=>e.checkpointMissingLocal?[{...e,localLatestMigration:e.localLatestMigration??null,historyIdMismatch:e.historyIdMismatch??!1}]:[]),l),a.some(e=>e.hasDrift)){for(let n of a)await assertMainRunSettled(e,t,n.namespace,{number:n.remoteMigrationNumber,inProgress:n.migrationInProgress??null},l);throw C.error(`Remote schema drift detected:`),C.log(formatRemoteVerificationResults(a)),C.newline(),logRemoteDriftGuidance(l,a),C.newline(),C.info(`Use '--no-schema-check' to skip this check (not recommended).`),E({code:`MIGRATION_REMOTE_DRIFT`,message:`Remote schema verification failed`,suggestion:unsetCheckpointDriftHints(a,l).join(`
|
|
102
|
-
`)||void 0})}for(let e of p)C.warn(`Remote migration checkpoint for ${e.namespace} will be reset to 0000 after confirmation (${formatMigrationNumber(e.from)} → 0000); the remote schema already matches the local baseline.`);for(let e of a)e.unfinishedRemovals&&(b.set(e.namespace,e.unfinishedRemovals),e.unfinishedRemovals.length!==0&&C.warn(`An earlier deploy committed migration ${e.namespace}/${formatMigrationNumber(e.remoteMigrationNumber)} but did not delete the tables it removed: ${e.unfinishedRemovals.join(`, `)}. They will be deleted after confirmation.`));for(let{namespace:e,interruptedMigration:t}of a)t!==void 0&&(x[e]=t,C.info(`An earlier deploy left the pre-migration schema or maintenance mode of migration ${e}/${formatMigrationNumber(t)} in place without recording it as in progress; this deploy runs it again from the start.`))}let s=new Map(p.map(e=>[e.namespace,e.to])),c=/* @__PURE__ */ new Map;f=await detectPendingMigrations(e,t,u,r.path,s,c),i&&assertCheckpointsInLocalHistory([...c].flatMap(([e,t])=>{let n=locateRemoteCheckpoint(t,a(d.get(e),`every namespace with a remote state has a migrations directory`),_.get(e));return n.kind===`outside`?[{namespace:e,remoteMigrationNumber:n.number,localLatestMigration:n.localLatestMigration,historyIdMismatch:n.historyIdMismatch,...n.rebaselinePending?{rebaselinePending:n.rebaselinePending}:{}}]:[]}),l),m=await validateMigrationsInProgress(e,t,c,h,f,l);for(let e of p)v.set(e.namespace,{number:e.to,historyId:e.toHistoryId});for(let[e,t]of c)v.set(e,{number:t.number,historyId:t.historyId}),t.maintenanceModeCheckpoint!==null&&(y[e]=t.maintenanceModeCheckpoint);if(f.length>0){C.newline();let e=f.filter(e=>e.hasScript),t=f.filter(e=>!e.hasScript);C.info(`${f.length} pending migration(s) will be applied:`),t.length>0&&C.info(` • ${t.length} schema change(s) (applied automatically with schema deployment)`,{mode:`plain`}),e.length>0&&C.info(` • ${e.length} data migration(s) (requires migration script execution)`,{mode:`plain`})}}return{pendingMigrations:f,checkpointRepairs:p,namespacesWithMigrations:u,migrationFileState:captureMigrationFileState(u),migrationHistoryIds:g,checkpoints:v,...m,maintenanceModeCheckpoints:y,unfinishedRemovals:b,interruptedMigrations:x}}function deployCommandContext(e){return migrationCommandContext({workspaceId:e.workspaceId,configPath:e.config.path,extraArgs:e.migrationRecoveryArgs})}async function reconcileMigrationLabels(e,t,n,r,i){for(let{namespace:a,migrationsDir:o}of n){if(getMigrationFiles(o).length===0)continue;let n=getLatestMigrationNumber(o),s=r[a]??null,c=await fetchRemoteMigrationState(e,resourceTrn(t,`tailordb`,a)).catch(()=>null),l=c?.number??null;c&&l===n&&c.historyId===s||(c&&locateRemoteCheckpoint(c,o,reconstructSnapshotFromMigrations(o,0)?.rebaseline).kind===`outside`?C.warn(`Migration checkpoint of namespace ${a} is ${describeMigrationCheckpoint(l)}, which is not in the local migration history, so it was left unchanged. Run ${formatNamespaceMigrationHint({...i,subcommand:[`status`],namespace:a})} to compare.`):(await updateMigrationLabel(e,t,a,n,s??void 0),c?C.info(`Migration label for namespace ${a} reconciled: ${describeMigrationCheckpoint(l)} → ${formatMigrationNumber(n)}.`):C.info(`Migration label for namespace ${a} reconciled to ${formatMigrationNumber(n)}.`)))}}async function buildMigrationContextForScripts(e,t,n,r,i){let a=await kt(e,t.workspaceId,t.application.env);return{client:e,workspaceId:t.workspaceId,authNamespace:n.authNamespace,machineUserByNamespace:n.byNamespace,env:a,configPath:t.config.path,...t.migrationRecoveryArgs?{migrationRecoveryArgs:t.migrationRecoveryArgs}:{},appName:t.application.name,appId:t.application.id,maintenanceMode:r,skipSteps:t.migrationSkipSteps,migrationHistoryIds:i}}async function validateTailorDBMigrationState(e,t){let{context:n}=t;if(n.migrationTestBaselines){let e=captureMigrationFileState(getNamespacesWithMigrations(n.config,H.dirname(n.config.path)));if(!migrationFileStatesEqual(n.migrationFileState,e))throw E({code:`DEPLOY_PLAN_STALE`,message:`Migration files changed after deployment planning.`,suggestion:`Run the migration test again to create a fresh plan.`});return{pendingMigrations:[],checkpointRepairs:[],namespacesWithMigrations:[],migrationFileState:e,migrationHistoryIds:{},checkpoints:/* @__PURE__ */ new Map,inProgressMigrations:{},staleInProgress:[],maintenanceModeCheckpoints:{},unfinishedRemovals:/* @__PURE__ */ new Map,interruptedMigrations:{},migrationMachineUsers:void 0}}let r=/* @__PURE__ */ new Map;for(let e of n.tailorDBInputs)r.set(e.namespace,e.types);let i=await validateAndDetectMigrations(e,n.workspaceId,r,n.config,n.noSchemaCheck,n.tailorDBInputs,n.migrationRecoveryArgs),a=n.checkpointRepairs;if(a.length!==i.checkpointRepairs.length||i.checkpointRepairs.some(e=>!a.some(t=>t.namespace===e.namespace&&t.from===e.from&&t.fromHistoryId===e.fromHistoryId&&t.toHistoryId===e.toHistoryId)))throw E({code:`DEPLOY_PLAN_STALE`,message:`Remote migration checkpoint repair changed after deployment planning.`,suggestion:`Run the deployment again to review the updated repair.`});for(let[e,n]of i.unfinishedRemovals){let r=n.filter(n=>!t.changeSet.type.deletes.some(t=>t.request.namespaceName===e&&t.name===n));if(r.length>0)throw E({code:`DEPLOY_PLAN_STALE`,message:`Tables to delete in namespace ${e} changed after deployment planning: ${r.join(`, `)}.`,suggestion:`Run the deployment again to review the deletion.`})}if(!migrationFileStatesEqual(n.migrationFileState,i.migrationFileState))throw E({code:`DEPLOY_PLAN_STALE`,message:`Migration files changed after deployment planning.`,suggestion:`Run the deployment again to create a fresh plan.`});return await assertMigrationSkipSteps({client:e,workspaceId:n.workspaceId,requested:selectSkipStepsOfNamespaces(n.migrationSkipSteps,n.tailorDBInputs.map(e=>e.namespace)),pendingMigrations:i.pendingMigrations,inProgressByNamespace:i.inProgressMigrations}),{...i,migrationMachineUsers:resolveMigrationMachineUsers(n,i.pendingMigrations)}}async function preflightTailorDB(e,t){await validateTailorDBMigrationState(e,t)}async function reapplyPrePhaseAfterPostPhaseFailure(e,t,n,r,i,a){try{await executeSingleMigrationPrePhase(e,t,n,r,i,a)}catch(e){C.warn(`Could not return migration ${n.namespace}/${formatMigrationNumber(n.number)} to its pre-migration schema: ${e instanceof Error?e.message:String(e)}. The original migration error is reported below.`)}}async function readRecordState(e,t,n){try{let r=await fetchRemoteMigrationState(e,resourceTrn(t,`tailordb`,n.namespace));return r.inProgressInvalid||(r.number??(n.number===1?0:null))!==n.number-1?`unknown`:r.inProgress===null?`cleared`:r.inProgress.number===n.number?`in-progress`:`unknown`}catch{return`unknown`}}async function clearRolledBackRecord(e,t,n,r){let{namespace:i}=n;try{return await clearMigrationInProgress(e,t,i),`cleared`}catch(a){let o=await readRecordState(e,t,n);return o===`cleared`||C.warn(`Could not clear the in-progress record of migration ${i}/${formatMigrationNumber(n.number)}: ${a instanceof Error?a.message:String(a)}. Its schema is left as it is, the migration stays in progress, and its tables stay in maintenance mode; `+(r===`main`?`settle it with 'tailor tailordb migration resolve'.`:`deploy again to resume it.`)),o}}function keepMigrationTablesRestricted(e,t,n,r,i){let a=n.get(e),o=/* @__PURE__ */ new Set([...Object.keys(a?.tables??{}),...Object.keys(Js.load(t).tables),...getTablesDeletedAfterCheckpoint(t.diff)]);return a&&(n.set(e,{...a,tables:{}}),r.set(e,new Map([...r.get(e)??[]].filter(([e])=>!o.has(e))))),restrictedByDeploy(e,o,i)}function describeSkippedTables(e){return e.length>0?`Restricted tables: ${e.join(`, `)}. `:``}function restrictedByDeploy(e,t,n){return n.maintenanceMode?[...new Set(t)].filter(t=>{let r=n.captured.get(e)?.get(t);return n.resumed||!r||acceptsMigrationWrites(r)||n.touched.has(t)}).toSorted():[]}function skippedRestorationTables(e,t,n,r){return restrictedByDeploy(e,[...Object.keys(t.get(e)?.tables??{}),...n.get(e)?.keys()??[]],r)}async function clearRecordAfterRelease(e,t,n){try{await clearMaintenanceModeRecord(e,t,n)}catch(e){C.warn(`Namespace '${n}' left maintenance mode, but its record could not be removed: ${T(e).message}. A later deploy removes it.`)}}async function findUnownedMigrationCheckpoints(e,t,n,r){let i=/* @__PURE__ */ new Map;for(let[a,o]of n)try{let n=await fetchRemoteMigrationState(e,resourceTrn(t,`tailordb`,a));if(isCheckpointStillOwned(n,o))continue;i.set(a,E({code:`MIGRATION_CHECKPOINT_CONFLICT`,message:`Migration checkpoint ${a}/${describeMigrationCheckpoint(o.number)} advanced concurrently to ${describeMigrationCheckpoint(n.number)}. ${r}`}))}catch(e){i.set(a,E({code:`MIGRATION_CHECKPOINT_UNVERIFIED`,message:`Could not verify ownership of migration checkpoint ${a}/${describeMigrationCheckpoint(o.number)} before restoring table settings: ${e instanceof Error?e.message:String(e)}. ${r}`}))}return i}async function applyTailorDB(e,t,n=`create-update`,r={}){let{changeSet:i}=t;if(n===`create-update`)return applyCreateUpdate(e,t,r);n===`delete-resources`?(await Promise.all(i.gqlPermission.deletes.map(t=>e.deleteTailorDBGQLPermission(t.request))),await Promise.all(i.type.deletes.map(t=>e.deleteTailorDBType(t.request)))):await Promise.all(i.service.deletes.map(t=>e.deleteTailorDBService(t.request)))}async function applyCreateUpdate(e,t,n){let{changeSet:r,context:i}=t,a=i.config.maintenanceMode??`migration`,o={tailorDBInputs:i.tailorDBInputs,executorUsedTables:i.executorUsedTables,restricted:a!==!1},s=await validateTailorDBMigrationState(e,t),{pendingMigrations:c,checkpointRepairs:l,namespacesWithMigrations:u,migrationHistoryIds:d,staleInProgress:f,maintenanceModeCheckpoints:p,unfinishedRemovals:m,migrationMachineUsers:h}=s,g=c.filter(e=>e.hasScript),_=h?await buildMigrationContextForScripts(e,i,h,o.restricted,d):void 0;for(let t of l)await updateMigrationLabel(e,i.workspaceId,t.namespace,t.to,t.toHistoryId),C.info(`Migration checkpoint for namespace ${t.namespace} reset: ${formatMigrationNumber(t.from)} → 0000.`);for(let t of f)await clearMigrationInProgress(e,i.workspaceId,t.namespace),await removeRunResources(e,i.workspaceId,t.namespace,t.migrationNumber);Ys.reset();for(let[t,n]of m)await deletePlannedTables(e,r,t,new Set(n)),await clearCleanupRecord(e,i.workspaceId,t);let v=new Set(c.map(e=>e.namespace)),y;c.length>0?y=await applyWithMigrations({client:e,changeSet:r,migrationContext:i,phaseSettings:o,validation:s,migrationsRequiringScripts:g,migrationCtx:_,holdMaintenanceMode:a===`deploy`?n.holdMaintenanceMode:void 0}):await applyWithoutMigrations(e,r),u.length>0&&c.length===0&&await reconcileMigrationLabels(e,i.workspaceId,u,d,deployCommandContext(i));for(let t of Object.keys(p))v.has(t)||await clearRecordAfterRelease(e,i.workspaceId,t);return y}const ec=[`Run 'tailor tailordb migration generate' to create migration files.`,`Migration scripts allow you to handle existing data before applying the schema change.`];async function applyWithMigrations(e){let{holdMaintenanceMode:t,...n}=e,{client:r,changeSet:i,migrationContext:o,phaseSettings:c,validation:u}=e;qs.reset(),Js.reset();let d=new Set(u.pendingMigrations.map(e=>e.namespace)),f=await captureMigrationRestrictionState(r,o.workspaceId,d);await executeServicesCreation(r,i);let p=indexPendingMigrations(u.pendingMigrations),m=loadPreMigrationSnapshots(p.firstByNamespace),h={...n,migratingNamespaces:d,pending:p,preMigrationSnapshots:m,restrictionState:f,settingsBeforeMaintenanceMode:releaseRecordedMaintenanceModes(o,p.firstByNamespace,m,f,u.maintenanceModeCheckpoints),timeline:c.restricted?new MaintenanceTimeline:void 0},g=await applyChangesBeforeMigrations(h);h.migrationsRequiringScripts.length>0&&(C.info(`Executing ${h.migrationsRequiringScripts.length} data migration(s)...`),C.newline());let _={snapshots:new Map(h.preMigrationSnapshots),settings:new Map(h.settingsBeforeMaintenanceMode),checkpoints:new Map([...p.firstByNamespace.keys()].map(e=>[e,a(u.checkpoints.get(e),`validation read the checkpoint of every namespace with pending migrations`)])),skipped:/* @__PURE__ */ new Set},v={reached:/* @__PURE__ */ new Set,partial:/* @__PURE__ */ new Map,unrolledBack:[],touchedTables:[],recordedNamespaces:/* @__PURE__ */ new Set},y=await runPendingMigrations(h,_,v);h.timeline?.enter(`restore`);let b=await verifyRestorationCheckpoints(h,_,v,y),{restorationFailures:x}=b,S=b.failure??await applyLocalDefinitions(h,_);keepPartialMigrationsRestricted(h,_,v);let w=S?void 0:t,T=[];if(w?(h.timeline?.enter(`remainingDeploy`),w(e=>releaseHeldMaintenanceMode(h,_,v,e))):T=await restoreAfterMigrations(h,_,v,{failure:S,restorationFailures:x}),warnIncompleteRollbacks(h,_,v,T),S){h.timeline?.finish();let{error:e}=S;throw e instanceof Error&&Object.keys(x).length>0?l(e,{causes:{...s(e).causes,...x}}):e}let E=w?void 0:finishMaintenance(h);return await applyDeferredGqlPermissions(h,g),await applyRemainingDeletions(h),await Promise.all([...i.type.creates,...i.type.updates,...i.type.unchanged].flatMap(e=>e.metaRequest?[writeMetadataLabels(r,e.metaRequest)]:[])),E}function indexPendingMigrations(e){let t={firstByNamespace:/* @__PURE__ */ new Map,lastByNamespace:/* @__PURE__ */ new Map,deletedTables:/* @__PURE__ */ new Map,snapshotTableKeys:/* @__PURE__ */ new Set};for(let n of e){let e=t.firstByNamespace.get(n.namespace);(!e||n.number<e.number)&&t.firstByNamespace.set(n.namespace,n);let r=t.lastByNamespace.get(n.namespace);(!r||n.number>r.number)&&t.lastByNamespace.set(n.namespace,n);let i=t.deletedTables.get(n.namespace)??/* @__PURE__ */ new Set;for(let e of getTablesDeletedAfterCheckpoint(n.diff))i.add(e);t.deletedTables.set(n.namespace,i);for(let e of Object.keys(Js.load(n).tables))t.snapshotTableKeys.add(`${n.namespace}/${e}`)}return t}function loadPreMigrationSnapshots(e){let t=/* @__PURE__ */ new Map;for(let[n,r]of e){let e=reconstructSnapshotFromMigrations(r.migrationsDir,r.number-1);if(!e)throw E({code:`MIGRATION_HISTORY_INVALID`,message:`Cannot reconstruct the schema state before migration ${formatMigrationNumber(r.number)} for namespace "${n}"`});t.set(n,e)}return t}function releaseRecordedMaintenanceModes(e,t,n,r,i){let a=new Map(r);for(let[o,s]of t){let t=e.tailorDBInputs.find(e=>e.namespace===o),c=r.get(o),l=n.get(o);i[o]===s.number-1&&t&&c&&l&&a.set(o,releaseRecordedMaintenanceMode(c,l,t,e.executorUsedTables))}return a}function migrationWithEarlierPrePhase(e,t){return e.inProgressMigrations[t]?.number??e.interruptedMigrations[t]}function isOutsideMigrations(e,t){return t!==void 0&&!e.migratingNamespaces.has(t)}async function applyChangesBeforeMigrations(e){let{client:t,changeSet:n,migrationContext:r,phaseSettings:i,pending:a}=e,o=new Set([...n.gqlPermission.creates,...n.gqlPermission.updates].filter(t=>{let n=t.request.namespaceName;return r.noSchemaCheck&&n!==void 0&&e.migratingNamespaces.has(n)&&!a.snapshotTableKeys.has(`${n}/${t.name}`)}).map(e=>`${e.request.namespaceName}/${e.name}`));try{for(let r of n.type.creates){let n=r.request.namespaceName;if(isOutsideMigrations(e,n)){await t.createTailorDBType(r.request);continue}let o=r.request.tailordbType?.name;if(!n||!o)continue;let s=e.preMigrationSnapshots.get(n)?.tables[o];s&&(a.deletedTables.get(n)?.has(o)||(qs.created.add(namespacedTableKey(n,o)),await t.createTailorDBType({workspaceId:r.request.workspaceId,namespaceName:n,tailordbType:generateMigrationPhaseManifest(s,n,i)})))}for(let r of n.type.updates)isOutsideMigrations(e,r.request.namespaceName)&&await t.updateTailorDBType(r.request)}catch(e){handleOptionalToRequiredError(e,ec)}return await Promise.all([...n.gqlPermission.creates.filter(t=>isOutsideMigrations(e,t.request.namespaceName)).map(e=>t.createTailorDBGQLPermission(e.request)),...n.gqlPermission.updates.filter(t=>isOutsideMigrations(e,t.request.namespaceName)).map(e=>t.updateTailorDBGQLPermission(e.request))]),o}async function runPendingMigrations(e,t,n){let{client:r,migrationContext:i}=e;try{e.timeline?.enter(`restrict`),e.phaseSettings.restricted&&await applyMigrationRestrictions(r,e.preMigrationSnapshots,e.restrictionState,i.tailorDBInputs,i.executorUsedTables,i.workspaceId);for(let r of e.validation.pendingMigrations)await runMigration(e,r,t,n);e.migrationsRequiringScripts.length>0&&(C.newline(),C.success(`All data migrations completed successfully.`));return}catch(e){return{error:e}}}async function runMigration(e,t,n,r){r.reached.add(t);let i=/* @__PURE__ */ new Set;r.touchedTables.push({namespace:t.namespace,tables:i});let a=e.validation.inProgressMigrations[t.namespace]?.number===t.number,o=usesStepRunner(t.scriptForm,a),s={migration:t,attemptedTables:i,inProgress:a,resumesPrePhase:migrationWithEarlierPrePhase(e.validation,t.namespace)===t.number,runsSteps:o,runsMain:t.hasScript&&!o,rollsBackOnFailure:o&&t.scriptForm?.kind===`steps`&&t.scriptForm.rollbackOnFailure===!0,gqlPermissionUndo:/* @__PURE__ */ new Map};await runPreMigrationPhase(e,s,n,r),await runPostMigrationPhase(e,s,n,r),await commitMigration(e,s,n,r)}async function runPreMigrationPhase(e,t,n,r){let{client:i,changeSet:a,phaseSettings:o,migrationCtx:s}=e,{migration:c,attemptedTables:l,inProgress:u,rollsBackOnFailure:d,gqlPermissionUndo:f}=t;e.timeline?.enter(`preMigration`);try{await B(`apply.tailorDB.migration.prePhase`,()=>executeSingleMigrationPrePhase(i,a,c,o,l,f)),c.hasScript&&s&&await B(`apply.tailorDB.migration.script`,()=>executeMigrations(s,[c],n.checkpoints,e.validation.inProgressMigrations,e.timeline))}catch(i){throw isMigrationOutcomeUnknown(i)||(d?!isRollbackSafe(i,u):u||isMigrationPartiallyApplied(i))?(r.partial.set(c.namespace,c),i):await rollbackMigration(e,t,n,r,i,u||isMigrationPartiallyApplied(i))}}function isRollbackSafe(e,t){return isMigrationRunEnded(e)?!0:!t&&!isMigrationPartiallyApplied(e)}async function runPostMigrationPhase(e,t,n,r){let{client:i,changeSet:a,phaseSettings:o}=e,{migration:s,attemptedTables:c,inProgress:l,runsSteps:u,rollsBackOnFailure:d,gqlPermissionUndo:f}=t;e.timeline?.enter(`postMigration`);try{await B(`apply.tailorDB.migration.postPhase`,()=>executeSingleMigrationPostPhase(i,a,s,o,c))}catch(p){if(!d&&(l||u))throw r.partial.set(s.namespace,s),await reapplyPrePhaseAfterPostPhaseFailure(i,a,s,o,c,f),p;let m=await rollbackMigration(e,t,n,r,p,!0);throw isRollbackSkippedWithRecord(m)&&await reapplyPrePhaseAfterPostPhaseFailure(i,a,s,o,c,f),m}}async function rollbackMigration(e,t,n,r,i,a){let{client:o,migrationContext:s,phaseSettings:c}=e,{migration:l,rollsBackOnFailure:u,runsMain:d,resumesPrePhase:f,gqlPermissionUndo:p}=t,{workspaceId:m}=s,h=d?`main`:`steps`,g=(u||d)&&a,_=g?await clearRolledBackRecord(o,m,l,h):`cleared`;if(_!==`cleared`)return r.partial.set(l.namespace,l),rollbackSkippedError(l,i,c.restricted,{confirmed:_===`in-progress`,kind:h},deployCommandContext(s));let v=new Set(t.attemptedTables),y=e.pending.lastByNamespace.get(l.namespace)??l;for(let e of readRollbackScope(l,y,p,f))v.add(e);return r.unrolledBack.push({migration:l,...await rollbackSingleMigrationAfterFailure(o,l,m,c,v,p)}),(u||g)&&await removeRunResources(o,m,l.namespace,l.number),isMigrationStartRefused(i)?i:(f&&settleRolledBackRestorationSettings(e,l,n),u?rolledBackError(l,i):i)}function readRollbackScope(e,t,n,r){try{let i=r?getPreMigrationTargetTableNames(e):/* @__PURE__ */ new Set,a=r?new Set(n.keys()):void 0;for(let[i,o]of gqlPermissionUndoFromSnapshots(e,t,a))(r||!n.has(i))&&n.set(i,o);return i}catch(t){return C.warn(`Could not read migration ${e.namespace}/${formatMigrationNumber(e.number)} or its prior checkpoint: ${t instanceof Error?t.message:String(t)}. Only what this deploy wrote is rolled back.`),/* @__PURE__ */ new Set}}function settleRolledBackRestorationSettings(e,t,n){let r=e.migrationContext.tailorDBInputs.find(e=>e.namespace===t.namespace),i=n.snapshots.get(t.namespace);if(!r||!i)return;let a=resolveMigrationSnapshotSettings(i,r,e.migrationContext.executorUsedTables),o=Js.load(t).tables;for(let[e,r]of n.settings.get(t.namespace)??[])!i.tables[e]&&!o[e]&&a.set(e,r);n.settings.set(t.namespace,a)}async function commitMigration(e,t,n,r){let{client:i,changeSet:a,migrationContext:o,phaseSettings:c}=e,{migration:u,resumesPrePhase:d,runsSteps:f,runsMain:p}=t,m=n.snapshots.get(u.namespace),h=n.settings.get(u.namespace),g=Js.load(u);n.snapshots.set(u.namespace,g);let _=e.validation.migrationHistoryIds[u.namespace]??null,v=c.restricted,y=getTablesDeletedAfterCheckpoint(u.diff),b=y.size>0,x=d,settleRestorationSettings=()=>{let e=o.tailorDBInputs.find(e=>e.namespace===u.namespace);if(!e)return;let t=resolveMigrationSnapshotSettings(g,e,o.executorUsedTables);for(let[e,n]of h??[])m?.tables[e]||(!x&&!isMigrationRestricted(n)||g.tables[e]===void 0)&&t.set(e,n);n.settings.set(u.namespace,t)};x&&settleRestorationSettings();try{await updateMigrationLabel(i,o.workspaceId,u.namespace,u.number,_??void 0,v,b)}catch(r){await confirmCheckpointAfterUpdateFailure(e,t,r,n,g)}n.checkpoints.set(u.namespace,{number:u.number,historyId:_}),v&&r.recordedNamespaces.add(u.namespace),(f||p)&&await removeRunResources(i,o.workspaceId,u.namespace,u.number),x||settleRestorationSettings();try{await deletePlannedTables(i,a,u.namespace,y)}catch(e){let t=formatNamespaceMigrationHint({...deployCommandContext(o),subcommand:[`sync`,formatMigrationNumber(u.number)],namespace:u.namespace});C.warn(`Migration checkpoint ${u.namespace}/${formatMigrationNumber(u.number)} was committed, but post-checkpoint cleanup failed.`+(c.restricted?` The leftover resources remain locked.`:``));let n=T(e);throw l(n,{suggestion:[`Deploy again to delete the leftover tables, or run ${t}.`,s(n).suggestion].filter(Boolean).join(` `)})}b&&await clearCleanupRecord(i,o.workspaceId,u.namespace)}async function clearCleanupRecord(e,t,n){try{await clearMigrationCleanupRecord(e,t,n)}catch(e){C.warn(`The tables of namespace '${n}' that were pending deletion have been deleted, but the record of the pending deletion could not be removed: ${T(e).message}. A later deploy removes it.`)}}async function confirmCheckpointAfterUpdateFailure(e,t,n,r,i){let{migration:a}=t,o=e.validation.migrationHistoryIds[a.namespace]??null,s;try{s=await fetchRemoteMigrationState(e.client,resourceTrn(e.migrationContext.workspaceId,`tailordb`,a.namespace))}catch(e){throw C.warn(`Could not verify migration checkpoint ${a.namespace}/${formatMigrationNumber(a.number)} after its update failed: ${e instanceof Error?e.message:String(e)}. Leaving the post-migration schema unchanged to avoid rolling back a committed checkpoint.`),n}let c=s.number??void 0,l=s.historyIdInvalid||s.historyId!==o?`${describeMigrationCheckpoint(s.number)} in a different migration history`:c!==void 0&&c>a.number?formatMigrationNumber(c):void 0;if(l!==void 0)throw r.snapshots.delete(a.namespace),E({code:`MIGRATION_CHECKPOINT_CONFLICT`,message:`Migration checkpoint ${a.namespace}/${formatMigrationNumber(a.number)} advanced concurrently to ${l}. Leaving the post-migration schema unchanged and aborting this deployment.`,cause:n});if(c!==a.number){r.snapshots.set(a.namespace,includeTablesDeletedAfterCheckpoint(i,a.diff));let e=s.inProgress?.kind===`steps`&&s.inProgress.number===a.number&&(c??0)===a.number-1;throw C.warn(`Migration checkpoint ${a.namespace}/${formatMigrationNumber(a.number)} could not be confirmed after its update failed; remote remains at ${describeMigrationCheckpoint(c)}. Leaving the post-migration schema unchanged to avoid rolling back a concurrent deployment. `+(e?`Deploy again to resume the migration; unless you add, remove, rename, or reorder steps, steps that already completed do not run again.`:`Repair the checkpoint before retrying.`)),n}}function restrictionHistoryOf(e,t,n){return{maintenanceMode:e.phaseSettings.restricted,captured:e.settingsBeforeMaintenanceMode,resumed:migrationWithEarlierPrePhase(e.validation,n)!==void 0,touched:new Set(t.touchedTables.flatMap(e=>e.namespace===n?[...e.tables]:[]))}}async function verifyRestorationCheckpoints(e,t,n,r){let i=r,a={};for(let[r,o]of t.checkpoints){let s=await checkRestorationCheckpoint(e,t,n,r,o);s&&(i?(C.warn(`${s.message} The original migration error is reported below.`),s.suggestion&&C.log(s.suggestion),a[`restorationSkipped:${r}`]=s):i={error:s})}return{failure:i,restorationFailures:a}}async function checkRestorationCheckpoint(e,t,n,r,i){let{restricted:a}=e.phaseSettings,o=formatNamespaceMigrationHint({...deployCommandContext(e.migrationContext),subcommand:[`status`],namespace:r}),s;try{s=await fetchRemoteMigrationState(e.client,resourceTrn(e.migrationContext.workspaceId,`tailordb`,r))}catch(s){let c=skipRestoration(e,t,n,r);return E({code:`MIGRATION_CHECKPOINT_UNVERIFIED`,message:`Could not verify ownership of migration checkpoint ${r}/${describeMigrationCheckpoint(i.number)} before restoring table settings: ${s instanceof Error?s.message:String(s)}. Skipping restoration for this namespace and aborting this deployment.`,suggestion:(a?`The tables of namespace '${r}' keep the restrictions this deploy set (${Xs}). `:`The table settings of namespace '${r}' are left unchanged. `)+`${describeSkippedTables(c)}Run ${o} to check the checkpoint, restore connectivity if it fails, then deploy again.`,context:{namespace:r,expectedCheckpoint:i.number,tables:c}})}if(isCheckpointStillOwned(s,i))return;let c=skipRestoration(e,t,n,r);return E({code:`MIGRATION_CHECKPOINT_CONFLICT`,message:`Migration checkpoint ${r}/${describeMigrationCheckpoint(i.number)} advanced concurrently to ${describeMigrationCheckpoint(s.number)}. Skipping restoration for this namespace and aborting this deployment.`,suggestion:(a?`Another deploy changed the checkpoint, so the tables of namespace '${r}' keep the restrictions this deploy set (${Xs}). `:`Another deploy changed the checkpoint, so the table settings of namespace '${r}' are left unchanged. `)+`${describeSkippedTables(c)}Wait for the other deploy to finish, run ${o} to see the checkpoint and any migration in progress, then check the tables before deploying again.`,context:{namespace:r,expectedCheckpoint:i.number,remoteCheckpoint:s.number,tables:c}})}function skipRestoration(e,t,n,r){let i=skippedRestorationTables(r,t.snapshots,t.settings,restrictionHistoryOf(e,n,r));return t.snapshots.delete(r),t.skipped.add(r),i}function keepPartialMigrationsRestricted(e,t,n){let{pendingMigrations:r,inProgressMigrations:i}=e.validation;for(let e of r)i[e.namespace]?.number===e.number&&!n.reached.has(e)&&n.partial.set(e.namespace,e);for(let[r,i]of n.partial){let a=keepMigrationTablesRestricted(r,i,t.snapshots,t.settings,restrictionHistoryOf(e,n,r));warnTablesLeftRestricted(`Migration ${r}/${formatMigrationNumber(i.number)} is partially applied.`,[{namespace:r,tables:a}])}}async function restoreTables(e,t,n,r){let{migrationContext:i}=e;await restoreMigrationRestrictions(r,t.snapshots,t.settings,i.tailorDBInputs,i.executorUsedTables,i.workspaceId,e.phaseSettings.restricted),e.timeline?.finish();let a=/* @__PURE__ */ new Set([...n.recordedNamespaces,...Object.keys(e.validation.maintenanceModeCheckpoints)]);for(let e of a)t.snapshots.has(e)&&await clearRecordAfterRelease(r,i.workspaceId,e)}async function releaseHeldMaintenanceMode(e,t,n,r){e.timeline?.enter(`restore`);let i=await findUnownedMigrationCheckpoints(r,e.migrationContext.workspaceId,t.checkpoints,`Leaving its table settings unchanged.`);for(let e of i.keys())t.snapshots.delete(e);let[a,...o]=i.values();for(let e of o)C.warn(e.message);try{await restoreTables(e,t,n,r)}catch(e){if(!a)throw e;C.warn(`Could not restore every TailorDB table: ${T(e).message}.`)}if(a)throw a;return finishMaintenance(e)}async function restoreAfterMigrations(e,t,n,r){try{return await restoreTables(e,t,n,e.client),[]}catch(t){if(!r.failure)throw t;let n=readUnrestoredTables(t),i=`Could not restore every TailorDB table after the migration failed: ${T(t).message}.`;return e.phaseSettings.restricted?warnTablesLeftRestricted(i,n,{namesUnknown:n.every(e=>e.tables.length===0)}):C.warn(i),C.log(`The original migration error is reported below.`),t instanceof Error&&(r.restorationFailures.restoration=t),n}}function warnIncompleteRollbacks(e,t,n,r){for(let{migration:i,tables:a,permissions:o}of n.unrolledBack){let n=r.find(e=>e.namespace===i.namespace),s=new Set(t.skipped.has(i.namespace)||n?.tables.length===0?[]:[...Object.keys(t.snapshots.get(i.namespace)?.tables??{}),...t.settings.get(i.namespace)?.keys()??[]].filter(e=>!n?.tables.includes(e)));o.length>0&&(C.warn(`Migration ${i.namespace}/${formatMigrationNumber(i.number)} was not rolled back completely. GraphQL permissions needing manual repair in namespace '${i.namespace}': ${o.join(`, `)}.`),C.log(`Check the GraphQL permission of these tables in the workspace and set it back by hand.`));let c=a.filter(e=>!s.has(e));c.length!==0&&(e.phaseSettings.restricted?warnTablesLeftRestricted(`Migration ${i.namespace}/${formatMigrationNumber(i.number)} was not rolled back completely.`,[{namespace:i.namespace,tables:c}],{recovery:Qs}):(C.warn(`Migration ${i.namespace}/${formatMigrationNumber(i.number)} was not rolled back completely. Tables needing manual repair in namespace '${i.namespace}': ${c.join(`, `)}.`),C.log(Qs)))}}function finishMaintenance(e){if(!e.timeline)return;let t=e.timeline.report([...e.migratingNamespaces]);return C.info(formatMaintenanceSummary(t)),t}function collectLocalDefinitionWrites(e){let{changeSet:t,migrationContext:n}=e,r=/* @__PURE__ */ new Map,i=/* @__PURE__ */ new Set;for(let n of t.type.creates){let t=n.request.namespaceName,a=n.request.tailordbType?.name;if(!t||!a||!e.migratingNamespaces.has(t))continue;let o=namespacedTableKey(t,a);qs.created.has(o)||(r.set(t,[...r.get(t)??[],n]),i.add(o))}let a=/* @__PURE__ */ new Map;for(let[r,o]of e.pending.lastByNamespace){let e=n.tailorDBInputs.find(e=>e.namespace===r);if(!e)continue;let s=Js.load(o).tables,comparable=t=>normalizeComparableTailorDBType(generateTailorDBTypeManifestFromSnapshot(t,{subscribed:n.executorUsedTables.has(t.name),namespaceGqlOperations:e.config.gqlOperations})),c=Object.entries(e.types).filter(([e,n])=>{let a=namespacedTableKey(r,e);if(i.has(a))return!1;let o=s[e];return o?!areNormalizedEqual(comparable(n),comparable(o)):qs.created.has(a)||t.type.updates.some(t=>t.request.namespaceName===r&&t.name===e)});c.length>0&&a.set(r,Object.fromEntries(c))}return{creates:r,updates:a}}function isRefusedByRecords(e){return e instanceof q?e.code===K.AlreadyExists||e.code===K.FailedPrecondition&&e.details.some(e=>`type`in e&&e.type===`google.rpc.PreconditionFailure`):!1}function localDefinitionError(e,t,n){let{namespaceName:r,tableName:i,refusedByRecords:o}=t,c=T(n),u=a(e.pending.lastByNamespace.get(r),`local definitions are written only to namespaces with pending migrations`),d=[...t.created].map(([e,t])=>({namespace:e,tables:t})),f=formatNamespaceMigrationHint({subcommand:[`generate`],namespace:r,configPath:e.migrationContext.config.path});return l(c,{code:`MIGRATION_LOCAL_DEFINITIONS_FAILED`,suggestion:[`The pending migrations completed, and the existing tables of namespace '${r}' keep the definitions of migration ${r}/${formatMigrationNumber(u.number)}.`,d.length>0&&`Tables created for their local definitions remain: ${d.map(e=>`namespace '${e.namespace}': ${e.tables.join(`, `)}`).join(`; `)}.`,o&&`The local definition of table '${i}' conflicts with its existing records and is not in any migration: run ${f} to add it with a migration script that updates those records, then deploy again.`,s(c).suggestion,!o&&`Once the cause is fixed, deploy again to apply the local definition of table '${i}'.`].filter(Boolean).join(` `),context:{namespace:r,table:i,created:d}})}async function applyLocalDefinitions(e,t){let{client:n,migrationContext:r,phaseSettings:i}=e;if(!r.noSchemaCheck)return;let{creates:o,updates:s}=collectLocalDefinitionWrites(e);if(o.size===0&&s.size===0)return;let c=/* @__PURE__ */ new Map;e.timeline?.enter(`postMigration`);try{for(let[t,r]of o)for(let i of r){let r=i.name;try{await n.createTailorDBType(i.request)}catch(n){return{error:localDefinitionError(e,{namespaceName:t,tableName:r,created:c,refusedByRecords:!1},n)}}c.set(t,[...c.get(t)??[],r])}for(let[t,a]of s)for(let[o,s]of Object.entries(a))try{await n.updateTailorDBType({workspaceId:r.workspaceId,namespaceName:t,tailordbType:generateMigrationPhaseManifest(s,t,i)})}catch(n){return{error:localDefinitionError(e,{namespaceName:t,tableName:o,created:c,refusedByRecords:isRefusedByRecords(n)},n)}}}finally{e.timeline?.enter(`restore`)}for(let[e,n]of s){let i=a(t.snapshots.get(e),`every migrating namespace that passed checkpoint verification has a snapshot to restore`);t.snapshots.set(e,{...i,tables:{...i.tables,...n}});let o=a(r.tailorDBInputs.find(t=>t.namespace===e),`local definitions come from the namespace's deploy input`),s=t.settings.get(e);s&&t.settings.set(e,new Map([...s,...resolveMigrationSnapshotSettings({...i,tables:n},o,r.executorUsedTables)]))}for(let t of e.migratingNamespaces){let n=[...(o.get(t)??[]).map(e=>e.name),...Object.keys(s.get(t)??{})].toSorted();if(n.length===0)continue;let r=a(e.pending.lastByNamespace.get(t),`every migrating namespace has a last pending migration`);C.info(`Applied local definitions that migration ${t}/${formatMigrationNumber(r.number)} does not include, after the pending migrations: ${n.join(`, `)}.`)}}async function applyDeferredGqlPermissions(e,t){let{client:n,changeSet:r}=e;await Promise.all([...r.gqlPermission.creates.filter(e=>t.has(`${e.request.namespaceName}/${e.name}`)).map(e=>n.createTailorDBGQLPermission(e.request)),...r.gqlPermission.updates.filter(e=>t.has(`${e.request.namespaceName}/${e.name}`)).map(e=>n.updateTailorDBGQLPermission(e.request))])}function isDeleted(e,t){return e.has(`${t.request.namespaceName}/${t.name}`)}async function applyRemainingDeletions(e){let{client:t,changeSet:n}=e,r=n.gqlPermission.deletes.filter(e=>!isDeleted(Ys.gqlPermissions,e));r.length>0&&await Promise.all(r.map(e=>t.deleteTailorDBGQLPermission(e.request))),await Promise.all(n.type.deletes.filter(t=>isOutsideMigrations(e,t.request.namespaceName)&&!isDeleted(Ys.types,t)).map(e=>t.deleteTailorDBType(e.request)))}async function applyWithoutMigrations(e,t){await executeServicesCreation(e,t);try{for(let n of t.type.creates)await e.createTailorDBType(n.request),await writeMetadataLabels(e,n.metaRequest);for(let n of t.type.updates)await e.updateTailorDBType(n.request),await writeMetadataLabels(e,n.metaRequest);await Promise.all(t.type.unchanged.flatMap(t=>t.metaRequest?[writeMetadataLabels(e,t.metaRequest)]:[]))}catch(e){handleOptionalToRequiredError(e,ec)}await Promise.all([...t.gqlPermission.creates.map(t=>e.createTailorDBGQLPermission(t.request)),...t.gqlPermission.updates.map(t=>e.updateTailorDBGQLPermission(t.request))]),await Promise.all(t.gqlPermission.deletes.filter(e=>!isDeleted(Ys.gqlPermissions,e)).map(t=>e.deleteTailorDBGQLPermission(t.request))),await Promise.all(t.type.deletes.filter(e=>!isDeleted(Ys.types,e)).map(t=>e.deleteTailorDBType(t.request)))}async function executeServicesCreation(e,t){await Promise.all([...t.service.creates.map(async t=>{await e.createTailorDBService(t.request),await writeMetadataLabels(e,t.metaRequest)}),...t.service.updates.map(t=>writeMetadataLabels(e,t.metaRequest))])}function itemKey(e){return`${e.request?.namespaceName??``}/${e.name}`}function collectTailorDBDisplayEntries(e,t,n){let r=new Set(t.map(itemKey)),i=new Map(n.map(e=>[itemKey(e),e])),a=t.map(t=>{let n=i.get(itemKey(t)),r=t.forcedBySdkVersion&&(!n||n.forcedBySdkVersion);return{action:e,symbol:xa[e],name:t.name,labels:n?[`table`,`gqlPermission`]:[`table`],namespace:t.request?.namespaceName,...r&&{forcedBySdkVersion:!0}}}),o=n.filter(e=>!r.has(itemKey(e))).map(t=>({action:e,symbol:xa[e],name:t.name,labels:[`gqlPermission`],namespace:t.request?.namespaceName,...t.forcedBySdkVersion&&{forcedBySdkVersion:!0}}));return[...a,...o]}function formatTailorDBResourceChangeEntries(e,t){return[...collectTailorDBDisplayEntries(`create`,e.creates,t.creates),...collectTailorDBDisplayEntries(`delete`,e.deletes,t.deletes),...collectTailorDBDisplayEntries(`update`,e.updates,t.updates),...collectTailorDBDisplayEntries(`replace`,e.replaces,t.replaces)]}async function planTailorDB(e){let{client:t,workspaceId:n,application:r,forRemoval:i,config:a,noSchemaCheck:o,migrationSkipSteps:s,migrationRecoveryArgs:c,forceApplyAll:l=!1}=e,u=[],d=e.migrationTestSnapshots??(e.migrationTestBaselines?new Map([...e.migrationTestBaselines].map(([e,t])=>[e,t.snapshot])):void 0);if(!i)for(let e of r.tailorDBServices){await e.loadTypes();let t=toTailorDBDeployInput(e),n=d?.get(e.namespace);u.push(n?{...t,types:n.tables}:t)}let f=i?[]:Object.values(await r.executorService?.loadExecutors()??{}),p=new Set(e.executorUsedTailorDBTables??[]);for(let e of f)subscribesToEvents(e)&&e.trigger.kind===`tailordb`&&p.add(e.trigger.tableName);let m=/* @__PURE__ */ new Map;for(let e of u)m.set(e.namespace,e.types);let h=e.migrationTestBaselines;if(d){for(let e of d.keys())if(!u.some(t=>t.namespace===e))throw E({code:`MIGRATION_TEST_SNAPSHOT_INVALID`,message:`Migration test snapshot targets unknown TailorDB namespace "${e}".`});let e=/* @__PURE__ */ new Map;for(let t of u)for(let n of Object.keys(t.types)){let r=e.get(n);if(r)throw E({code:`MIGRATION_TEST_SNAPSHOT_INVALID`,message:`Migration test snapshot has duplicate TailorDB table name "${n}" in namespaces "${r}" and "${t.namespace}".`});e.set(n,t.namespace)}}let g=i?[]:getNamespacesWithMigrations(a,H.dirname(a.path)),_=i||h?void 0:await validateAndDetectMigrations(t,n,m,a,o??!1,u,c);_&&await assertPendingMigrationsRunnable({client:t,workspaceId:n,requested:selectSkipStepsOfNamespaces(s,u.map(e=>e.namespace)),pendingMigrations:_.pendingMigrations,inProgressByNamespace:_.inProgressMigrations,source:e});let{namespacesWithMigrations:v,migrationFileState:y,checkpointRepairs:b}=_??{namespacesWithMigrations:g,migrationFileState:captureMigrationFileState(g),checkpointRepairs:[]},{changeSet:x,conflicts:S,unmanaged:C,resourceOwners:w}=await planServices(t,n,r.name,r.id,u),T=x.deletes.map(e=>e.name),[D,O]=await Promise.all([planTypes(t,n,u,p,T,void 0,l,{appName:r.name,appId:r.id,dependentApps:e.dependentApps,runAppIds:e.runAppIds}),planGqlPermissions(t,n,u,T,l)]);return D.creates.sort(Et),D.updates.sort(Et),D.deletes.sort(Et),{changeSet:{service:x,type:D,gqlPermission:O},conflicts:S,unmanaged:C,resourceOwners:w,context:{workspaceId:n,application:r,tailorDBInputs:u,executorUsedTables:p,config:a,noSchemaCheck:o??!1,...s?{migrationSkipSteps:s}:{},...c?{migrationRecoveryArgs:c}:{},...h?{migrationTestBaselines:h}:{},...e.migrationMachineUserOverride===void 0?{}:{migrationMachineUserOverride:e.migrationMachineUserOverride},namespacesWithMigrations:v,migrationFileState:y,checkpointRepairs:b}}}async function planServices(e,t,n,r,i){let a=createChangeSet(`TailorDB services`),o=createOwnershipTracker(n,r),s=await fetchExistingResourcesWithLabels({client:e,fetchPage:async(n,r)=>{let{tailordbServices:i,nextPageToken:a}=await e.listTailorDBServices({workspaceId:t,pageToken:n,pageSize:r});return[i,a]},getName:e=>e.namespace?.name,getTrn:e=>resourceTrn(t,`tailordb`,e)});for(let e of i){let i=s[e.namespace],c=await buildMetaRequest({trn:resourceTrn(t,`tailordb`,e.namespace),appName:n,appId:r});if(i){let t=o.ownsDesired(i.allLabels,{resourceType:`tailordb.service`,resourceLabel:`TailorDB service`,resourceName:e.namespace})&&areTailorDBServicesEqual(i.resource,e);t&&hasMatchingSdkVersion(i.allLabels,c.labels)?a.unchanged.push({name:e.namespace}):a.updates.push({name:e.namespace,metaRequest:c,...t&&{forcedBySdkVersion:!0}}),delete s[e.namespace]}else a.creates.push({name:e.namespace,request:{workspaceId:t,namespaceName:e.namespace,defaultTimezone:`UTC`},metaRequest:c})}return Object.entries(s).forEach(([e])=>{let n=s[e];o.ownsRemaining(n?.allLabels)&&a.deletes.push({name:e,request:{workspaceId:t,namespaceName:e}})}),{changeSet:a,...o.result}}async function planTypes(e,t,n,r,i,a,o=!1,s={}){let c=createChangeSet(`TailorDB tables`),{appName:l,appId:u,dependentApps:d,runAppIds:f}=s,typeMetaRequest=async(e,n,r)=>addDependencyRecords(await buildMetaRequest({trn:tailorDBTypeTrn(t,e,n),appName:l??``,appId:u}),{key:Z.tailorDBType(e,n),dependentApps:d,runAppIds:f,pinned:r!==void 0}),fetchTypes=n=>F(async(r,i)=>{let{tailordbTypes:a,nextPageToken:o}=await e.listTailorDBTypes({workspaceId:t,namespaceName:n,pageToken:r,pageSize:i});return[a,o]});for(let e of n){let t=a?.get(e.namespace)??e.types;for(let[e,n]of Object.entries(t))assertNoPublishEventsConflict({explicit:n.settings?.publishEvents,subscribed:r.has(e),conflict:Ca.tailorDBType(e)})}for(let e of n){let n=await fetchTypes(e.namespace),i=new Map(n.map(e=>[e.name,e])),s=a?.get(e.namespace)??e.types,typeMeta=t=>typeMetaRequest(e.namespace,t,s[t]?.settings?.publishEvents);for(let[n,a]of Object.entries(s)){let s=generateTailorDBTypeManifestFromSnapshot(a,{subscribed:r.has(n),namespaceGqlOperations:e.config.gqlOperations}),l=i.get(n);if(l){let r=areNormalizedEqual(normalizeComparableTailorDBType(l),normalizeComparableTailorDBType(s));!o&&r?c.unchanged.push({name:n,metaRequest:await typeMeta(n)}):c.updates.push({name:n,request:{workspaceId:t,namespaceName:e.namespace,tailordbType:s},metaRequest:await typeMeta(n),...r&&{forcedBySdkVersion:!0}}),i.delete(n)}else c.creates.push({name:n,request:{workspaceId:t,namespaceName:e.namespace,tailordbType:s},metaRequest:await typeMeta(n)})}i.forEach((n,r)=>{c.deletes.push({name:r,request:{workspaceId:t,namespaceName:e.namespace,tailordbTypeName:r}})})}for(let e of i)(await fetchTypes(e)).forEach(n=>{c.deletes.push({name:n.name,request:{workspaceId:t,namespaceName:e,tailordbTypeName:n.name}})});return c}async function planGqlPermissions(e,t,n,r,i=!1){let a=createChangeSet(`TailorDB gqlPermissions`),fetchGqlPermissions=n=>F(async(r,i)=>{let{permissions:a,nextPageToken:o}=await e.listTailorDBGQLPermissions({workspaceId:t,namespaceName:n,pageToken:r,pageSize:i});return[a,o]});for(let e of n){let n=await fetchGqlPermissions(e.namespace),r=/* @__PURE__ */ new Set;n.forEach(e=>{r.add(e.typeName)});let o=e.types;for(let[s,c]of Object.entries(o)){let o=c.permissions?.gql;if(!o)continue;let l=protoGqlPermission(o),u=n.find(e=>e.typeName===s);if(r.has(s)){let n=!!u&&areNormalizedEqual(normalizeComparableGqlPermission(u.permission),normalizeComparableGqlPermission(l));!i&&n?a.unchanged.push({name:s}):a.updates.push({name:s,request:{workspaceId:t,namespaceName:e.namespace,typeName:s,permission:l},previousPermission:u?.permission,...n&&{forcedBySdkVersion:!0}}),r.delete(s)}else a.creates.push({name:s,request:{workspaceId:t,namespaceName:e.namespace,typeName:s,permission:l}})}r.forEach(n=>{a.deletes.push({name:n,request:{workspaceId:t,namespaceName:e.namespace,typeName:n}})})}for(let e of r)(await fetchGqlPermissions(e)).forEach(n=>{a.deletes.push({name:n.typeName,request:{workspaceId:t,namespaceName:e,typeName:n.typeName}})});return a}async function applyWorkflow(e,t,n=`create-update`){let{changeSet:r,appName:i,appId:a}=t;if(n===`create-update`){let n=await registerJobFunctions(e,r,i,a,t.unchangedWorkflowJobNames,t.jobFunctionPublishEvents);await Promise.all([...r.creates.map(async t=>{let r=filterJobFunctionVersions(n,t.usedJobNames),i=buildWorkflowValidationShape(t.workspaceId,t.workflow);await e.createWorkflow({workspaceId:i.workspaceId,workflowName:i.workflowName,mainJobFunctionName:i.mainJobFunctionName,retryPolicy:i.retryPolicy,concurrencyPolicy:i.concurrencyPolicy,jobFunctions:r,publishExecutionEvents:i.publishExecutionEvents}),await writeMetadataLabels(e,t.metaRequest)}),...r.updates.map(async t=>{let r=filterJobFunctionVersions(n,t.usedJobNames),i=buildWorkflowValidationShape(t.workspaceId,t.workflow);await e.updateWorkflow({workspaceId:i.workspaceId,workflowName:i.workflowName,mainJobFunctionName:i.mainJobFunctionName,retryPolicy:i.retryPolicy,concurrencyPolicy:i.concurrencyPolicy,jobFunctions:r,publishExecutionEvents:i.publishExecutionEvents}),await writeMetadataLabels(e,t.metaRequest)}),...r.unchanged.flatMap(t=>t.metaRequest?[writeMetadataLabels(e,t.metaRequest)]:[])])}else await deleteAllSettled(r.deletes.map(t=>({resourceLabel:`workflow`,resourceName:t.name,run:()=>e.deleteWorkflow({workspaceId:t.workspaceId,workflowId:t.workflowId})}))),await deleteAllSettled(t.jobFunctionDeletes.map(t=>({resourceLabel:`workflow job function`,resourceName:t.jobFunctionName,run:()=>e.deleteWorkflowJobFunction({workspaceId:t.workspaceId,jobFunctionName:t.jobFunctionName})})))}async function deleteAllSettled(e){let t=await Promise.allSettled(e.map(e=>e.run())),n=[];t.forEach((t,r)=>{if(t.status===`fulfilled`)return;let i=a(e[r],`operation missing at index`),o=t.reason;o instanceof q&&o.code===K.NotFound||(o instanceof q&&o.code===K.FailedPrecondition?C.warn(`Skipped deleting ${i.resourceLabel} "${i.resourceName}" because it is still referenced.`):n.push(T(o)))});let r=n[0];if(r)throw r}function filterJobFunctionVersions(e,t){let n={};for(let r of t)e[r]!==void 0&&(n[r]=e[r]);return n}async function registerJobFunctions(e,t,n,r,i=/* @__PURE__ */ new Set,a=/* @__PURE__ */ new Map){let o={},s=t.creates[0]||t.updates[0]||t.deletes[0];if(!s)return o;let{workspaceId:c}=s,l=/* @__PURE__ */ new Set;i.forEach(e=>l.add(e));for(let e of[...t.creates,...t.updates])for(let t of e.usedJobNames)l.add(t);let u=await jt(async(t,n)=>{let r=await e.listWorkflowJobFunctions({workspaceId:c,pageToken:t,pageSize:n});return[r.jobFunctions.map(e=>e.name),r.nextPageToken]}),d=new Set(u);if(t.creates.length>0||t.updates.length>0){let t=await Promise.all(Array.from(l).map(async t=>{let i=d.has(t),o={workspaceId:c,jobFunctionName:t,scriptRef:workflowJobFunctionName(t),publishExecutionEvents:a.get(t)??!1},s=i?await e.updateWorkflowJobFunction(o):await e.createWorkflowJobFunction(o);return await writeMetadataLabels(e,await buildMetaRequest({trn:resourceTrn(c,`workflow_job_function`,t),appName:n,appId:r})),{jobName:t,version:s.jobFunction?.version}}));for(let{jobName:e,version:n}of t)n&&(o[e]=n)}return o}function parseDurationToProto(e){let t=he(e),n=Math.floor(t/1e3),r=t%1e3*1e6;return{seconds:BigInt(n),nanos:r}}function toRetryPolicy(e){return{maxRetries:e.maxRetries,initialBackoff:parseDurationToProto(e.initialBackoff),maxBackoff:parseDurationToProto(e.maxBackoff),backoffMultiplier:e.backoffMultiplier}}function toConcurrencyPolicy(e){return{maxConcurrentExecutions:e.maxConcurrentExecutions}}function buildWorkflowValidationShape(e,t){return{workspaceId:e,workflowName:t.name,mainJobFunctionName:t.mainJob.name,...t.retryPolicy&&{retryPolicy:toRetryPolicy(t.retryPolicy)},...t.concurrencyPolicy&&{concurrencyPolicy:toConcurrencyPolicy(t.concurrencyPolicy)},publishExecutionEvents:t.publishEvents??!1}}const tc={workflowNames:/* @__PURE__ */ new Set};function isSubscribed(e,t){return e.workflowNames.has(t)}function subscribedWorkflowJobNames(e){let{workflows:t,mainJobDeps:n,isSubscribed:r}=e,i=/* @__PURE__ */ new Set;for(let e of t)if(r(e.name))for(let t of n[e.mainJob.name]??[])i.add(t);return i}function resolveJobPublishEvents(e){let{workflows:t,mainJobDeps:n,subscribers:r,explicit:i}=e,a=/* @__PURE__ */ new Set;for(let e of Object.values(t))for(let t of n[e.mainJob.name]??[])a.add(t);let o=subscribedWorkflowJobNames({workflows:Object.values(t),mainJobDeps:n,isSubscribed:e=>isSubscribed(r,e)}),s=/* @__PURE__ */ new Map;for(let e of a)s.set(e,resolvePublishEvents({explicit:i.get(e),subscribed:o.has(e),conflict:Ca.workflowJob(e)}));return s}function collectStaleJobFunctionNames(e,t){let n=/* @__PURE__ */ new Set;for(let[r,i]of t){let t=e.get(r);t&&t.publishExecutionEvents!==i&&n.add(r)}return n}async function planWorkflow(e,t,n,r,i,a,o=/* @__PURE__ */ new Set,s={},c,l=/* @__PURE__ */ new Set){let u=createChangeSet(`Workflows`),d=createOwnershipTracker(n,r),f=/* @__PURE__ */ new Set,p=/* @__PURE__ */ new Set,m=s.execution??tc,{dependentApps:h,runAppIds:g}=s,everyJobDeclaresPublishEvents=e=>{let t=a[i[e]?.mainJob.name??``]??[],n=s.jobPublishEvents??/* @__PURE__ */ new Map;return t.length>0&&t.every(e=>n.has(e))},_=c?.existingJobFunctions??await fetchExistingJobFunctions(e,t),v=resolveJobPublishEvents({workflows:i,mainJobDeps:a,subscribers:s.jobExecution??tc,explicit:s.jobPublishEvents??/* @__PURE__ */ new Map}),y=collectStaleJobFunctionNames(_,v),b=c?.existingWorkflows??await fetchExistingResourcesWithLabels({client:e,fetchPage:async(n,r)=>{let i=await e.listWorkflows({workspaceId:t,pageToken:n,pageSize:r});return[i.workflows,i.nextPageToken]},getName:e=>e.name,getTrn:e=>resourceTrn(t,`workflow`,e)}),x={...b};for(let e of Object.values(i)){let i=x[e.name],s=addDependencyRecords(await buildMetaRequest({trn:resourceTrn(t,`workflow`,e.name),appName:n,appId:r}),{key:Z.workflow(e.name),dependentApps:h,runAppIds:g,pinned:e.publishEvents!==void 0});addDependencyRecords(s,{key:Z.workflowJobs(e.name),dependentApps:h,runAppIds:g,pinned:everyJobDeclaresPublishEvents(e.name),scope:`jobs`});let c=a[e.mainJob.name];if(!c)throw E({code:`WORKFLOW_MAIN_JOB_NOT_FOUND`,message:`Job "${e.mainJob.name}" (mainJob of workflow "${e.name}") was not found.`,details:`Possible causes:
|
|
102
|
+
`)||void 0})}for(let e of a)e.unfinishedRemovals&&b.set(e.namespace,{migrationNumber:e.remoteMigrationNumber,tableNames:e.unfinishedRemovals}),e.interruptedMigration!==void 0&&(x[e.namespace]=e.interruptedMigration)}let s=new Map(p.map(e=>[e.namespace,e.to])),c=/* @__PURE__ */ new Map;f=await detectPendingMigrations(e,t,u,r.path,s,c),i&&assertCheckpointsInLocalHistory([...c].flatMap(([e,t])=>{let n=locateRemoteCheckpoint(t,a(d.get(e),`every namespace with a remote state has a migrations directory`),_.get(e));return n.kind===`outside`?[{namespace:e,remoteMigrationNumber:n.number,localLatestMigration:n.localLatestMigration,historyIdMismatch:n.historyIdMismatch,...n.rebaselinePending?{rebaselinePending:n.rebaselinePending}:{}}]:[]}),l),m=await validateMigrationsInProgress(e,t,c,h,f,l);for(let e of p)v.set(e.namespace,{number:e.to,historyId:e.toHistoryId});for(let[e,t]of c)v.set(e,{number:t.number,historyId:t.historyId}),t.maintenanceModeCheckpoint!==null&&(y[e]=t.maintenanceModeCheckpoint)}return{pendingMigrations:f,checkpointRepairs:p,namespacesWithMigrations:u,migrationFileState:captureMigrationFileState(u),migrationHistoryIds:g,checkpoints:v,...m,maintenanceModeCheckpoints:y,unfinishedRemovals:b,interruptedMigrations:x}}function logMigrationPlanNotices(e){let{checkpointRepairs:t,unfinishedRemovals:n,interruptedMigrations:r,pendingMigrations:i}=e;for(let e of t)C.warn(`Remote migration checkpoint for ${e.namespace} will be reset to 0000 after confirmation (${formatMigrationNumber(e.from)} → 0000); the remote schema already matches the local baseline.`);for(let[e,{migrationNumber:t,tableNames:r}]of n)r.length!==0&&C.warn(`An earlier deploy committed migration ${e}/${formatMigrationNumber(t)} but did not delete the tables it removed: ${r.join(`, `)}. They will be deleted after confirmation.`);for(let[e,t]of Object.entries(r))C.info(`An earlier deploy left the pre-migration schema or maintenance mode of migration ${e}/${formatMigrationNumber(t)} in place without recording it as in progress; this deploy runs it again from the start.`);for(let e of i){let t=`${e.namespace}/${formatMigrationNumber(e.number)}`,{scriptSkipped:n}=e.diff;n&&C.info(`Migration ${t} runs without a script (skip acknowledged at ${n.acknowledgedAt}: ${n.reason})`),e.scriptForm?.kind===`main`&&e.scriptForm.ignoredSteps&&C.warn(ignoredStepsWarning(t))}if(i.length===0)return;C.newline();let a=i.filter(e=>e.hasScript),o=i.filter(e=>!e.hasScript);C.info(`${i.length} pending migration(s) will be applied:`),o.length>0&&C.info(` • ${o.length} schema change(s) (applied automatically with schema deployment)`,{mode:`plain`}),a.length>0&&C.info(` • ${a.length} data migration(s) (requires migration script execution)`,{mode:`plain`})}function deployCommandContext(e){return migrationCommandContext({workspaceId:e.workspaceId,configPath:e.config.path,extraArgs:e.migrationRecoveryArgs})}async function reconcileMigrationLabels(e,t,n,r,i){for(let{namespace:a,migrationsDir:o}of n){if(getMigrationFiles(o).length===0)continue;let n=getLatestMigrationNumber(o),s=r[a]??null,c=await fetchRemoteMigrationState(e,resourceTrn(t,`tailordb`,a)).catch(()=>null),l=c?.number??null;c&&l===n&&c.historyId===s||(c&&locateRemoteCheckpoint(c,o,reconstructSnapshotFromMigrations(o,0)?.rebaseline).kind===`outside`?C.warn(`Migration checkpoint of namespace ${a} is ${describeMigrationCheckpoint(l)}, which is not in the local migration history, so it was left unchanged. Run ${formatNamespaceMigrationHint({...i,subcommand:[`status`],namespace:a})} to compare.`):(await updateMigrationLabel(e,t,a,n,s??void 0),c?C.info(`Migration label for namespace ${a} reconciled: ${describeMigrationCheckpoint(l)} → ${formatMigrationNumber(n)}.`):C.info(`Migration label for namespace ${a} reconciled to ${formatMigrationNumber(n)}.`)))}}async function buildMigrationContextForScripts(e,t,n,r,i){let a=await Ot(e,t.workspaceId,t.application.env);return{client:e,workspaceId:t.workspaceId,authNamespace:n.authNamespace,machineUserByNamespace:n.byNamespace,env:a,configPath:t.config.path,...t.migrationRecoveryArgs?{migrationRecoveryArgs:t.migrationRecoveryArgs}:{},appName:t.application.name,appId:t.application.id,maintenanceMode:r,skipSteps:t.migrationSkipSteps,migrationHistoryIds:i}}function assertPendingMigrationsUnchanged(e,t){let labelOf=e=>`${e.namespace}/${formatMigrationNumber(e.number)}`,n=e.map(labelOf),r=t.map(labelOf);if(n.length===r.length&&n.every((e,t)=>e===r[t]))return;let refs=e=>e.map(({namespace:e,number:t})=>({namespace:e,migrationNumber:t}));throw E({code:`DEPLOY_PLAN_STALE`,message:`Pending migrations changed after deployment planning because the remote migration checkpoint moved (planned: ${n.join(`, `)||`none`}; now: ${r.join(`, `)||`none`}).`,suggestion:`Run the deployment again to review the pending migrations.`,context:{plannedPendingMigrations:refs(e),pendingMigrations:refs(t)}})}async function validateTailorDBMigrationState(e,t){let{context:n}=t;if(n.migrationTestBaselines){let e=captureMigrationFileState(getNamespacesWithMigrations(n.config,H.dirname(n.config.path)));if(!migrationFileStatesEqual(n.migrationFileState,e))throw E({code:`DEPLOY_PLAN_STALE`,message:`Migration files changed after deployment planning.`,suggestion:`Run the migration test again to create a fresh plan.`});return{pendingMigrations:[],checkpointRepairs:[],namespacesWithMigrations:[],migrationFileState:e,migrationHistoryIds:{},checkpoints:/* @__PURE__ */ new Map,inProgressMigrations:{},staleInProgress:[],maintenanceModeCheckpoints:{},unfinishedRemovals:/* @__PURE__ */ new Map,interruptedMigrations:{},migrationMachineUsers:void 0}}let r=/* @__PURE__ */ new Map;for(let e of n.tailorDBInputs)r.set(e.namespace,e.types);let i=await validateAndDetectMigrations(e,n.workspaceId,r,n.config,n.noSchemaCheck,n.tailorDBInputs,n.migrationRecoveryArgs),a=n.checkpointRepairs;if(a.length!==i.checkpointRepairs.length||i.checkpointRepairs.some(e=>!a.some(t=>t.namespace===e.namespace&&t.from===e.from&&t.fromHistoryId===e.fromHistoryId&&t.toHistoryId===e.toHistoryId)))throw E({code:`DEPLOY_PLAN_STALE`,message:`Remote migration checkpoint repair changed after deployment planning.`,suggestion:`Run the deployment again to review the updated repair.`});for(let[e,{tableNames:n}]of i.unfinishedRemovals){let r=n.filter(n=>!t.changeSet.type.deletes.some(t=>t.request.namespaceName===e&&t.name===n));if(r.length>0)throw E({code:`DEPLOY_PLAN_STALE`,message:`Tables to delete in namespace ${e} changed after deployment planning: ${r.join(`, `)}.`,suggestion:`Run the deployment again to review the deletion.`})}if(!migrationFileStatesEqual(n.migrationFileState,i.migrationFileState))throw E({code:`DEPLOY_PLAN_STALE`,message:`Migration files changed after deployment planning.`,suggestion:`Run the deployment again to create a fresh plan.`});return assertPendingMigrationsUnchanged(n.pendingMigrations,i.pendingMigrations),await assertMigrationSkipSteps({client:e,workspaceId:n.workspaceId,requested:selectSkipStepsOfNamespaces(n.migrationSkipSteps,n.tailorDBInputs.map(e=>e.namespace)),pendingMigrations:i.pendingMigrations,inProgressByNamespace:i.inProgressMigrations}),{...i,migrationMachineUsers:resolveMigrationMachineUsers(n,i.pendingMigrations)}}async function preflightTailorDB(e,t){await validateTailorDBMigrationState(e,t)}async function reapplyPrePhaseAfterPostPhaseFailure(e,t,n,r,i,a){try{await executeSingleMigrationPrePhase(e,t,n,r,i,a)}catch(e){C.warn(`Could not return migration ${n.namespace}/${formatMigrationNumber(n.number)} to its pre-migration schema: ${e instanceof Error?e.message:String(e)}. The original migration error is reported below.`)}}async function readRecordState(e,t,n){try{let r=await fetchRemoteMigrationState(e,resourceTrn(t,`tailordb`,n.namespace));return r.inProgressInvalid||(r.number??(n.number===1?0:null))!==n.number-1?`unknown`:r.inProgress===null?`cleared`:r.inProgress.number===n.number?`in-progress`:`unknown`}catch{return`unknown`}}async function clearRolledBackRecord(e,t,n,r){let{namespace:i}=n;try{return await clearMigrationInProgress(e,t,i),`cleared`}catch(a){let o=await readRecordState(e,t,n);return o===`cleared`||C.warn(`Could not clear the in-progress record of migration ${i}/${formatMigrationNumber(n.number)}: ${a instanceof Error?a.message:String(a)}. Its schema is left as it is, the migration stays in progress, and its tables stay in maintenance mode; `+(r===`main`?`settle it with 'tailor tailordb migration resolve'.`:`deploy again to resume it.`)),o}}function keepMigrationTablesRestricted(e,t,n,r,i){let a=n.get(e),o=/* @__PURE__ */ new Set([...Object.keys(a?.tables??{}),...Object.keys($s.load(t).tables),...getTablesDeletedAfterCheckpoint(t.diff)]);return a&&(n.set(e,{...a,tables:{}}),r.set(e,new Map([...r.get(e)??[]].filter(([e])=>!o.has(e))))),restrictedByDeploy(e,o,i)}function describeSkippedTables(e){return e.length>0?`Restricted tables: ${e.join(`, `)}. `:``}function restrictedByDeploy(e,t,n){return n.maintenanceMode?[...new Set(t)].filter(t=>{let r=n.captured.get(e)?.get(t);return n.resumed||!r||acceptsMigrationWrites(r)||n.touched.has(t)}).toSorted():[]}function skippedRestorationTables(e,t,n,r){return restrictedByDeploy(e,[...Object.keys(t.get(e)?.tables??{}),...n.get(e)?.keys()??[]],r)}async function clearRecordAfterRelease(e,t,n){try{await clearMaintenanceModeRecord(e,t,n)}catch(e){C.warn(`Namespace '${n}' left maintenance mode, but its record could not be removed: ${T(e).message}. A later deploy removes it.`)}}async function findUnownedMigrationCheckpoints(e,t,n,r){let i=/* @__PURE__ */ new Map;for(let[a,o]of n)try{let n=await fetchRemoteMigrationState(e,resourceTrn(t,`tailordb`,a));if(isCheckpointStillOwned(n,o))continue;i.set(a,E({code:`MIGRATION_CHECKPOINT_CONFLICT`,message:`Migration checkpoint ${a}/${describeMigrationCheckpoint(o.number)} advanced concurrently to ${describeMigrationCheckpoint(n.number)}. ${r}`}))}catch(e){i.set(a,E({code:`MIGRATION_CHECKPOINT_UNVERIFIED`,message:`Could not verify ownership of migration checkpoint ${a}/${describeMigrationCheckpoint(o.number)} before restoring table settings: ${e instanceof Error?e.message:String(e)}. ${r}`}))}return i}async function applyTailorDB(e,t,n=`create-update`,r={}){let{changeSet:i}=t;if(n===`create-update`)return applyCreateUpdate(e,t,r);n===`delete-resources`?(await Promise.all(i.gqlPermission.deletes.map(t=>e.deleteTailorDBGQLPermission(t.request))),await Promise.all(i.type.deletes.map(t=>e.deleteTailorDBType(t.request)))):await Promise.all(i.service.deletes.map(t=>e.deleteTailorDBService(t.request)))}async function applyCreateUpdate(e,t,n){let{changeSet:r,context:i}=t,a=i.config.maintenanceMode??`migration`,o={tailorDBInputs:i.tailorDBInputs,executorUsedTables:i.executorUsedTables,restricted:a!==!1},s=await validateTailorDBMigrationState(e,t),{pendingMigrations:c,checkpointRepairs:l,namespacesWithMigrations:u,migrationHistoryIds:d,staleInProgress:f,maintenanceModeCheckpoints:p,unfinishedRemovals:m,migrationMachineUsers:h}=s,g=c.filter(e=>e.hasScript),_=h?await buildMigrationContextForScripts(e,i,h,o.restricted,d):void 0;for(let t of l)await updateMigrationLabel(e,i.workspaceId,t.namespace,t.to,t.toHistoryId),C.info(`Migration checkpoint for namespace ${t.namespace} reset: ${formatMigrationNumber(t.from)} → 0000.`);for(let t of f)await clearMigrationInProgress(e,i.workspaceId,t.namespace),await removeRunResources(e,i.workspaceId,t.namespace,t.migrationNumber);ec.reset();for(let[t,{tableNames:n}]of m)await deletePlannedTables(e,r,t,new Set(n)),await clearCleanupRecord(e,i.workspaceId,t);let v=new Set(c.map(e=>e.namespace)),y;c.length>0?y=await applyWithMigrations({client:e,changeSet:r,migrationContext:i,phaseSettings:o,validation:s,migrationsRequiringScripts:g,migrationCtx:_,holdMaintenanceMode:a===`deploy`?n.holdMaintenanceMode:void 0}):await applyWithoutMigrations(e,r),u.length>0&&c.length===0&&await reconcileMigrationLabels(e,i.workspaceId,u,d,deployCommandContext(i));for(let t of Object.keys(p))v.has(t)||await clearRecordAfterRelease(e,i.workspaceId,t);return y}const ac=[`Run 'tailor tailordb migration generate' to create migration files.`,`Migration scripts allow you to handle existing data before applying the schema change.`];async function applyWithMigrations(e){let{holdMaintenanceMode:t,...n}=e,{client:r,changeSet:i,migrationContext:o,phaseSettings:c,validation:u}=e;Qs.reset(),$s.reset();let d=new Set(u.pendingMigrations.map(e=>e.namespace)),f=await captureMigrationRestrictionState(r,o.workspaceId,d);await executeServicesCreation(r,i);let p=indexPendingMigrations(u.pendingMigrations),m=loadPreMigrationSnapshots(p.firstByNamespace),h={...n,migratingNamespaces:d,pending:p,preMigrationSnapshots:m,restrictionState:f,settingsBeforeMaintenanceMode:releaseRecordedMaintenanceModes(o,p.firstByNamespace,m,f,u.maintenanceModeCheckpoints),timeline:c.restricted?new MaintenanceTimeline:void 0},g=await applyChangesBeforeMigrations(h);h.migrationsRequiringScripts.length>0&&(C.info(`Executing ${h.migrationsRequiringScripts.length} data migration(s)...`),C.newline());let _={snapshots:new Map(h.preMigrationSnapshots),settings:new Map(h.settingsBeforeMaintenanceMode),checkpoints:new Map([...p.firstByNamespace.keys()].map(e=>[e,a(u.checkpoints.get(e),`validation read the checkpoint of every namespace with pending migrations`)])),skipped:/* @__PURE__ */ new Set},v={reached:/* @__PURE__ */ new Set,partial:/* @__PURE__ */ new Map,unrolledBack:[],touchedTables:[],recordedNamespaces:/* @__PURE__ */ new Set},y=await runPendingMigrations(h,_,v);h.timeline?.enter(`restore`);let b=await verifyRestorationCheckpoints(h,_,v,y),{restorationFailures:x}=b,S=b.failure??await applyLocalDefinitions(h,_);keepPartialMigrationsRestricted(h,_,v);let w=S?void 0:t,T=[];if(w?(h.timeline?.enter(`remainingDeploy`),w(e=>releaseHeldMaintenanceMode(h,_,v,e))):T=await restoreAfterMigrations(h,_,v,{failure:S,restorationFailures:x}),warnIncompleteRollbacks(h,_,v,T),S){h.timeline?.finish();let{error:e}=S;throw e instanceof Error&&Object.keys(x).length>0?l(e,{causes:{...s(e).causes,...x}}):e}let E=w?void 0:finishMaintenance(h);return await applyDeferredGqlPermissions(h,g),await applyRemainingDeletions(r,i,e=>excludeFromRestoration(_,e)),await Promise.all([...i.type.creates,...i.type.updates,...i.type.unchanged].flatMap(e=>e.metaRequest?[writeMetadataLabels(r,e.metaRequest)]:[])),E}function indexPendingMigrations(e){let t={firstByNamespace:/* @__PURE__ */ new Map,lastByNamespace:/* @__PURE__ */ new Map,deletedTables:/* @__PURE__ */ new Map,snapshotTableKeys:/* @__PURE__ */ new Set};for(let n of e){let e=t.firstByNamespace.get(n.namespace);(!e||n.number<e.number)&&t.firstByNamespace.set(n.namespace,n);let r=t.lastByNamespace.get(n.namespace);(!r||n.number>r.number)&&t.lastByNamespace.set(n.namespace,n);let i=t.deletedTables.get(n.namespace)??/* @__PURE__ */ new Set;for(let e of getTablesDeletedAfterCheckpoint(n.diff))i.add(e);t.deletedTables.set(n.namespace,i);for(let e of Object.keys($s.load(n).tables))t.snapshotTableKeys.add(`${n.namespace}/${e}`)}return t}function loadPreMigrationSnapshots(e){let t=/* @__PURE__ */ new Map;for(let[n,r]of e){let e=reconstructSnapshotFromMigrations(r.migrationsDir,r.number-1);if(!e)throw E({code:`MIGRATION_HISTORY_INVALID`,message:`Cannot reconstruct the schema state before migration ${formatMigrationNumber(r.number)} for namespace "${n}"`});t.set(n,e)}return t}function releaseRecordedMaintenanceModes(e,t,n,r,i){let a=new Map(r);for(let[o,s]of t){let t=e.tailorDBInputs.find(e=>e.namespace===o),c=r.get(o),l=n.get(o);i[o]===s.number-1&&t&&c&&l&&a.set(o,releaseRecordedMaintenanceMode(c,l,t,e.executorUsedTables))}return a}function migrationWithEarlierPrePhase(e,t){return e.inProgressMigrations[t]?.number??e.interruptedMigrations[t]}function isOutsideMigrations(e,t){return t!==void 0&&!e.migratingNamespaces.has(t)}async function applyChangesBeforeMigrations(e){let{client:t,changeSet:n,migrationContext:r,phaseSettings:i,pending:a}=e,o=new Set([...n.gqlPermission.creates,...n.gqlPermission.updates].filter(t=>{let n=t.request.namespaceName;return r.noSchemaCheck&&n!==void 0&&e.migratingNamespaces.has(n)&&!a.snapshotTableKeys.has(`${n}/${t.name}`)}).map(e=>`${e.request.namespaceName}/${e.name}`));try{for(let r of n.type.creates){let n=r.request.namespaceName;if(isOutsideMigrations(e,n)){await t.createTailorDBType(r.request);continue}let o=r.request.tailordbType?.name;if(!n||!o)continue;let s=e.preMigrationSnapshots.get(n)?.tables[o];s&&(a.deletedTables.get(n)?.has(o)||(Qs.created.add(namespacedTableKey(n,o)),await t.createTailorDBType({workspaceId:r.request.workspaceId,namespaceName:n,tailordbType:generateMigrationPhaseManifest(s,n,i)})))}for(let r of n.type.updates)isOutsideMigrations(e,r.request.namespaceName)&&await t.updateTailorDBType(r.request)}catch(e){handleOptionalToRequiredError(e,ac)}return await Promise.all([...n.gqlPermission.creates.filter(t=>isOutsideMigrations(e,t.request.namespaceName)).map(e=>t.createTailorDBGQLPermission(e.request)),...n.gqlPermission.updates.filter(t=>isOutsideMigrations(e,t.request.namespaceName)).map(e=>t.updateTailorDBGQLPermission(e.request))]),o}async function runPendingMigrations(e,t,n){let{client:r,migrationContext:i}=e;try{e.timeline?.enter(`restrict`),e.phaseSettings.restricted&&await applyMigrationRestrictions(r,e.preMigrationSnapshots,e.restrictionState,i.tailorDBInputs,i.executorUsedTables,i.workspaceId);for(let r of e.validation.pendingMigrations)await runMigration(e,r,t,n);e.migrationsRequiringScripts.length>0&&(C.newline(),C.success(`All data migrations completed successfully.`));return}catch(e){return{error:e}}}async function runMigration(e,t,n,r){r.reached.add(t);let i=/* @__PURE__ */ new Set;r.touchedTables.push({namespace:t.namespace,tables:i});let a=e.validation.inProgressMigrations[t.namespace]?.number===t.number,o=usesStepRunner(t.scriptForm,a),s={migration:t,attemptedTables:i,inProgress:a,resumesPrePhase:migrationWithEarlierPrePhase(e.validation,t.namespace)===t.number,runsSteps:o,runsMain:t.hasScript&&!o,rollsBackOnFailure:o&&t.scriptForm?.kind===`steps`&&t.scriptForm.rollbackOnFailure===!0,gqlPermissionUndo:/* @__PURE__ */ new Map};await runPreMigrationPhase(e,s,n,r),await runPostMigrationPhase(e,s,n,r),await commitMigration(e,s,n,r)}async function runPreMigrationPhase(e,t,n,r){let{client:i,changeSet:a,phaseSettings:o,migrationCtx:s}=e,{migration:c,attemptedTables:l,inProgress:u,rollsBackOnFailure:d,gqlPermissionUndo:f}=t;e.timeline?.enter(`preMigration`);try{await B(`apply.tailorDB.migration.prePhase`,()=>executeSingleMigrationPrePhase(i,a,c,o,l,f)),c.hasScript&&s&&await B(`apply.tailorDB.migration.script`,()=>executeMigrations(s,[c],n.checkpoints,e.validation.inProgressMigrations,e.timeline))}catch(i){throw isMigrationOutcomeUnknown(i)||(d?!isRollbackSafe(i,u):u||isMigrationPartiallyApplied(i))?(r.partial.set(c.namespace,c),i):await rollbackMigration(e,t,n,r,i,u||isMigrationPartiallyApplied(i))}}function isRollbackSafe(e,t){return isMigrationRunEnded(e)?!0:!t&&!isMigrationPartiallyApplied(e)}async function runPostMigrationPhase(e,t,n,r){let{client:i,changeSet:a,phaseSettings:o}=e,{migration:s,attemptedTables:c,inProgress:l,runsSteps:u,rollsBackOnFailure:d,gqlPermissionUndo:f}=t;e.timeline?.enter(`postMigration`);try{await B(`apply.tailorDB.migration.postPhase`,()=>executeSingleMigrationPostPhase(i,a,s,o,c))}catch(p){if(!d&&(l||u))throw r.partial.set(s.namespace,s),await reapplyPrePhaseAfterPostPhaseFailure(i,a,s,o,c,f),p;let m=await rollbackMigration(e,t,n,r,p,!0);throw isRollbackSkippedWithRecord(m)&&await reapplyPrePhaseAfterPostPhaseFailure(i,a,s,o,c,f),m}}async function rollbackMigration(e,t,n,r,i,a){let{client:o,migrationContext:s,phaseSettings:c}=e,{migration:l,rollsBackOnFailure:u,runsMain:d,resumesPrePhase:f,gqlPermissionUndo:p}=t,{workspaceId:m}=s,h=d?`main`:`steps`,g=(u||d)&&a,_=g?await clearRolledBackRecord(o,m,l,h):`cleared`;if(_!==`cleared`)return r.partial.set(l.namespace,l),rollbackSkippedError(l,i,c.restricted,{confirmed:_===`in-progress`,kind:h},deployCommandContext(s));let v=new Set(t.attemptedTables),y=e.pending.lastByNamespace.get(l.namespace)??l;for(let e of readRollbackScope(l,y,p,f))v.add(e);return r.unrolledBack.push({migration:l,...await rollbackSingleMigrationAfterFailure(o,l,m,c,v,p)}),(u||g)&&await removeRunResources(o,m,l.namespace,l.number),isMigrationStartRefused(i)?i:(f&&settleRolledBackRestorationSettings(e,l,n),u?rolledBackError(l,i):i)}function readRollbackScope(e,t,n,r){try{let i=r?getPreMigrationTargetTableNames(e):/* @__PURE__ */ new Set,a=r?new Set(n.keys()):void 0;for(let[i,o]of gqlPermissionUndoFromSnapshots(e,t,a))(r||!n.has(i))&&n.set(i,o);return i}catch(t){return C.warn(`Could not read migration ${e.namespace}/${formatMigrationNumber(e.number)} or its prior checkpoint: ${t instanceof Error?t.message:String(t)}. Only what this deploy wrote is rolled back.`),/* @__PURE__ */ new Set}}function settleRolledBackRestorationSettings(e,t,n){let r=e.migrationContext.tailorDBInputs.find(e=>e.namespace===t.namespace),i=n.snapshots.get(t.namespace);if(!r||!i)return;let a=resolveMigrationSnapshotSettings(i,r,e.migrationContext.executorUsedTables),o=$s.load(t).tables;for(let[e,r]of n.settings.get(t.namespace)??[])!i.tables[e]&&!o[e]&&a.set(e,r);n.settings.set(t.namespace,a)}async function commitMigration(e,t,n,r){let{client:i,changeSet:a,migrationContext:o,phaseSettings:c}=e,{migration:u,resumesPrePhase:d,runsSteps:f,runsMain:p}=t,m=n.snapshots.get(u.namespace),h=n.settings.get(u.namespace),g=$s.load(u);n.snapshots.set(u.namespace,g);let _=e.validation.migrationHistoryIds[u.namespace]??null,v=c.restricted,y=getTablesDeletedAfterCheckpoint(u.diff),b=y.size>0,x=d,settleRestorationSettings=()=>{let e=o.tailorDBInputs.find(e=>e.namespace===u.namespace);if(!e)return;let t=resolveMigrationSnapshotSettings(g,e,o.executorUsedTables);for(let[e,n]of h??[])m?.tables[e]||(!x&&!isMigrationRestricted(n)||g.tables[e]===void 0)&&t.set(e,n);n.settings.set(u.namespace,t)};x&&settleRestorationSettings();try{await updateMigrationLabel(i,o.workspaceId,u.namespace,u.number,_??void 0,v,b)}catch(r){await confirmCheckpointAfterUpdateFailure(e,t,r,n,g)}n.checkpoints.set(u.namespace,{number:u.number,historyId:_}),v&&r.recordedNamespaces.add(u.namespace),(f||p)&&await removeRunResources(i,o.workspaceId,u.namespace,u.number),x||settleRestorationSettings();try{await deletePlannedTables(i,a,u.namespace,y)}catch(e){let t=formatNamespaceMigrationHint({...deployCommandContext(o),subcommand:[`sync`,formatMigrationNumber(u.number)],namespace:u.namespace});C.warn(`Migration checkpoint ${u.namespace}/${formatMigrationNumber(u.number)} was committed, but post-checkpoint cleanup failed.`+(c.restricted?` The leftover resources remain locked.`:``));let n=T(e);throw l(n,{suggestion:[`Deploy again to delete the leftover tables, or run ${t}.`,s(n).suggestion].filter(Boolean).join(` `)})}b&&await clearCleanupRecord(i,o.workspaceId,u.namespace)}async function clearCleanupRecord(e,t,n){try{await clearMigrationCleanupRecord(e,t,n)}catch(e){C.warn(`The tables of namespace '${n}' that were pending deletion have been deleted, but the record of the pending deletion could not be removed: ${T(e).message}. A later deploy removes it.`)}}async function confirmCheckpointAfterUpdateFailure(e,t,n,r,i){let{migration:a}=t,o=e.validation.migrationHistoryIds[a.namespace]??null,s;try{s=await fetchRemoteMigrationState(e.client,resourceTrn(e.migrationContext.workspaceId,`tailordb`,a.namespace))}catch(e){throw C.warn(`Could not verify migration checkpoint ${a.namespace}/${formatMigrationNumber(a.number)} after its update failed: ${e instanceof Error?e.message:String(e)}. Leaving the post-migration schema unchanged to avoid rolling back a committed checkpoint.`),n}let c=s.number??void 0,l=s.historyIdInvalid||s.historyId!==o?`${describeMigrationCheckpoint(s.number)} in a different migration history`:c!==void 0&&c>a.number?formatMigrationNumber(c):void 0;if(l!==void 0)throw r.snapshots.delete(a.namespace),E({code:`MIGRATION_CHECKPOINT_CONFLICT`,message:`Migration checkpoint ${a.namespace}/${formatMigrationNumber(a.number)} advanced concurrently to ${l}. Leaving the post-migration schema unchanged and aborting this deployment.`,cause:n});if(c!==a.number){r.snapshots.set(a.namespace,includeTablesDeletedAfterCheckpoint(i,a.diff));let e=s.inProgress?.kind===`steps`&&s.inProgress.number===a.number&&(c??0)===a.number-1;throw C.warn(`Migration checkpoint ${a.namespace}/${formatMigrationNumber(a.number)} could not be confirmed after its update failed; remote remains at ${describeMigrationCheckpoint(c)}. Leaving the post-migration schema unchanged to avoid rolling back a concurrent deployment. `+(e?`Deploy again to resume the migration; unless you add, remove, rename, or reorder steps, steps that already completed do not run again.`:`Repair the checkpoint before retrying.`)),n}}function restrictionHistoryOf(e,t,n){return{maintenanceMode:e.phaseSettings.restricted,captured:e.settingsBeforeMaintenanceMode,resumed:migrationWithEarlierPrePhase(e.validation,n)!==void 0,touched:new Set(t.touchedTables.flatMap(e=>e.namespace===n?[...e.tables]:[]))}}async function verifyRestorationCheckpoints(e,t,n,r){let i=r,a={};for(let[r,o]of t.checkpoints){let s=await checkRestorationCheckpoint(e,t,n,r,o);s&&(i?(C.warn(`${s.message} The original migration error is reported below.`),s.suggestion&&C.log(s.suggestion),a[`restorationSkipped:${r}`]=s):i={error:s})}return{failure:i,restorationFailures:a}}async function checkRestorationCheckpoint(e,t,n,r,i){let{restricted:a}=e.phaseSettings,o=formatNamespaceMigrationHint({...deployCommandContext(e.migrationContext),subcommand:[`status`],namespace:r}),s;try{s=await fetchRemoteMigrationState(e.client,resourceTrn(e.migrationContext.workspaceId,`tailordb`,r))}catch(s){let c=skipRestoration(e,t,n,r);return E({code:`MIGRATION_CHECKPOINT_UNVERIFIED`,message:`Could not verify ownership of migration checkpoint ${r}/${describeMigrationCheckpoint(i.number)} before restoring table settings: ${s instanceof Error?s.message:String(s)}. Skipping restoration for this namespace and aborting this deployment.`,suggestion:(a?`The tables of namespace '${r}' keep the restrictions this deploy set (${tc}). `:`The table settings of namespace '${r}' are left unchanged. `)+`${describeSkippedTables(c)}Run ${o} to check the checkpoint, restore connectivity if it fails, then deploy again.`,context:{namespace:r,expectedCheckpoint:i.number,tables:c}})}if(isCheckpointStillOwned(s,i))return;let c=skipRestoration(e,t,n,r);return E({code:`MIGRATION_CHECKPOINT_CONFLICT`,message:`Migration checkpoint ${r}/${describeMigrationCheckpoint(i.number)} advanced concurrently to ${describeMigrationCheckpoint(s.number)}. Skipping restoration for this namespace and aborting this deployment.`,suggestion:(a?`Another deploy changed the checkpoint, so the tables of namespace '${r}' keep the restrictions this deploy set (${tc}). `:`Another deploy changed the checkpoint, so the table settings of namespace '${r}' are left unchanged. `)+`${describeSkippedTables(c)}Wait for the other deploy to finish, run ${o} to see the checkpoint and any migration in progress, then check the tables before deploying again.`,context:{namespace:r,expectedCheckpoint:i.number,remoteCheckpoint:s.number,tables:c}})}function skipRestoration(e,t,n,r){let i=skippedRestorationTables(r,t.snapshots,t.settings,restrictionHistoryOf(e,n,r));return t.snapshots.delete(r),t.skipped.add(r),i}function keepPartialMigrationsRestricted(e,t,n){let{pendingMigrations:r,inProgressMigrations:i}=e.validation;for(let e of r)i[e.namespace]?.number===e.number&&!n.reached.has(e)&&n.partial.set(e.namespace,e);for(let[r,i]of n.partial){let a=keepMigrationTablesRestricted(r,i,t.snapshots,t.settings,restrictionHistoryOf(e,n,r));warnTablesLeftRestricted(`Migration ${r}/${formatMigrationNumber(i.number)} is partially applied.`,[{namespace:r,tables:a}])}}async function restoreTables(e,t,n,r){let{migrationContext:i}=e;await restoreMigrationRestrictions(r,t.snapshots,t.settings,i.tailorDBInputs,i.executorUsedTables,i.workspaceId,e.phaseSettings.restricted),e.timeline?.finish();let a=/* @__PURE__ */ new Set([...n.recordedNamespaces,...Object.keys(e.validation.maintenanceModeCheckpoints)]);for(let e of a)t.snapshots.has(e)&&await clearRecordAfterRelease(r,i.workspaceId,e)}async function releaseHeldMaintenanceMode(e,t,n,r){e.timeline?.enter(`restore`);let i=await findUnownedMigrationCheckpoints(r,e.migrationContext.workspaceId,t.checkpoints,`Leaving its table settings unchanged.`);for(let e of i.keys())t.snapshots.delete(e);let[a,...o]=i.values();for(let e of o)C.warn(e.message);try{await restoreTables(e,t,n,r)}catch(e){if(!a)throw e;C.warn(`Could not restore every TailorDB table: ${T(e).message}.`)}if(a)throw a;return finishMaintenance(e)}async function restoreAfterMigrations(e,t,n,r){try{return await restoreTables(e,t,n,e.client),[]}catch(t){if(!r.failure)throw t;let n=readUnrestoredTables(t),i=`Could not restore every TailorDB table after the migration failed: ${T(t).message}.`;return e.phaseSettings.restricted?warnTablesLeftRestricted(i,n,{namesUnknown:n.every(e=>e.tables.length===0)}):C.warn(i),C.log(`The original migration error is reported below.`),t instanceof Error&&(r.restorationFailures.restoration=t),n}}function warnIncompleteRollbacks(e,t,n,r){for(let{migration:i,tables:a,permissions:o}of n.unrolledBack){let n=r.find(e=>e.namespace===i.namespace),s=new Set(t.skipped.has(i.namespace)||n?.tables.length===0?[]:[...Object.keys(t.snapshots.get(i.namespace)?.tables??{}),...t.settings.get(i.namespace)?.keys()??[]].filter(e=>!n?.tables.includes(e)));o.length>0&&(C.warn(`Migration ${i.namespace}/${formatMigrationNumber(i.number)} was not rolled back completely. GraphQL permissions needing manual repair in namespace '${i.namespace}': ${o.join(`, `)}.`),C.log(`Check the GraphQL permission of these tables in the workspace and set it back by hand.`));let c=a.filter(e=>!s.has(e));c.length!==0&&(e.phaseSettings.restricted?warnTablesLeftRestricted(`Migration ${i.namespace}/${formatMigrationNumber(i.number)} was not rolled back completely.`,[{namespace:i.namespace,tables:c}],{recovery:rc}):(C.warn(`Migration ${i.namespace}/${formatMigrationNumber(i.number)} was not rolled back completely. Tables needing manual repair in namespace '${i.namespace}': ${c.join(`, `)}.`),C.log(rc)))}}function finishMaintenance(e){if(!e.timeline)return;let t=e.timeline.report([...e.migratingNamespaces]);return C.info(formatMaintenanceSummary(t)),t}function collectLocalDefinitionWrites(e){let{changeSet:t,migrationContext:n}=e,r=/* @__PURE__ */ new Map,i=/* @__PURE__ */ new Set;for(let n of t.type.creates){let t=n.request.namespaceName,a=n.request.tailordbType?.name;if(!t||!a||!e.migratingNamespaces.has(t))continue;let o=namespacedTableKey(t,a);Qs.created.has(o)||(r.set(t,[...r.get(t)??[],n]),i.add(o))}let a=/* @__PURE__ */ new Map;for(let[r,o]of e.pending.lastByNamespace){let e=n.tailorDBInputs.find(e=>e.namespace===r);if(!e)continue;let s=$s.load(o).tables,comparable=t=>normalizeComparableTailorDBType(generateTailorDBTypeManifestFromSnapshot(t,{subscribed:n.executorUsedTables.has(t.name),namespaceGqlOperations:e.config.gqlOperations})),c=Object.entries(e.types).filter(([e,n])=>{let a=namespacedTableKey(r,e);if(i.has(a))return!1;let o=s[e];return o?!areNormalizedEqual(comparable(n),comparable(o)):Qs.created.has(a)||t.type.updates.some(t=>t.request.namespaceName===r&&t.name===e)});c.length>0&&a.set(r,Object.fromEntries(c))}return{creates:r,updates:a}}function isRefusedByRecords(e){return e instanceof q?e.code===K.AlreadyExists||e.code===K.FailedPrecondition&&e.details.some(e=>`type`in e&&e.type===`google.rpc.PreconditionFailure`):!1}function localDefinitionError(e,t,n){let{namespaceName:r,tableName:i,refusedByRecords:o}=t,c=T(n),u=a(e.pending.lastByNamespace.get(r),`local definitions are written only to namespaces with pending migrations`),d=[...t.created].map(([e,t])=>({namespace:e,tables:t})),f=formatNamespaceMigrationHint({subcommand:[`generate`],namespace:r,configPath:e.migrationContext.config.path});return l(c,{code:`MIGRATION_LOCAL_DEFINITIONS_FAILED`,suggestion:[`The pending migrations completed, and the existing tables of namespace '${r}' keep the definitions of migration ${r}/${formatMigrationNumber(u.number)}.`,d.length>0&&`Tables created for their local definitions remain: ${d.map(e=>`namespace '${e.namespace}': ${e.tables.join(`, `)}`).join(`; `)}.`,o&&`The local definition of table '${i}' conflicts with its existing records and is not in any migration: run ${f} to add it with a migration script that updates those records, then deploy again.`,s(c).suggestion,!o&&`Once the cause is fixed, deploy again to apply the local definition of table '${i}'.`].filter(Boolean).join(` `),context:{namespace:r,table:i,created:d}})}async function applyLocalDefinitions(e,t){let{client:n,migrationContext:r,phaseSettings:i}=e;if(!r.noSchemaCheck)return;let{creates:o,updates:s}=collectLocalDefinitionWrites(e);if(o.size===0&&s.size===0)return;let c=/* @__PURE__ */ new Map;e.timeline?.enter(`postMigration`);try{for(let[t,r]of o)for(let i of r){let r=i.name;try{await n.createTailorDBType(i.request)}catch(n){return{error:localDefinitionError(e,{namespaceName:t,tableName:r,created:c,refusedByRecords:!1},n)}}c.set(t,[...c.get(t)??[],r])}for(let[t,a]of s)for(let[o,s]of Object.entries(a))try{await n.updateTailorDBType({workspaceId:r.workspaceId,namespaceName:t,tailordbType:generateMigrationPhaseManifest(s,t,i)})}catch(n){return{error:localDefinitionError(e,{namespaceName:t,tableName:o,created:c,refusedByRecords:isRefusedByRecords(n)},n)}}}finally{e.timeline?.enter(`restore`)}for(let[e,n]of s){let i=a(t.snapshots.get(e),`every migrating namespace that passed checkpoint verification has a snapshot to restore`);t.snapshots.set(e,{...i,tables:{...i.tables,...n}});let o=a(r.tailorDBInputs.find(t=>t.namespace===e),`local definitions come from the namespace's deploy input`),s=t.settings.get(e);s&&t.settings.set(e,new Map([...s,...resolveMigrationSnapshotSettings({...i,tables:n},o,r.executorUsedTables)]))}for(let t of e.migratingNamespaces){let n=[...(o.get(t)??[]).map(e=>e.name),...Object.keys(s.get(t)??{})].toSorted();if(n.length===0)continue;let r=a(e.pending.lastByNamespace.get(t),`every migrating namespace has a last pending migration`);C.info(`Applied local definitions that migration ${t}/${formatMigrationNumber(r.number)} does not include, after the pending migrations: ${n.join(`, `)}.`)}}async function applyDeferredGqlPermissions(e,t){let{client:n,changeSet:r}=e;await Promise.all([...r.gqlPermission.creates.filter(e=>t.has(`${e.request.namespaceName}/${e.name}`)).map(e=>n.createTailorDBGQLPermission(e.request)),...r.gqlPermission.updates.filter(e=>t.has(`${e.request.namespaceName}/${e.name}`)).map(e=>n.updateTailorDBGQLPermission(e.request))])}function isDeleted(e,t){return e.has(`${t.request.namespaceName}/${t.name}`)}async function applyRemainingDeletions(e,t,n){await Promise.all(t.gqlPermission.deletes.filter(e=>!isDeleted(ec.gqlPermissions,e)).map(t=>e.deleteTailorDBGQLPermission(t.request))),await awaitAllSettledOrThrow(t.type.deletes.filter(e=>!isDeleted(ec.types,e)).map(async t=>{await e.deleteTailorDBType(t.request),n(t)}))}function excludeFromRestoration(e,t){let n=a(t.request.namespaceName,`every planned table deletion names its namespace`),r=e.settings.get(n);r?.has(t.name)&&e.settings.set(n,new Map([...r].filter(([e])=>e!==t.name)))}async function applyWithoutMigrations(e,t){await executeServicesCreation(e,t);try{for(let n of t.type.creates)await e.createTailorDBType(n.request),await writeMetadataLabels(e,n.metaRequest);for(let n of t.type.updates)await e.updateTailorDBType(n.request),await writeMetadataLabels(e,n.metaRequest);await Promise.all(t.type.unchanged.flatMap(t=>t.metaRequest?[writeMetadataLabels(e,t.metaRequest)]:[]))}catch(e){handleOptionalToRequiredError(e,ac)}await Promise.all([...t.gqlPermission.creates.map(t=>e.createTailorDBGQLPermission(t.request)),...t.gqlPermission.updates.map(t=>e.updateTailorDBGQLPermission(t.request))]),await applyRemainingDeletions(e,t,()=>{})}async function executeServicesCreation(e,t){await Promise.all([...t.service.creates.map(async t=>{await e.createTailorDBService(t.request),await writeMetadataLabels(e,t.metaRequest)}),...t.service.updates.map(t=>writeMetadataLabels(e,t.metaRequest))])}function itemKey(e){return`${e.request?.namespaceName??``}/${e.name}`}function collectTailorDBDisplayEntries(e,t,n){let r=new Set(t.map(itemKey)),i=new Map(n.map(e=>[itemKey(e),e])),a=t.map(t=>{let n=i.get(itemKey(t)),r=t.forcedBySdkVersion&&(!n||n.forcedBySdkVersion);return{action:e,symbol:wa[e],name:t.name,labels:n?[`table`,`gqlPermission`]:[`table`],namespace:t.request?.namespaceName,...r&&{forcedBySdkVersion:!0}}}),o=n.filter(e=>!r.has(itemKey(e))).map(t=>({action:e,symbol:wa[e],name:t.name,labels:[`gqlPermission`],namespace:t.request?.namespaceName,...t.forcedBySdkVersion&&{forcedBySdkVersion:!0}}));return[...a,...o]}function formatTailorDBResourceChangeEntries(e,t){return[...collectTailorDBDisplayEntries(`create`,e.creates,t.creates),...collectTailorDBDisplayEntries(`delete`,e.deletes,t.deletes),...collectTailorDBDisplayEntries(`update`,e.updates,t.updates),...collectTailorDBDisplayEntries(`replace`,e.replaces,t.replaces)]}async function planTailorDB(e){let{client:t,workspaceId:n,application:r,forRemoval:i,config:a,noSchemaCheck:o,migrationSkipSteps:s,migrationRecoveryArgs:c,forceApplyAll:l=!1}=e,u=[],d=e.migrationTestSnapshots??(e.migrationTestBaselines?new Map([...e.migrationTestBaselines].map(([e,t])=>[e,t.snapshot])):void 0);if(!i)for(let e of r.tailorDBServices){await e.loadTypes();let t=toTailorDBDeployInput(e),n=d?.get(e.namespace);u.push(n?{...t,types:n.tables}:t)}let f=i?[]:Object.values(await r.executorService?.loadExecutors()??{}),p=new Set(e.executorUsedTailorDBTables??[]);for(let e of f)subscribesToEvents(e)&&e.trigger.kind===`tailordb`&&p.add(e.trigger.tableName);let m=/* @__PURE__ */ new Map;for(let e of u)m.set(e.namespace,e.types);let h=e.migrationTestBaselines;if(d){for(let e of d.keys())if(!u.some(t=>t.namespace===e))throw E({code:`MIGRATION_TEST_SNAPSHOT_INVALID`,message:`Migration test snapshot targets unknown TailorDB namespace "${e}".`});let e=/* @__PURE__ */ new Map;for(let t of u)for(let n of Object.keys(t.types)){let r=e.get(n);if(r)throw E({code:`MIGRATION_TEST_SNAPSHOT_INVALID`,message:`Migration test snapshot has duplicate TailorDB table name "${n}" in namespaces "${r}" and "${t.namespace}".`});e.set(n,t.namespace)}}let g=i?[]:getNamespacesWithMigrations(a,H.dirname(a.path)),_=i||h?void 0:await validateAndDetectMigrations(t,n,m,a,o??!1,u,c);_&&(await assertPendingMigrationsRunnable({client:t,workspaceId:n,requested:selectSkipStepsOfNamespaces(s,u.map(e=>e.namespace)),pendingMigrations:_.pendingMigrations,inProgressByNamespace:_.inProgressMigrations,source:e}),logMigrationPlanNotices(_));let{namespacesWithMigrations:v,migrationFileState:y,checkpointRepairs:b,pendingMigrations:x}=_??{namespacesWithMigrations:g,migrationFileState:captureMigrationFileState(g),checkpointRepairs:[],pendingMigrations:[]},{changeSet:S,conflicts:C,unmanaged:w,resourceOwners:T}=await planServices(t,n,r.name,r.id,u),ee=S.deletes.map(e=>e.name),[D,te]=await Promise.all([planTypes(t,n,u,p,ee,void 0,l,{appName:r.name,appId:r.id,dependentApps:e.dependentApps,runAppIds:e.runAppIds}),planGqlPermissions(t,n,u,ee,l)]);return D.creates.sort(Mt),D.updates.sort(Mt),D.deletes.sort(Mt),{changeSet:{service:S,type:D,gqlPermission:te},conflicts:C,unmanaged:w,resourceOwners:T,context:{workspaceId:n,application:r,tailorDBInputs:u,executorUsedTables:p,config:a,noSchemaCheck:o??!1,...s?{migrationSkipSteps:s}:{},...c?{migrationRecoveryArgs:c}:{},...h?{migrationTestBaselines:h}:{},...e.migrationMachineUserOverride===void 0?{}:{migrationMachineUserOverride:e.migrationMachineUserOverride},namespacesWithMigrations:v,migrationFileState:y,checkpointRepairs:b,pendingMigrations:x.map(({namespace:e,number:t})=>({namespace:e,number:t}))}}}async function planServices(e,t,n,r,i){let a=createChangeSet(`TailorDB services`),o=createOwnershipTracker(n,r),s=await fetchExistingResourcesWithLabels({client:e,fetchPage:async(n,r)=>{let{tailordbServices:i,nextPageToken:a}=await e.listTailorDBServices({workspaceId:t,pageToken:n,pageSize:r});return[i,a]},getName:e=>e.namespace?.name,getTrn:e=>resourceTrn(t,`tailordb`,e)});for(let e of i){let i=s[e.namespace],c=await buildMetaRequest({trn:resourceTrn(t,`tailordb`,e.namespace),appName:n,appId:r});if(i){let t=o.ownsDesired(i.allLabels,{resourceType:`tailordb.service`,resourceLabel:`TailorDB service`,resourceName:e.namespace})&&areTailorDBServicesEqual(i.resource,e);t&&hasMatchingSdkVersion(i.allLabels,c.labels)?a.unchanged.push({name:e.namespace}):a.updates.push({name:e.namespace,metaRequest:c,...t&&{forcedBySdkVersion:!0}}),delete s[e.namespace]}else a.creates.push({name:e.namespace,request:{workspaceId:t,namespaceName:e.namespace,defaultTimezone:`UTC`},metaRequest:c})}return Object.entries(s).forEach(([e])=>{let n=s[e];o.ownsRemaining(n?.allLabels)&&a.deletes.push({name:e,request:{workspaceId:t,namespaceName:e}})}),{changeSet:a,...o.result}}async function planTypes(e,t,n,r,i,a,o=!1,s={}){let c=createChangeSet(`TailorDB tables`),{appName:l,appId:u,dependentApps:d,runAppIds:f}=s,typeMetaRequest=async(e,n,r)=>addDependencyRecords(await buildMetaRequest({trn:tailorDBTypeTrn(t,e,n),appName:l??``,appId:u}),{key:Z.tailorDBType(e,n),dependentApps:d,runAppIds:f,pinned:r!==void 0}),fetchTypes=n=>F(async(r,i)=>{let{tailordbTypes:a,nextPageToken:o}=await e.listTailorDBTypes({workspaceId:t,namespaceName:n,pageToken:r,pageSize:i});return[a,o]});for(let e of n){let t=a?.get(e.namespace)??e.types;for(let[e,n]of Object.entries(t))assertNoPublishEventsConflict({explicit:n.settings?.publishEvents,subscribed:r.has(e),conflict:Ea.tailorDBType(e)})}for(let e of n){let n=await fetchTypes(e.namespace),i=new Map(n.map(e=>[e.name,e])),s=a?.get(e.namespace)??e.types,typeMeta=t=>typeMetaRequest(e.namespace,t,s[t]?.settings?.publishEvents);for(let[n,a]of Object.entries(s)){let s=generateTailorDBTypeManifestFromSnapshot(a,{subscribed:r.has(n),namespaceGqlOperations:e.config.gqlOperations}),l=i.get(n);if(l){let r=areNormalizedEqual(normalizeComparableTailorDBType(l),normalizeComparableTailorDBType(s));!o&&r?c.unchanged.push({name:n,metaRequest:await typeMeta(n)}):c.updates.push({name:n,request:{workspaceId:t,namespaceName:e.namespace,tailordbType:s},metaRequest:await typeMeta(n),...r&&{forcedBySdkVersion:!0}}),i.delete(n)}else c.creates.push({name:n,request:{workspaceId:t,namespaceName:e.namespace,tailordbType:s},metaRequest:await typeMeta(n)})}i.forEach((n,r)=>{c.deletes.push({name:r,request:{workspaceId:t,namespaceName:e.namespace,tailordbTypeName:r}})})}for(let e of i)(await fetchTypes(e)).forEach(n=>{c.deletes.push({name:n.name,request:{workspaceId:t,namespaceName:e,tailordbTypeName:n.name}})});return c}async function planGqlPermissions(e,t,n,r,i=!1){let a=createChangeSet(`TailorDB gqlPermissions`),fetchGqlPermissions=n=>F(async(r,i)=>{let{permissions:a,nextPageToken:o}=await e.listTailorDBGQLPermissions({workspaceId:t,namespaceName:n,pageToken:r,pageSize:i});return[a,o]});for(let e of n){let n=await fetchGqlPermissions(e.namespace),r=/* @__PURE__ */ new Set;n.forEach(e=>{r.add(e.typeName)});let o=e.types;for(let[s,c]of Object.entries(o)){let o=c.permissions?.gql;if(!o)continue;let l=protoGqlPermission(o),u=n.find(e=>e.typeName===s);if(r.has(s)){let n=!!u&&areNormalizedEqual(normalizeComparableGqlPermission(u.permission),normalizeComparableGqlPermission(l));!i&&n?a.unchanged.push({name:s}):a.updates.push({name:s,request:{workspaceId:t,namespaceName:e.namespace,typeName:s,permission:l},previousPermission:u?.permission,...n&&{forcedBySdkVersion:!0}}),r.delete(s)}else a.creates.push({name:s,request:{workspaceId:t,namespaceName:e.namespace,typeName:s,permission:l}})}r.forEach(n=>{a.deletes.push({name:n,request:{workspaceId:t,namespaceName:e.namespace,typeName:n}})})}for(let e of r)(await fetchGqlPermissions(e)).forEach(n=>{a.deletes.push({name:n.typeName,request:{workspaceId:t,namespaceName:e,typeName:n.typeName}})});return a}async function applyWorkflow(e,t,n=`create-update`){let{changeSet:r,appName:i,appId:a}=t;if(n===`create-update`){let n=await registerJobFunctions(e,r,i,a,t.unchangedWorkflowJobNames,t.jobFunctionPublishEvents);await Promise.all([...r.creates.map(async t=>{let r=filterJobFunctionVersions(n,t.usedJobNames),i=buildWorkflowValidationShape(t.workspaceId,t.workflow);await e.createWorkflow({workspaceId:i.workspaceId,workflowName:i.workflowName,mainJobFunctionName:i.mainJobFunctionName,retryPolicy:i.retryPolicy,concurrencyPolicy:i.concurrencyPolicy,jobFunctions:r,publishExecutionEvents:i.publishExecutionEvents}),await writeMetadataLabels(e,t.metaRequest)}),...r.updates.map(async t=>{let r=filterJobFunctionVersions(n,t.usedJobNames),i=buildWorkflowValidationShape(t.workspaceId,t.workflow);await e.updateWorkflow({workspaceId:i.workspaceId,workflowName:i.workflowName,mainJobFunctionName:i.mainJobFunctionName,retryPolicy:i.retryPolicy,concurrencyPolicy:i.concurrencyPolicy,jobFunctions:r,publishExecutionEvents:i.publishExecutionEvents}),await writeMetadataLabels(e,t.metaRequest)}),...r.unchanged.flatMap(t=>t.metaRequest?[writeMetadataLabels(e,t.metaRequest)]:[])])}else await deleteAllSettled(r.deletes.map(t=>({resourceLabel:`workflow`,resourceName:t.name,run:()=>e.deleteWorkflow({workspaceId:t.workspaceId,workflowId:t.workflowId})}))),await deleteAllSettled(t.jobFunctionDeletes.map(t=>({resourceLabel:`workflow job function`,resourceName:t.jobFunctionName,run:()=>e.deleteWorkflowJobFunction({workspaceId:t.workspaceId,jobFunctionName:t.jobFunctionName})})))}async function deleteAllSettled(e){let t=await Promise.allSettled(e.map(e=>e.run())),n=[];t.forEach((t,r)=>{if(t.status===`fulfilled`)return;let i=a(e[r],`operation missing at index`),o=t.reason;o instanceof q&&o.code===K.NotFound||(o instanceof q&&o.code===K.FailedPrecondition?C.warn(`Skipped deleting ${i.resourceLabel} "${i.resourceName}" because it is still referenced.`):n.push(T(o)))});let r=n[0];if(r)throw r}function filterJobFunctionVersions(e,t){let n={};for(let r of t)e[r]!==void 0&&(n[r]=e[r]);return n}async function registerJobFunctions(e,t,n,r,i=/* @__PURE__ */ new Set,a=/* @__PURE__ */ new Map){let o={},s=t.creates[0]||t.updates[0]||t.deletes[0];if(!s)return o;let{workspaceId:c}=s,l=/* @__PURE__ */ new Set;i.forEach(e=>l.add(e));for(let e of[...t.creates,...t.updates])for(let t of e.usedJobNames)l.add(t);let u=await Nt(async(t,n)=>{let r=await e.listWorkflowJobFunctions({workspaceId:c,pageToken:t,pageSize:n});return[r.jobFunctions.map(e=>e.name),r.nextPageToken]}),d=new Set(u);if(t.creates.length>0||t.updates.length>0){let t=await Promise.all(Array.from(l).map(async t=>{let i=d.has(t),o={workspaceId:c,jobFunctionName:t,scriptRef:workflowJobFunctionName(t),publishExecutionEvents:a.get(t)??!1},s=i?await e.updateWorkflowJobFunction(o):await e.createWorkflowJobFunction(o);return await writeMetadataLabels(e,await buildMetaRequest({trn:resourceTrn(c,`workflow_job_function`,t),appName:n,appId:r})),{jobName:t,version:s.jobFunction?.version}}));for(let{jobName:e,version:n}of t)n&&(o[e]=n)}return o}function parseDurationToProto(e){let t=he(e),n=Math.floor(t/1e3),r=t%1e3*1e6;return{seconds:BigInt(n),nanos:r}}function toRetryPolicy(e){return{maxRetries:e.maxRetries,initialBackoff:parseDurationToProto(e.initialBackoff),maxBackoff:parseDurationToProto(e.maxBackoff),backoffMultiplier:e.backoffMultiplier}}function toConcurrencyPolicy(e){return{maxConcurrentExecutions:e.maxConcurrentExecutions}}function buildWorkflowValidationShape(e,t){return{workspaceId:e,workflowName:t.name,mainJobFunctionName:t.mainJob.name,...t.retryPolicy&&{retryPolicy:toRetryPolicy(t.retryPolicy)},...t.concurrencyPolicy&&{concurrencyPolicy:toConcurrencyPolicy(t.concurrencyPolicy)},publishExecutionEvents:t.publishEvents??!1}}const oc={workflowNames:/* @__PURE__ */ new Set};function isSubscribed(e,t){return e.workflowNames.has(t)}function subscribedWorkflowJobNames(e){let{workflows:t,mainJobDeps:n,isSubscribed:r}=e,i=/* @__PURE__ */ new Set;for(let e of t)if(r(e.name))for(let t of n[e.mainJob.name]??[])i.add(t);return i}function resolveJobPublishEvents(e){let{workflows:t,mainJobDeps:n,subscribers:r,explicit:i}=e,a=/* @__PURE__ */ new Set;for(let e of Object.values(t))for(let t of n[e.mainJob.name]??[])a.add(t);let o=subscribedWorkflowJobNames({workflows:Object.values(t),mainJobDeps:n,isSubscribed:e=>isSubscribed(r,e)}),s=/* @__PURE__ */ new Map;for(let e of a)s.set(e,resolvePublishEvents({explicit:i.get(e),subscribed:o.has(e),conflict:Ea.workflowJob(e)}));return s}function collectStaleJobFunctionNames(e,t){let n=/* @__PURE__ */ new Set;for(let[r,i]of t){let t=e.get(r);t&&t.publishExecutionEvents!==i&&n.add(r)}return n}async function planWorkflow(e,t,n,r,i,a,o=/* @__PURE__ */ new Set,s={},c,l=/* @__PURE__ */ new Set){let u=createChangeSet(`Workflows`),d=createOwnershipTracker(n,r),f=/* @__PURE__ */ new Set,p=/* @__PURE__ */ new Set,m=s.execution??oc,{dependentApps:h,runAppIds:g}=s,everyJobDeclaresPublishEvents=e=>{let t=a[i[e]?.mainJob.name??``]??[],n=s.jobPublishEvents??/* @__PURE__ */ new Map;return t.length>0&&t.every(e=>n.has(e))},_=c?.existingJobFunctions??await fetchExistingJobFunctions(e,t),v=resolveJobPublishEvents({workflows:i,mainJobDeps:a,subscribers:s.jobExecution??oc,explicit:s.jobPublishEvents??/* @__PURE__ */ new Map}),y=collectStaleJobFunctionNames(_,v),b=c?.existingWorkflows??await fetchExistingResourcesWithLabels({client:e,fetchPage:async(n,r)=>{let i=await e.listWorkflows({workspaceId:t,pageToken:n,pageSize:r});return[i.workflows,i.nextPageToken]},getName:e=>e.name,getTrn:e=>resourceTrn(t,`workflow`,e)}),x={...b};for(let e of Object.values(i)){let i=x[e.name],s=addDependencyRecords(await buildMetaRequest({trn:resourceTrn(t,`workflow`,e.name),appName:n,appId:r}),{key:Z.workflow(e.name),dependentApps:h,runAppIds:g,pinned:e.publishEvents!==void 0});addDependencyRecords(s,{key:Z.workflowJobs(e.name),dependentApps:h,runAppIds:g,pinned:everyJobDeclaresPublishEvents(e.name),scope:`jobs`});let c=a[e.mainJob.name];if(!c)throw E({code:`WORKFLOW_MAIN_JOB_NOT_FOUND`,message:`Job "${e.mainJob.name}" (mainJob of workflow "${e.name}") was not found.`,details:`Possible causes:
|
|
103
103
|
- The job is not exported as a named export
|
|
104
|
-
- The file containing the job is not included in workflow.files glob pattern`,suggestion:`Export the job: export const ${e.mainJob.name} = createWorkflowJob({ name: "${e.mainJob.name}", ... })`});c.forEach(e=>p.add(e));let _={...e,publishEvents:resolvePublishEvents({explicit:e.publishEvents,subscribed:isSubscribed(m,e.name),conflict:Ca.workflow(e.name)})};if(i){let n=d.ownsDesired(i.allLabels,{resourceType:`workflow`,resourceLabel:`Workflow`,resourceName:e.name})&&!c.some(e=>y.has(e))&&areWorkflowsEqual(i.resource,_,c),r=hasMatchingSdkVersion(i.allLabels,s.labels);if(n&&r&&c.every(e=>o.has(e))){u.unchanged.push({name:e.name,metaRequest:s});for(let e of c)f.add(e)}else{let r=n&&c.every(e=>o.has(e)||l.has(e));u.updates.push({name:e.name,workspaceId:t,workflow:_,usedJobNames:c,metaRequest:s,...r&&{forcedBySdkVersion:!0}})}delete x[e.name]}else u.creates.push({name:e.name,workspaceId:t,workflow:_,usedJobNames:c,metaRequest:s})}let S=[];Object.values(x).forEach(e=>{if(!e)return;let n=d.ownsRemaining(e.allLabels),r=getExistingWorkflowJobNames(e.resource);n?S.push({name:e.resource.name,workspaceId:t,workflowId:e.resource.id,usedJobNames:r,deletableJobNames:[]}):r.forEach(e=>p.add(e))});let C=await planWorkflowJobFunctionDeletes({client:e,workspaceId:t,ownership:d,existingJobFunctionNames:[..._.keys()],retainedWorkflowJobNames:p}),w=new Set(C.map(e=>e.jobFunctionName));for(let e of S)u.deletes.push({...e,deletableJobNames:e.usedJobNames.filter(e=>!p.has(e)&&w.has(e))});return{changeSet:u,...d.result,appName:n,appId:r,unchangedWorkflowJobNames:f,jobFunctionDeletes:C,jobFunctionPublishEvents:v,existingJobFunctions:_,existingWorkflows:b}}async function fetchExistingJobFunctions(e,t){let n=await jt(async(n,r)=>{let i=await e.listWorkflowJobFunctions({workspaceId:t,pageToken:n,pageSize:r});return[i.jobFunctions,i.nextPageToken]});return new Map(n.map(e=>[e.name,e]))}async function planWorkflowJobFunctionDeletes(e){let{client:t,workspaceId:n,ownership:r,existingJobFunctionNames:i,retainedWorkflowJobNames:a}=e,o=i.filter(e=>!a.has(e));return(await Promise.all(o.map(async e=>{let{metadata:i}=await t.getMetadata({trn:resourceTrn(n,`workflow_job_function`,e)});return r.ownsRemaining(i?.labels)?{workspaceId:n,jobFunctionName:e}:void 0}))).filter(e=>e!==void 0)}function formatWorkflowChangeEntries(e,t,n){let r=new Set(n.map(e=>workflowJobFunctionName(e.jobFunctionName))),isJobFunctionRegistryDelete=e=>r.has(e.name);return[...formatChangeEntriesWithFunctionRegistry(`workflow`,e,{...t,deletes:t.deletes.filter(e=>!isJobFunctionRegistryDelete(e))},e=>`usedJobNames`in e?e.usedJobNames.map(e=>workflowJobFunctionName(e)):[]),...formatChangeEntriesWithFunctionRegistry(`jobFunction`,{creates:[],updates:[],deletes:n.map(e=>({name:e.jobFunctionName})),replaces:[]},{creates:[],updates:[],deletes:t.deletes.filter(isJobFunctionRegistryDelete),replaces:[]},e=>[workflowJobFunctionName(e.name)])]}function areWorkflowsEqual(e,t,n){return e.mainJobFunctionName===t.mainJob.name&&(e.publishExecutionEvents??!1)===(t.publishEvents??!1)&&areNormalizedEqual(normalizeComparableExistingWorkflowRetryPolicy(e.retryPolicy),normalizeComparableWorkflowRetryPolicy(t.retryPolicy))&&areNormalizedEqual(normalizeComparableConcurrencyPolicy(e.concurrencyPolicy),normalizeComparableConcurrencyPolicy(t.concurrencyPolicy))&&areNormalizedEqual(normalizeComparableWorkflowJobNames(e.jobFunctions),normalizeComparableWorkflowJobNames(n))}function normalizeComparableExistingWorkflowRetryPolicy(e){if(e)return normalizeRetryPolicyForCompare({maxRetries:e.maxRetries??0,backoffMultiplier:e.backoffMultiplier??0,initialBackoff:{seconds:e.initialBackoff?.seconds??0n,nanos:e.initialBackoff?.nanos??0},maxBackoff:{seconds:e.maxBackoff?.seconds??0n,nanos:e.maxBackoff?.nanos??0}})}function normalizeComparableWorkflowRetryPolicy(e){if(e)return normalizeRetryPolicyForCompare({maxRetries:e.maxRetries,backoffMultiplier:e.backoffMultiplier,initialBackoff:parseDurationToProto(e.initialBackoff),maxBackoff:parseDurationToProto(e.maxBackoff)})}function normalizeComparableConcurrencyPolicy(e){if(e&&e.maxConcurrentExecutions)return{maxConcurrentExecutions:e.maxConcurrentExecutions}}function normalizeComparableWorkflowJobNames(e){return Array.isArray(e)?e.toSorted():Object.keys(e??{}).toSorted()}function getExistingWorkflowJobNames(e){let t=new Set(Object.keys(e.jobFunctions??{}));return e.mainJobFunctionName&&t.add(e.mainJobFunctionName),[...t].toSorted()}function normalizeRetryPolicyForCompare(e){return{maxRetries:e.maxRetries,backoffMultiplier:e.backoffMultiplier,initialBackoff:{seconds:String(e.initialBackoff.seconds),nanos:e.initialBackoff.nanos},maxBackoff:{seconds:String(e.maxBackoff.seconds),nanos:e.maxBackoff.nanos}}}function toConcurrencyPolicyInit(e){if(e)return{maxConcurrentExecutions:e.maxConcurrentExecutions}}function normalizeComparableConcurrency(e){if(e&&e.maxConcurrentExecutions)return{maxConcurrentExecutions:e.maxConcurrentExecutions}}function declaredKey(e){if(e.matchType===`exact`)return e.key;let t=e.key;if(typeof t!=`string`)throw E({code:`WORKFLOW_EXECUTION_POLICY_INVALID`,message:`Invalid workflow execution policy "${e.name}": prefix policies must be created via defineWorkflowExecutionPolicy() or defineWorkflowExecutionPolicies(), not a hand-constructed object.`});return t}function toPlatformExecutionPolicyKey(e){return it(declaredKey(e),e.matchType)}function validatePolicy(e){if(declaredKey(e).endsWith(`*`))throw E({code:`WORKFLOW_EXECUTION_POLICY_INVALID`,message:`Invalid workflow execution policy "${e.name}": ${at}`});let t=dt.safeParse({name:e.name,key:toPlatformExecutionPolicyKey(e),concurrencyPolicy:e.concurrencyPolicy});if(!t.success)throw E({code:`WORKFLOW_EXECUTION_POLICY_INVALID`,message:`Invalid workflow execution policy "${e.name}": ${t.error.issues.map(e=>e.message).join(`; `)}`})}async function planWorkflowJobFunctionExecutionPolicy(e,t,n,r,i){let a=createChangeSet(`Workflow execution policies`),o=createOwnershipTracker(n,r),s=Object.values(i);for(let e of s)validatePolicy(e);let c=await fetchExistingResourcesWithLabels({client:e,fetchPage:async(n,r)=>{let i=await e.listWorkflowJobFunctionExecutionPolicies({workspaceId:t,pageToken:n,pageSize:r});return[i.policies,i.nextPageToken]},getName:e=>e.name,getTrn:e=>resourceTrn(t,`workflow_job_function_execution_policy`,e)}),l=/* @__PURE__ */ new Set;for(let e of s){if(l.has(e.name))throw E({code:`WORKFLOW_EXECUTION_POLICY_DUPLICATE`,message:`Duplicate workflow execution policy name "${e.name}". Each policy must have a unique name within the workspace.`});l.add(e.name);let i=await buildMetaRequest({trn:resourceTrn(t,`workflow_job_function_execution_policy`,e.name),appName:n,appId:r}),s=c[e.name];if(s){let n=o.ownsDesired(s.allLabels,{resourceType:`workflow_job_function_execution_policy`,resourceLabel:`Workflow execution policy`,resourceName:e.name}),r=s.resource.executionPolicyKey,l=toPlatformExecutionPolicyKey(e),u=normalizeComparableConcurrency(s.resource.concurrencyPolicy),d=normalizeComparableConcurrency(e.concurrencyPolicy),f=n&&r===l&&areNormalizedEqual(u,d);f&&hasMatchingSdkVersion(s.allLabels,i.labels)?a.unchanged.push({name:e.name}):r===l?a.updates.push({name:e.name,workspaceId:t,policy:e,metaRequest:i,...f&&{forcedBySdkVersion:!0}}):a.replaces.push({name:e.name,workspaceId:t,policy:e,metaRequest:i}),delete c[e.name]}else a.creates.push({name:e.name,workspaceId:t,policy:e,metaRequest:i})}for(let[e,n]of Object.entries(c))n&&o.ownsRemaining(n.allLabels)&&a.deletes.push({name:e,workspaceId:t});return{changeSet:a,...o.result}}async function applyWorkflowJobFunctionExecutionPolicy(e,t,n=`create-update`){let{changeSet:r}=t;n===`create-update`?await Promise.all([...r.replaces.map(async t=>{await e.deleteWorkflowJobFunctionExecutionPolicy({workspaceId:t.workspaceId,executionPolicyName:t.name}),await e.createWorkflowJobFunctionExecutionPolicy({workspaceId:t.workspaceId,executionPolicyName:t.policy.name,executionPolicyKey:toPlatformExecutionPolicyKey(t.policy),concurrencyPolicy:toConcurrencyPolicyInit(t.policy.concurrencyPolicy)}),await writeMetadataLabels(e,t.metaRequest)}),...r.creates.map(async t=>{await e.createWorkflowJobFunctionExecutionPolicy({workspaceId:t.workspaceId,executionPolicyName:t.policy.name,executionPolicyKey:toPlatformExecutionPolicyKey(t.policy),concurrencyPolicy:toConcurrencyPolicyInit(t.policy.concurrencyPolicy)}),await writeMetadataLabels(e,t.metaRequest)}),...r.updates.map(async t=>{await e.updateWorkflowJobFunctionExecutionPolicy({workspaceId:t.workspaceId,executionPolicyName:t.policy.name,concurrencyPolicy:toConcurrencyPolicyInit(t.policy.concurrencyPolicy)}),await writeMetadataLabels(e,t.metaRequest)})]):await Promise.all(r.deletes.map(t=>e.deleteWorkflowJobFunctionExecutionPolicy({workspaceId:t.workspaceId,executionPolicyName:t.name})))}function deploymentPlanResults(e){let{application:t,forceApplyAll:n,...r}=e;return r}function forEachDeployment(e,t){return(async()=>{for(let n of e)await t(n)})()}function makeStep(e){return(t,n)=>B(t,()=>forEachDeployment(e,n))}async function preflightAllTailorDB(e,t){await B(`apply.preflight`,async()=>{await forEachDeployment(t,t=>preflightTailorDB(e,t.tailorDB))})}async function applyPrerequisiteResources(e,t){let n=makeStep(t);await withMetadataWriteBatch(e,async e=>{await B(`apply.createUpdatePrerequisiteServices`,async()=>{await n(`apply.secretManager.createUpdate`,t=>applySecretManager(e,t.secretManager,`create-update`,t.application)),await n(`apply.staticWebsite.createUpdate`,t=>applyStaticWebsite(e,t.staticWebsite,`create-update`)),await n(`apply.aiGateway.createUpdate`,t=>applyAIGateway(e,t.aiGateway,`create-update`)),await n(`apply.idp.createUpdate`,t=>applyIdP(e,t.idp,`create-update`)),await n(`apply.auth.createUpdatePrerequisites`,t=>applyAuth(e,t.auth,`create-update-prerequisites`))})})}async function releaseMaintenanceModes(e,t,n){let r=[],i;for(let{deployment:a,release:o}of t)try{let t=await o(e);t&&r.push({application:a.application.name,...t})}catch(e){if(!n&&!i){i={error:e};continue}C.warn(`Could not lift the maintenance mode of TailorDB tables: ${e instanceof Error?e.message:String(e)}`)}if(i)throw i.error;if(n)return r;let a=/* @__PURE__ */ new Set;for(let{deployment:n}of t)a.has(n)||(a.add(n),await recomposeApplication(e,n.app));return r}async function applyRemainingResources(e,t,n){let r=[],i;try{i=await applyRemainingResourcesHoldingMaintenanceMode(e,t,n,r)}catch(t){throw await releaseMaintenanceModes(e,r,!0),t}let a=await releaseMaintenanceModes(e,r,!1),o=new Map(n.map((e,t)=>[e.application.name,t]));return[...i,...a].toSorted((e,t)=>(o.get(e.application)??0)-(o.get(t.application)??0))}async function applyRemainingResourcesHoldingMaintenanceMode(e,t,n,r){let i=makeStep(n),a=[];return await withMetadataWriteBatch(e,async e=>{await B(`apply.createUpdateServices`,async()=>{await i(`apply.functionRegistry.createUpdate`,n=>applyFunctionRegistry(e,t,n.functionRegistry,`create-update`)),await i(`apply.tailorDB.createUpdate`,async t=>{let n=await applyTailorDB(e,t.tailorDB,`create-update`,{holdMaintenanceMode:e=>r.push({deployment:t,release:e})});n&&a.push({application:t.application.name,...n})}),await i(`apply.auth.createUpdateDependents`,t=>applyAuth(e,t.auth,`create-update-dependents`)),await i(`apply.pipeline.createUpdate`,t=>applyPipeline(e,t.pipeline,`create-update`))}),await B(`apply.deleteSubgraphResources`,async()=>{await forEachDeployment(n,t=>applyPipeline(e,t.pipeline,`delete-resources`)),await forEachDeployment(n,t=>applyAuth(e,t.auth,`delete-resources`)),await forEachDeployment(n,t=>applyIdP(e,t.idp,`delete-resources`))}),await B(`apply.createUpdateApplication`,async()=>{await forEachDeployment(n,t=>applyApplication(e,t.app,`create-update`))}),await B(`apply.createUpdateDependentServices`,async()=>{await i(`apply.executor.createUpdate`,t=>applyExecutor(e,t.executor,`create-update`)),await i(`apply.workflowExecutionPolicy.createUpdate`,t=>applyWorkflowJobFunctionExecutionPolicy(e,t.workflowExecutionPolicy,`create-update`)),await i(`apply.workflow.createUpdate`,t=>applyWorkflow(e,t.workflow,`create-update`))})}),await B(`apply.deleteDependentServices`,async()=>{await forEachDeployment(n,t=>applyWorkflow(e,t.workflow,`delete`)),await forEachDeployment(n,t=>applyWorkflowJobFunctionExecutionPolicy(e,t.workflowExecutionPolicy,`delete`)),await forEachDeployment(n,t=>applyExecutor(e,t.executor,`delete`)),await forEachDeployment(n,t=>applyStaticWebsite(e,t.staticWebsite,`delete`)),await forEachDeployment(n,t=>applyAIGateway(e,t.aiGateway,`delete`)),await forEachDeployment(n,t=>applySecretManager(e,t.secretManager,`delete`,t.application))}),await B(`apply.deleteApplication`,async()=>{await forEachDeployment(n,t=>applyApplication(e,t.app,`delete`))}),await B(`apply.deleteSubgraphServices`,async()=>{await forEachDeployment(n,t=>applyPipeline(e,t.pipeline,`delete-services`)),await forEachDeployment(n,t=>applyAuth(e,t.auth,`delete-services`)),await forEachDeployment(n,t=>applyIdP(e,t.idp,`delete-services`)),await forEachDeployment(n,t=>applyTailorDB(e,t.tailorDB,`delete-services`))}),await B(`apply.cleanup`,async()=>{await forEachDeployment(n,n=>applyFunctionRegistry(e,t,n.functionRegistry,`delete`))}),a}function findDuplicateResourceNames(e,t){return t.flatMap(({resourceType:t,resourceLabel:n,namesOf:r})=>{let i=/* @__PURE__ */ new Map;for(let t of e)for(let e of r(t)){let n=i.get(e);n?n.push(t.config.path):i.set(e,[t.config.path])}return[...i].filter(([,e])=>e.length>1).map(([e,r])=>({resourceType:t,resourceLabel:n,name:e,configPaths:[...new Set(r)]}))})}function assertNoDuplicateResourceNames(e,t){let n=findDuplicateResourceNames(e,t);if(n.length===0)return;let r=n.some(({resourceType:e,configPaths:t})=>e.endsWith(`.service`)&&t.length>1);throw E({code:`DEPLOY_DUPLICATE_RESOURCE_NAME`,message:[`Duplicate resource names in this deploy:`,...n.map(({resourceLabel:e,name:t,configPaths:n})=>` - ${e} "${t}": ${n.map(e=>H.relative(process.cwd(),e)).join(`, `)}`)].join(`
|
|
105
|
-
`),suggestion:[`Rename the duplicates so each name is defined once across all configs in a single deploy.`,...r?["To share a service namespace across configs, define it in one config and declare it with `external: true` in the others."]:[]].join(` `),context:{duplicates:n.map(({resourceType:e,name:t,configPaths:n})=>({resourceType:e,name:t,configPaths:n}))}})}const
|
|
104
|
+
- The file containing the job is not included in workflow.files glob pattern`,suggestion:`Export the job: export const ${e.mainJob.name} = createWorkflowJob({ name: "${e.mainJob.name}", ... })`});c.forEach(e=>p.add(e));let _={...e,publishEvents:resolvePublishEvents({explicit:e.publishEvents,subscribed:isSubscribed(m,e.name),conflict:Ea.workflow(e.name)})};if(i){let n=d.ownsDesired(i.allLabels,{resourceType:`workflow`,resourceLabel:`Workflow`,resourceName:e.name})&&!c.some(e=>y.has(e))&&areWorkflowsEqual(i.resource,_,c),r=hasMatchingSdkVersion(i.allLabels,s.labels);if(n&&r&&c.every(e=>o.has(e))){u.unchanged.push({name:e.name,metaRequest:s});for(let e of c)f.add(e)}else{let r=n&&c.every(e=>o.has(e)||l.has(e));u.updates.push({name:e.name,workspaceId:t,workflow:_,usedJobNames:c,metaRequest:s,...r&&{forcedBySdkVersion:!0}})}delete x[e.name]}else u.creates.push({name:e.name,workspaceId:t,workflow:_,usedJobNames:c,metaRequest:s})}let S=[];Object.values(x).forEach(e=>{if(!e)return;let n=d.ownsRemaining(e.allLabels),r=getExistingWorkflowJobNames(e.resource);n?S.push({name:e.resource.name,workspaceId:t,workflowId:e.resource.id,usedJobNames:r,deletableJobNames:[]}):r.forEach(e=>p.add(e))});let C=await planWorkflowJobFunctionDeletes({client:e,workspaceId:t,ownership:d,existingJobFunctionNames:[..._.keys()],retainedWorkflowJobNames:p}),w=new Set(C.map(e=>e.jobFunctionName));for(let e of S)u.deletes.push({...e,deletableJobNames:e.usedJobNames.filter(e=>!p.has(e)&&w.has(e))});return{changeSet:u,...d.result,appName:n,appId:r,unchangedWorkflowJobNames:f,jobFunctionDeletes:C,jobFunctionPublishEvents:v,existingJobFunctions:_,existingWorkflows:b}}async function fetchExistingJobFunctions(e,t){let n=await Nt(async(n,r)=>{let i=await e.listWorkflowJobFunctions({workspaceId:t,pageToken:n,pageSize:r});return[i.jobFunctions,i.nextPageToken]});return new Map(n.map(e=>[e.name,e]))}async function planWorkflowJobFunctionDeletes(e){let{client:t,workspaceId:n,ownership:r,existingJobFunctionNames:i,retainedWorkflowJobNames:a}=e,o=i.filter(e=>!a.has(e));return(await Promise.all(o.map(async e=>{let{metadata:i}=await t.getMetadata({trn:resourceTrn(n,`workflow_job_function`,e)});return r.ownsRemaining(i?.labels)?{workspaceId:n,jobFunctionName:e}:void 0}))).filter(e=>e!==void 0)}function formatWorkflowChangeEntries(e,t,n){let r=new Set(n.map(e=>workflowJobFunctionName(e.jobFunctionName))),isJobFunctionRegistryDelete=e=>r.has(e.name);return[...formatChangeEntriesWithFunctionRegistry(`workflow`,e,{...t,deletes:t.deletes.filter(e=>!isJobFunctionRegistryDelete(e))},e=>`usedJobNames`in e?e.usedJobNames.map(e=>workflowJobFunctionName(e)):[]),...formatChangeEntriesWithFunctionRegistry(`jobFunction`,{creates:[],updates:[],deletes:n.map(e=>({name:e.jobFunctionName})),replaces:[]},{creates:[],updates:[],deletes:t.deletes.filter(isJobFunctionRegistryDelete),replaces:[]},e=>[workflowJobFunctionName(e.name)])]}function areWorkflowsEqual(e,t,n){return e.mainJobFunctionName===t.mainJob.name&&(e.publishExecutionEvents??!1)===(t.publishEvents??!1)&&areNormalizedEqual(normalizeComparableExistingWorkflowRetryPolicy(e.retryPolicy),normalizeComparableWorkflowRetryPolicy(t.retryPolicy))&&areNormalizedEqual(normalizeComparableConcurrencyPolicy(e.concurrencyPolicy),normalizeComparableConcurrencyPolicy(t.concurrencyPolicy))&&areNormalizedEqual(normalizeComparableWorkflowJobNames(e.jobFunctions),normalizeComparableWorkflowJobNames(n))}function normalizeComparableExistingWorkflowRetryPolicy(e){if(e)return normalizeRetryPolicyForCompare({maxRetries:e.maxRetries??0,backoffMultiplier:e.backoffMultiplier??0,initialBackoff:{seconds:e.initialBackoff?.seconds??0n,nanos:e.initialBackoff?.nanos??0},maxBackoff:{seconds:e.maxBackoff?.seconds??0n,nanos:e.maxBackoff?.nanos??0}})}function normalizeComparableWorkflowRetryPolicy(e){if(e)return normalizeRetryPolicyForCompare({maxRetries:e.maxRetries,backoffMultiplier:e.backoffMultiplier,initialBackoff:parseDurationToProto(e.initialBackoff),maxBackoff:parseDurationToProto(e.maxBackoff)})}function normalizeComparableConcurrencyPolicy(e){if(e&&e.maxConcurrentExecutions)return{maxConcurrentExecutions:e.maxConcurrentExecutions}}function normalizeComparableWorkflowJobNames(e){return Array.isArray(e)?e.toSorted():Object.keys(e??{}).toSorted()}function getExistingWorkflowJobNames(e){let t=new Set(Object.keys(e.jobFunctions??{}));return e.mainJobFunctionName&&t.add(e.mainJobFunctionName),[...t].toSorted()}function normalizeRetryPolicyForCompare(e){return{maxRetries:e.maxRetries,backoffMultiplier:e.backoffMultiplier,initialBackoff:{seconds:String(e.initialBackoff.seconds),nanos:e.initialBackoff.nanos},maxBackoff:{seconds:String(e.maxBackoff.seconds),nanos:e.maxBackoff.nanos}}}function toConcurrencyPolicyInit(e){if(e)return{maxConcurrentExecutions:e.maxConcurrentExecutions}}function normalizeComparableConcurrency(e){if(e&&e.maxConcurrentExecutions)return{maxConcurrentExecutions:e.maxConcurrentExecutions}}function declaredKey(e){if(e.matchType===`exact`)return e.key;let t=e.key;if(typeof t!=`string`)throw E({code:`WORKFLOW_EXECUTION_POLICY_INVALID`,message:`Invalid workflow execution policy "${e.name}": prefix policies must be created via defineWorkflowExecutionPolicy() or defineWorkflowExecutionPolicies(), not a hand-constructed object.`});return t}function toPlatformExecutionPolicyKey(e){return at(declaredKey(e),e.matchType)}function validatePolicy(e){if(declaredKey(e).endsWith(`*`))throw E({code:`WORKFLOW_EXECUTION_POLICY_INVALID`,message:`Invalid workflow execution policy "${e.name}": ${ot}`});let t=ft.safeParse({name:e.name,key:toPlatformExecutionPolicyKey(e),concurrencyPolicy:e.concurrencyPolicy});if(!t.success)throw E({code:`WORKFLOW_EXECUTION_POLICY_INVALID`,message:`Invalid workflow execution policy "${e.name}": ${t.error.issues.map(e=>e.message).join(`; `)}`})}async function planWorkflowJobFunctionExecutionPolicy(e,t,n,r,i){let a=createChangeSet(`Workflow execution policies`),o=createOwnershipTracker(n,r),s=Object.values(i);for(let e of s)validatePolicy(e);let c=await fetchExistingResourcesWithLabels({client:e,fetchPage:async(n,r)=>{let i=await e.listWorkflowJobFunctionExecutionPolicies({workspaceId:t,pageToken:n,pageSize:r});return[i.policies,i.nextPageToken]},getName:e=>e.name,getTrn:e=>resourceTrn(t,`workflow_job_function_execution_policy`,e)}),l=/* @__PURE__ */ new Set;for(let e of s){if(l.has(e.name))throw E({code:`WORKFLOW_EXECUTION_POLICY_DUPLICATE`,message:`Duplicate workflow execution policy name "${e.name}". Each policy must have a unique name within the workspace.`});l.add(e.name);let i=await buildMetaRequest({trn:resourceTrn(t,`workflow_job_function_execution_policy`,e.name),appName:n,appId:r}),s=c[e.name];if(s){let n=o.ownsDesired(s.allLabels,{resourceType:`workflow_job_function_execution_policy`,resourceLabel:`Workflow execution policy`,resourceName:e.name}),r=s.resource.executionPolicyKey,l=toPlatformExecutionPolicyKey(e),u=normalizeComparableConcurrency(s.resource.concurrencyPolicy),d=normalizeComparableConcurrency(e.concurrencyPolicy),f=n&&r===l&&areNormalizedEqual(u,d);f&&hasMatchingSdkVersion(s.allLabels,i.labels)?a.unchanged.push({name:e.name}):r===l?a.updates.push({name:e.name,workspaceId:t,policy:e,metaRequest:i,...f&&{forcedBySdkVersion:!0}}):a.replaces.push({name:e.name,workspaceId:t,policy:e,metaRequest:i}),delete c[e.name]}else a.creates.push({name:e.name,workspaceId:t,policy:e,metaRequest:i})}for(let[e,n]of Object.entries(c))n&&o.ownsRemaining(n.allLabels)&&a.deletes.push({name:e,workspaceId:t});return{changeSet:a,...o.result}}async function applyWorkflowJobFunctionExecutionPolicy(e,t,n=`create-update`){let{changeSet:r}=t;n===`create-update`?await Promise.all([...r.replaces.map(async t=>{await e.deleteWorkflowJobFunctionExecutionPolicy({workspaceId:t.workspaceId,executionPolicyName:t.name}),await e.createWorkflowJobFunctionExecutionPolicy({workspaceId:t.workspaceId,executionPolicyName:t.policy.name,executionPolicyKey:toPlatformExecutionPolicyKey(t.policy),concurrencyPolicy:toConcurrencyPolicyInit(t.policy.concurrencyPolicy)}),await writeMetadataLabels(e,t.metaRequest)}),...r.creates.map(async t=>{await e.createWorkflowJobFunctionExecutionPolicy({workspaceId:t.workspaceId,executionPolicyName:t.policy.name,executionPolicyKey:toPlatformExecutionPolicyKey(t.policy),concurrencyPolicy:toConcurrencyPolicyInit(t.policy.concurrencyPolicy)}),await writeMetadataLabels(e,t.metaRequest)}),...r.updates.map(async t=>{await e.updateWorkflowJobFunctionExecutionPolicy({workspaceId:t.workspaceId,executionPolicyName:t.policy.name,concurrencyPolicy:toConcurrencyPolicyInit(t.policy.concurrencyPolicy)}),await writeMetadataLabels(e,t.metaRequest)})]):await Promise.all(r.deletes.map(t=>e.deleteWorkflowJobFunctionExecutionPolicy({workspaceId:t.workspaceId,executionPolicyName:t.name})))}function deploymentPlanResults(e){let{application:t,forceApplyAll:n,...r}=e;return r}function forEachDeployment(e,t){return(async()=>{for(let n of e)await t(n)})()}function makeStep(e){return(t,n)=>B(t,()=>forEachDeployment(e,n))}async function preflightAllTailorDB(e,t){await B(`apply.preflight`,async()=>{await forEachDeployment(t,t=>preflightTailorDB(e,t.tailorDB))})}async function applyPrerequisiteResources(e,t){let n=makeStep(t);await withMetadataWriteBatch(e,async e=>{await B(`apply.createUpdatePrerequisiteServices`,async()=>{await n(`apply.secretManager.createUpdate`,t=>applySecretManager(e,t.secretManager,`create-update`,t.application)),await n(`apply.staticWebsite.createUpdate`,t=>applyStaticWebsite(e,t.staticWebsite,`create-update`)),await n(`apply.aiGateway.createUpdate`,t=>applyAIGateway(e,t.aiGateway,`create-update`)),await n(`apply.idp.createUpdate`,t=>applyIdP(e,t.idp,`create-update`)),await n(`apply.auth.createUpdatePrerequisites`,t=>applyAuth(e,t.auth,`create-update-prerequisites`))})})}async function releaseMaintenanceModes(e,t,n){let r=[],i;for(let{deployment:a,release:o}of t)try{let t=await o(e);t&&r.push({application:a.application.name,...t})}catch(e){if(!n&&!i){i={error:e};continue}C.warn(`Could not lift the maintenance mode of TailorDB tables: ${e instanceof Error?e.message:String(e)}`)}if(i)throw i.error;if(n)return r;let a=/* @__PURE__ */ new Set;for(let{deployment:n}of t)a.has(n)||(a.add(n),await recomposeApplication(e,n.app));return r}async function applyRemainingResources(e,t,n){let r=[],i;try{i=await applyRemainingResourcesHoldingMaintenanceMode(e,t,n,r)}catch(t){throw await releaseMaintenanceModes(e,r,!0),t}let a=await releaseMaintenanceModes(e,r,!1),o=new Map(n.map((e,t)=>[e.application.name,t]));return[...i,...a].toSorted((e,t)=>(o.get(e.application)??0)-(o.get(t.application)??0))}async function applyRemainingResourcesHoldingMaintenanceMode(e,t,n,r){let i=makeStep(n),a=[];return await withMetadataWriteBatch(e,async e=>{await B(`apply.createUpdateServices`,async()=>{await i(`apply.functionRegistry.createUpdate`,n=>applyFunctionRegistry(e,t,n.functionRegistry,`create-update`)),await i(`apply.tailorDB.createUpdate`,async t=>{let n=await applyTailorDB(e,t.tailorDB,`create-update`,{holdMaintenanceMode:e=>r.push({deployment:t,release:e})});n&&a.push({application:t.application.name,...n})}),await i(`apply.auth.createUpdateDependents`,t=>applyAuth(e,t.auth,`create-update-dependents`)),await i(`apply.pipeline.createUpdate`,t=>applyPipeline(e,t.pipeline,`create-update`))}),await B(`apply.deleteSubgraphResources`,async()=>{await forEachDeployment(n,t=>applyPipeline(e,t.pipeline,`delete-resources`)),await forEachDeployment(n,t=>applyAuth(e,t.auth,`delete-resources`)),await forEachDeployment(n,t=>applyIdP(e,t.idp,`delete-resources`))}),await B(`apply.createUpdateApplication`,async()=>{await forEachDeployment(n,t=>applyApplication(e,t.app,`create-update`))}),await B(`apply.createUpdateDependentServices`,async()=>{await i(`apply.executor.createUpdate`,t=>applyExecutor(e,t.executor,`create-update`)),await i(`apply.workflowExecutionPolicy.createUpdate`,t=>applyWorkflowJobFunctionExecutionPolicy(e,t.workflowExecutionPolicy,`create-update`)),await i(`apply.workflow.createUpdate`,t=>applyWorkflow(e,t.workflow,`create-update`))})}),await B(`apply.deleteDependentServices`,async()=>{await forEachDeployment(n,t=>applyWorkflow(e,t.workflow,`delete`)),await forEachDeployment(n,t=>applyWorkflowJobFunctionExecutionPolicy(e,t.workflowExecutionPolicy,`delete`)),await forEachDeployment(n,t=>applyExecutor(e,t.executor,`delete`)),await forEachDeployment(n,t=>applyStaticWebsite(e,t.staticWebsite,`delete`)),await forEachDeployment(n,t=>applyAIGateway(e,t.aiGateway,`delete`)),await forEachDeployment(n,t=>applySecretManager(e,t.secretManager,`delete`,t.application))}),await B(`apply.deleteApplication`,async()=>{await forEachDeployment(n,t=>applyApplication(e,t.app,`delete`))}),await B(`apply.deleteSubgraphServices`,async()=>{await forEachDeployment(n,t=>applyPipeline(e,t.pipeline,`delete-services`)),await forEachDeployment(n,t=>applyAuth(e,t.auth,`delete-services`)),await forEachDeployment(n,t=>applyIdP(e,t.idp,`delete-services`)),await forEachDeployment(n,t=>applyTailorDB(e,t.tailorDB,`delete-services`))}),await B(`apply.cleanup`,async()=>{await forEachDeployment(n,n=>applyFunctionRegistry(e,t,n.functionRegistry,`delete`))}),a}function findDuplicateResourceNames(e,t){return t.flatMap(({resourceType:t,resourceLabel:n,namesOf:r})=>{let i=/* @__PURE__ */ new Map;for(let t of e)for(let e of r(t)){let n=i.get(e);n?n.push(t.config.path):i.set(e,[t.config.path])}return[...i].filter(([,e])=>e.length>1).map(([e,r])=>({resourceType:t,resourceLabel:n,name:e,configPaths:[...new Set(r)]}))})}function assertNoDuplicateResourceNames(e,t){let n=findDuplicateResourceNames(e,t);if(n.length===0)return;let r=n.some(({resourceType:e,configPaths:t})=>e.endsWith(`.service`)&&t.length>1);throw E({code:`DEPLOY_DUPLICATE_RESOURCE_NAME`,message:[`Duplicate resource names in this deploy:`,...n.map(({resourceLabel:e,name:t,configPaths:n})=>` - ${e} "${t}": ${n.map(e=>H.relative(process.cwd(),e)).join(`, `)}`)].join(`
|
|
105
|
+
`),suggestion:[`Rename the duplicates so each name is defined once across all configs in a single deploy.`,...r?["To share a service namespace across configs, define it in one config and declare it with `external: true` in the others."]:[]].join(` `),context:{duplicates:n.map(({resourceType:e,name:t,configPaths:n})=>({resourceType:e,name:t,configPaths:n}))}})}const sc={resolvers:{resourceType:`pipeline.resolver`,resourceLabel:`Resolver bundle`},executors:{resourceType:`executor`,resourceLabel:`Executor bundle`},workflowJobs:{resourceType:`workflow_job_function`,resourceLabel:`Workflow job bundle`},authHooks:{resourceType:`auth.hook`,resourceLabel:`Auth hook bundle`}},cc=Object.keys(sc);function mergeBundledScripts(e){assertNoDuplicateResourceNames(e,cc.map(e=>({...sc[e],namesOf:t=>t.bundledScripts[e].keys()})));let mergeKind=t=>new Map(e.flatMap(e=>[...e.bundledScripts[t]]));return{resolvers:mergeKind(`resolvers`),executors:mergeKind(`executors`),workflowJobs:mergeKind(`workflowJobs`),authHooks:mergeKind(`authHooks`)}}function collectHttpAdapterScripts(e){return assertNoDuplicateResourceNames(e,[{resourceType:`application`,resourceLabel:`Application`,namesOf:e=>e.httpAdapterBuildResult?[e.application.name]:[]}]),new Map(e.flatMap(({application:e,httpAdapterBuildResult:t})=>t?[[e.name,t]]:[]))}async function confirmMigrationCheckpointRepairs(e,t){if(e.length!==0){C.warn(`TailorDB migration checkpoints and history IDs need to be updated before this deployment:`);for(let t of e.toSorted((e,t)=>e.namespace.localeCompare(t.namespace)))C.log(` ${t.namespace}:`),C.log(` Checkpoint: ${formatMigrationNumber(t.from)} → ${formatMigrationNumber(t.to)}`),C.log(` Migration history ID: ${t.fromHistoryId??`<unset>`} → ${t.toHistoryId}`);if(C.log(` The checkpoint reset itself changes only metadata.`),C.log(` This deployment may still apply pending schema or data migrations afterward.`),t===`prompt`&&!await X.confirm({message:`Reset these migration checkpoints, align their history IDs, and continue with the deployment?`,default:!1}))throw E({code:`DEPLOY_CANCELLED`,message:`Apply cancelled: migration checkpoint reset was not confirmed.`})}}async function confirmOwnerConflict(e,t,n,r){if(e.length===0)return;let i=e.filter(e=>e.currentOwner===t),a=e.filter(e=>e.currentOwner!==t);i.length>0&&await(r?confirmIdRegeneration(i,t,n):confirmMissingConfigId(i,t,n)),a.length>0&&await confirmNameMismatch(a,t,n)}async function confirmIdRegeneration(e,t,n){if(logIdMismatch(`Application id was regenerated for "${t}":`,e),n!==`dry-run`){if(n===`yes`)C.success(`Re-tagging resources with the new id (--yes flag specified)...`,{mode:`plain`});else if(!await X.confirm({message:`Re-tag these resources with the new id for "${t}"?\n${h.dim(`(The app id recorded for this config was removed since the previous deploy, so a new one was generated)`)}`,default:!1}))throw E({code:`DEPLOY_CANCELLED`,message:M`
|
|
106
106
|
Apply cancelled. Resources remain tagged with the previous id.
|
|
107
107
|
To override, run again and confirm, or use --yes flag.
|
|
108
108
|
`})}}function logIdMismatch(e,t){C.warn(e),C.log(` These resources are tagged with an id from an earlier deploy.`),C.newline(),C.log(` ${h.info(`Resources`)}:`);for(let e of t)C.log(` • ${h.bold(e.resourceLabel)} ${h.info(`"${e.resourceName}"`)}`)}async function confirmMissingConfigId(e,t,n){if(logIdMismatch(`No application id resolved for "${t}":`,e),n!==`dry-run`){if(n===`yes`)C.success(`Managing these resources by name (--yes flag specified)...`,{mode:`plain`});else if(!await X.confirm({message:`Drop that id and manage these resources by name for "${t}"?\n${h.dim(`(the config resolves without an 'id', so ownership falls back to the application name)`)}`,default:!1}))throw E({code:`DEPLOY_CANCELLED`,message:M`
|
|
@@ -120,10 +120,10 @@ If a value is genuinely safe to keep in 'env', allow it where it is defined: ${a
|
|
|
120
120
|
`})}}}async function confirmMissingDependentApps(e,t){if(e.length!==0){C.warn(`Applications recorded as depending on this deploy are missing:`);for(let t of e)C.log(` • application id ${h.info(t.appId)} depends on ${h.bold(t.resource)} (${t.reason})`);if(C.newline(),C.log(` Applying without them turns off event publishing on the resources above:`),C.log(` nothing in this deploy subscribes to them, so the value resolves to false.`),C.log(` To keep it, add their configs to --config, or set publishEvents on`),C.log(` the resources above.`),t!==`dry-run`){if(t===`yes`)C.warn(`Continuing without them (--yes flag specified); applying turns publishing off.`);else if(!await X.confirm({message:`Continue without them?`,default:!1}))throw E({code:`DEPLOY_CANCELLED`,message:M`
|
|
121
121
|
Apply cancelled. Add the missing configs to --config, or set publishEvents
|
|
122
122
|
explicitly on the resources that should keep publishing.
|
|
123
|
-
`})}}}function assertNoSingleRunTransferHandoff(e){let t=/* @__PURE__ */ new Map,n=/* @__PURE__ */ new Set;for(let r of e){let{staticWebsite:e}=r;assertStaticWebsiteDeletesNotOffered(e);for(let t of e.customDomainChangeSet.deletes){let n=e.customDomainLiveOffers.get(t.name);if(n)throw E({code:`CUSTOM_DOMAIN_TRANSFER_IN_FLIGHT`,message:`Custom domain "${t.name}" is offered to workspace ${n.targetWorkspaceId} and is no longer declared on a static website.`,suggestion:`Change the entry back to a plain string to cancel the transfer, deploy, then remove it.`,details:`Removing the domain now would tear down its edge configuration while the transfer is still pending, and the target could no longer accept it.`,context:{resourceType:`staticwebsite.custom_domain_transfer`,domain:t.name,targetWorkspaceId:n.targetWorkspaceId}})}for(let n of e.customDomainTransferChangeSet.creates)t.set(n.name,n.staticWebsiteName);for(let t of e.customDomainChangeSet.creates)n.add(t.name)}for(let[e,r]of t)if(n.has(e))throw E({code:`CUSTOM_DOMAIN_TRANSFER_SAME_RUN`,message:`Custom domain "${e}" is both offered for transfer and added to a static website in this deploy.`,suggestion:`Deploy the offer first, then add the domain to the receiving site in a second deploy.`,details:`The receiving side completes the transfer by adding the domain, which the platform refuses until the offer exists.`,context:{resourceType:`staticwebsite.custom_domain_transfer`,domain:e,staticWebsiteName:r}})}function recomputedResources(e,t,n,r){let i=[];for(let n of t.tailorDBServices)for(let[t,r]of Object.entries(n.types))r.settings.publishEvents===void 0&&i.push({trn:tailorDBTypeTrn(e,n.namespace,t),key:Z.tailorDBType(n.namespace,t),scope:`resource`,resource:
|
|
124
|
-
`)}}}async function withTimeout(e,t,n){let r=new AbortController;try{return await Promise.race([e,
|
|
123
|
+
`})}}}function assertNoSingleRunTransferHandoff(e){let t=/* @__PURE__ */ new Map,n=/* @__PURE__ */ new Set;for(let r of e){let{staticWebsite:e}=r;assertStaticWebsiteDeletesNotOffered(e);for(let t of e.customDomainChangeSet.deletes){let n=e.customDomainLiveOffers.get(t.name);if(n)throw E({code:`CUSTOM_DOMAIN_TRANSFER_IN_FLIGHT`,message:`Custom domain "${t.name}" is offered to workspace ${n.targetWorkspaceId} and is no longer declared on a static website.`,suggestion:`Change the entry back to a plain string to cancel the transfer, deploy, then remove it.`,details:`Removing the domain now would tear down its edge configuration while the transfer is still pending, and the target could no longer accept it.`,context:{resourceType:`staticwebsite.custom_domain_transfer`,domain:t.name,targetWorkspaceId:n.targetWorkspaceId}})}for(let n of e.customDomainTransferChangeSet.creates)t.set(n.name,n.staticWebsiteName);for(let t of e.customDomainChangeSet.creates)n.add(t.name)}for(let[e,r]of t)if(n.has(e))throw E({code:`CUSTOM_DOMAIN_TRANSFER_SAME_RUN`,message:`Custom domain "${e}" is both offered for transfer and added to a static website in this deploy.`,suggestion:`Deploy the offer first, then add the domain to the receiving site in a second deploy.`,details:`The receiving side completes the transfer by adding the domain, which the platform refuses until the offer exists.`,context:{resourceType:`staticwebsite.custom_domain_transfer`,domain:e,staticWebsiteName:r}})}function recomputedResources(e,t,n,r){let i=[];for(let n of t.tailorDBServices)for(let[t,r]of Object.entries(n.types))r.settings.publishEvents===void 0&&i.push({trn:tailorDBTypeTrn(e,n.namespace,t),key:Z.tailorDBType(n.namespace,t),scope:`resource`,resource:Ta.tailorDBType(t),resourceType:`tailordb.type`,namespace:n.namespace,name:t});for(let n of t.resolverServices)for(let t of Object.values(n.resolvers))t.publishEvents===void 0&&i.push({trn:resolverTrn(e,n.namespace,t.name),key:Z.resolver(n.namespace,t.name),scope:`resource`,resource:Ta.resolver(t.name),resourceType:`pipeline.resolver`,namespace:n.namespace,name:t.name});for(let n of t.idpServices)n.publishEvents===void 0&&i.push({trn:resourceTrn(e,`idp`,n.name),key:Z.idp(n.name),scope:`resource`,resource:Ta.idpService(n.name),resourceType:`idp.service`,name:n.name});let a=new Map((t.workflowService?.jobs??[]).map(e=>[e.name,e.publishEvents])),o=subscribedWorkflowJobNames({workflows:Object.values(t.workflowService?.workflows??{}),mainJobDeps:n,isSubscribed:e=>r.has(Z.workflowJobs(e))});for(let r of Object.values(t.workflowService?.workflows??{})){let t=resourceTrn(e,`workflow`,r.name);r.publishEvents===void 0&&i.push({trn:t,key:Z.workflow(r.name),scope:`resource`,resource:Ta.workflow(r.name),resourceType:`workflow`,name:r.name}),(n[r.mainJob.name]??[]).some(e=>a.get(e)===void 0&&!o.has(e))&&i.push({trn:t,key:Z.workflowJobs(r.name),scope:`jobs`,resource:Ta.workflowJobs(r.name),resourceType:`workflow`,name:r.name})}return i}async function fetchMissingDependentApps(e){let{client:t,workspaceId:n,application:r,runAppIds:i,subscribedKeys:a,jobsByWorkflow:o}=e;return(await Promise.all(recomputedResources(n,r,o,a).filter(({key:e})=>!a.has(e)).map(async({trn:e,key:n,...r})=>recordedDependencies((await P(()=>t.getMetadata({trn:e})))?.metadata?.labels,r.scope).filter(e=>!i.has(e.appId)).map(e=>({...r,...e}))))).flat()}function createProgress(e,t){let n=0;return{update:()=>{n+=1;let r=Math.round(n/t*100);process.stderr.write(`\r${e} ${n}/${t} (${r}%)`)},finish:()=>{process.stderr.write(`
|
|
124
|
+
`)}}}async function withTimeout(e,t,n){let r=new AbortController;try{return await Promise.race([e,Fi(t,void 0,{signal:r.signal}).then(()=>{throw Error(n)})])}finally{r.abort()}}const lc=/* @__PURE__ */ new Set([`.DS_Store`,`thumbs.db`,`desktop.ini`]);function shouldIgnoreFile(e){let t=H.basename(e).toLowerCase();return lc.has(t)}async function deployStaticWebsite(e,t,n,r,i=!0){let{deploymentId:a}=await e.createDeployment({workspaceId:t,name:n});if(!a)throw b(`createDeployment returned empty deploymentId`);let o=await uploadDirectory(e,t,a,r,i),{url:s}=await e.publishDeployment({workspaceId:t,deploymentId:a});if(!s)throw b(`publishDeployment returned empty url`);return{url:s,skippedFiles:o}}async function uploadDirectory(e,t,n,r,i){let a=await collectFiles(r);if(a.length===0)return C.warn(`No files found under ${r}`),[];let o=mi(5),s=a.length,c=i?createProgress(`Uploading files`,s):void 0,l=[];return await Promise.all(a.map(i=>o(async()=>{await uploadSingleFile(e,t,n,r,i,l),c&&c.update()}))),c&&c.finish(),l}async function collectFiles(e,t=``){let n=H.join(e,t),r=await Ii.promises.readdir(n,{withFileTypes:!0}),i=[];for(let n of r){let r=H.join(t,n.name);if(n.isDirectory()){let t=await collectFiles(e,r);i.push(...t)}else n.isFile()&&!n.isSymbolicLink()&&!shouldIgnoreFile(r)&&i.push(r)}return i}async function uploadSingleFile(e,t,n,r,i,a){let o=H.join(r,i),s=Li(i);if(!s){a.push(`${i} (unsupported content type; no MIME mapping found)`);return}let c=s,l=Ii.createReadStream(o,{highWaterMark:65536});async function*requestStream(){yield{payload:{case:`initialMetadata`,value:{workspaceId:t,deploymentId:n,filePath:i,contentType:c}}};for await(let e of l)yield{payload:{case:`chunkData`,value:e}}}async function uploadWithLogging(){try{await e.uploadFile(requestStream())}catch(e){if(e instanceof q&&e.code===K.InvalidArgument){a.push(`${i} (server rejected file as invalid: ${e.message})`);return}throw e}}await withTimeout(uploadWithLogging(),12e4,`Upload timed out for "${i}"`)}function logSkippedFiles(e){if(e.length!==0){C.warn(`Deployment completed, but some files failed to upload. These files may have unsupported content types or other validation issues. Please review the list below:`);for(let t of e)C.log(` - ${t}`)}}const uc=Y({name:`deploy`,description:`Deploy a static website from a local build directory.`,args:U.strictObject({...j,name:V(U.string(),{alias:`n`,description:`Static website name`}),dir:V(U.string(),{alias:`d`,description:`Path to the static website files`,completion:{type:`directory`}})}),run:async e=>{await assertWritable({profile:e.profile}),C.info(`Deploying static website "${e.name}" from directory: ${e.dir}`);let t=await A({profile:e.profile}),n=await N(t),r=e.name,i=H.resolve(process.cwd(),e.dir),a=await xe({workspaceId:e[`workspace-id`],profile:e.profile});if(!Ii.existsSync(i)||!Ii.statSync(i).isDirectory())throw E({code:`DIRECTORY_NOT_FOUND`,message:`Directory not found or not a directory: ${i}`});let{url:o,skippedFiles:s}=await withTimeout(deployStaticWebsite(n,a,r,i,!e.json),6e5,`Deployment timed out after 10 minutes.`);e.json?C.out({name:r,workspaceId:a,url:o,skippedFiles:s}):(C.success(`Static website "${r}" deployed successfully. URL: ${o}`),logSkippedFiles(s))}});function stdioFor(e){return e===`capture`?[`ignore`,`pipe`,`pipe`]:e===`ignore`?`ignore`:[`ignore`,process.stderr,process.stderr]}function execPluginCommand(e,t){let{workingDir:n,env:r,output:i=`stream`}=t;return new Promise((t,a)=>{let o=Ri(e,{shell:!0,cwd:n,env:{...process.env,...r},stdio:stdioFor(i)}),s=``,c=``;o.stdout?.setEncoding(`utf8`).on(`data`,e=>{s+=e}),o.stderr?.setEncoding(`utf8`).on(`data`,e=>{c+=e}),o.once(`error`,t=>{a(E({code:`PLUGIN_COMMAND_START_FAILED`,message:`Failed to start command: ${e} (working directory: ${n}): ${t.message}`,cause:t}))}),o.once(`close`,(r,i)=>{if(r===0){t({stdout:s,stderr:c});return}let o=c.trimEnd().split(`
|
|
125
125
|
`).slice(-20).join(`
|
|
126
|
-
`);a(E({code:`PLUGIN_COMMAND_FAILED`,message:`Command failed: ${e} (working directory: ${n}, exit code: ${r}${i?`, signal: ${i}`:``})${o?`\n${o}`:``}`}))})})}async function loadSiteUrl(e,t,n){let r=await e.getStaticWebsite({workspaceId:t,name:n}),i=a(r.staticwebsite,`Static website "${n}" not found after deploy`);if(!i.url)throw E({code:`STATIC_WEBSITE_URL_NOT_ASSIGNED`,message:`Static website "${n}" has no URL assigned yet`,suggestion:`Re-run the deploy once the static website's URL is available.`});return i.url}function oauth2ClientLoader(e,t){let n=/* @__PURE__ */ new Map;return r=>{let i=n.get(r);return i||(i=
|
|
126
|
+
`);a(E({code:`PLUGIN_COMMAND_FAILED`,message:`Command failed: ${e} (working directory: ${n}, exit code: ${r}${i?`, signal: ${i}`:``})${o?`\n${o}`:``}`}))})})}async function loadSiteUrl(e,t,n){let r=await e.getStaticWebsite({workspaceId:t,name:n}),i=a(r.staticwebsite,`Static website "${n}" not found after deploy`);if(!i.url)throw E({code:`STATIC_WEBSITE_URL_NOT_ASSIGNED`,message:`Static website "${n}" has no URL assigned yet`,suggestion:`Re-run the deploy once the static website's URL is available.`});return i.url}function oauth2ClientLoader(e,t){let n=/* @__PURE__ */ new Map;return r=>{let i=n.get(r);return i||(i=Pt(async(n,i)=>{let a=await e.listAuthOAuth2Clients({workspaceId:t,namespaceName:r,pageToken:n,pageSize:i});for(let e of a.oauth2Clients)C.registerSecret(e.clientSecret);return[a.oauth2Clients,a.nextPageToken]}).then(e=>e.map(({name:e,clientId:t})=>({name:e,clientId:t}))),n.set(r,i)),i}}function byName(e){let t=Object.create(null);for(let n of e)t[n.name]=n;return t}async function loadDeployedTarget(e,t,n,r){let i=n.application.name,o=nt({authService:n.application.authService,config:n.config}),[s,c,l,u]=await Promise.all([n.application.subgraphs.length?e.getApplication({workspaceId:t,applicationName:i}):P(()=>e.getApplication({workspaceId:t,applicationName:i})),Promise.all(n.application.staticWebsiteServices.map(async n=>({name:n.name,url:await loadSiteUrl(e,t,n.name)}))),Promise.all((n.config.aiGateways??[]).map(async n=>{let r=await P(()=>e.getAIGateway({workspaceId:t,aigatewayName:n.name})),i=a(r?.aigateway,`AI Gateway "${n.name}" not found after deploy`);return{name:n.name,url:i.url}})),o?r(o):[]]),d=n.application.subgraphs.length?a(s?.application,`Application "${i}" not found after deploy`):s?.application;return{application:{...n.application.id?{id:n.application.id}:{},name:i,configPath:n.config.path,...d?{url:d.url,domain:d.domain}:{},aiGateways:l,staticWebsites:byName(c),...o?{auth:{namespace:o,oauth2Clients:u}}:{}}}}async function loadDeployedApplications(e){let{client:t,workspaceId:n,targets:r}=e,i=oauth2ClientLoader(t,n);return(await Promise.all(r.map(e=>loadDeployedTarget(t,n,e,i)))).map(({application:e})=>e)}function ignoreMissingPath(e){let t=e instanceof Error&&`code`in e?e.code:void 0;if(t!==`ENOENT`&&t!==`ENOTDIR`)throw e}async function publishStaticWebsite(e,t,n,r){let i=H.resolve(r);if(!(await Ni(i).catch(ignoreMissingPath))?.isDirectory())throw E({code:`DIRECTORY_NOT_FOUND`,message:`Static website publish directory does not exist or is not a directory: ${i}`});return withTimeout(deployStaticWebsite(e,t,n,i,!C.jsonMode),6e5,`Deployment timed out after 10 minutes.`)}function deployedHookFailure(e,t,n){let r=t instanceof Error?t.message:String(t);return E({code:`DEPLOYED_HOOK_FAILED`,message:`Platform resources were applied successfully, but ${e}: ${r}${n.length?`. Hooks not run: ${n.join(`, `)}`:``}`,suggestion:"Fix the error and run `tailor deploy` again. Unchanged resources are not re-applied.",cause:t})}function deployedHookLoadFailure(e,t){return deployedHookFailure(`loading the deployed information for onDeployed hooks failed`,e,t)}function isPlainObject$1(e){let t=Object.getPrototypeOf(e);return t===null||t===Object.prototype}function invalidOutputs(e){return E({code:`DEPLOYED_HOOK_OUTPUTS_INVALID`,message:`outputs are not JSON-serializable: ${e} is not a JSON value`})}function toJsonValue(e,t,n){if(e===null||typeof e==`string`||typeof e==`boolean`||typeof e==`number`&&Number.isFinite(e))return e;if(typeof e!=`object`||n.has(e)||!Array.isArray(e)&&!isPlainObject$1(e))throw invalidOutputs(t);n.add(e);try{return Array.isArray(e)?Array.from(e,(e,r)=>toJsonValue(e,`${t}[${r}]`,n)):Object.fromEntries(Object.entries(e).map(([e,r])=>[e,toJsonValue(r,`${t}.${e}`,n)]))}finally{n.delete(e)}}function hookLabel(e){return`${e.plugin.id} (app: ${e.target.application.name})`}function copyJsonOutputs(e){if(typeof e!=`object`||!e||!isPlainObject$1(e))throw E({code:`DEPLOYED_HOOK_OUTPUTS_INVALID`,message:`outputs must be a plain object`});return toJsonValue(e,`outputs`,/* @__PURE__ */ new Set)}async function runDeployedHooks(e){let{client:t,workspaceId:n,targets:r}=e,i=r.flatMap((e,t)=>e.plugins.flatMap(n=>n.onDeployed?[{target:e,index:t,plugin:n,hook:n.onDeployed}]:[]));if(i.length===0)return[];let o=e.applications??await loadDeployedApplications(e).catch(e=>{throw deployedHookLoadFailure(e,i.map(hookLabel))}),publishable=e=>({...e,staticWebsites:byName(Object.values(e.staticWebsites).map(e=>{let{name:r,url:i}=a(e,`Deployed static website missing`);return{name:r,url:i,publish:e=>publishStaticWebsite(t,n,r,e)}}))}),s=[];for(let[e,t]of i.entries()){let{target:r,index:c,plugin:l,hook:u}=t;try{let e=(await B(`deploy.onDeployed`,async e=>(e.setAttribute(`plugin.id`,l.id),e.setAttribute(`app.name`,r.application.name),u.call(l,{workspaceId:n,application:publishable(a(o[c],`Deployed application missing`)),applications:o,configPath:r.config.path,pluginConfig:l.pluginConfig,logger:{info:C.info,warn:C.warn,success:C.success},exec:execPluginCommand}))))?.outputs;e!==void 0&&s.push({application:r.application.name,pluginId:l.id,outputs:copyJsonOutputs(e)})}catch(t){throw deployedHookFailure(`the onDeployed hook of plugin "${l.id}" failed for app "${r.application.name}"`,t,i.slice(e+1).map(hookLabel))}}return s}const dc=U.object({outputPath:U.string(),contentHash:U.string()}),fc=U.object({kind:U.literal(`bundle`),inputHash:U.string(),dependencyPaths:U.array(U.string()),outputFiles:U.array(dc),packageRuntimeGlobals:U.record(U.string(),U.array(U.string())).optional(),createdAt:U.string()}),pc=U.object({version:U.literal(1),sdkVersion:U.string(),lockfileHash:U.string().optional(),entries:U.record(U.string(),fc)});function createCacheStore(e){let t=null;function manifestPath(){return H.join(e.cacheDir,`manifest.json`)}function bundlesDir(){return H.join(e.cacheDir,`bundles`)}function bundlePath(e){return H.join(bundlesDir(),`${Ze(e)}.js`)}function loadManifest(){try{let e=W.readFileSync(manifestPath(),`utf-8`),n=pc.safeParse(JSON.parse(e));if(!n.success){t=void 0;return}return t=n.data,t}catch{t=void 0;return}}function getCurrentManifest(){return t===null&&loadManifest(),t??void 0}function ensureManifestLoaded(){return t===null&&loadManifest(),t??={version:1,sdkVersion:``,entries:{}},t}function saveManifest(n){W.mkdirSync(e.cacheDir,{recursive:!0});let r=manifestPath(),i=H.join(e.cacheDir,`.manifest.${process.pid}.tmp`);try{W.writeFileSync(i,JSON.stringify(n,null,2),`utf-8`),W.renameSync(i,r)}catch(e){try{W.rmSync(i,{force:!0})}catch{}throw e}t=n}function getEntry(e){return ensureManifestLoaded().entries[e]}function setEntry(e,t){let n=ensureManifestLoaded();n.entries[e]=t}function deleteEntry(e){let t=ensureManifestLoaded();delete t.entries[e]}function storeBundleContent(e,t){let n=bundlesDir();W.mkdirSync(n,{recursive:!0}),W.writeFileSync(bundlePath(e),t,`utf-8`)}function restoreBundleContent(e){try{return W.readFileSync(bundlePath(e),`utf-8`)}catch(e){if(e.code===`ENOENT`)return;throw e}}function clean(){W.rmSync(e.cacheDir,{recursive:!0,force:!0}),t=null}return{loadManifest,getCurrentManifest,saveManifest,getEntry,setEntry,deleteEntry,storeBundleContent,restoreBundleContent,clean}}function createCacheManager(e){if(!(e.enabled??!0))return{enabled:!1,bundleCache:{tryRestore(){},save(){}},finalize(){}};let t=createCacheStore({cacheDir:e.cacheDir??H.resolve(Qe(),`cache`)}),n=t.loadManifest();return n&&(n.sdkVersion===e.sdkVersion?n.lockfileHash!==e.lockfileHash&&(C.debug(`Cache invalidated: lockfile changed`),t.clean()):(C.debug(`Cache invalidated: SDK version changed from ${n.sdkVersion} to ${e.sdkVersion}`),t.clean())),{enabled:!0,bundleCache:Ye(t),finalize(){let n=t.getCurrentManifest()??{version:1,sdkVersion:e.sdkVersion,lockfileHash:e.lockfileHash,entries:{}},r=t.loadManifest(),i=r?.sdkVersion===e.sdkVersion&&r.lockfileHash===e.lockfileHash?{...r,entries:{...r.entries,...n.entries}}:n;i.sdkVersion=e.sdkVersion,i.lockfileHash=e.lockfileHash,t.saveManifest(i)}}}function extractAttributesFromConfig(e){return collectAttributesFromConfig(e)}const isValidIdentifier=e=>/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(e);function generateTypeDefinition(e,t,n,r,i,a,o,s,c,l){let u=e?Object.entries(e).map(([e,{type:t,optional:n}])=>` ${e}${n?`?`:``}: ${t};`).join(`
|
|
127
127
|
`):``,d=!e||Object.keys(e).length===0?`{}`:`{
|
|
128
128
|
${u}
|
|
129
129
|
}`,f=`{
|
|
@@ -147,9 +147,9 @@ ${x}
|
|
|
147
147
|
`):``,w=!s||s.length===0?`{}`:`{
|
|
148
148
|
${C}
|
|
149
149
|
}`,T=c?Object.entries(c):[],E=T.length?T.map(([e,t])=>` ${isValidIdentifier(e)?e:JSON.stringify(e)}: ${t.length?t.map(e=>JSON.stringify(e)).join(` | `):`never`};`).join(`
|
|
150
|
-
`):``,
|
|
150
|
+
`):``,ee=T.length===0?`{}`:`{
|
|
151
151
|
${E}
|
|
152
|
-
}`,
|
|
152
|
+
}`,D=l?`{
|
|
153
153
|
${isValidIdentifier(l.appName)?l.appName:JSON.stringify(l.appName)}: ${JSON.stringify(l.defaultDateRepresentation??`unset`)};
|
|
154
154
|
}`:`{}`;return M`
|
|
155
155
|
// This file is auto-generated by @tailor-platform/sdk
|
|
@@ -165,31 +165,31 @@ declare module "@tailor-platform/sdk" {
|
|
|
165
165
|
interface ConnectionNameRegistry ${b}
|
|
166
166
|
interface AIGatewayNameRegistry ${S}
|
|
167
167
|
interface AuthNamespaceNameRegistry ${w}
|
|
168
|
-
interface SecretVaultNameRegistry ${
|
|
169
|
-
interface DateRepresentationRegistry ${
|
|
168
|
+
interface SecretVaultNameRegistry ${ee}
|
|
169
|
+
interface DateRepresentationRegistry ${D}
|
|
170
170
|
}
|
|
171
171
|
|
|
172
172
|
export {};
|
|
173
173
|
|
|
174
|
-
`}function collectAttributesFromConfig(e){let t=e.idp?.length?[...new Set(e.idp.map(e=>e.name))]:void 0,n=e.aiGateways?.length?[...new Set(e.aiGateways.map(e=>e.name))]:void 0,r=e.secrets?Object.fromEntries(Object.entries(e.secrets.vaults).map(([e,t])=>[e,Object.keys(t)])):void 0,i=e.auth,a=i&&typeof i==`object`&&typeof i.name==`string`?[i.name]:void 0;if(!i||typeof i!=`object`)return{idpNames:t,aiGatewayNames:n,authNamespaceNames:a,secretVaultNames:r};let o=i.machineUsers,s=o&&typeof o==`object`?Object.keys(o):void 0,c=i.connections,l=c&&typeof c==`object`?Object.keys(c):void 0,inferAttributeType=e=>{let t=e?.type,n=e?.metadata;if(!n)return{type:`string`};let r=`string`;return t===`boolean`?r=`boolean`:t===`enum`&&n.allowedValues&&(r=n.allowedValues.map(e=>`"${e.value}"`).join(` | `)),n.array&&(r=r.includes(` | `)?`(${r})[]`:`${r}[]`),{type:r,optional:n.required===!1}};if(`userProfile`in i){let e=i.userProfile,o=e?.attributes,c=e?.type?.fields,u=e?.attributeList;return{attributes:o?Object.keys(o).reduce((e,t)=>(e[t]=inferAttributeType(c?.[t]),e),{}):void 0,attributeList:u,machineUserNames:s,idpNames:t,connectionNames:l,aiGatewayNames:n,authNamespaceNames:a,secretVaultNames:r}}if(`machineUserAttributes`in i){let e=i.machineUserAttributes;return e?{attributes:Object.entries(e).reduce((e,[t,n])=>(e[t]=inferAttributeType(n),e),{}),machineUserNames:s,idpNames:t,connectionNames:l,aiGatewayNames:n,authNamespaceNames:a,secretVaultNames:r}:{machineUserNames:s,idpNames:t,connectionNames:l,aiGatewayNames:n,authNamespaceNames:a,secretVaultNames:r}}return{machineUserNames:s,idpNames:t,connectionNames:l,aiGatewayNames:n,authNamespaceNames:a,secretVaultNames:r}}function resolveTypeDefinitionPath(e){let t=process.env.TAILOR_DTS_PATH;return t?H.resolve(t):H.join(H.dirname(H.resolve(e)),`tailor.d.ts`)}async function generateUserTypes(e){let{config:t,configPath:n}=e;try{let{attributes:e,attributeList:r,machineUserNames:i,idpNames:a,connectionNames:o,aiGatewayNames:s,authNamespaceNames:c,secretVaultNames:l}=extractAttributesFromConfig(t);!e&&!r&&C.info(`No attributes found in configuration`,{mode:`plain`}),e&&C.debug(`Extracted Attributes: ${JSON.stringify(e)}`),r&&C.debug(`Extracted AttributeList: ${JSON.stringify(r)}`),i?.length&&C.debug(`Extracted MachineUserNames: ${JSON.stringify(i)}`),a?.length&&C.debug(`Extracted IdpNames: ${JSON.stringify(a)}`),o?.length&&C.debug(`Extracted ConnectionNames: ${JSON.stringify(o)}`),s?.length&&C.debug(`Extracted AIGatewayNames: ${JSON.stringify(s)}`),c?.length&&C.debug(`Extracted AuthNamespaceNames: ${JSON.stringify(c)}`),l&&Object.keys(l).length&&C.debug(`Extracted SecretVaultNames: ${JSON.stringify(l)}`);let u=t.env;u&&C.debug(`Extracted Env: ${JSON.stringify(u)}`);let d=generateTypeDefinition(e,r,u,i,a,o,s,c,l,{appName:t.name,defaultDateRepresentation:t.defaultDateRepresentation}),f=resolveTypeDefinitionPath(n);W.mkdirSync(H.dirname(f),{recursive:!0}),W.writeFileSync(f,d);let p=H.relative(process.cwd(),f);C.newline(),C.success(`Generated type definitions: ${p}`,{mode:`plain`})}catch(e){C.error(`Error generating types`),C.error(String(e))}}const
|
|
174
|
+
`}function collectAttributesFromConfig(e){let t=e.idp?.length?[...new Set(e.idp.map(e=>e.name))]:void 0,n=e.aiGateways?.length?[...new Set(e.aiGateways.map(e=>e.name))]:void 0,r=e.secrets?Object.fromEntries(Object.entries(e.secrets.vaults).map(([e,t])=>[e,Object.keys(t)])):void 0,i=e.auth,a=i&&typeof i==`object`&&typeof i.name==`string`?[i.name]:void 0;if(!i||typeof i!=`object`)return{idpNames:t,aiGatewayNames:n,authNamespaceNames:a,secretVaultNames:r};let o=i.machineUsers,s=o&&typeof o==`object`?Object.keys(o):void 0,c=i.connections,l=c&&typeof c==`object`?Object.keys(c):void 0,inferAttributeType=e=>{let t=e?.type,n=e?.metadata;if(!n)return{type:`string`};let r=`string`;return t===`boolean`?r=`boolean`:t===`enum`&&n.allowedValues&&(r=n.allowedValues.map(e=>`"${e.value}"`).join(` | `)),n.array&&(r=r.includes(` | `)?`(${r})[]`:`${r}[]`),{type:r,optional:n.required===!1}};if(`userProfile`in i){let e=i.userProfile,o=e?.attributes,c=e?.type?.fields,u=e?.attributeList;return{attributes:o?Object.keys(o).reduce((e,t)=>(e[t]=inferAttributeType(c?.[t]),e),{}):void 0,attributeList:u,machineUserNames:s,idpNames:t,connectionNames:l,aiGatewayNames:n,authNamespaceNames:a,secretVaultNames:r}}if(`machineUserAttributes`in i){let e=i.machineUserAttributes;return e?{attributes:Object.entries(e).reduce((e,[t,n])=>(e[t]=inferAttributeType(n),e),{}),machineUserNames:s,idpNames:t,connectionNames:l,aiGatewayNames:n,authNamespaceNames:a,secretVaultNames:r}:{machineUserNames:s,idpNames:t,connectionNames:l,aiGatewayNames:n,authNamespaceNames:a,secretVaultNames:r}}return{machineUserNames:s,idpNames:t,connectionNames:l,aiGatewayNames:n,authNamespaceNames:a,secretVaultNames:r}}function resolveTypeDefinitionPath(e){let t=process.env.TAILOR_DTS_PATH;return t?H.resolve(t):H.join(H.dirname(H.resolve(e)),`tailor.d.ts`)}async function generateUserTypes(e){let{config:t,configPath:n}=e;try{let{attributes:e,attributeList:r,machineUserNames:i,idpNames:a,connectionNames:o,aiGatewayNames:s,authNamespaceNames:c,secretVaultNames:l}=extractAttributesFromConfig(t);!e&&!r&&C.info(`No attributes found in configuration`,{mode:`plain`}),e&&C.debug(`Extracted Attributes: ${JSON.stringify(e)}`),r&&C.debug(`Extracted AttributeList: ${JSON.stringify(r)}`),i?.length&&C.debug(`Extracted MachineUserNames: ${JSON.stringify(i)}`),a?.length&&C.debug(`Extracted IdpNames: ${JSON.stringify(a)}`),o?.length&&C.debug(`Extracted ConnectionNames: ${JSON.stringify(o)}`),s?.length&&C.debug(`Extracted AIGatewayNames: ${JSON.stringify(s)}`),c?.length&&C.debug(`Extracted AuthNamespaceNames: ${JSON.stringify(c)}`),l&&Object.keys(l).length&&C.debug(`Extracted SecretVaultNames: ${JSON.stringify(l)}`);let u=t.env;u&&C.debug(`Extracted Env: ${JSON.stringify(u)}`);let d=generateTypeDefinition(e,r,u,i,a,o,s,c,l,{appName:t.name,defaultDateRepresentation:t.defaultDateRepresentation}),f=resolveTypeDefinitionPath(n);W.mkdirSync(H.dirname(f),{recursive:!0}),W.writeFileSync(f,d);let p=H.relative(process.cwd(),f);C.newline(),C.success(`Generated type definitions: ${p}`,{mode:`plain`})}catch(e){C.error(`Error generating types`),C.error(String(e))}}const mc=`To use this config for a separate app, delete it.`;function warnMissingAppId(e){e||(C.warn(`The config resolved without an 'id'.`),C.log(` Resources tagged with an id from an earlier deploy read as another application's:
|
|
175
175
|
deploy asks before taking them over, and remove leaves them in place. Only resources
|
|
176
176
|
carrying no id are matched by application name.
|
|
177
177
|
Add an 'id' to the object passed to defineConfig() — a config that re-exports it from
|
|
178
|
-
another file cannot have one injected automatically. 'tailor deploy' can add it for you.`))}const
|
|
179
|
-
`,n.start-1)+1,o=e.slice(i,n.start);if(!/^[\t ]*$/.test(o))return e.slice(0,n.start)+`${r}, `+e.slice(n.start);let s=`${
|
|
180
|
-
`,t.start)+1,s=e.slice(o).match(/^[\t ]*/)?.[0]??``,c=`${s} `,l=`\n${c}${
|
|
178
|
+
another file cannot have one injected automatically. 'tailor deploy' can add it for you.`))}const hc=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function findDefineConfigCalls(e,t){if(!e||typeof e!=`object`)return;let n=e;if(n.type===`CallExpression`){let e=n;if(e.callee.type===`Identifier`&&e.callee.name===`defineConfig`){let n=e.arguments[0],r=n&&n.type===`ObjectExpression`?n:null;t.push({callExpr:e,configObj:r})}}for(let e of Object.keys(n)){let r=n[e];if(Array.isArray(r))for(let e of r)findDefineConfigCalls(e,t);else r&&typeof r==`object`&&findDefineConfigCalls(r,t)}}function findIdProperties(e){let t=[];for(let n of e.properties)n.type===`Property`&&(n.key.type===`Identifier`?n.key.name:n.key.type===`Literal`?n.key.value:null)===`id`&&t.push(n);return t}function findIdProperty(e){return findIdProperties(e)[0]??null}function namesId(e){return e?.type===`Identifier`&&e.name===`id`||e?.type===`Literal`&&e.value===`id`}function readsIdMember(e){if(!e||typeof e!=`object`)return!1;let t=e;return t.type===`MemberExpression`&&namesId(t.property)||t.type===`ObjectPattern`&&t.properties.some(e=>e.type===`Property`&&namesId(e.key))?!0:Object.values(t).some(e=>Array.isArray(e)?e.some(readsIdMember):readsIdMember(e))}async function ensureConfigId(e){let t=await W.promises.readFile(e,`utf-8`),{program:n}=Ei(e,t),r=[];if(findDefineConfigCalls(n,r),r.length===0)return null;if(r.length>1)throw E({code:`CONFIG_ID_UNMANAGEABLE`,message:`Multiple defineConfig() calls found in ${e}. Only one is supported.`});let{configObj:i}=a(r[0],`defineConfig call site missing`);if(!i)throw E({code:`CONFIG_ID_UNMANAGEABLE`,message:`defineConfig() argument must be an inline object literal in ${e} so the SDK can manage the 'id' field.`});let o=findIdProperty(i);if(o){let t=o.value;if(t.type!==`Literal`)throw E({code:`CONFIG_ID_INVALID`,message:`'id' field in ${e} must be a string literal.`,suggestion:mc});let n=t.value;if(typeof n!=`string`||n===``)throw E({code:`CONFIG_ID_INVALID`,message:`'id' field in ${e} must be a non-empty string literal.`,suggestion:mc});if(!hc.test(n))throw E({code:`CONFIG_ID_INVALID`,message:`'id' field in ${e} must be a UUID.`,suggestion:mc});return{id:n,injected:!1}}let s=crypto.randomUUID(),c=insertIdProperty(t,i,s);return await W.promises.writeFile(e,c,`utf-8`),C.info(`Generated app id and wrote to ${e}: ${s}`),{id:s,injected:!0}}async function readConfigId(e){let t=await W.promises.readFile(e,`utf-8`),{program:n}=Ei(e,t),r=[];if(findDefineConfigCalls(n,r),r.length===0)return null;if(r.length>1)throw E({code:`CONFIG_ID_UNMANAGEABLE`,message:`Multiple defineConfig() calls found in ${e}. Only one is supported.`});let{configObj:i}=a(r[0],`defineConfig call site missing`);if(!i)throw E({code:`CONFIG_ID_UNMANAGEABLE`,message:`defineConfig() argument must be an inline object literal in ${e} so the SDK can manage the 'id' field.`});let o=findIdProperty(i);if(!o||o.value.type!==`Literal`)return{id:null};let s=o.value.value;return{id:typeof s==`string`&&s!==``?s:null}}async function assertConfigIdInCI(e){let t=await readConfigId(e);if(t!==null){if(!t.id)throw E({code:`CONFIG_ID_REQUIRED_IN_CI`,message:`tailor.config.ts is missing an 'id'.`,details:`CI does not auto-generate one (each run would be treated as a separate app and break resource ownership).`,suggestion:`Run 'tailor deploy' locally and commit the injected id.`});if(!hc.test(t.id))throw E({code:`CONFIG_ID_INVALID`,message:`'id' in ${e} must be a UUID.`,suggestion:mc})}}async function ensureConfigIdForDeploy(e){let{configPath:t,dryRun:n,buildOnly:r}=e;if(r)return;let i=p(process.env.TAILOR_CI_ALLOW_ID_INJECTION)===!0,a=ui&&!i;n?a&&await assertConfigIdInCI(t):a?await assertConfigIdInCI(t):await ensureConfigId(t)}const gc=`// SDK-managed app id — do not edit, except when copying this config to a separate app.`;function insertIdProperty(e,t,n){let r=`id: ${JSON.stringify(n)}`;if(t.properties.length>0){let n=a(t.properties[0],`first property missing`),i=e.lastIndexOf(`
|
|
179
|
+
`,n.start-1)+1,o=e.slice(i,n.start);if(!/^[\t ]*$/.test(o))return e.slice(0,n.start)+`${r}, `+e.slice(n.start);let s=`${gc}\n${o}${r},\n${o}`;return e.slice(0,n.start)+s+e.slice(n.start)}let i=t.start+1,o=e.lastIndexOf(`
|
|
180
|
+
`,t.start)+1,s=e.slice(o).match(/^[\t ]*/)?.[0]??``,c=`${s} `,l=`\n${c}${gc}\n${c}${r},\n${s}`;return e.slice(0,i)+l+e.slice(i)}function removeIdProperty(e,t,n){let r=removeIdPropertyText(e,n);if(t.properties.length>1)return r;let i=t.end-(e.length-r.length);return r.slice(t.start+1,i-1).trim()===``?`${r.slice(0,t.start+1)}${r.slice(i-1)}`:r}function removeIdPropertyText(e,t){let n=t.end,r=/^[\t ]*,/.exec(e.slice(n));r&&(n+=r[0].length);let i=e.lastIndexOf(`
|
|
181
181
|
`,t.start-1)+1,a=e.indexOf(`
|
|
182
182
|
`,n),o=a===-1?e.length:a+1;if(/^[\t ]*$/.test(e.slice(i,t.start))&&/^[\t \r]*$/.test(e.slice(n,o).replace(/\n$/,``))){let t=i;if(i>1){let n=e.lastIndexOf(`
|
|
183
|
-
`,i-2)+1;e.slice(n,i).trim()===
|
|
183
|
+
`,i-2)+1;e.slice(n,i).trim()===gc&&(t=n)}return e.slice(0,t)+e.slice(o)}if(r){let r=/^[\t ]*/.exec(e.slice(n))?.[0].length??0;return e.slice(0,t.start)+e.slice(n+r)}let s=e.slice(0,t.start),c=/,?[\t ]*$/.exec(s)?.[0].length??0;return s.slice(0,s.length-c)+e.slice(n)}async function removeConfigId(e,t){let n=await W.promises.readFile(e,`utf-8`),{program:r}=Ei(e,n),i=[];findDefineConfigCalls(r,i);let a=i.length===1?i[0]?.configObj:null;if(!a||readsIdMember(r))return!1;let o=findIdProperties(a),s=o.length===1?o[0]:void 0;if(!s||s.value.type!==`Literal`)return!1;let c=s.value.value;if(typeof c!=`string`||c.toLowerCase()!==t.toLowerCase())return!1;let l=removeIdProperty(n,a,s);return Ei(e,l).errors.length>0?!1:(await W.promises.writeFile(e,l,`utf-8`),!0)}const Q=`.github/tailor.lock`,_c=2,vc=`The lock file is machine-owned; restore it from git (git checkout -- ${Q}) and re-run setup.`;function isPlainObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function isRepositoryRelativeKey(e){return e===``||H.isAbsolute(e)||e.includes(`\\`)?!1:e.split(`/`).every(e=>e!==``&&e!==`.`&&e!==`..`)}function assertSafeLockPath(e){for(let t of[`.github`,Q])try{if(W.lstatSync(H.join(e,t)).isSymbolicLink())throw E({code:`APP_ID_LOCK_INVALID`,message:`Refusing to use ${Q}: "${t}" is a symbolic link.`})}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)continue;throw e}}function parseAppIds(e){if(e===void 0)return{};if(!isPlainObject(e))throw E({code:`APP_ID_LOCK_INVALID`,message:`${Q} has an invalid 'appIds' section: expected an object mapping config paths to app ids.`,suggestion:vc});let t=/* @__PURE__ */ new Map;for(let[n,r]of Object.entries(e)){if(!isRepositoryRelativeKey(n))throw E({code:`APP_ID_LOCK_INVALID`,message:`${Q} 'appIds' key "${n}" must be a repository-relative config path (no absolute paths, "..", or backslashes).`,suggestion:vc});if(typeof r!=`string`||!hc.test(r))throw E({code:`APP_ID_LOCK_INVALID`,message:`${Q} 'appIds' entry for "${n}" must be a UUID.`,suggestion:vc});let e=t.get(r.toLowerCase());if(e!==void 0)throw E({code:`APP_ID_CONFLICT`,message:`${Q} records the same app id "${r}" for "${e}" and "${n}".`,suggestion:`Each config needs its own app id: delete the entry of the copied config so the next local deploy assigns a fresh one.`});t.set(r.toLowerCase(),n)}return e}function readRawLock(e){assertSafeLockPath(e);let t=H.join(e,Q);if(!W.existsSync(t))return null;let n;try{n=W.readFileSync(t,`utf-8`)}catch(t){throw E({code:`APP_ID_LOCK_UNREADABLE`,message:`${Q} under ${e} could not be read.`,cause:t})}let r;try{r=JSON.parse(n)}catch(e){throw E({code:`APP_ID_LOCK_INVALID`,message:`${Q} is not valid JSON.`,suggestion:vc,cause:e})}if(!isPlainObject(r)||typeof r.version!=`number`)throw E({code:`APP_ID_LOCK_INVALID`,message:`${Q} has no valid 'version' field.`,suggestion:vc});if(r.version>2)throw E({code:`APP_ID_LOCK_VERSION_UNSUPPORTED`,message:`${Q} was written by a newer SDK (lock version ${String(r.version)}).`,suggestion:`Update @tailor-platform/sdk and @tailor-platform/sdk-plugin-setup to continue.`});return r}function readAppIdLock(e){let t=readRawLock(e);return t===null?null:{root:e,appIds:parseAppIds(t.appIds)}}function findAppIdLock(e){let t=H.dirname(e);for(;;){if(W.existsSync(H.join(t,`.github/tailor.lock`)))return readAppIdLock(t);let e=H.dirname(t);if(e===t||W.existsSync(H.join(t,`.git`)))return null;t=e}}function appIdLockKey(e,t){let n=H.relative(e,t);if(!isRepositoryRelativeKey(n))throw E({code:`CONFIG_OUTSIDE_REPOSITORY`,message:`${t} is outside the repository that holds ${Q} (${e}).`});return n}function resolveAppId(e){let{configPath:t,configId:n}=e;if(n!==void 0&&!hc.test(n))throw configIdInvalid(t);let r=findAppIdLock(t);if(r===null)return n;let i=appIdLockKey(r.root,t),a=r.appIds[i];if(a!==void 0){if(n!==void 0&&n.toLowerCase()!==a.toLowerCase())throw recordedIdConflict(i,a,n);return a}if(n===void 0)return;let o=Object.entries(r.appIds).find(([,e])=>e.toLowerCase()===n.toLowerCase())?.[0];if(o!==void 0&&o!==i&&W.existsSync(H.join(r.root,o)))throw claimedIdConflict(t,o);return n}function recordedIdConflict(e,t,n){return E({code:`APP_ID_CONFLICT`,message:`${Q} records app id "${t}" for ${e}, but the config's 'id' is "${n}".`,suggestion:`Neither can be chosen automatically: remove the 'id' from the config to keep the recorded id, or replace the recorded value with the config's id.`})}function claimedIdConflict(e,t){return E({code:`APP_ID_CONFLICT`,message:`${e} carries the app id already recorded for ${t} in ${Q}.`,suggestion:`If this config was copied from that app, delete its 'id' so it gets a fresh one.`})}function configIdInvalid(e){return E({code:`CONFIG_ID_INVALID`,message:`'id' in ${e} must be a UUID.`,suggestion:`To use this config for a separate app, delete it.`})}function warnConfigStillCarriesId(e){C.warn(`${e} still carries an 'id' that is also recorded in ${Q}. Remove it from the config, or run 'tailor deploy' locally to move it; the lock is where the id lives now.`)}function warnUnrecordedConfigId(e){C.warn(`The app id of ${e} is read from the config and not yet recorded in ${Q}. Run 'tailor deploy' locally and commit ${Q}.`)}function warnMissingLockedAppId(e){C.warn(`No app id is recorded for ${e} in ${Q}.`),C.log(` Resources tagged with an id from an earlier deploy read as another application's:
|
|
184
184
|
deploy asks before taking them over, and remove leaves them in place. Only resources
|
|
185
|
-
carrying no id are matched by application name. 'tailor deploy' records an id for you.`)}function rekeyInstructions(e){return`${Q} has entries whose config no longer exists: ${e.join(`, `)}. If an app directory was moved, re-key its entry to the new path under 'appIds' so the app keeps its id; delete the entries of removed apps.`}function missingInCIError(e,t){let n=`Run 'tailor deploy' locally and commit ${Q}.`;return t.length>0&&(n+=` ${rekeyInstructions(t)}`),E({code:`CONFIG_ID_REQUIRED_IN_CI`,message:`No app id is recorded for ${e.join(`, `)} in ${Q}, and the config has no 'id'.`,details:`CI does not generate one (each run would be treated as a separate app and break resource ownership).`,suggestion:n})}async function confirmMove(e,t){if(!canPrompt())throw E({code:`APP_ID_NOT_RECORDED`,message:`No app id is recorded for ${t}.`,suggestion:rekeyInstructions([e])});return C.warn(`${Q} records an app id for ${e}, which no longer exists, and ${t} has none.`),X.confirm({message:`Was ${e} moved to ${t}? Yes keeps its app id; no assigns a fresh one.`,default:!1})}async function planAppIds(e){let{lock:t,entries:n,mode:r}=e,i={...t.appIds},o=!1,s=n.map(()=>void 0),c=[],l=new Map(Object.entries(i).map(([e,t])=>[t.toLowerCase(),e])),exists=e=>W.existsSync(H.join(t.root,e));n.forEach(({configPath:e,configId:n},a)=>{let u=appIdLockKey(t.root,e),d=i[u];if(d!==void 0){if(n!==void 0&&n.toLowerCase()!==d.toLowerCase())throw recordedIdConflict(u,d,n);let t=n!==void 0&&r===`write`;n!==void 0&&!t&&warnConfigStillCarriesId(u),s[a]={configPath:e,key:u,id:d,source:`lock`,removeConfigId:t}}else if(n!==void 0){if(!uc.test(n))throw configIdInvalid(e);let t=l.get(n.toLowerCase()),c=t!==void 0&&t!==u&&!exists(t)?t:void 0;if(t!==void 0&&t!==u&&c===void 0)throw claimedIdConflict(e,t);l.set(n.toLowerCase(),u);let d=r===`write`;d?(c!==void 0&&(delete i[c],C.info(`Keeping the app id of ${c} for ${u}: ${n}`)),i[u]=n,o=!0):warnUnrecordedConfigId(u),s[a]={configPath:e,key:u,id:n,source:`config`,removeConfigId:d}}else c.push({index:a,configPath:e,key:u})});let finish=()=>({appIds:i,changed:o,entries:s.map(e=>a(e,`app id entry missing`))});if(c.length===0)return finish();if(r===`read`){for(let{index:e,configPath:t,key:n}of c)warnMissingLockedAppId(n),s[e]={configPath:t,key:n,id:void 0,source:`none`,removeConfigId:!1};return finish()}let u=Object.keys(i).filter(e=>!exists(e)),d=[...new Set(c.map(({key:e})=>e))];if(r===`require`)throw missingInCIError(d,u);let f;if(u.length===1&&d.length===1){let e=a(u[0],`orphan missing`),t=a(d[0],`key missing`);await confirmMove(e,t)&&(f={from:e,key:t})}else if(u.length>0)throw E({code:`APP_ID_NOT_RECORDED`,message:`No app id is recorded for ${d.join(`, `)}.`,suggestion:rekeyInstructions(u)});for(let{index:e,configPath:t,key:n}of c){let r=i[n];if(r!==void 0){s[e]={configPath:t,key:n,id:r,source:`generated`,removeConfigId:!1};continue}let c;f?.key===n?(c=a(i[f.from],`orphaned app id missing`),delete i[f.from],C.info(`Keeping the app id of ${f.from} for ${n}: ${c}`)):(c=crypto.randomUUID(),C.info(`Generated app id for ${n}: ${c}`)),i[n]=c,o=!0;let l=f?.key===n?`lock`:`generated`;s[e]={configPath:t,key:n,id:c,source:l,removeConfigId:!1}}return finish()}function writeAppIds(e){let{lock:t,appIds:n}=e,r=readRawLock(t.root);if(r===null)throw E({code:`APP_ID_LOCK_NOT_FOUND`,message:`${Q} does not exist under ${t.root}.`,suggestion:`Create it with 'tailor setup'.`});let i={...parseAppIds(r.appIds)};for(let e of Object.keys(t.appIds))e in n||delete i[e];for(let[e,r]of Object.entries(n))t.appIds[e]!==r&&(i[e]=r);let a={...r,version:2,appIds:i};W.writeFileSync(H.join(t.root,Q),`${JSON.stringify(a,null,2)}\n`,`utf-8`)}async function removeAdoptedConfigIds(e){let t=!1,n=/* @__PURE__ */ new Set;for(let r of e.entries)r.removeConfigId&&r.id!==void 0&&!n.has(r.configPath)&&(n.add(r.configPath),await removeConfigId(r.configPath,r.id)?(t=!0,C.info(`Moved the app id of ${r.key} from the config into ${Q}.`)):C.warn(`The app id of ${r.key} is recorded in ${Q}. Remove the 'id' from the object passed to defineConfig() by hand; the SDK could not edit ${r.configPath} to do it.`));return{configEdited:t}}async function resolveLockedAppIds(e){let t=await planAppIds(e);return e.mode===`write`&&(t.changed&&writeAppIds({lock:e.lock,appIds:t.appIds}),await removeAdoptedConfigIds(t)),t}function appIdPlanModeForDeploy(e){let t=p(process.env.TAILOR_CI_ALLOW_ID_INJECTION)===!0;return si&&!t?`require`:e?`read`:`write`}function parseDeployConfigPaths(e){let t=e??ve();if(t===void 0)return[void 0];let n=t.split(`,`).map(e=>e.trim());if(n.some(e=>e.length===0))throw E({code:`DEPLOY_CONFIG_REQUIRED`,message:`--config must contain one or more non-empty config paths.`,command:`deploy`});return n}async function buildDeploymentTarget(e){let{configPath:t,loadedConfig:n,dryRun:r,buildOnly:i,noCache:o,packageVersion:s,cacheDir:c,client:l,workspaceId:u,expectedLocalStaticWebsiteNames:d,previous:f}=e,{config:p,plugins:m}=n??a((await loadDeployConfigs({configPaths:[t],dryRun:r,buildOnly:i}))[0],`loaded config missing`),h=H.dirname(p.path),g=li(`pnpm-lock.yaml`,{cwd:h})??li(`package-lock.json`,{cwd:h})??li(`yarn.lock`,{cwd:h})??li(`bun.lock`,{cwd:h}),_=createCacheManager({enabled:!o,cacheDir:c,sdkVersion:s,lockfileHash:g?Ge(g):void 0}),v;m.length>0&&(v=new Cr(m)),f||await B(`build.generateUserTypes`,()=>generateUserTypes({config:p,configPath:p.path}));let y,b,x,S,C;try{let e=await B(`build.loadApplication`,()=>ot({config:p,pluginManager:v,bundleCache:_.bundleCache,client:l,workspaceId:u,expectedLocalStaticWebsiteNames:d,previous:f}));y=e.application,b=e.workflowBuildResult,x=e.httpAdapterBuildResult,S=e.bundledScripts,C=e.reusableBuildState}finally{_.finalize()}return{plugins:m,config:p,application:y,workflowBuildResult:b,httpAdapterBuildResult:x,bundledScripts:S,reusableBuildState:C}}function resolveExistingConfigPath(e){let t=Ee(e);if(!t)return;let n=H.resolve(process.cwd(),t);return W.existsSync(n)?n:void 0}async function prepareDeployConfigs(e){let{configPaths:t,dryRun:n,buildOnly:r}=e;if(r)return;let i=new Set(t.map(resolveExistingConfigPath).filter(e=>e!==void 0));await Promise.all([...i].map(e=>B(`build.prepareConfig`,async()=>{findAppIdLock(e)===null&&await ensureConfigIdForDeploy({configPath:e,dryRun:n,buildOnly:r})})))}async function loadPreparedDeployConfig(e){return B(`build.loadConfig`,()=>loadConfig(e.configPath))}async function resolveDeployAppIds(e){let{loaded:t,dryRun:n,buildOnly:r}=e;if(r)return[...t];let i=[...t],o=/* @__PURE__ */ new Map;t.forEach((e,t)=>{let n=findAppIdLock(e.config.path);if(n===null){warnMissingAppId(e.config.id);return}let r=o.get(n.root)??{lock:n,indexes:[]};r.indexes.push(t),o.set(n.root,r)});let s=appIdPlanModeForDeploy(n);for(let{lock:e,indexes:n}of o.values()){let r=await resolveLockedAppIds({lock:e,mode:s,entries:n.map(e=>{let{config:n}=a(t[e],`loaded config missing`);return{configPath:n.path,configId:n.id}})});n.forEach((e,n)=>{let o=a(t[e],`loaded config missing`),s=a(r.entries[n],`planned app id entry missing`).id;i[e]={...o,config:{...o.config,id:s}}})}return i}async function loadDeployConfigs(e){return await prepareDeployConfigs(e),resolveDeployAppIds({loaded:await Promise.all(e.configPaths.map(t=>loadPreparedDeployConfig({...e,configPath:t}))),dryRun:e.dryRun,buildOnly:e.buildOnly})}async function buildDeploymentTargets(e){let{configPaths:t,loadedConfigs:n,buildTarget:r,previousTargets:i,...a}=e;if(n!==void 0&&(n.length!==t.length||t.some((e,t)=>n[t]===void 0)))throw b(`loadedConfigs must contain exactly one entry for every configPath`);let o=r===void 0&&n===void 0?await loadDeployConfigs({configPaths:t,dryRun:e.dryRun,buildOnly:e.buildOnly}):n,s=r??buildDeploymentTarget;return Promise.all(t.map((e,t)=>s({...a,configPath:e,loadedConfig:o?.[t],previous:i?.[t]})))}function addPossiblyAmbiguousNamespace(e,t,n){e.has(t)?e.get(t)!==n&&e.set(t,void 0):e.set(t,n)}function collectVisibleResources(e){let{application:t,applications:n,visibleKeysOf:r,resourcesOf:i,createResult:a,addResource:o}=e,s=r(t),c=a();for(let e of n)for(let t of i(e))s.has(t.visibilityKey)&&o(c,t.resourceKey,t.visibilityKey);return c}function collectApplicationTailorDBNamespaces(e){return/* @__PURE__ */ new Set([...e.tailorDBServices.map(e=>e.namespace),...e.externalTailorDBNamespaces])}function*tailorDBTypeResources(e){for(let t of e.tailorDBServices)for(let e of Object.keys(t.types))yield{visibilityKey:t.namespace,resourceKey:e}}function collectVisibleTailorDBTypeNamespaces(e,t){return collectVisibleResources({application:e,applications:t,visibleKeysOf:collectApplicationTailorDBNamespaces,resourcesOf:tailorDBTypeResources,createResult:()=>/* @__PURE__ */ new Map,addResource:addPossiblyAmbiguousNamespace})}function collectApplicationResolverNamespaces(e){return new Set(e.subgraphs.filter(e=>e.Type===`pipeline`).map(e=>e.Name))}function*idpNameResources(e){for(let t of collectApplicationIdpNames(e))yield{visibilityKey:t,resourceKey:t}}function collectVisibleIdpNames(e,t){return collectVisibleResources({application:e,applications:t,visibleKeysOf:collectApplicationIdpNames,resourcesOf:idpNameResources,createResult:()=>/* @__PURE__ */ new Set,addResource:(e,t)=>{e.add(t)}})}function*resolverResources(e){for(let t of e.resolverServices)for(let e of Object.values(t.resolvers))yield{visibilityKey:t.namespace,resourceKey:e.name}}function collectVisibleResolverNamespaces(e,t){return collectVisibleResources({application:e,applications:t,visibleKeysOf:collectApplicationResolverNamespaces,resourcesOf:resolverResources,createResult:()=>/* @__PURE__ */ new Map,addResource:addPossiblyAmbiguousNamespace})}function subscribedIdpName(e,t){if(t.idp!=null)return t.idp;let n=collectApplicationIdpNames(e);if(n.size!==1)return;let[r]=n;return r}function missingOwnerMessage(e,t,n){let r=`Executor "${e}" subscribes to ${t.resource}, which no config in this deploy declares.`,i=t.externalHint(n);return i?`${r} This config declares ${i}, so add the config that owns it to --config.`:t.trigger.kind===`workflowExecution`||t.trigger.kind===`workflowJobExecution`?`${r} A workflow has no "external" declaration, unlike a TailorDB namespace or resolver, so nothing in this config points at the one that owns it. Check the name, or add the config that declares the workflow to --config.`:`${r} This config declares nothing external that could hold it, so check the name.`}function collectEventSubscriptions(e){let t=[],n=e.map(e=>e.application);for(let r of e){let i=r.application.executorService?.executors??{},a=collectSubscriberVisibility(r,n);for(let n of Object.values(i)){let i=eventSourceLookup(n,r,a);if(!i)continue;let o={subscriber:r,executorName:n.name,resource:i.resource,disabled:!subscribesToEvents(n),trigger:i.trigger};if(i.declaredBy(r)){t.push({...o,owner:r,pinned:i.pinned(r),key:i.keyIn(r)});continue}let s=e.filter(e=>e.config.path!==r.config.path&&i.declaredBy(e)),c=i.narrowOwners(s);if(c===`ambiguous`)continue;let[l]=c;if(!l)throw E({code:`EVENT_SUBSCRIPTION_OWNER_NOT_FOUND`,message:missingOwnerMessage(n.name,i,r)});t.push({...o,owner:l,pinned:i.pinned(l),key:i.keyIn(l)})}}return t}function subscribedResourceKeys(e,t){return new Set(publishingSubscriptions(ownedSubscriptions(e,t)).flatMap(e=>e.key??[]))}function ownedSubscriptions(e,t){return e.filter(e=>e.owner.config.path===t.config.path)}function publishingSubscriptions(e){return e.filter(e=>!e.disabled)}function subscribedTailorDBTables(e){return new Set(publishingSubscriptions(e).flatMap(e=>e.trigger.kind===`tailordb`?[e.trigger.tableName]:[]))}function subscribedResolvers(e){return new Set(publishingSubscriptions(e).flatMap(e=>e.trigger.kind===`resolverExecuted`?[e.trigger.resolverName]:[]))}function subscribedIdps(e){return new Set(publishingSubscriptions(e).flatMap(e=>e.trigger.kind===`idpUser`?[subscribedIdpName(e.subscriber.application,e.trigger)??[]].flat():[]))}function subscribedWorkflows(e){let t={workflowNames:/* @__PURE__ */ new Set},n={workflowNames:/* @__PURE__ */ new Set};for(let{trigger:r}of publishingSubscriptions(e))r.kind===`workflowExecution`?t.workflowNames.add(r.workflowName):r.kind===`workflowJobExecution`&&n.workflowNames.add(r.workflowName);return{execution:t,jobExecution:n}}function collectDependentApps(e){let t=/* @__PURE__ */ new Map;for(let{subscriber:n,owner:r,pinned:i,key:a}of publishingSubscriptions(e)){if(n.config.path===r.config.path||i||a===void 0)continue;let e=n.application.id;if(e===void 0)continue;let o=t.get(a)??/* @__PURE__ */ new Map;o.set(e,`publish-events`),t.set(a,o)}return t}function collectWorkflowJobPublishEvents(e){let t=/* @__PURE__ */ new Map;for(let n of e.application.workflowService?.jobs??[])n.publishEvents!==void 0&&t.set(n.name,n.publishEvents);return t}function collectSubscriberVisibility(e,t){return{tailorDBTypes:collectVisibleTailorDBTypeNamespaces(e.application,t),resolvers:collectVisibleResolverNamespaces(e.application,t),idps:collectVisibleIdpNames(e.application,t)}}function externalTailorDBNamespaces(e){return e.application.externalTailorDBNamespaces}function externalSubgraphNames(e,t,n){return e.application.subgraphs.filter(e=>e.Type===t&&!n.has(e.Name)).map(e=>e.Name)}function externalResolverNamespaces(e){return externalSubgraphNames(e,`pipeline`,new Set(e.application.resolverServices.map(e=>e.namespace)))}function externalIdpNames(e){return externalSubgraphNames(e,`idp`,new Set(e.application.idpServices.map(e=>e.name)))}function describeExternal(e,t){if(t.length!==0)return`external ${t.length===1?e:`${e}s`} ${t.map(e=>`"${e}"`).join(`, `)}`}function declaresTailorDBType(e,t){return e.application.tailorDBServices.some(e=>e.types[t])||void 0}function declaresResolver(e,t){return e.application.resolverServices.some(e=>Object.values(e.resolvers).some(e=>e.name===t))||void 0}function declaresIdp(e,t){return e.application.idpServices.some(e=>e.name===t)||void 0}function declaresWorkflow(e,t){return Object.values(e.application.workflowService?.workflows??{}).some(e=>e.name===t)||void 0}function pinsTailorDBType(e,t){for(let n of e.application.tailorDBServices){let e=n.types[t];if(e)return e.settings.publishEvents!==void 0}return!1}function pinsResolverIn(e,t,n){return e.application.resolverServices.some(e=>e.namespace===t&&Object.values(e.resolvers).some(e=>e.name===n&&e.publishEvents!==void 0))}function pinsIdp(e,t){return e.application.idpServices.some(e=>e.name===t&&e.publishEvents!==void 0)}function pinsWorkflow(e,t){return Object.values(e.application.workflowService?.workflows??{}).some(e=>e.name===t&&e.publishEvents!==void 0)}function pinsEveryJobOfWorkflow(e,t){let n=Object.values(e.application.workflowService?.workflows??{}).find(e=>e.name===t);if(n===void 0)return!1;let r=e.workflowBuildResult?.mainJobDeps[n.mainJob.name]??[],i=collectWorkflowJobPublishEvents(e);return r.length>0&&r.every(e=>i.has(e))}function tailorDBTypeNamespaceIn(e,t){return e.application.tailorDBServices.find(e=>e.types[t])?.namespace}function narrowByVisibleNamespace(e){let{candidates:t,visible:n,resourceKey:r,declaresIn:i}=e;if(!n.has(r))return[];let a=n.get(r);return a===void 0?`ambiguous`:t.filter(e=>i(e,a))}function declaresTailorDBTypeIn(e,t,n){return e.application.tailorDBServices.some(e=>e.namespace===t&&!!e.types[n])}function declaresResolverIn(e,t,n){return e.application.resolverServices.some(e=>e.namespace===t&&Object.values(e.resolvers).some(e=>e.name===n))}function eventSourceLookup(e,t,n){let{trigger:r}=e;switch(r.kind){case`tailordb`:return{resource:Ca.tailorDBType(r.tableName).resource,trigger:r,declaredBy:e=>declaresTailorDBType(e,r.tableName),pinned:e=>pinsTailorDBType(e,r.tableName),keyIn:e=>{let t=tailorDBTypeNamespaceIn(e,r.tableName);return t&&Z.tailorDBType(t,r.tableName)},narrowOwners:e=>narrowByVisibleNamespace({candidates:e,visible:n.tailorDBTypes,resourceKey:r.tableName,declaresIn:(e,t)=>declaresTailorDBTypeIn(e,t,r.tableName)}),externalHint:e=>describeExternal(`TailorDB namespace`,externalTailorDBNamespaces(e))};case`resolverExecuted`:{let e=findResolverNamespace(t.application,r.resolverName)??n.resolvers.get(r.resolverName);return{resource:Ca.resolver(r.resolverName).resource,trigger:r,declaredBy:e=>declaresResolver(e,r.resolverName),pinned:t=>e!==void 0&&pinsResolverIn(t,e,r.resolverName),keyIn:()=>e&&Z.resolver(e,r.resolverName),narrowOwners:e=>narrowByVisibleNamespace({candidates:e,visible:n.resolvers,resourceKey:r.resolverName,declaresIn:(e,t)=>declaresResolverIn(e,t,r.resolverName)}),externalHint:e=>describeExternal(`resolver namespace`,externalResolverNamespaces(e))}}case`idpUser`:{let e=subscribedIdpName(t.application,r);return e===void 0?void 0:{resource:Ca.idpService(e).resource,trigger:r,declaredBy:t=>declaresIdp(t,e),pinned:t=>pinsIdp(t,e),keyIn:()=>Z.idp(e),narrowOwners:t=>n.idps.has(e)?t.filter(t=>declaresIdp(t,e)):[],externalHint:t=>describeExternal(`IdP`,externalIdpNames(t).filter(t=>t===e))}}case`workflowExecution`:case`workflowJobExecution`:return{resource:r.kind===`workflowExecution`?Sa.workflow(r.workflowName):Sa.workflowJobs(r.workflowName),trigger:r,declaredBy:e=>declaresWorkflow(e,r.workflowName),pinned:e=>r.kind===`workflowExecution`?pinsWorkflow(e,r.workflowName):pinsEveryJobOfWorkflow(e,r.workflowName),keyIn:()=>r.kind===`workflowExecution`?Z.workflow(r.workflowName):Z.workflowJobs(r.workflowName),narrowOwners:e=>e.filter(e=>declaresWorkflow(e,r.workflowName)),externalHint:()=>void 0};default:return}}function assertRecordableDependencies(e,t){for(let{subscriber:n,owner:r,executorName:i,resource:a,pinned:o}of publishingSubscriptions(e)){if(n.config.path===r.config.path||o||!t)continue;let e=n.application.id;if(e!==void 0&&dependedByAppLabelKey(e)!==void 0)continue;let s=e===void 0?`${n.config.path} resolves without an "id" — a config that re-exports defineConfig() from another file never gets one`:`${n.config.path} resolves to the id "${e}", which is not the lowercase UUID deploy writes`,c=e===void 0?`Call defineConfig() inline in ${n.config.path} so deploy can manage its "id".`:`Restore the generated value in ${n.config.path}'s "id".`;throw E({code:`EVENT_SUBSCRIPTION_OWNER_UNRECORDED`,message:`Executor "${i}" in ${n.config.path} subscribes to ${a} in ${r.config.path}, which would enable event publishing on it for this deploy only. ${s} — so deploy cannot record which config the dependency belongs to.`,details:`Deploying ${r.config.path} alone later would turn publishing back off without asking.`,suggestion:c})}}function computeRenamedAppDeletions(e){let{conflicts:t,resourceOwners:n,protectedAppNames:r}=e;return[...new Set(t.map(e=>e.currentOwner))].filter(e=>!n.has(e)&&!r.has(e))}function assertUniqueGlobalResourceNames(e){assertNoDuplicateResourceNames(e,mc)}function ownershipTrackedPlans(e){return Object.values(e)}function collectOwnerConflicts(e){return ownershipTrackedPlans(e).flatMap(e=>e.conflicts)}function collectUnmanagedResources(e){return ownershipTrackedPlans(e).flatMap(e=>e.unmanaged)}function collectResourceOwners(e){return new Set(ownershipTrackedPlans(e).flatMap(e=>[...e.resourceOwners]))}function collectImportantResourceDeletions(e){let t=[];for(let n of e.tailorDB.changeSet.type.deletes)t.push({resourceLabel:`TailorDB table`,resourceName:n.name});for(let n of e.staticWebsite.changeSet.deletes)t.push({resourceLabel:`StaticWebsite`,resourceName:n.name});for(let n of e.aiGateway.changeSet.deletes)t.push({resourceLabel:`AIGateway`,resourceName:n.name});for(let n of e.auth.changeSet.oauth2Client.deletes)t.push({resourceLabel:`OAuth2 client`,resourceName:n.name});for(let n of e.auth.changeSet.oauth2Client.replaces)t.push({resourceLabel:`OAuth2 client (client type change)`,resourceName:n.name});for(let n of e.auth.changeSet.connection.deletes)t.push({resourceLabel:`Auth connection`,resourceName:n.name});for(let n of e.secretManager.vaultChangeSet.deletes)t.push({resourceLabel:`Secret Manager vault`,resourceName:n.name});for(let n of e.secretManager.secretChangeSet.deletes)t.push({resourceLabel:`Secret Manager secret`,resourceName:n.name});return t}function readResourceField(e,t){let n=e;for(let e of[`request`,`deleteRequest`,`createRequest`]){let r=n[e];if(r&&typeof r==`object`&&t in r){let e=r[t];return e==null?void 0:String(e)}}let r=n[t];return r==null?void 0:String(r)}function managedResourceName(e,t){return e.getName?e.getName(t):t.name}function managedResourceKey(e,t){let n=e.namespaceFields?.map(e=>readResourceField(t,e)).find(e=>e!==void 0),r=managedResourceName(e,t);return n===void 0?`${e.resourceType}:${r}`:`${e.resourceType}:${n}:${r}`}function managedNamespaceOwnerKey(e,t){if(!e.namespaceOwnerResourceType)return;let n=e.namespaceFields?.map(e=>readResourceField(t,e)).find(e=>e!==void 0);return n===void 0?void 0:`${e.namespaceOwnerResourceType}:${n}`}function addManagedResourceClaims(e,t,n){e.add(managedResourceKey(t,n));let r=managedNamespaceOwnerKey(t,n);r&&e.add(r)}function isManagedResourceClaimed(e,t,n){if(e.has(managedResourceKey(t,n)))return!0;let r=managedNamespaceOwnerKey(t,n);return r?e.has(r):!1}function retainDeletesNotClaimed(e,t){let n=0;for(let r of e.changeSet.deletes)isManagedResourceClaimed(t,e,r)?C.debug(`Skipping delete of ${managedResourceKey(e,r)}: still managed by another config in this deploy.`):(e.changeSet.deletes[n]=r,n+=1);e.changeSet.deletes.length=n}function workflowJobFunctionItems(e){let t=/* @__PURE__ */ new Set;for(let n of e){let e=n.usedJobNames;if(Array.isArray(e))for(let n of e)typeof n==`string`&&t.add(n)}return[...t].map(e=>({name:e}))}function workflowJobFunctionResourceGroup(e){return{changeSet:{creates:workflowJobFunctionItems(e.workflow.changeSet.creates),updates:workflowJobFunctionItems(e.workflow.changeSet.updates),replaces:workflowJobFunctionItems(e.workflow.changeSet.replaces),unchanged:[...e.workflow.unchangedWorkflowJobNames].map(e=>({name:e})),deletes:e.workflow.jobFunctionDeletes},resourceType:`workflow_job_function`,getName:e=>`jobFunctionName`in e?e.jobFunctionName:e.name}}const $=[`namespaceName`,`authNamespace`,`vaultName`,`staticWebsiteName`],mc=[{resourceLabel:`Application`,resourceType:`application`,namesOf:e=>[e.application.name],changeSetOf:e=>e.app},{resourceLabel:`Executor`,resourceType:`executor`,namesOf:e=>Object.values(e.application.executorService?.executors??{}).map(e=>e.name),changeSetOf:e=>e.executor.changeSet},{resourceLabel:`Workflow job`,resourceType:`workflow_job_function`,namesOf:e=>e.bundledScripts.workflowJobs.keys(),changeSetOf:e=>workflowJobFunctionResourceGroup(e).changeSet,getName:e=>`jobFunctionName`in e?e.jobFunctionName:e.name},{resourceLabel:`Workflow`,resourceType:`workflow`,namesOf:e=>Object.values(e.application.workflowService?.workflows??{}).map(e=>e.name),changeSetOf:e=>e.workflow.changeSet},{resourceLabel:`Workflow execution policy`,resourceType:`workflow_job_function_execution_policy`,namesOf:e=>Object.values(e.config.workflow?.executionPolicies??{}).map(e=>e.name),changeSetOf:e=>e.workflowExecutionPolicy.changeSet},{resourceLabel:`Auth connection`,resourceType:`auth.connection`,namespaceFields:$,namespaceOwnerResourceType:`auth.service`,namesOf:e=>Object.keys(e.application.authService?.connections??{}),changeSetOf:e=>e.auth.changeSet.connection},{resourceLabel:`StaticWebsite`,resourceType:`staticwebsite`,namesOf:e=>e.application.staticWebsiteServices.map(e=>e.name),changeSetOf:e=>e.staticWebsite.changeSet},{resourceLabel:`TailorDB namespace`,resourceType:`tailordb.service`,namesOf:e=>e.application.tailorDBServices.map(e=>e.namespace),changeSetOf:e=>e.tailorDB.changeSet.service},{resourceLabel:`Auth namespace`,resourceType:`auth.service`,namesOf:e=>{let t=e.application.authService?.config.name;return t===void 0?[]:[t]},changeSetOf:e=>e.auth.changeSet.service},{resourceLabel:`IdP namespace`,resourceType:`idp.service`,namesOf:e=>e.application.idpServices.map(e=>e.name),changeSetOf:e=>e.idp.changeSet.service},{resourceLabel:`Resolver namespace`,resourceType:`pipeline.service`,namesOf:e=>e.application.resolverServices.map(e=>e.namespace),changeSetOf:e=>e.pipeline.changeSet.service},{resourceLabel:`AIGateway`,resourceType:`aigateway`,namesOf:e=>e.application.aiGatewayServices.map(e=>e.name),changeSetOf:e=>e.aiGateway.changeSet},{resourceLabel:`Secret Manager vault`,resourceType:`secret.vault`,namesOf:e=>e.application.secrets.map(e=>e.vaultName),changeSetOf:e=>e.secretManager.vaultChangeSet}];function managedResourceGroupFromDefinition(e,t){let{changeSetOf:n,namesOf:r,resourceLabel:i,...a}=e;return{...a,changeSet:n(t)}}function managedResourceGroups(e){return[{changeSet:e.functionRegistry.changeSet,resourceType:`function_registry`},...mc.map(t=>managedResourceGroupFromDefinition(t,e)),{changeSet:e.tailorDB.changeSet.type,resourceType:`tailordb.type`,namespaceFields:$,namespaceOwnerResourceType:`tailordb.service`},{changeSet:e.tailorDB.changeSet.gqlPermission,resourceType:`tailordb.gql_permission`,namespaceFields:$,namespaceOwnerResourceType:`tailordb.service`},{changeSet:e.staticWebsite.customDomainChangeSet,resourceType:`staticwebsite.custom_domain`,namespaceFields:$,namespaceOwnerResourceType:`staticwebsite`},{changeSet:e.idp.changeSet.client,resourceType:`idp.client`,namespaceFields:$,namespaceOwnerResourceType:`idp.service`},{changeSet:e.auth.changeSet.idpConfig,resourceType:`auth.idp_config`,namespaceFields:$,namespaceOwnerResourceType:`auth.service`},{changeSet:e.auth.changeSet.userProfileConfig,resourceType:`auth.user_profile_config`,namespaceFields:$,namespaceOwnerResourceType:`auth.service`},{changeSet:e.auth.changeSet.tenantConfig,resourceType:`auth.tenant_config`,namespaceFields:$,namespaceOwnerResourceType:`auth.service`},{changeSet:e.auth.changeSet.machineUser,resourceType:`auth.machine_user`,namespaceFields:$,namespaceOwnerResourceType:`auth.service`},{changeSet:e.auth.changeSet.oauth2Client,resourceType:`auth.oauth2_client`,namespaceFields:$,namespaceOwnerResourceType:`auth.service`},{changeSet:e.auth.changeSet.authHook,resourceType:`auth.hook`,namespaceFields:$,namespaceOwnerResourceType:`auth.service`},{changeSet:e.auth.changeSet.scim,resourceType:`auth.scim`,namespaceFields:$,namespaceOwnerResourceType:`auth.service`},{changeSet:e.auth.changeSet.scimResource,resourceType:`auth.scim_resource`,namespaceFields:$,namespaceOwnerResourceType:`auth.service`},{changeSet:e.pipeline.changeSet.resolver,resourceType:`pipeline.resolver`,namespaceFields:$,namespaceOwnerResourceType:`pipeline.service`},{changeSet:e.secretManager.secretChangeSet,resourceType:`secret.secret`,namespaceFields:$,namespaceOwnerResourceType:`secret.vault`}]}function dropCrossDeploymentManagedDeletes(e){let t=e.map(e=>managedResourceGroups(deploymentPlanResults(e))),n=t.map(e=>e.reduce((e,t)=>{for(let n of[...t.changeSet.creates,...t.changeSet.updates,...t.changeSet.replaces,...t.changeSet.unchanged])addManagedResourceClaims(e,t,n);return e},/* @__PURE__ */ new Set));t.forEach((e,t)=>{let r=/* @__PURE__ */ new Set;n.forEach((e,n)=>{if(n!==t)for(let t of e)r.add(t)});for(let t of e)retainDeletesNotClaimed(t,r)})}function collectDeploymentResourceOwners(e){let t=/* @__PURE__ */ new Set;for(let n of e)for(let e of collectResourceOwners(deploymentPlanResults(n)))t.add(e);return t}function scheduleRenamedAppDeletes(e){let t=new Set(e.map(e=>e.application.name)),n=collectDeploymentResourceOwners(e),r=new Set(e.flatMap(e=>e.app.deletes.map(e=>e.name)));for(let i of e){let e=collectOwnerConflicts(deploymentPlanResults(i));for(let a of computeRenamedAppDeletions({conflicts:e,resourceOwners:n,protectedAppNames:t}))r.has(a)||(r.add(a),i.app.deletes.push({name:a,request:{workspaceId:i.tailorDB.context.workspaceId,applicationName:a}}))}}function ownershipFilters(e){let t=/* @__PURE__ */ new Map;for(let n of e)if(t.set(`${la}\0${n.name}`,{[la]:n.name}),n.id){let e=sdkAppIdLabelValue(n.id);t.set(`${da}\0${e}`,{[da]:e})}return[...t.values()]}async function createMetadataLookupClient(e){let{client:t,workspaceId:n,applications:r}=e,i=await Promise.all(ownershipFilters(r).map(e=>F(async(r,i)=>{let{results:a,nextPageToken:o}=await t.listMetadata({workspaceId:n,labels:e,pageToken:r,pageSize:i});return[a,o]}))),a=/* @__PURE__ */ new Map;for(let e of i.flat())e.metadata&&a.set(e.trn,e.metadata);let o=/* @__PURE__ */ new Map,getMetadata=(e,n)=>{let r=a.get(e.trn??``);if(r)return Promise.resolve(Kr(Kt,{metadata:r}));let i=e.trn??``,s=o.get(i);return s||(s=t.getMetadata(e,n),o.set(i,s)),s};return new Proxy(t,{get(e,t,n){return t===`getMetadata`?getMetadata:Reflect.get(e,t,n)}})}function buildPlanReport(e){let t=formatExecutorChangeEntries(e.executor.changeSet,buildPlannedExecutorsByName(e.executor.changeSet),e.functionRegistry.executorFunctionChanges),n=formatResolverChangeEntries(e.pipeline.changeSet.resolver,e.functionRegistry.resolverFunctionChanges),r=formatWorkflowChangeEntries(e.workflow.changeSet,e.functionRegistry.workflowJobChanges,e.workflow.jobFunctionDeletes),i=formatChangeSetEntries(e.workflowExecutionPolicy.changeSet,[`executionPolicy`]),a=[...r,...i],o=formatAuthHookChangeEntries(e.auth.changeSet.authHook,e.functionRegistry.authHookFunctionChanges),s=formatTailorDBResourceChangeEntries(e.tailorDB.changeSet.type,e.tailorDB.changeSet.gqlPermission),c=e.tailorDB.context.checkpointRepairs.map(e=>({action:`update`,symbol:xa.update,name:`migration checkpoint ${formatMigrationNumber(e.from)} → ${formatMigrationNumber(e.to)}`,labels:[`migrationCheckpoint`],namespace:e.namespace})),l=[...s,...c],u=[...n],namespaceOf=e=>{if(`request`in e&&e.request&&typeof e.request==`object`&&`namespaceName`in e.request)return e.request.namespaceName;if(`namespaceName`in e)return e.namespaceName},authNamespaceOf=e=>`request`in e&&e.request&&typeof e.request==`object`&&`authNamespace`in e.request?e.request.authNamespace:void 0,d=[...formatChangeSetEntries(e.idp.changeSet.client,[`client`],namespaceOf)],f=[...formatChangeSetEntries(e.auth.changeSet.idpConfig,[`idpConfig`],namespaceOf),...formatChangeSetEntries(e.auth.changeSet.userProfileConfig,[`userProfileConfig`],namespaceOf),...formatChangeSetEntries(e.auth.changeSet.tenantConfig,[`tenantConfig`],namespaceOf),...formatChangeSetEntries(e.auth.changeSet.machineUser,[`machineUser`],authNamespaceOf),...o,...formatChangeSetEntries(e.auth.changeSet.oauth2Client,[`oauth2Client`],namespaceOf),...formatChangeSetEntries(e.auth.changeSet.scim,[`scimConfig`],namespaceOf),...formatChangeSetEntries(e.auth.changeSet.scimResource,[`scimResource`],namespaceOf),...formatChangeSetEntries(e.auth.changeSet.connection,[`connection`],namespaceOf)],{otherChanges:p}=splitFunctionRegistryChanges(e.functionRegistry.changeSet),m=extractServiceActions(e.tailorDB.changeSet.service),g=extractServiceActions(e.pipeline.changeSet.service),_=extractServiceActions(e.idp.changeSet.service),v=extractServiceActions(e.auth.changeSet.service),y=[...l,...u,...t,...a,...d,...f],b=summarizePlanResults(e,y,[...m,...g,..._,...v]),x=collectUnmanagedResources(e),S=collectOwnerConflicts(e),serviceEntries=(e,t)=>e.map(e=>({...e,labels:[t],namespace:void 0})),C=[...y,...serviceEntries(m,`tailorDB`),...serviceEntries(g,`pipeline`),...serviceEntries(_,`idp`),...serviceEntries(v,`auth`),...formatChangeSetEntries(p),...formatChangeSetEntries(e.staticWebsite.changeSet,[`staticWebsite`]),...formatChangeSetEntries(e.staticWebsite.customDomainChangeSet,[`customDomain`]),...formatChangeSetEntries(e.staticWebsite.customDomainTransferChangeSet,[`customDomainTransfer`]),...formatChangeSetEntries(e.aiGateway.changeSet,[`aiGateway`]),...formatChangeSetEntries(e.app,[`application`]),...formatChangeSetEntries(e.secretManager.vaultChangeSet,[`vault`]),...formatChangeSetEntries(e.secretManager.secretChangeSet,[`secret`])].map(({action:e,name:t,labels:n,namespace:r,forcedBySdkVersion:i})=>({action:e,name:t,labels:n,namespace:r,...i&&{forcedBySdkVersion:i}})),w=[...x.map(({resourceType:e,resourceName:t})=>({type:`unmanaged`,resourceType:e,name:t})),...e.secretManager.skippedSecrets.map(e=>({type:`skippedSecret`,resourceType:`secret.secret`,name:e}))],T=S.map(({resourceType:e,resourceName:t,currentOwner:n})=>({resourceType:e,name:t,currentOwner:n})),E=[...buildGroupedDisplayLines(e.functionRegistry.changeSet.title,formatChangeSetEntries(p)),...e.staticWebsite.changeSet.lines(),...e.staticWebsite.customDomainChangeSet.lines(),...e.staticWebsite.customDomainTransferChangeSet.lines(),...e.aiGateway.changeSet.lines(),...e.app.lines(),...buildGroupedDisplayLines(`TailorDB`,l,m),...buildGroupedDisplayLines(`Resolver`,u,g),...buildGroupedDisplayLines(`Executor`,t),...buildGroupedDisplayLines(`Workflow`,a),...buildGroupedDisplayLines(`IdP`,d,_),...buildGroupedDisplayLines(`Auth`,f,v),...e.secretManager.vaultChangeSet.lines(),...e.secretManager.secretChangeSet.lines()];if(x.length>0){E.push(h.bold(`Unmanaged resources (not in config):`));for(let{resourceLabel:e,resourceName:t}of x)E.push(` ${h.warning(`⚠`)} ${h.bold(e)} "${t}"`)}if(e.secretManager.skippedSecrets.length>0){E.push(h.bold(`Secret Manager secrets (skipped - no value provided):`));for(let t of e.secretManager.skippedSecrets)E.push(` ${h.dim(`○`)} ${t}`)}let D=e.staticWebsite.customDomainNotes;if(D.length>0){E.push(h.bold(`Custom domains (no change):`));for(let e of D)E.push(` ${h.dim(`○`)} ${e.domain} \u2014 ${e.message}`)}if(S.length>0){E.push(h.bold(`Owner conflicts (will require confirmation on apply):`));for(let{resourceLabel:e,resourceName:t,currentOwner:n}of S)E.push(` ${h.warning(`!`)} ${h.bold(e)} "${t}" — owned by "${n}"`)}return E.push(formatPlanSummary(b)),{summary:b,json:{summary:b,changes:C,warnings:w,conflicts:T,notes:D.map(e=>({type:e.kind,resourceType:`staticwebsite.custom_domain_transfer`,name:e.domain,message:e.message}))},lines:E}}function printPlanResults(e,t){let n=buildPlanReport(e);if(C.jsonMode&&t?.dryRun)return C.out(n.json),n.summary;let r=n.lines.join(`
|
|
186
|
-
`);return t?.dryRun?C.out(r):C.log(r),n.summary}function summarizePlanResults(e,t,n){let r={create:0,update:0,delete:0,replace:0,forcedBySdkVersion:0};for(let e of[...t,...n])r[e.action]+=1,e.forcedBySdkVersion&&(r.forcedBySdkVersion+=1);let{otherChanges:i}=splitFunctionRegistryChanges(e.functionRegistry.changeSet);return sumPlanSummaries([r,summarizeChangeSets([i,e.staticWebsite.changeSet,e.staticWebsite.customDomainChangeSet,e.staticWebsite.customDomainTransferChangeSet,e.aiGateway.changeSet,e.app,e.secretManager.vaultChangeSet,e.secretManager.secretChangeSet])])}function sumPlanSummaries(e){return e.reduce((e,t)=>({create:e.create+t.create,update:e.update+t.update,delete:e.delete+t.delete,replace:e.replace+t.replace,forcedBySdkVersion:e.forcedBySdkVersion+t.forcedBySdkVersion}),{create:0,update:0,delete:0,replace:0,forcedBySdkVersion:0})}function printDeploymentPlans(e,t){if(C.jsonMode&&t?.dryRun){let n=e.map(e=>buildPlanReport(deploymentPlanResults(e))),r=sumPlanSummaries(n.map(e=>e.summary));return C.out({summary:r,changes:n.flatMap(e=>e.json.changes),warnings:[...n.flatMap(e=>e.json.warnings),...(t.missingDependentApps??[]).map(({resourceType:e,namespace:t,name:n,scope:r,appId:i,reason:a})=>({type:`missingDependentApp`,resourceType:e,namespace:t,name:n,...r===`jobs`&&{scope:r},appId:i,reason:a}))],conflicts:n.flatMap(e=>e.json.conflicts),notes:n.flatMap(e=>e.json.notes),...t.pendingDeployedHooks?.length?{pendingDeployedHooks:t.pendingDeployedHooks}:{}}),r}return sumPlanSummaries(e.map(e=>printPlanResults(deploymentPlanResults(e),t)))}const hc=/* @__PURE__ */ new Map;function validatorFor(e){let t=hc.get(e.typeName);if(t)return t;let n=Ri({registry:qr(e,...Li(e))});return hc.set(e.typeName,n),n}function validateItems(e){let{schema:t,kind:n,action:r,items:i,requestKey:a,violations:o}=e;if(i.length===0)return;let s=validatorFor(t);for(let e of i){let i=e[a],c=Kr(t,i),l=s.validate(t,c);if(l.kind===`invalid`)for(let t of l.violations)o.push({kind:n,name:e.name,action:r,fieldPath:t.field.length>0?Ii(t.field):`(message)`,message:t.message});else l.kind===`error`&&C.warn(`Could not validate ${n} "${e.name}" (${r}): ${l.error.message}`)}}async function validatePlan(e){let{tailorDB:t,staticWebsite:n,aiGateway:r,idp:i,auth:a,pipeline:o,app:s,executor:c,workflow:l,workflowExecutionPolicy:u,secretManager:d}=e,f=[];function creates(e,t,n){validateItems({schema:e,kind:t,action:`create`,items:n,requestKey:`request`,violations:f})}function updates(e,t,n){validateItems({schema:e,kind:t,action:`update`,items:n,requestKey:`request`,violations:f})}function replaces(e,t,n){validateItems({schema:e,kind:t,action:`replace`,items:n,requestKey:`createRequest`,violations:f})}function inPlaceReplaces(e,t,n){validateItems({schema:e,kind:t,action:`replace`,items:n,requestKey:`updateRequest`,violations:f})}creates(Ln,`TailorDB service`,t.changeSet.service.creates),creates(Vn,`TailorDB table`,t.changeSet.type.creates),updates(nr,`TailorDB table`,t.changeSet.type.updates),creates(qt,`StaticWebsite`,n.changeSet.creates),updates(xn,`StaticWebsite`,n.changeSet.updates),creates(yn,`StaticWebsite custom domain`,n.customDomainChangeSet.creates),creates(hr,`StaticWebsite custom domain transfer`,n.customDomainTransferChangeSet.creates),creates(zn,`AIGateway`,r.changeSet.creates.map(e=>({name:e.name,request:{...e.request,cors:void 0}}))),updates(ur,`AIGateway`,r.changeSet.updates.map(e=>({name:e.name,request:{...e.request,cors:void 0}})));let substituteIdpReturnOrigins=e=>{let t=e.request,n=t.userAuthPolicy?.allowedReturnOrigins;if(!Array.isArray(n)||n.length===0)return e;let r=n.map(e=>typeof e==`string`&&/^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]:url$/.test(e)?`https://placeholder.invalid`:e);return{...e,request:{...t,userAuthPolicy:{...t.userAuthPolicy,allowedReturnOrigins:r}}}};creates(en,`IdP service`,i.changeSet.service.creates.map(substituteIdpReturnOrigins)),updates(Cn,`IdP service`,i.changeSet.service.updates.map(substituteIdpReturnOrigins));let p=[...i.changeSet.client.creates.map(e=>({clientName:e.request.client?.name??``,namespaceName:e.request.namespaceName??``,workspaceId:e.request.workspaceId??``})),...i.changeSet.client.updates.map(e=>({clientName:e.name,namespaceName:e.namespaceName,workspaceId:e.workspaceId}))];creates(Wt,`IdP client secret`,p.map(e=>({name:e.clientName,request:{workspaceId:e.workspaceId,secretmanagerVaultName:idpClientVaultName(e.namespaceName,e.clientName)}}))),creates(Xn,`IdP client secret`,p.map(e=>({name:e.clientName,request:{workspaceId:e.workspaceId,secretmanagerVaultName:idpClientVaultName(e.namespaceName,e.clientName),secretmanagerSecretName:idpClientSecretName(e.namespaceName,e.clientName)}}))),creates($n,`Auth service`,a.changeSet.service.creates),updates(gr,`Auth service`,a.changeSet.service.updates),creates(Qn,`Auth IDP config`,a.changeSet.idpConfig.creates),updates(br,`Auth IDP config`,a.changeSet.idpConfig.updates),creates(Wn,`Auth user profile config`,a.changeSet.userProfileConfig.creates),updates(Xt,`Auth user profile config`,a.changeSet.userProfileConfig.updates),creates(Gn,`Auth tenant config`,a.changeSet.tenantConfig.creates),updates(Sn,`Auth tenant config`,a.changeSet.tenantConfig.updates),creates(fr,`Auth machine user`,a.changeSet.machineUser.creates),updates(Fn,`Auth machine user`,a.changeSet.machineUser.updates),creates(In,`Auth hook`,a.changeSet.authHook.creates),updates(mr,`Auth hook`,a.changeSet.authHook.updates),creates(Hn,`Auth SCIM config`,a.changeSet.scim.creates),updates(bn,`Auth SCIM config`,a.changeSet.scim.updates),creates(rr,`Auth SCIM resource`,a.changeSet.scimResource.creates),updates(Jt,`Auth SCIM resource`,a.changeSet.scimResource.updates),creates(Rn,`OAuth2 client`,a.changeSet.oauth2Client.creates),updates(vr,`OAuth2 client`,a.changeSet.oauth2Client.updates),replaces(Rn,`OAuth2 client`,a.changeSet.oauth2Client.replaces),creates(pn,`Pipeline service`,o.changeSet.service.creates),updates(nn,`Pipeline service`,o.changeSet.service.updates),creates(ln,`Resolver`,o.changeSet.resolver.creates),updates(Zt,`Resolver`,o.changeSet.resolver.updates),creates(Bn,`Executor`,c.changeSet.creates),updates(dr,`Executor`,c.changeSet.updates),creates(Nn,`Workflow`,l.changeSet.creates.map(e=>({name:e.name,request:buildWorkflowValidationShape(e.workspaceId,e.workflow)}))),updates(sr,`Workflow`,l.changeSet.updates.map(e=>({name:e.name,request:buildWorkflowValidationShape(e.workspaceId,e.workflow)})));let m=l.changeSet.creates[0]?.workspaceId??l.changeSet.updates[0]?.workspaceId??``;if(m){let e=/* @__PURE__ */ new Set;for(let t of[...l.changeSet.creates,...l.changeSet.updates])for(let n of t.usedJobNames)e.add(n);for(let t of l.unchangedWorkflowJobNames)e.add(t);creates(Kn,`Workflow job function`,[...e].map(e=>({name:e,request:{workspaceId:m,jobFunctionName:e,scriptRef:e}})))}if(creates(ar,`Workflow execution policy`,[...u.changeSet.creates,...u.changeSet.replaces].map(e=>({name:e.name,request:{workspaceId:e.workspaceId,executionPolicyName:e.policy.name,executionPolicyKey:toPlatformExecutionPolicyKey(e.policy),...e.policy.concurrencyPolicy&&{concurrencyPolicy:{maxConcurrentExecutions:e.policy.concurrencyPolicy.maxConcurrentExecutions}}}}))),updates(er,`Workflow execution policy`,u.changeSet.updates.map(e=>({name:e.name,request:{workspaceId:e.workspaceId,executionPolicyName:e.policy.name,...e.policy.concurrencyPolicy&&{concurrencyPolicy:{maxConcurrentExecutions:e.policy.concurrencyPolicy.maxConcurrentExecutions}}}}))),creates(Wt,`Secret Manager vault`,d.vaultChangeSet.creates.map(e=>({name:e.name,request:vaultCreateRequest(e)}))),creates(Xn,`Secret Manager secret`,d.secretChangeSet.creates.map(e=>({name:e.name,request:secretCreateRequest(e)}))),updates(Jn,`Secret Manager secret`,d.secretChangeSet.updates.map(e=>({name:e.name,request:secretUpdateRequest(e)}))),creates(an,`Application`,s.creates.map(e=>({name:e.name,request:{...e.request,cors:void 0}}))),updates(Dn,`Application`,[...s.updates,...s.unchanged].map(e=>({name:e.name,request:{...e.request,cors:void 0}}))),creates(cr,`Auth connection`,a.changeSet.connection.creates),inPlaceReplaces(Mn,`Auth connection`,a.changeSet.connection.replaces),f.length===0)return;let g=new Set(f.map(e=>`${e.kind}:${e.name}`));C.error(`Pre-flight validation found ${f.length} violation(s) across ${g.size} resource(s):`);for(let e of f)C.log(` ${h.resourceType(e.kind)} ${h.resourceName(e.name)} (${e.action}) — ${h.bold(e.fieldPath)}: ${e.message}`);throw E({code:`DEPLOY_VALIDATION_FAILED`,message:`${f.length} validation error(s) found in ${g.size} resource(s)`})}function formatIssues(e){return e.map(e=>e.message).join(`; `)||`Invalid options`}function parseOptions(e,t){let n=e.safeParse(t);if(!n.success)throw E({code:`OPTIONS_INVALID`,message:formatIssues(n.error.issues),context:{issues:u(n.error.issues)},cause:n.error});return n.data}const gc=U.string().min(1,`Profile must not be empty`),_c=63,vc=U.string().min(3,`Name must be at least 3 characters`).max(63,`Name must be at most 63 characters`).regex(/^[a-z0-9-]+$/,`Name can only contain lowercase letters, numbers, and hyphens`).refine(e=>!e.startsWith(`-`)&&!e.endsWith(`-`),`Name cannot start or end with a hyphen`);function validateWorkspaceName(e){let t=vc.safeParse(e);return t.success?!0:formatIssues(t.error.issues)}const yc=/^(\d+)(s|m|h|d)$/,bc={s:1e3,m:6e4,h:36e5,d:864e5},xc=U.string().regex(yc,{message:`Invalid duration format. Expected a number with a unit: '30m', '24h', '7d'`}),Sc=5e7,Cc=`less than ${Sc.toLocaleString(`en-US`)} days`,wc=xc.pipe(U.string().refine(e=>parseAge(e)<Sc*bc.d,{message:`TTL must be ${Cc}`}));function parseAge(e){let t=e.match(yc);if(!t?.[1]||!t[2])throw E({code:`PRUNE_AGE_INVALID`,message:`invalid age format: ${e}`,command:`workspace prune`});let n=t[2];return parseInt(t[1],10)*bc[n]}const Tc=`sdk-expires-at`,Ec=/^s-(\d{1,15})$/;function workspaceTrn(e){return`trn:v1:workspace:${e}`}function encodeExpiresAt(e){return`s-${Math.floor(e.getTime()/1e3)}`}function decodeExpiresAt(e){let t=e?.match(Ec);if(!t?.[1])return;let n=Number(t[1]);if(!Number.isSafeInteger(n))return;let r=/* @__PURE__ */ new Date(n*1e3);return Number.isNaN(r.getTime())?void 0:r}function recordedExpiresAt(e){return a(decodeExpiresAt(encodeExpiresAt(e)),`encoded workspace expiry must decode`)}function readWorkspaceExpiry(e,t){let n=e?.[Tc];if(n===void 0||n===``)return{state:`unset`};let r=decodeExpiresAt(n);return r?r.getTime()<=t.getTime()?{state:`expired`,expiresAt:r}:{state:`pending`,expiresAt:r}:{state:`invalid`,value:n}}async function fetchWorkspaceExpiry(e,t,n){try{return{expiry:readWorkspaceExpiry((await e.getMetadata({trn:workspaceTrn(t)})).metadata?.labels,n)}}catch(e){return{error:T(e)}}}async function writeWorkspaceExpiry(e,t,n){return writeMetadataLabelsDirect(e,{trn:workspaceTrn(t),labels:{[Tc]:encodeExpiresAt(n)}})}async function clearWorkspaceExpiry(e,t){return writeMetadataLabelsDirect(e,{trn:workspaceTrn(t),remove:[Tc]})}function reportedExpiry(e){if(`error`in e)return`unavailable`;switch(e.expiry.state){case`unset`:return null;case`invalid`:return`invalid`;default:return e.expiry.expiresAt.toISOString()}}async function fetchReportedExpiries(e,t,n){let r=At();return Promise.all(t.map(async t=>reportedExpiry(await r(()=>fetchWorkspaceExpiry(e,t,n)))))}const Dc=[`asia-northeast`,`us-west`,`europe-west`];function formatTimestamp(e){if(!e)return null;let t=G(e);return Number.isNaN(t.getTime())?null:t}function formatTable(e,t){return D(e,t)}function formatKeyValueTable(e){return formatTable(e,{singleLine:!0})}function humanizeRelativeTime(e){if(e===null)return`N/A`;let t=e instanceof Date?e:new Date(e);return Number.isNaN(t.getTime())?typeof e==`string`?e:`N/A`:oi(t,{addSuffix:!0})}const workspaceInfo=(e,t)=>{let n={id:e.id,name:e.name,region:e.region,...e.organizationId?{organizationId:e.organizationId}:{},...e.folderId?{folderId:e.folderId}:{},createdAt:formatTimestamp(e.createTime),updatedAt:formatTimestamp(e.updateTime)};return t?{...n,folderName:t}:n},workspaceDetails=(e,t)=>({...workspaceInfo(e,t),deleteProtection:e.deleteProtection,organizationId:e.organizationId,folderId:e.folderId});async function resolveWorkspaceFolderName(e,t){if(t.organizationId&&t.folderId)try{return(await e.getOrganizationFolder({organizationId:t.organizationId,folderId:t.folderId})).folder?.name||void 0}catch(e){if(e instanceof q&&(e.code===K.NotFound||e.code===K.PermissionDenied))return;C.warn(`Failed to resolve workspace folder name: ${e}`);return}}function createWorkspaceFolderNameResolver(e){let t=/* @__PURE__ */ new Map;return n=>{if(!n.organizationId||!n.folderId)return Promise.resolve(void 0);let r=`${n.organizationId}/${n.folderId}`,i=t.get(r);if(i)return i;let a=resolveWorkspaceFolderName(e,n);return t.set(r,a),a}}async function workspaceInfoWithFolderName(e,t){let n=await resolveWorkspaceFolderName(e,t);return workspaceInfo(t,n)}async function workspaceDetailsWithFolderName(e,t){let n=await resolveWorkspaceFolderName(e,t);return workspaceDetails(t,n)}async function workspaceInfosWithFolderNames(e,t){let n=createWorkspaceFolderNameResolver(e),r=di(5);return Promise.all(t.map(e=>r(async()=>workspaceInfo(e,await n(e)))))}function workspaceDisplayName(e){return e.folderName?`${e.folderName}/${e.name}`:e.name}function createWorkspaceNameTransformer(e,t){return(n,r)=>{let i=r,a=i[e],o=i[t];return typeof a==`string`&&typeof o==`string`?workspaceDisplayName({name:a,folderName:o}):String(n??``)}}const Oc=createWorkspaceNameTransformer(`name`,`folderName`),kc=U.object({name:vc,region:U.string(),deleteProtection:U.boolean().optional(),organizationId:U.uuid().optional(),folderId:U.uuid().optional(),ttl:wc.optional(),profile:gc.optional()});async function resolveWorkspaceCreationLocation(e){let t=e.organizationId!==void 0||e.folderId!==void 0?void 0:await we({profile:e.profile});return{organizationId:t?t.organizationId:e.organizationId,folderId:t?t.folderId:e.folderId,defaults:t}}const validateRegion=async(e,t)=>{let n=await t.listAvailableWorkspaceRegions({});if(!n.regions.includes(e))throw E({code:`WORKSPACE_REGION_INVALID`,message:`Region must be one of: ${n.regions.join(`, `)}.`,command:`workspace create`})};function profilePlatformSettings(e){let t=e?.oauth2ClientId||process.env.TAILOR_PLATFORM_OAUTH2_CLIENT_ID,n=e?.consoleUrl??process.env.TAILOR_PLATFORM_CONSOLE_URL;return{...wt(e)?{}:{platform_url:Ct(e)},...t?{oauth2_client_id:Lt(e)}:{},...n?{console_url:Nt(n)}:{}}}async function createWorkspace$1(e){let{client:t,validated:n}=await prepareWorkspaceCreation(e);return createValidatedWorkspaceWithClient(t,n)}async function prepareWorkspaceCreation(e){let t=parseCreateWorkspaceOptions(e),{organizationId:n,folderId:r,defaults:i}=await resolveWorkspaceCreationLocation(t),a=validateCreateWorkspaceOptions({...t,organizationId:n,folderId:r}),o=await A({profile:a.profile}),s=await De({profile:a.profile}),c=await N(o,s);return await validateRegion(a.region,c),{client:c,validated:a,defaults:i}}async function createValidatedWorkspaceWithClient(e,t){let n=await e.createWorkspace({workspaceName:t.name,workspaceRegion:t.region,deleteProtection:t.deleteProtection??!1,organizationId:t.organizationId,folderId:t.folderId}),r=a(n.workspace,`createWorkspace response missing workspace`),i=t.ttl===void 0?void 0:await recordTtl(e,r.id,t.ttl,r.createTime),o=await workspaceInfoWithFolderName(e,r);return i?{...o,ttl:i}:o}async function recordTtl(e,t,n,r){let i=r?G(r):/* @__PURE__ */ new Date,a=recordedExpiresAt(new Date(i.getTime()+parseAge(n))),write=()=>writeWorkspaceExpiry(e,t,a);try{return await write().catch(()=>write()),{state:`written`,expiresAt:a}}catch(e){return{state:`unconfirmed`,expiresAt:a,requested:n,message:e instanceof Error?e.message:String(e)}}}function ttlOutput(e){let t=e.expiresAt.toISOString();return e.state===`written`?{state:e.state,expiresAt:t}:{state:e.state,requestedExpiresAt:t}}function parseCreateWorkspaceOptions(e){let t=parseOptions(kc,e);if(t.folderId!==void 0&&t.organizationId===void 0)throw E({code:`WORKSPACE_FOLDER_WITHOUT_ORGANIZATION`,message:`A folder ID requires an organization ID.`,suggestion:`Give the organization that owns the folder as well.`});return t}function validateCreateWorkspaceOptions(e){let t=parseCreateWorkspaceOptions(e);if(t.organizationId===void 0)throw E({code:`WORKSPACE_ORGANIZATION_REQUIRED`,message:`A workspace must be created in an organization.`,suggestion:ge()?`Pass --organization-id or set TAILOR_PLATFORM_ORGANIZATION_ID.`:"Pass --organization-id (or set TAILOR_PLATFORM_ORGANIZATION_ID), or set a default organization with `tailor user update --default-organization-id`."});return t}function describeUserDefaults(e){return e.folderId?`folder ${e.folderId} in organization ${e.organizationId}`:`organization ${e.organizationId}`}function announceUserDefaults(e){C.info(`Creating the workspace in ${describeUserDefaults(e)}, the default set by \`tailor user update\`.`)}function userDefaultsTarget(e){return`This run targeted ${describeUserDefaults(e)}, the default set by \`tailor user update\`.`}function userDefaultsContext(e){return{defaultOrganizationId:e.organizationId,defaultFolderId:e.folderId??null}}function pointAtUserDefaults(e,t){e instanceof q&&(e.code===K.NotFound||e.code===K.PermissionDenied)&&l(e,{suggestion:`${userDefaultsTarget(t)} Check that it exists and that this user can create workspaces there, or pass --organization-id (and --folder-id) to choose another location.`,context:{...s(e).context,...userDefaultsContext(t)}})}const Ac=Y({name:`create`,description:`Create a new Tailor Platform workspace.`,notes:M`
|
|
185
|
+
carrying no id are matched by application name. 'tailor deploy' records an id for you.`)}function rekeyInstructions(e){return`${Q} has entries whose config no longer exists: ${e.join(`, `)}. If an app directory was moved, re-key its entry to the new path under 'appIds' so the app keeps its id; delete the entries of removed apps.`}function missingInCIError(e,t){let n=`Run 'tailor deploy' locally and commit ${Q}.`;return t.length>0&&(n+=` ${rekeyInstructions(t)}`),E({code:`CONFIG_ID_REQUIRED_IN_CI`,message:`No app id is recorded for ${e.join(`, `)} in ${Q}, and the config has no 'id'.`,details:`CI does not generate one (each run would be treated as a separate app and break resource ownership).`,suggestion:n})}async function confirmMove(e,t){if(!canPrompt())throw E({code:`APP_ID_NOT_RECORDED`,message:`No app id is recorded for ${t}.`,suggestion:rekeyInstructions([e])});return C.warn(`${Q} records an app id for ${e}, which no longer exists, and ${t} has none.`),X.confirm({message:`Was ${e} moved to ${t}? Yes keeps its app id; no assigns a fresh one.`,default:!1})}async function planAppIds(e){let{lock:t,entries:n,mode:r}=e,i={...t.appIds},o=!1,s=n.map(()=>void 0),c=[],l=new Map(Object.entries(i).map(([e,t])=>[t.toLowerCase(),e])),exists=e=>W.existsSync(H.join(t.root,e));n.forEach(({configPath:e,configId:n},a)=>{let u=appIdLockKey(t.root,e),d=i[u];if(d!==void 0){if(n!==void 0&&n.toLowerCase()!==d.toLowerCase())throw recordedIdConflict(u,d,n);let t=n!==void 0&&r===`write`;n!==void 0&&!t&&warnConfigStillCarriesId(u),s[a]={configPath:e,key:u,id:d,source:`lock`,removeConfigId:t}}else if(n!==void 0){if(!hc.test(n))throw configIdInvalid(e);let t=l.get(n.toLowerCase()),c=t!==void 0&&t!==u&&!exists(t)?t:void 0;if(t!==void 0&&t!==u&&c===void 0)throw claimedIdConflict(e,t);l.set(n.toLowerCase(),u);let d=r===`write`;d?(c!==void 0&&(delete i[c],C.info(`Keeping the app id of ${c} for ${u}: ${n}`)),i[u]=n,o=!0):warnUnrecordedConfigId(u),s[a]={configPath:e,key:u,id:n,source:`config`,removeConfigId:d}}else c.push({index:a,configPath:e,key:u})});let finish=()=>({appIds:i,changed:o,entries:s.map(e=>a(e,`app id entry missing`))});if(c.length===0)return finish();if(r===`read`){for(let{index:e,configPath:t,key:n}of c)warnMissingLockedAppId(n),s[e]={configPath:t,key:n,id:void 0,source:`none`,removeConfigId:!1};return finish()}let u=Object.keys(i).filter(e=>!exists(e)),d=[...new Set(c.map(({key:e})=>e))];if(r===`require`)throw missingInCIError(d,u);let f;if(u.length===1&&d.length===1){let e=a(u[0],`orphan missing`),t=a(d[0],`key missing`);await confirmMove(e,t)&&(f={from:e,key:t})}else if(u.length>0)throw E({code:`APP_ID_NOT_RECORDED`,message:`No app id is recorded for ${d.join(`, `)}.`,suggestion:rekeyInstructions(u)});for(let{index:e,configPath:t,key:n}of c){let r=i[n];if(r!==void 0){s[e]={configPath:t,key:n,id:r,source:`generated`,removeConfigId:!1};continue}let c;f?.key===n?(c=a(i[f.from],`orphaned app id missing`),delete i[f.from],C.info(`Keeping the app id of ${f.from} for ${n}: ${c}`)):(c=crypto.randomUUID(),C.info(`Generated app id for ${n}: ${c}`)),i[n]=c,o=!0;let l=f?.key===n?`lock`:`generated`;s[e]={configPath:t,key:n,id:c,source:l,removeConfigId:!1}}return finish()}function writeAppIds(e){let{lock:t,appIds:n}=e,r=readRawLock(t.root);if(r===null)throw E({code:`APP_ID_LOCK_NOT_FOUND`,message:`${Q} does not exist under ${t.root}.`,suggestion:`Create it with 'tailor setup'.`});let i={...parseAppIds(r.appIds)};for(let e of Object.keys(t.appIds))e in n||delete i[e];for(let[e,r]of Object.entries(n))t.appIds[e]!==r&&(i[e]=r);let a={...r,version:2,appIds:i};W.writeFileSync(H.join(t.root,Q),`${JSON.stringify(a,null,2)}\n`,`utf-8`)}async function removeAdoptedConfigIds(e){let t=!1,n=/* @__PURE__ */ new Set;for(let r of e.entries)r.removeConfigId&&r.id!==void 0&&!n.has(r.configPath)&&(n.add(r.configPath),await removeConfigId(r.configPath,r.id)?(t=!0,C.info(`Moved the app id of ${r.key} from the config into ${Q}.`)):C.warn(`The app id of ${r.key} is recorded in ${Q}. Remove the 'id' from the object passed to defineConfig() by hand; the SDK could not edit ${r.configPath} to do it.`));return{configEdited:t}}async function resolveLockedAppIds(e){let t=await planAppIds(e);return e.mode===`write`&&(t.changed&&writeAppIds({lock:e.lock,appIds:t.appIds}),await removeAdoptedConfigIds(t)),t}function appIdPlanModeForDeploy(e){let t=p(process.env.TAILOR_CI_ALLOW_ID_INJECTION)===!0;return ui&&!t?`require`:e?`read`:`write`}function parseDeployConfigPaths(e){let t=e??ve();if(t===void 0)return[void 0];let n=t.split(`,`).map(e=>e.trim());if(n.some(e=>e.length===0))throw E({code:`DEPLOY_CONFIG_REQUIRED`,message:`--config must contain one or more non-empty config paths.`,command:`deploy`});return n}async function buildDeploymentTarget(e){let{configPath:t,loadedConfig:n,dryRun:r,buildOnly:i,noCache:o,packageVersion:s,cacheDir:c,client:l,workspaceId:u,expectedLocalStaticWebsiteNames:d,previous:f}=e,{config:p,plugins:m}=n??a((await loadDeployConfigs({configPaths:[t],dryRun:r,buildOnly:i}))[0],`loaded config missing`),h=H.dirname(p.path),g=fi(`pnpm-lock.yaml`,{cwd:h})??fi(`package-lock.json`,{cwd:h})??fi(`yarn.lock`,{cwd:h})??fi(`bun.lock`,{cwd:h}),_=createCacheManager({enabled:!o,cacheDir:c,sdkVersion:s,lockfileHash:g?Ke(g):void 0}),v;m.length>0&&(v=new Er(m)),f||await B(`build.generateUserTypes`,()=>generateUserTypes({config:p,configPath:p.path}));let y,b,x,S,C;try{let e=await B(`build.loadApplication`,()=>st({config:p,pluginManager:v,bundleCache:_.bundleCache,client:l,workspaceId:u,expectedLocalStaticWebsiteNames:d,previous:f}));y=e.application,b=e.workflowBuildResult,x=e.httpAdapterBuildResult,S=e.bundledScripts,C=e.reusableBuildState}finally{_.finalize()}return{plugins:m,config:p,application:y,workflowBuildResult:b,httpAdapterBuildResult:x,bundledScripts:S,reusableBuildState:C}}function resolveExistingConfigPath(e){let t=Ee(e);if(!t)return;let n=H.resolve(process.cwd(),t);return W.existsSync(n)?n:void 0}async function prepareDeployConfigs(e){let{configPaths:t,dryRun:n,buildOnly:r}=e;if(r)return;let i=new Set(t.map(resolveExistingConfigPath).filter(e=>e!==void 0));await Promise.all([...i].map(e=>B(`build.prepareConfig`,async()=>{findAppIdLock(e)===null&&await ensureConfigIdForDeploy({configPath:e,dryRun:n,buildOnly:r})})))}async function loadPreparedDeployConfig(e){return B(`build.loadConfig`,()=>loadConfig(e.configPath))}async function resolveDeployAppIds(e){let{loaded:t,dryRun:n,buildOnly:r}=e;if(r)return[...t];let i=[...t],o=/* @__PURE__ */ new Map;t.forEach((e,t)=>{let n=findAppIdLock(e.config.path);if(n===null){warnMissingAppId(e.config.id);return}let r=o.get(n.root)??{lock:n,indexes:[]};r.indexes.push(t),o.set(n.root,r)});let s=appIdPlanModeForDeploy(n);for(let{lock:e,indexes:n}of o.values()){let r=await resolveLockedAppIds({lock:e,mode:s,entries:n.map(e=>{let{config:n}=a(t[e],`loaded config missing`);return{configPath:n.path,configId:n.id}})});n.forEach((e,n)=>{let o=a(t[e],`loaded config missing`),s=a(r.entries[n],`planned app id entry missing`).id;i[e]={...o,config:{...o.config,id:s}}})}return i}async function loadDeployConfigs(e){return await prepareDeployConfigs(e),resolveDeployAppIds({loaded:await Promise.all(e.configPaths.map(t=>loadPreparedDeployConfig({...e,configPath:t}))),dryRun:e.dryRun,buildOnly:e.buildOnly})}async function buildDeploymentTargets(e){let{configPaths:t,loadedConfigs:n,buildTarget:r,previousTargets:i,...a}=e;if(n!==void 0&&(n.length!==t.length||t.some((e,t)=>n[t]===void 0)))throw b(`loadedConfigs must contain exactly one entry for every configPath`);let o=r===void 0&&n===void 0?await loadDeployConfigs({configPaths:t,dryRun:e.dryRun,buildOnly:e.buildOnly}):n,s=r??buildDeploymentTarget;return Promise.all(t.map((e,t)=>s({...a,configPath:e,loadedConfig:o?.[t],previous:i?.[t]})))}function addPossiblyAmbiguousNamespace(e,t,n){e.has(t)?e.get(t)!==n&&e.set(t,void 0):e.set(t,n)}function collectVisibleResources(e){let{application:t,applications:n,visibleKeysOf:r,resourcesOf:i,createResult:a,addResource:o}=e,s=r(t),c=a();for(let e of n)for(let t of i(e))s.has(t.visibilityKey)&&o(c,t.resourceKey,t.visibilityKey);return c}function collectApplicationTailorDBNamespaces(e){return/* @__PURE__ */ new Set([...e.tailorDBServices.map(e=>e.namespace),...e.externalTailorDBNamespaces])}function*tailorDBTypeResources(e){for(let t of e.tailorDBServices)for(let e of Object.keys(t.types))yield{visibilityKey:t.namespace,resourceKey:e}}function collectVisibleTailorDBTypeNamespaces(e,t){return collectVisibleResources({application:e,applications:t,visibleKeysOf:collectApplicationTailorDBNamespaces,resourcesOf:tailorDBTypeResources,createResult:()=>/* @__PURE__ */ new Map,addResource:addPossiblyAmbiguousNamespace})}function collectApplicationResolverNamespaces(e){return new Set(e.subgraphs.filter(e=>e.Type===`pipeline`).map(e=>e.Name))}function*idpNameResources(e){for(let t of collectApplicationIdpNames(e))yield{visibilityKey:t,resourceKey:t}}function collectVisibleIdpNames(e,t){return collectVisibleResources({application:e,applications:t,visibleKeysOf:collectApplicationIdpNames,resourcesOf:idpNameResources,createResult:()=>/* @__PURE__ */ new Set,addResource:(e,t)=>{e.add(t)}})}function*resolverResources(e){for(let t of e.resolverServices)for(let e of Object.values(t.resolvers))yield{visibilityKey:t.namespace,resourceKey:e.name}}function collectVisibleResolverNamespaces(e,t){return collectVisibleResources({application:e,applications:t,visibleKeysOf:collectApplicationResolverNamespaces,resourcesOf:resolverResources,createResult:()=>/* @__PURE__ */ new Map,addResource:addPossiblyAmbiguousNamespace})}function subscribedIdpName(e,t){if(t.idp!=null)return t.idp;let n=collectApplicationIdpNames(e);if(n.size!==1)return;let[r]=n;return r}function missingOwnerMessage(e,t,n){let r=`Executor "${e}" subscribes to ${t.resource}, which no config in this deploy declares.`,i=t.externalHint(n);return i?`${r} This config declares ${i}, so add the config that owns it to --config.`:t.trigger.kind===`workflowExecution`||t.trigger.kind===`workflowJobExecution`?`${r} A workflow has no "external" declaration, unlike a TailorDB namespace or resolver, so nothing in this config points at the one that owns it. Check the name, or add the config that declares the workflow to --config.`:`${r} This config declares nothing external that could hold it, so check the name.`}function collectEventSubscriptions(e){let t=[],n=e.map(e=>e.application);for(let r of e){let i=r.application.executorService?.executors??{},a=collectSubscriberVisibility(r,n);for(let n of Object.values(i)){let i=eventSourceLookup(n,r,a);if(!i)continue;let o={subscriber:r,executorName:n.name,resource:i.resource,disabled:!subscribesToEvents(n),trigger:i.trigger};if(i.declaredBy(r)){t.push({...o,owner:r,pinned:i.pinned(r),key:i.keyIn(r)});continue}let s=e.filter(e=>e.config.path!==r.config.path&&i.declaredBy(e)),c=i.narrowOwners(s);if(c===`ambiguous`)continue;let[l]=c;if(!l)throw E({code:`EVENT_SUBSCRIPTION_OWNER_NOT_FOUND`,message:missingOwnerMessage(n.name,i,r)});t.push({...o,owner:l,pinned:i.pinned(l),key:i.keyIn(l)})}}return t}function subscribedResourceKeys(e,t){return new Set(publishingSubscriptions(ownedSubscriptions(e,t)).flatMap(e=>e.key??[]))}function ownedSubscriptions(e,t){return e.filter(e=>e.owner.config.path===t.config.path)}function publishingSubscriptions(e){return e.filter(e=>!e.disabled)}function subscribedTailorDBTables(e){return new Set(publishingSubscriptions(e).flatMap(e=>e.trigger.kind===`tailordb`?[e.trigger.tableName]:[]))}function subscribedResolvers(e){return new Set(publishingSubscriptions(e).flatMap(e=>e.trigger.kind===`resolverExecuted`?[e.trigger.resolverName]:[]))}function subscribedIdps(e){return new Set(publishingSubscriptions(e).flatMap(e=>e.trigger.kind===`idpUser`?[subscribedIdpName(e.subscriber.application,e.trigger)??[]].flat():[]))}function subscribedWorkflows(e){let t={workflowNames:/* @__PURE__ */ new Set},n={workflowNames:/* @__PURE__ */ new Set};for(let{trigger:r}of publishingSubscriptions(e))r.kind===`workflowExecution`?t.workflowNames.add(r.workflowName):r.kind===`workflowJobExecution`&&n.workflowNames.add(r.workflowName);return{execution:t,jobExecution:n}}function collectDependentApps(e){let t=/* @__PURE__ */ new Map;for(let{subscriber:n,owner:r,pinned:i,key:a}of publishingSubscriptions(e)){if(n.config.path===r.config.path||i||a===void 0)continue;let e=n.application.id;if(e===void 0)continue;let o=t.get(a)??/* @__PURE__ */ new Map;o.set(e,`publish-events`),t.set(a,o)}return t}function collectWorkflowJobPublishEvents(e){let t=/* @__PURE__ */ new Map;for(let n of e.application.workflowService?.jobs??[])n.publishEvents!==void 0&&t.set(n.name,n.publishEvents);return t}function collectSubscriberVisibility(e,t){return{tailorDBTypes:collectVisibleTailorDBTypeNamespaces(e.application,t),resolvers:collectVisibleResolverNamespaces(e.application,t),idps:collectVisibleIdpNames(e.application,t)}}function externalTailorDBNamespaces(e){return e.application.externalTailorDBNamespaces}function externalSubgraphNames(e,t,n){return e.application.subgraphs.filter(e=>e.Type===t&&!n.has(e.Name)).map(e=>e.Name)}function externalResolverNamespaces(e){return externalSubgraphNames(e,`pipeline`,new Set(e.application.resolverServices.map(e=>e.namespace)))}function externalIdpNames(e){return externalSubgraphNames(e,`idp`,new Set(e.application.idpServices.map(e=>e.name)))}function describeExternal(e,t){if(t.length!==0)return`external ${t.length===1?e:`${e}s`} ${t.map(e=>`"${e}"`).join(`, `)}`}function declaresTailorDBType(e,t){return e.application.tailorDBServices.some(e=>e.types[t])||void 0}function declaresResolver(e,t){return e.application.resolverServices.some(e=>Object.values(e.resolvers).some(e=>e.name===t))||void 0}function declaresIdp(e,t){return e.application.idpServices.some(e=>e.name===t)||void 0}function declaresWorkflow(e,t){return Object.values(e.application.workflowService?.workflows??{}).some(e=>e.name===t)||void 0}function pinsTailorDBType(e,t){for(let n of e.application.tailorDBServices){let e=n.types[t];if(e)return e.settings.publishEvents!==void 0}return!1}function pinsResolverIn(e,t,n){return e.application.resolverServices.some(e=>e.namespace===t&&Object.values(e.resolvers).some(e=>e.name===n&&e.publishEvents!==void 0))}function pinsIdp(e,t){return e.application.idpServices.some(e=>e.name===t&&e.publishEvents!==void 0)}function pinsWorkflow(e,t){return Object.values(e.application.workflowService?.workflows??{}).some(e=>e.name===t&&e.publishEvents!==void 0)}function pinsEveryJobOfWorkflow(e,t){let n=Object.values(e.application.workflowService?.workflows??{}).find(e=>e.name===t);if(n===void 0)return!1;let r=e.workflowBuildResult?.mainJobDeps[n.mainJob.name]??[],i=collectWorkflowJobPublishEvents(e);return r.length>0&&r.every(e=>i.has(e))}function tailorDBTypeNamespaceIn(e,t){return e.application.tailorDBServices.find(e=>e.types[t])?.namespace}function narrowByVisibleNamespace(e){let{candidates:t,visible:n,resourceKey:r,declaresIn:i}=e;if(!n.has(r))return[];let a=n.get(r);return a===void 0?`ambiguous`:t.filter(e=>i(e,a))}function declaresTailorDBTypeIn(e,t,n){return e.application.tailorDBServices.some(e=>e.namespace===t&&!!e.types[n])}function declaresResolverIn(e,t,n){return e.application.resolverServices.some(e=>e.namespace===t&&Object.values(e.resolvers).some(e=>e.name===n))}function eventSourceLookup(e,t,n){let{trigger:r}=e;switch(r.kind){case`tailordb`:return{resource:Ea.tailorDBType(r.tableName).resource,trigger:r,declaredBy:e=>declaresTailorDBType(e,r.tableName),pinned:e=>pinsTailorDBType(e,r.tableName),keyIn:e=>{let t=tailorDBTypeNamespaceIn(e,r.tableName);return t&&Z.tailorDBType(t,r.tableName)},narrowOwners:e=>narrowByVisibleNamespace({candidates:e,visible:n.tailorDBTypes,resourceKey:r.tableName,declaresIn:(e,t)=>declaresTailorDBTypeIn(e,t,r.tableName)}),externalHint:e=>describeExternal(`TailorDB namespace`,externalTailorDBNamespaces(e))};case`resolverExecuted`:{let e=findResolverNamespace(t.application,r.resolverName)??n.resolvers.get(r.resolverName);return{resource:Ea.resolver(r.resolverName).resource,trigger:r,declaredBy:e=>declaresResolver(e,r.resolverName),pinned:t=>e!==void 0&&pinsResolverIn(t,e,r.resolverName),keyIn:()=>e&&Z.resolver(e,r.resolverName),narrowOwners:e=>narrowByVisibleNamespace({candidates:e,visible:n.resolvers,resourceKey:r.resolverName,declaresIn:(e,t)=>declaresResolverIn(e,t,r.resolverName)}),externalHint:e=>describeExternal(`resolver namespace`,externalResolverNamespaces(e))}}case`idpUser`:{let e=subscribedIdpName(t.application,r);return e===void 0?void 0:{resource:Ea.idpService(e).resource,trigger:r,declaredBy:t=>declaresIdp(t,e),pinned:t=>pinsIdp(t,e),keyIn:()=>Z.idp(e),narrowOwners:t=>n.idps.has(e)?t.filter(t=>declaresIdp(t,e)):[],externalHint:t=>describeExternal(`IdP`,externalIdpNames(t).filter(t=>t===e))}}case`workflowExecution`:case`workflowJobExecution`:return{resource:r.kind===`workflowExecution`?Ta.workflow(r.workflowName):Ta.workflowJobs(r.workflowName),trigger:r,declaredBy:e=>declaresWorkflow(e,r.workflowName),pinned:e=>r.kind===`workflowExecution`?pinsWorkflow(e,r.workflowName):pinsEveryJobOfWorkflow(e,r.workflowName),keyIn:()=>r.kind===`workflowExecution`?Z.workflow(r.workflowName):Z.workflowJobs(r.workflowName),narrowOwners:e=>e.filter(e=>declaresWorkflow(e,r.workflowName)),externalHint:()=>void 0};default:return}}function assertRecordableDependencies(e,t){for(let{subscriber:n,owner:r,executorName:i,resource:a,pinned:o}of publishingSubscriptions(e)){if(n.config.path===r.config.path||o||!t)continue;let e=n.application.id;if(e!==void 0&&dependedByAppLabelKey(e)!==void 0)continue;let s=e===void 0?`${n.config.path} resolves without an "id" — a config that re-exports defineConfig() from another file never gets one`:`${n.config.path} resolves to the id "${e}", which is not the lowercase UUID deploy writes`,c=e===void 0?`Call defineConfig() inline in ${n.config.path} so deploy can manage its "id".`:`Restore the generated value in ${n.config.path}'s "id".`;throw E({code:`EVENT_SUBSCRIPTION_OWNER_UNRECORDED`,message:`Executor "${i}" in ${n.config.path} subscribes to ${a} in ${r.config.path}, which would enable event publishing on it for this deploy only. ${s} — so deploy cannot record which config the dependency belongs to.`,details:`Deploying ${r.config.path} alone later would turn publishing back off without asking.`,suggestion:c})}}function computeRenamedAppDeletions(e){let{conflicts:t,resourceOwners:n,protectedAppNames:r}=e;return[...new Set(t.map(e=>e.currentOwner))].filter(e=>!n.has(e)&&!r.has(e))}function assertUniqueGlobalResourceNames(e){assertNoDuplicateResourceNames(e,yc)}function ownershipTrackedPlans(e){return Object.values(e)}function collectOwnerConflicts(e){return ownershipTrackedPlans(e).flatMap(e=>e.conflicts)}function collectUnmanagedResources(e){return ownershipTrackedPlans(e).flatMap(e=>e.unmanaged)}function collectResourceOwners(e){return new Set(ownershipTrackedPlans(e).flatMap(e=>[...e.resourceOwners]))}function collectImportantResourceDeletions(e){let t=[];for(let n of e.tailorDB.changeSet.type.deletes)t.push({resourceLabel:`TailorDB table`,resourceName:n.name});for(let n of e.staticWebsite.changeSet.deletes)t.push({resourceLabel:`StaticWebsite`,resourceName:n.name});for(let n of e.aiGateway.changeSet.deletes)t.push({resourceLabel:`AIGateway`,resourceName:n.name});for(let n of e.auth.changeSet.oauth2Client.deletes)t.push({resourceLabel:`OAuth2 client`,resourceName:n.name});for(let n of e.auth.changeSet.oauth2Client.replaces)t.push({resourceLabel:`OAuth2 client (client type change)`,resourceName:n.name});for(let n of e.auth.changeSet.connection.deletes)t.push({resourceLabel:`Auth connection`,resourceName:n.name});for(let n of e.secretManager.vaultChangeSet.deletes)t.push({resourceLabel:`Secret Manager vault`,resourceName:n.name});for(let n of e.secretManager.secretChangeSet.deletes)t.push({resourceLabel:`Secret Manager secret`,resourceName:n.name});return t}function readResourceField(e,t){let n=e;for(let e of[`request`,`deleteRequest`,`createRequest`]){let r=n[e];if(r&&typeof r==`object`&&t in r){let e=r[t];return e==null?void 0:String(e)}}let r=n[t];return r==null?void 0:String(r)}function managedResourceName(e,t){return e.getName?e.getName(t):t.name}function managedResourceKey(e,t){let n=e.namespaceFields?.map(e=>readResourceField(t,e)).find(e=>e!==void 0),r=managedResourceName(e,t);return n===void 0?`${e.resourceType}:${r}`:`${e.resourceType}:${n}:${r}`}function managedNamespaceOwnerKey(e,t){if(!e.namespaceOwnerResourceType)return;let n=e.namespaceFields?.map(e=>readResourceField(t,e)).find(e=>e!==void 0);return n===void 0?void 0:`${e.namespaceOwnerResourceType}:${n}`}function addManagedResourceClaims(e,t,n){e.add(managedResourceKey(t,n));let r=managedNamespaceOwnerKey(t,n);r&&e.add(r)}function isManagedResourceClaimed(e,t,n){if(e.has(managedResourceKey(t,n)))return!0;let r=managedNamespaceOwnerKey(t,n);return r?e.has(r):!1}function retainDeletesNotClaimed(e,t){let n=0;for(let r of e.changeSet.deletes)isManagedResourceClaimed(t,e,r)?C.debug(`Skipping delete of ${managedResourceKey(e,r)}: still managed by another config in this deploy.`):(e.changeSet.deletes[n]=r,n+=1);e.changeSet.deletes.length=n}function workflowJobFunctionItems(e){let t=/* @__PURE__ */ new Set;for(let n of e){let e=n.usedJobNames;if(Array.isArray(e))for(let n of e)typeof n==`string`&&t.add(n)}return[...t].map(e=>({name:e}))}function workflowJobFunctionResourceGroup(e){return{changeSet:{creates:workflowJobFunctionItems(e.workflow.changeSet.creates),updates:workflowJobFunctionItems(e.workflow.changeSet.updates),replaces:workflowJobFunctionItems(e.workflow.changeSet.replaces),unchanged:[...e.workflow.unchangedWorkflowJobNames].map(e=>({name:e})),deletes:e.workflow.jobFunctionDeletes},resourceType:`workflow_job_function`,getName:e=>`jobFunctionName`in e?e.jobFunctionName:e.name}}const $=[`namespaceName`,`authNamespace`,`vaultName`,`staticWebsiteName`],yc=[{resourceLabel:`Application`,resourceType:`application`,namesOf:e=>[e.application.name],changeSetOf:e=>e.app},{resourceLabel:`Executor`,resourceType:`executor`,namesOf:e=>Object.values(e.application.executorService?.executors??{}).map(e=>e.name),changeSetOf:e=>e.executor.changeSet},{resourceLabel:`Workflow job`,resourceType:`workflow_job_function`,namesOf:e=>e.bundledScripts.workflowJobs.keys(),changeSetOf:e=>workflowJobFunctionResourceGroup(e).changeSet,getName:e=>`jobFunctionName`in e?e.jobFunctionName:e.name},{resourceLabel:`Workflow`,resourceType:`workflow`,namesOf:e=>Object.values(e.application.workflowService?.workflows??{}).map(e=>e.name),changeSetOf:e=>e.workflow.changeSet},{resourceLabel:`Workflow execution policy`,resourceType:`workflow_job_function_execution_policy`,namesOf:e=>Object.values(e.config.workflow?.executionPolicies??{}).map(e=>e.name),changeSetOf:e=>e.workflowExecutionPolicy.changeSet},{resourceLabel:`Auth connection`,resourceType:`auth.connection`,namespaceFields:$,namespaceOwnerResourceType:`auth.service`,namesOf:e=>Object.keys(e.application.authService?.connections??{}),changeSetOf:e=>e.auth.changeSet.connection},{resourceLabel:`StaticWebsite`,resourceType:`staticwebsite`,namesOf:e=>e.application.staticWebsiteServices.map(e=>e.name),changeSetOf:e=>e.staticWebsite.changeSet},{resourceLabel:`TailorDB namespace`,resourceType:`tailordb.service`,namesOf:e=>e.application.tailorDBServices.map(e=>e.namespace),changeSetOf:e=>e.tailorDB.changeSet.service},{resourceLabel:`Auth namespace`,resourceType:`auth.service`,namesOf:e=>{let t=e.application.authService?.config.name;return t===void 0?[]:[t]},changeSetOf:e=>e.auth.changeSet.service},{resourceLabel:`IdP namespace`,resourceType:`idp.service`,namesOf:e=>e.application.idpServices.map(e=>e.name),changeSetOf:e=>e.idp.changeSet.service},{resourceLabel:`Resolver namespace`,resourceType:`pipeline.service`,namesOf:e=>e.application.resolverServices.map(e=>e.namespace),changeSetOf:e=>e.pipeline.changeSet.service},{resourceLabel:`AIGateway`,resourceType:`aigateway`,namesOf:e=>e.application.aiGatewayServices.map(e=>e.name),changeSetOf:e=>e.aiGateway.changeSet},{resourceLabel:`Secret Manager vault`,resourceType:`secret.vault`,namesOf:e=>e.application.secrets.map(e=>e.vaultName),changeSetOf:e=>e.secretManager.vaultChangeSet}];function managedResourceGroupFromDefinition(e,t){let{changeSetOf:n,namesOf:r,resourceLabel:i,...a}=e;return{...a,changeSet:n(t)}}function managedResourceGroups(e){return[{changeSet:e.functionRegistry.changeSet,resourceType:`function_registry`},...yc.map(t=>managedResourceGroupFromDefinition(t,e)),{changeSet:e.tailorDB.changeSet.type,resourceType:`tailordb.type`,namespaceFields:$,namespaceOwnerResourceType:`tailordb.service`},{changeSet:e.tailorDB.changeSet.gqlPermission,resourceType:`tailordb.gql_permission`,namespaceFields:$,namespaceOwnerResourceType:`tailordb.service`},{changeSet:e.staticWebsite.customDomainChangeSet,resourceType:`staticwebsite.custom_domain`,namespaceFields:$,namespaceOwnerResourceType:`staticwebsite`},{changeSet:e.idp.changeSet.client,resourceType:`idp.client`,namespaceFields:$,namespaceOwnerResourceType:`idp.service`},{changeSet:e.auth.changeSet.idpConfig,resourceType:`auth.idp_config`,namespaceFields:$,namespaceOwnerResourceType:`auth.service`},{changeSet:e.auth.changeSet.userProfileConfig,resourceType:`auth.user_profile_config`,namespaceFields:$,namespaceOwnerResourceType:`auth.service`},{changeSet:e.auth.changeSet.tenantConfig,resourceType:`auth.tenant_config`,namespaceFields:$,namespaceOwnerResourceType:`auth.service`},{changeSet:e.auth.changeSet.machineUser,resourceType:`auth.machine_user`,namespaceFields:$,namespaceOwnerResourceType:`auth.service`},{changeSet:e.auth.changeSet.oauth2Client,resourceType:`auth.oauth2_client`,namespaceFields:$,namespaceOwnerResourceType:`auth.service`},{changeSet:e.auth.changeSet.authHook,resourceType:`auth.hook`,namespaceFields:$,namespaceOwnerResourceType:`auth.service`},{changeSet:e.auth.changeSet.scim,resourceType:`auth.scim`,namespaceFields:$,namespaceOwnerResourceType:`auth.service`},{changeSet:e.auth.changeSet.scimResource,resourceType:`auth.scim_resource`,namespaceFields:$,namespaceOwnerResourceType:`auth.service`},{changeSet:e.pipeline.changeSet.resolver,resourceType:`pipeline.resolver`,namespaceFields:$,namespaceOwnerResourceType:`pipeline.service`},{changeSet:e.secretManager.secretChangeSet,resourceType:`secret.secret`,namespaceFields:$,namespaceOwnerResourceType:`secret.vault`}]}function dropCrossDeploymentManagedDeletes(e){let t=e.map(e=>managedResourceGroups(deploymentPlanResults(e))),n=t.map(e=>e.reduce((e,t)=>{for(let n of[...t.changeSet.creates,...t.changeSet.updates,...t.changeSet.replaces,...t.changeSet.unchanged])addManagedResourceClaims(e,t,n);return e},/* @__PURE__ */ new Set));t.forEach((e,t)=>{let r=/* @__PURE__ */ new Set;n.forEach((e,n)=>{if(n!==t)for(let t of e)r.add(t)});for(let t of e)retainDeletesNotClaimed(t,r)})}function collectDeploymentResourceOwners(e){let t=/* @__PURE__ */ new Set;for(let n of e)for(let e of collectResourceOwners(deploymentPlanResults(n)))t.add(e);return t}function scheduleRenamedAppDeletes(e){let t=new Set(e.map(e=>e.application.name)),n=collectDeploymentResourceOwners(e),r=new Set(e.flatMap(e=>e.app.deletes.map(e=>e.name)));for(let i of e){let e=collectOwnerConflicts(deploymentPlanResults(i));for(let a of computeRenamedAppDeletions({conflicts:e,resourceOwners:n,protectedAppNames:t}))r.has(a)||(r.add(a),i.app.deletes.push({name:a,request:{workspaceId:i.tailorDB.context.workspaceId,applicationName:a}}))}}function ownershipFilters(e){let t=/* @__PURE__ */ new Map;for(let n of e)if(t.set(`${fa}\0${n.name}`,{[fa]:n.name}),n.id){let e=sdkAppIdLabelValue(n.id);t.set(`${ma}\0${e}`,{[ma]:e})}return[...t.values()]}async function createMetadataLookupClient(e){let{client:t,workspaceId:n,applications:r}=e,i=await Promise.all(ownershipFilters(r).map(e=>F(async(r,i)=>{let{results:a,nextPageToken:o}=await t.listMetadata({workspaceId:n,labels:e,pageToken:r,pageSize:i});return[a,o]}))),a=/* @__PURE__ */ new Map;for(let e of i.flat())e.metadata&&a.set(e.trn,e.metadata);let o=/* @__PURE__ */ new Map,getMetadata=(e,n)=>{let r=a.get(e.trn??``);if(r)return Promise.resolve(Yr(Yt,{metadata:r}));let i=e.trn??``,s=o.get(i);return s||(s=t.getMetadata(e,n),o.set(i,s)),s};return new Proxy(t,{get(e,t,n){return t===`getMetadata`?getMetadata:Reflect.get(e,t,n)}})}function buildPlanReport(e){let t=formatExecutorChangeEntries(e.executor.changeSet,buildPlannedExecutorsByName(e.executor.changeSet),e.functionRegistry.executorFunctionChanges),n=formatResolverChangeEntries(e.pipeline.changeSet.resolver,e.functionRegistry.resolverFunctionChanges),r=formatWorkflowChangeEntries(e.workflow.changeSet,e.functionRegistry.workflowJobChanges,e.workflow.jobFunctionDeletes),i=formatChangeSetEntries(e.workflowExecutionPolicy.changeSet,[`executionPolicy`]),a=[...r,...i],o=formatAuthHookChangeEntries(e.auth.changeSet.authHook,e.functionRegistry.authHookFunctionChanges),s=formatTailorDBResourceChangeEntries(e.tailorDB.changeSet.type,e.tailorDB.changeSet.gqlPermission),c=e.tailorDB.context.checkpointRepairs.map(e=>({action:`update`,symbol:wa.update,name:`migration checkpoint ${formatMigrationNumber(e.from)} → ${formatMigrationNumber(e.to)}`,labels:[`migrationCheckpoint`],namespace:e.namespace})),l=[...s,...c],u=[...n],namespaceOf=e=>{if(`request`in e&&e.request&&typeof e.request==`object`&&`namespaceName`in e.request)return e.request.namespaceName;if(`namespaceName`in e)return e.namespaceName},authNamespaceOf=e=>`request`in e&&e.request&&typeof e.request==`object`&&`authNamespace`in e.request?e.request.authNamespace:void 0,d=[...formatChangeSetEntries(e.idp.changeSet.client,[`client`],namespaceOf)],f=[...formatChangeSetEntries(e.auth.changeSet.idpConfig,[`idpConfig`],namespaceOf),...formatChangeSetEntries(e.auth.changeSet.userProfileConfig,[`userProfileConfig`],namespaceOf),...formatChangeSetEntries(e.auth.changeSet.tenantConfig,[`tenantConfig`],namespaceOf),...formatChangeSetEntries(e.auth.changeSet.machineUser,[`machineUser`],authNamespaceOf),...o,...formatChangeSetEntries(e.auth.changeSet.oauth2Client,[`oauth2Client`],namespaceOf),...formatChangeSetEntries(e.auth.changeSet.scim,[`scimConfig`],namespaceOf),...formatChangeSetEntries(e.auth.changeSet.scimResource,[`scimResource`],namespaceOf),...formatChangeSetEntries(e.auth.changeSet.connection,[`connection`],namespaceOf)],{otherChanges:p}=splitFunctionRegistryChanges(e.functionRegistry.changeSet),m=extractServiceActions(e.tailorDB.changeSet.service),g=extractServiceActions(e.pipeline.changeSet.service),_=extractServiceActions(e.idp.changeSet.service),v=extractServiceActions(e.auth.changeSet.service),y=[...l,...u,...t,...a,...d,...f],b=summarizePlanResults(e,y,[...m,...g,..._,...v]),x=collectUnmanagedResources(e),S=collectOwnerConflicts(e),serviceEntries=(e,t)=>e.map(e=>({...e,labels:[t],namespace:void 0})),C=[...y,...serviceEntries(m,`tailorDB`),...serviceEntries(g,`pipeline`),...serviceEntries(_,`idp`),...serviceEntries(v,`auth`),...formatChangeSetEntries(p),...formatChangeSetEntries(e.staticWebsite.changeSet,[`staticWebsite`]),...formatChangeSetEntries(e.staticWebsite.customDomainChangeSet,[`customDomain`]),...formatChangeSetEntries(e.staticWebsite.customDomainTransferChangeSet,[`customDomainTransfer`]),...formatChangeSetEntries(e.aiGateway.changeSet,[`aiGateway`]),...formatChangeSetEntries(e.app,[`application`]),...formatChangeSetEntries(e.secretManager.vaultChangeSet,[`vault`]),...formatChangeSetEntries(e.secretManager.secretChangeSet,[`secret`])].map(({action:e,name:t,labels:n,namespace:r,forcedBySdkVersion:i})=>({action:e,name:t,labels:n,namespace:r,...i&&{forcedBySdkVersion:i}})),w=[...x.map(({resourceType:e,resourceName:t})=>({type:`unmanaged`,resourceType:e,name:t})),...e.secretManager.skippedSecrets.map(e=>({type:`skippedSecret`,resourceType:`secret.secret`,name:e}))],T=S.map(({resourceType:e,resourceName:t,currentOwner:n})=>({resourceType:e,name:t,currentOwner:n})),E=[...buildGroupedDisplayLines(e.functionRegistry.changeSet.title,formatChangeSetEntries(p)),...e.staticWebsite.changeSet.lines(),...e.staticWebsite.customDomainChangeSet.lines(),...e.staticWebsite.customDomainTransferChangeSet.lines(),...e.aiGateway.changeSet.lines(),...e.app.lines(),...buildGroupedDisplayLines(`TailorDB`,l,m),...buildGroupedDisplayLines(`Resolver`,u,g),...buildGroupedDisplayLines(`Executor`,t),...buildGroupedDisplayLines(`Workflow`,a),...buildGroupedDisplayLines(`IdP`,d,_),...buildGroupedDisplayLines(`Auth`,f,v),...e.secretManager.vaultChangeSet.lines(),...e.secretManager.secretChangeSet.lines()];if(x.length>0){E.push(h.bold(`Unmanaged resources (not in config):`));for(let{resourceLabel:e,resourceName:t}of x)E.push(` ${h.warning(`⚠`)} ${h.bold(e)} "${t}"`)}if(e.secretManager.skippedSecrets.length>0){E.push(h.bold(`Secret Manager secrets (skipped - no value provided):`));for(let t of e.secretManager.skippedSecrets)E.push(` ${h.dim(`○`)} ${t}`)}let ee=e.staticWebsite.customDomainNotes;if(ee.length>0){E.push(h.bold(`Custom domains (no change):`));for(let e of ee)E.push(` ${h.dim(`○`)} ${e.domain} \u2014 ${e.message}`)}if(S.length>0){E.push(h.bold(`Owner conflicts (will require confirmation on apply):`));for(let{resourceLabel:e,resourceName:t,currentOwner:n}of S)E.push(` ${h.warning(`!`)} ${h.bold(e)} "${t}" — owned by "${n}"`)}return E.push(formatPlanSummary(b)),{summary:b,json:{summary:b,changes:C,warnings:w,conflicts:T,notes:ee.map(e=>({type:e.kind,resourceType:`staticwebsite.custom_domain_transfer`,name:e.domain,message:e.message}))},lines:E}}function printPlanResults(e,t){let n=buildPlanReport(e);if(C.jsonMode&&t?.dryRun)return C.out(n.json),n.summary;let r=n.lines.join(`
|
|
186
|
+
`);return t?.dryRun?C.out(r):C.log(r),n.summary}function summarizePlanResults(e,t,n){let r={create:0,update:0,delete:0,replace:0,forcedBySdkVersion:0};for(let e of[...t,...n])r[e.action]+=1,e.forcedBySdkVersion&&(r.forcedBySdkVersion+=1);let{otherChanges:i}=splitFunctionRegistryChanges(e.functionRegistry.changeSet);return sumPlanSummaries([r,summarizeChangeSets([i,e.staticWebsite.changeSet,e.staticWebsite.customDomainChangeSet,e.staticWebsite.customDomainTransferChangeSet,e.aiGateway.changeSet,e.app,e.secretManager.vaultChangeSet,e.secretManager.secretChangeSet])])}function sumPlanSummaries(e){return e.reduce((e,t)=>({create:e.create+t.create,update:e.update+t.update,delete:e.delete+t.delete,replace:e.replace+t.replace,forcedBySdkVersion:e.forcedBySdkVersion+t.forcedBySdkVersion}),{create:0,update:0,delete:0,replace:0,forcedBySdkVersion:0})}function printDeploymentPlans(e,t){if(C.jsonMode&&t?.dryRun){let n=e.map(e=>buildPlanReport(deploymentPlanResults(e))),r=sumPlanSummaries(n.map(e=>e.summary));return C.out({summary:r,changes:n.flatMap(e=>e.json.changes),warnings:[...n.flatMap(e=>e.json.warnings),...(t.missingDependentApps??[]).map(({resourceType:e,namespace:t,name:n,scope:r,appId:i,reason:a})=>({type:`missingDependentApp`,resourceType:e,namespace:t,name:n,...r===`jobs`&&{scope:r},appId:i,reason:a}))],conflicts:n.flatMap(e=>e.json.conflicts),notes:n.flatMap(e=>e.json.notes),...t.pendingDeployedHooks?.length?{pendingDeployedHooks:t.pendingDeployedHooks}:{}}),r}return sumPlanSummaries(e.map(e=>printPlanResults(deploymentPlanResults(e),t)))}const bc=/* @__PURE__ */ new Map;function validatorFor(e){let t=bc.get(e.typeName);if(t)return t;let n=Vi({registry:Xr(e,...Bi(e))});return bc.set(e.typeName,n),n}function validateItems(e){let{schema:t,kind:n,action:r,items:i,requestKey:a,violations:o}=e;if(i.length===0)return;let s=validatorFor(t);for(let e of i){let i=e[a],c=Yr(t,i),l=s.validate(t,c);if(l.kind===`invalid`)for(let t of l.violations)o.push({kind:n,name:e.name,action:r,fieldPath:t.field.length>0?zi(t.field):`(message)`,message:t.message});else l.kind===`error`&&C.warn(`Could not validate ${n} "${e.name}" (${r}): ${l.error.message}`)}}async function validatePlan(e){let{tailorDB:t,staticWebsite:n,aiGateway:r,idp:i,auth:a,pipeline:o,app:s,executor:c,workflow:l,workflowExecutionPolicy:u,secretManager:d}=e,f=[];function creates(e,t,n){validateItems({schema:e,kind:t,action:`create`,items:n,requestKey:`request`,violations:f})}function updates(e,t,n){validateItems({schema:e,kind:t,action:`update`,items:n,requestKey:`request`,violations:f})}function replaces(e,t,n){validateItems({schema:e,kind:t,action:`replace`,items:n,requestKey:`createRequest`,violations:f})}function inPlaceReplaces(e,t,n){validateItems({schema:e,kind:t,action:`replace`,items:n,requestKey:`updateRequest`,violations:f})}creates(Bn,`TailorDB service`,t.changeSet.service.creates),creates(Wn,`TailorDB table`,t.changeSet.type.creates),updates(ar,`TailorDB table`,t.changeSet.type.updates),creates(Xt,`StaticWebsite`,n.changeSet.creates),updates(wn,`StaticWebsite`,n.changeSet.updates),creates(Sn,`StaticWebsite custom domain`,n.customDomainChangeSet.creates),creates(vr,`StaticWebsite custom domain transfer`,n.customDomainTransferChangeSet.creates),creates(Hn,`AIGateway`,r.changeSet.creates.map(e=>({name:e.name,request:{...e.request,cors:void 0}}))),updates(pr,`AIGateway`,r.changeSet.updates.map(e=>({name:e.name,request:{...e.request,cors:void 0}})));let substituteIdpReturnOrigins=e=>{let t=e.request,n=t.userAuthPolicy?.allowedReturnOrigins;if(!Array.isArray(n)||n.length===0)return e;let r=n.map(e=>typeof e==`string`&&/^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]:url$/.test(e)?`https://placeholder.invalid`:e);return{...e,request:{...t,userAuthPolicy:{...t.userAuthPolicy,allowedReturnOrigins:r}}}};creates(rn,`IdP service`,i.changeSet.service.creates.map(substituteIdpReturnOrigins)),updates(En,`IdP service`,i.changeSet.service.updates.map(substituteIdpReturnOrigins));let p=[...i.changeSet.client.creates.map(e=>({clientName:e.request.client?.name??``,namespaceName:e.request.namespaceName??``,workspaceId:e.request.workspaceId??``})),...i.changeSet.client.updates.map(e=>({clientName:e.name,namespaceName:e.namespaceName,workspaceId:e.workspaceId}))];creates(qt,`IdP client secret`,p.map(e=>({name:e.clientName,request:{workspaceId:e.workspaceId,secretmanagerVaultName:idpClientVaultName(e.namespaceName,e.clientName)}}))),creates($n,`IdP client secret`,p.map(e=>({name:e.clientName,request:{workspaceId:e.workspaceId,secretmanagerVaultName:idpClientVaultName(e.namespaceName,e.clientName),secretmanagerSecretName:idpClientSecretName(e.namespaceName,e.clientName)}}))),creates(nr,`Auth service`,a.changeSet.service.creates),updates(yr,`Auth service`,a.changeSet.service.updates),creates(tr,`Auth IDP config`,a.changeSet.idpConfig.creates),updates(Cr,`Auth IDP config`,a.changeSet.idpConfig.updates),creates(qn,`Auth user profile config`,a.changeSet.userProfileConfig.creates),updates($t,`Auth user profile config`,a.changeSet.userProfileConfig.updates),creates(Jn,`Auth tenant config`,a.changeSet.tenantConfig.creates),updates(Tn,`Auth tenant config`,a.changeSet.tenantConfig.updates),creates(hr,`Auth machine user`,a.changeSet.machineUser.creates),updates(Rn,`Auth machine user`,a.changeSet.machineUser.updates),creates(zn,`Auth hook`,a.changeSet.authHook.creates),updates(_r,`Auth hook`,a.changeSet.authHook.updates),creates(Gn,`Auth SCIM config`,a.changeSet.scim.creates),updates(Cn,`Auth SCIM config`,a.changeSet.scim.updates),creates(or,`Auth SCIM resource`,a.changeSet.scimResource.creates),updates(Zt,`Auth SCIM resource`,a.changeSet.scimResource.updates),creates(Vn,`OAuth2 client`,a.changeSet.oauth2Client.creates),updates(xr,`OAuth2 client`,a.changeSet.oauth2Client.updates),replaces(Vn,`OAuth2 client`,a.changeSet.oauth2Client.replaces),creates(gn,`Pipeline service`,o.changeSet.service.creates),updates(on,`Pipeline service`,o.changeSet.service.updates),creates(fn,`Resolver`,o.changeSet.resolver.creates),updates(en,`Resolver`,o.changeSet.resolver.updates),creates(Un,`Executor`,c.changeSet.creates),updates(mr,`Executor`,c.changeSet.updates),creates(In,`Workflow`,l.changeSet.creates.map(e=>({name:e.name,request:buildWorkflowValidationShape(e.workspaceId,e.workflow)}))),updates(ur,`Workflow`,l.changeSet.updates.map(e=>({name:e.name,request:buildWorkflowValidationShape(e.workspaceId,e.workflow)})));let m=l.changeSet.creates[0]?.workspaceId??l.changeSet.updates[0]?.workspaceId??``;if(m){let e=/* @__PURE__ */ new Set;for(let t of[...l.changeSet.creates,...l.changeSet.updates])for(let n of t.usedJobNames)e.add(n);for(let t of l.unchangedWorkflowJobNames)e.add(t);creates(Yn,`Workflow job function`,[...e].map(e=>({name:e,request:{workspaceId:m,jobFunctionName:e,scriptRef:e}})))}if(creates(cr,`Workflow execution policy`,[...u.changeSet.creates,...u.changeSet.replaces].map(e=>({name:e.name,request:{workspaceId:e.workspaceId,executionPolicyName:e.policy.name,executionPolicyKey:toPlatformExecutionPolicyKey(e.policy),...e.policy.concurrencyPolicy&&{concurrencyPolicy:{maxConcurrentExecutions:e.policy.concurrencyPolicy.maxConcurrentExecutions}}}}))),updates(rr,`Workflow execution policy`,u.changeSet.updates.map(e=>({name:e.name,request:{workspaceId:e.workspaceId,executionPolicyName:e.policy.name,...e.policy.concurrencyPolicy&&{concurrencyPolicy:{maxConcurrentExecutions:e.policy.concurrencyPolicy.maxConcurrentExecutions}}}}))),creates(qt,`Secret Manager vault`,d.vaultChangeSet.creates.map(e=>({name:e.name,request:vaultCreateRequest(e)}))),creates($n,`Secret Manager secret`,d.secretChangeSet.creates.map(e=>({name:e.name,request:secretCreateRequest(e)}))),updates(Zn,`Secret Manager secret`,d.secretChangeSet.updates.map(e=>({name:e.name,request:secretUpdateRequest(e)}))),creates(cn,`Application`,s.creates.map(e=>({name:e.name,request:{...e.request,cors:void 0}}))),updates(An,`Application`,[...s.updates,...s.unchanged].map(e=>({name:e.name,request:{...e.request,cors:void 0}}))),creates(dr,`Auth connection`,a.changeSet.connection.creates),inPlaceReplaces(Fn,`Auth connection`,a.changeSet.connection.replaces),f.length===0)return;let g=new Set(f.map(e=>`${e.kind}:${e.name}`));C.error(`Pre-flight validation found ${f.length} violation(s) across ${g.size} resource(s):`);for(let e of f)C.log(` ${h.resourceType(e.kind)} ${h.resourceName(e.name)} (${e.action}) — ${h.bold(e.fieldPath)}: ${e.message}`);throw E({code:`DEPLOY_VALIDATION_FAILED`,message:`${f.length} validation error(s) found in ${g.size} resource(s)`})}function formatIssues(e){return e.map(e=>e.message).join(`; `)||`Invalid options`}function parseOptions(e,t){let n=e.safeParse(t);if(!n.success)throw E({code:`OPTIONS_INVALID`,message:formatIssues(n.error.issues),context:{issues:u(n.error.issues)},cause:n.error});return n.data}const xc=U.string().min(1,`Profile must not be empty`),Sc=63,Cc=U.string().min(3,`Name must be at least 3 characters`).max(63,`Name must be at most 63 characters`).regex(/^[a-z0-9-]+$/,`Name can only contain lowercase letters, numbers, and hyphens`).refine(e=>!e.startsWith(`-`)&&!e.endsWith(`-`),`Name cannot start or end with a hyphen`);function validateWorkspaceName(e){let t=Cc.safeParse(e);return t.success?!0:formatIssues(t.error.issues)}const wc=/^(\d+)(s|m|h|d)$/,Tc={s:1e3,m:6e4,h:36e5,d:864e5},Ec=U.string().regex(wc,{message:`Invalid duration format. Expected a number with a unit: '30m', '24h', '7d'`}),Dc=5e7,Oc=`less than ${Dc.toLocaleString(`en-US`)} days`,kc=Ec.pipe(U.string().refine(e=>parseAge(e)<Dc*Tc.d,{message:`TTL must be ${Oc}`}));function parseAge(e){let t=e.match(wc);if(!t?.[1]||!t[2])throw E({code:`PRUNE_AGE_INVALID`,message:`invalid age format: ${e}`,command:`workspace prune`});let n=t[2];return parseInt(t[1],10)*Tc[n]}const Ac=`sdk-expires-at`,jc=/^s-(\d{1,15})$/;function workspaceTrn(e){return`trn:v1:workspace:${e}`}function encodeExpiresAt(e){return`s-${Math.floor(e.getTime()/1e3)}`}function decodeExpiresAt(e){let t=e?.match(jc);if(!t?.[1])return;let n=Number(t[1]);if(!Number.isSafeInteger(n))return;let r=/* @__PURE__ */ new Date(n*1e3);return Number.isNaN(r.getTime())?void 0:r}function recordedExpiresAt(e){return a(decodeExpiresAt(encodeExpiresAt(e)),`encoded workspace expiry must decode`)}function readWorkspaceExpiry(e,t){let n=e?.[Ac];if(n===void 0||n===``)return{state:`unset`};let r=decodeExpiresAt(n);return r?r.getTime()<=t.getTime()?{state:`expired`,expiresAt:r}:{state:`pending`,expiresAt:r}:{state:`invalid`,value:n}}async function fetchWorkspaceExpiry(e,t,n){try{return{expiry:readWorkspaceExpiry((await e.getMetadata({trn:workspaceTrn(t)})).metadata?.labels,n)}}catch(e){return{error:T(e)}}}async function writeWorkspaceExpiry(e,t,n){return writeMetadataLabelsDirect(e,{trn:workspaceTrn(t),labels:{[Ac]:encodeExpiresAt(n)}})}async function clearWorkspaceExpiry(e,t){return writeMetadataLabelsDirect(e,{trn:workspaceTrn(t),remove:[Ac]})}function reportedExpiry(e){if(`error`in e)return`unavailable`;switch(e.expiry.state){case`unset`:return null;case`invalid`:return`invalid`;default:return e.expiry.expiresAt.toISOString()}}async function fetchReportedExpiries(e,t,n){let r=Bt();return Promise.all(t.map(async t=>reportedExpiry(await r(()=>fetchWorkspaceExpiry(e,t,n)))))}const Mc=[`asia-northeast`,`us-west`,`europe-west`];function formatTimestamp(e){if(!e)return null;let t=G(e);return Number.isNaN(t.getTime())?null:t}function formatTable(e,t){return ee(e,t)}function formatKeyValueTable(e){return formatTable(e,{singleLine:!0})}function humanizeRelativeTime(e){if(e===null)return`N/A`;let t=e instanceof Date?e:new Date(e);return Number.isNaN(t.getTime())?typeof e==`string`?e:`N/A`:li(t,{addSuffix:!0})}const workspaceInfo=(e,t)=>{if(!e.organizationId)throw E({code:`WORKSPACE_ORGANIZATION_MISSING`,message:`Workspace ${e.id} has no organization.`});let n={id:e.id,name:e.name,region:e.region,organizationId:e.organizationId,...e.folderId?{folderId:e.folderId}:{},createdAt:formatTimestamp(e.createTime),updatedAt:formatTimestamp(e.updateTime)};return t?{...n,folderName:t}:n},workspaceDetails=(e,t)=>({...workspaceInfo(e,t),deleteProtection:e.deleteProtection,organizationId:e.organizationId,folderId:e.folderId});async function resolveWorkspaceFolderName(e,t){if(t.organizationId&&t.folderId)try{return(await e.getOrganizationFolder({organizationId:t.organizationId,folderId:t.folderId})).folder?.name||void 0}catch(e){if(e instanceof q&&(e.code===K.NotFound||e.code===K.PermissionDenied))return;C.warn(`Failed to resolve workspace folder name: ${e}`);return}}function createWorkspaceFolderNameResolver(e){let t=/* @__PURE__ */ new Map;return n=>{if(!n.organizationId||!n.folderId)return Promise.resolve(void 0);let r=`${n.organizationId}/${n.folderId}`,i=t.get(r);if(i)return i;let a=resolveWorkspaceFolderName(e,n);return t.set(r,a),a}}async function workspaceInfoWithFolderName(e,t){let n=await resolveWorkspaceFolderName(e,t);return workspaceInfo(t,n)}async function workspaceDetailsWithFolderName(e,t){let n=await resolveWorkspaceFolderName(e,t);return workspaceDetails(t,n)}async function workspaceInfosWithFolderNames(e,t){let n=createWorkspaceFolderNameResolver(e),r=mi(5);return Promise.all(t.map(e=>r(async()=>workspaceInfo(e,await n(e)))))}function workspaceDisplayName(e){return e.folderName?`${e.folderName}/${e.name}`:e.name}function createWorkspaceNameTransformer(e,t){return(n,r)=>{let i=r,a=i[e],o=i[t];return typeof a==`string`&&typeof o==`string`?workspaceDisplayName({name:a,folderName:o}):String(n??``)}}const Nc=createWorkspaceNameTransformer(`name`,`folderName`),Pc=U.object({name:Cc,region:U.string(),deleteProtection:U.boolean().optional(),organizationId:U.uuid().optional(),folderId:U.uuid().optional(),ttl:kc.optional(),profile:xc.optional()});async function resolveWorkspaceCreationLocation(e){let t=e.organizationId!==void 0||e.folderId!==void 0?void 0:await we({profile:e.profile});return{organizationId:t?t.organizationId:e.organizationId,folderId:t?t.folderId:e.folderId,defaults:t}}const validateRegion=async(e,t)=>{let n=await t.listAvailableWorkspaceRegions({});if(!n.regions.includes(e))throw E({code:`WORKSPACE_REGION_INVALID`,message:`Region must be one of: ${n.regions.join(`, `)}.`,command:`workspace create`})};function profilePlatformSettings(e){let t=e?.oauth2ClientId||process.env.TAILOR_PLATFORM_OAUTH2_CLIENT_ID,n=e?.consoleUrl??process.env.TAILOR_PLATFORM_CONSOLE_URL;return{...Dt(e)?{}:{platform_url:Et(e)},...t?{oauth2_client_id:zt(e)}:{},...n?{console_url:Tt(n)}:{}}}async function createWorkspace$1(e){let{client:t,validated:n}=await prepareWorkspaceCreation(e);return createValidatedWorkspaceWithClient(t,n)}async function prepareWorkspaceCreation(e){let t=parseCreateWorkspaceOptions(e),{organizationId:n,folderId:r,defaults:i}=await resolveWorkspaceCreationLocation(t),a=validateCreateWorkspaceOptions({...t,organizationId:n,folderId:r}),o=await A({profile:a.profile}),s=await De({profile:a.profile}),c=await N(o,s);return await validateRegion(a.region,c),{client:c,validated:a,defaults:i}}async function createValidatedWorkspaceWithClient(e,t){let n=await e.createWorkspace({workspaceName:t.name,workspaceRegion:t.region,deleteProtection:t.deleteProtection??!1,organizationId:t.organizationId,folderId:t.folderId}),r=a(n.workspace,`createWorkspace response missing workspace`),i=t.ttl===void 0?void 0:await recordTtl(e,r.id,t.ttl,r.createTime),o=await workspaceInfoWithFolderName(e,r);return i?{...o,ttl:i}:o}async function recordTtl(e,t,n,r){let i=r?G(r):/* @__PURE__ */ new Date,a=recordedExpiresAt(new Date(i.getTime()+parseAge(n))),write=()=>writeWorkspaceExpiry(e,t,a);try{return await write().catch(()=>write()),{state:`written`,expiresAt:a}}catch(e){return{state:`unconfirmed`,expiresAt:a,requested:n,message:e instanceof Error?e.message:String(e)}}}function ttlOutput(e){let t=e.expiresAt.toISOString();return e.state===`written`?{state:e.state,expiresAt:t}:{state:e.state,requestedExpiresAt:t}}function parseCreateWorkspaceOptions(e){let t=parseOptions(Pc,e);if(t.folderId!==void 0&&t.organizationId===void 0)throw E({code:`WORKSPACE_FOLDER_WITHOUT_ORGANIZATION`,message:`A folder ID requires an organization ID.`,suggestion:`Give the organization that owns the folder as well.`});return t}function validateCreateWorkspaceOptions(e){let t=parseCreateWorkspaceOptions(e);if(t.organizationId===void 0)throw E({code:`WORKSPACE_ORGANIZATION_REQUIRED`,message:`A workspace must be created in an organization.`,suggestion:ge()?`Pass --organization-id or set TAILOR_PLATFORM_ORGANIZATION_ID.`:"Pass --organization-id (or set TAILOR_PLATFORM_ORGANIZATION_ID), or set a default organization with `tailor user update --default-organization-id`."});return t}function describeUserDefaults(e){return e.folderId?`folder ${e.folderId} in organization ${e.organizationId}`:`organization ${e.organizationId}`}function announceUserDefaults(e){C.info(`Creating the workspace in ${describeUserDefaults(e)}, the default set by \`tailor user update\`.`)}function userDefaultsTarget(e){return`This run targeted ${describeUserDefaults(e)}, the default set by \`tailor user update\`.`}function userDefaultsContext(e){return{defaultOrganizationId:e.organizationId,defaultFolderId:e.folderId??null}}function pointAtUserDefaults(e,t){e instanceof q&&(e.code===K.NotFound||e.code===K.PermissionDenied)&&l(e,{suggestion:`${userDefaultsTarget(t)} Check that it exists and that this user can create workspaces there, or pass --organization-id (and --folder-id) to choose another location.`,context:{...s(e).context,...userDefaultsContext(t)}})}const Fc=Y({name:`create`,description:`Create a new Tailor Platform workspace.`,notes:M`
|
|
187
187
|
Every workspace belongs to an organization. Without --organization-id and --folder-id, on the command line or through TAILOR_PLATFORM_ORGANIZATION_ID / TAILOR_PLATFORM_FOLDER_ID, the workspace is created in the default organization and folder that the logged-in user set with \`user update\`, unless TAILOR_PLATFORM_TOKEN is set. When none of these gives an organization, the command fails. Giving either option replaces both defaults, and --folder-id requires --organization-id.
|
|
188
188
|
|
|
189
189
|
Command-line options take precedence over TAILOR_PLATFORM_ORGANIZATION_ID and TAILOR_PLATFORM_FOLDER_ID, including values loaded by --env-file. An empty value of either variable is treated as not given.
|
|
190
190
|
|
|
191
191
|
When --ttl is given but the expiry cannot be confirmed, the command still prints the created workspace, then fails with WORKSPACE_TTL_WRITE_FAILED. With --json, the printed \`ttl.state\` is then \`unconfirmed\` instead of \`written\`, so a script can read the workspace ID and record the expiry again with \`workspace ttl set\`.
|
|
192
|
-
`,args:U.strictObject({name:V(vc,{alias:`n`,description:`Workspace name`}),region:V(U.string(),{alias:`r`,description:`Workspace region (${Dc.join(`, `)})`}),"delete-protection":V(U.boolean().default(!1),{alias:`d`,description:`Enable delete protection`}),"organization-id":V(U.string().optional(),{alias:`o`,description:`Organization ID to workspace associate with`,env:`TAILOR_PLATFORM_ORGANIZATION_ID`}),"folder-id":V(U.string().optional(),{alias:`f`,description:`Folder ID to workspace associate with`,env:`TAILOR_PLATFORM_FOLDER_ID`}),ttl:V(wc.optional(),{description:`Record on the workspace itself when it becomes prunable, such as 30m, 24h, or 7d (${Cc}). \`workspace prune --expired\` deletes it once that has passed`}),"profile-name":V(U.string().optional(),{alias:`p`,description:`Profile name to create`}),profile:V(gc.optional(),{description:`Workspace profile used for authentication and Platform selection`,env:`TAILOR_PLATFORM_PROFILE`}),"profile-user":V(U.string().optional(),{description:`User email address or machine user client ID for the profile (defaults to current user)`}),permission:V(U.enum([`write`,`read`]).default(`write`),{description:`Profile permission (requires --profile-name). 'read' blocks all write commands while the profile is active.`})}),run:async e=>{await assertWritable({profile:e.profile});let t=e[`profile-name`],n;if(t){let r=await Oe();if(r.profiles[t])throw E({code:`PROFILE_EXISTS`,message:`Profile "${t}" already exists.`});let i=e.profile,a=i?r.profiles[i]:void 0,o=a?ye(a):void 0,s=e[`profile-user`]||a?.user||r.current_user;if(!s)throw E({code:`USER_NOT_SET`,message:`Current user not found.`,suggestion:`Log in or specify --profile-user to create a profile.`,command:`workspace create`});let c=ke(r,s,o);if(!c)throw E({code:`USER_NOT_FOUND`,message:`User "${s}" not found.`,suggestion:`Verify the user name and log in.`,next:{command:`tailor`,args:[`login`,...Se({profile:i})]}});n={name:t,user:c,platformSettings:profilePlatformSettings(o)}}let{client:r,validated:i,defaults:a}=await prepareWorkspaceCreation({name:e.name,region:e.region,deleteProtection:e[`delete-protection`],...fe(e),ttl:e.ttl,profile:e.profile}),o;try{a&&!e.json&&announceUserDefaults(a),o=await createValidatedWorkspaceWithClient(r,i)}catch(e){throw a&&pointAtUserDefaults(e,a),e}let s;if(n){let t=await Oe(),r=n.platformSettings;t.profiles[n.name]={user:n.user,workspace_id:o.id,...e.permission===`read`?{readonly:!0}:{},...r},ce(t),s={name:n.name,user:n.user,workspaceId:o.id,permission:e.permission,...r.platform_url?{platformUrl:r.platform_url}:{},...r.oauth2_client_id?{oauth2ClientId:r.oauth2_client_id}:{},...r.console_url?{consoleUrl:r.console_url}:{}},e.json||C.success(`Profile "${n.name}" created successfully.`)}let{ttl:c,...l}=o;if(e.json||(C.success(`Workspace "${workspaceDisplayName(o)}" created successfully.`),c?.state===`written`&&C.info(`Workspace becomes prunable at ${c.expiresAt.toISOString()}.`)),e.json?C.out({...l,...c?{ttl:ttlOutput(c)}:{},...s?{profile:s}:{}}):(C.out(l,{display:{name:Oc,folderName:null}}),s&&(C.out(`Profile:`),C.out(s))),c?.state===`unconfirmed`)throw E({code:`WORKSPACE_TTL_WRITE_FAILED`,message:`Workspace "${workspaceDisplayName(o)}" was created, but --ttl could not be confirmed: ${c.message}`,details:`The workspace exists. Whether it records the expiry is unknown — the write may have landed. Set the expiry again to be sure.`,context:{workspaceId:o.id,requestedExpiresAt:c.expiresAt.toISOString(),...s?{profileCreated:s.name}:{}},next:{command:`tailor`,args:[`workspace`,`ttl`,`set`,`--ttl`,c.requested,...Se({workspaceId:o.id,profile:e.profile})]}})}});async function listWorkspaces(e){let t=parseOptions(gc.optional(),e?.profile),n=await A({profile:t}),r=await De({profile:t});return listWorkspacesWithClient(await N(n,r),e)}async function listWorkspacesWithExpiry(e){let t=parseOptions(gc.optional(),e?.profile),n=await A({profile:t}),r=await De({profile:t}),i=await N(n,r),a=await fetchWithinLimit(e?.limit,t=>fetchWorkspaces(i,{...e,limit:t})),o=await workspaceInfosWithFolderNames(i,a.items),s=await fetchReportedExpiries(i,o.map(({id:e})=>e),/* @__PURE__ */ new Date);return{items:o.map((e,t)=>{let n=s[t];return{...e,expiresAt:n===void 0?`unavailable`:n}}),truncated:a.truncated}}async function listWorkspacesWithClient(e,t){return workspaceInfosWithFolderNames(e,await fetchWorkspaces(e,t))}async function fetchWorkspaces(e,t){let n=Ce(t?.order);return Mt(async(t,r)=>{let{workspaces:i,nextPageToken:a}=await e.listWorkspaces({pageToken:t,pageSize:r,pageDirection:n});return[i,a]},{limit:t?.limit})}const jc=Y({name:`list`,description:`List all Tailor Platform workspaces.`,args:U.strictObject({...pe(),profile:V(gc.optional(),{description:`Workspace profile used for authentication and Platform selection`,env:`TAILOR_PLATFORM_PROFILE`})}),run:async e=>{let t=await listWorkspacesWithExpiry({order:e.order,limit:e.limit,profile:e.profile});C.out(t.items,{display:{name:Oc,folderName:null,organizationId:null,folderId:null,updatedAt:null}}),await reportTruncation(t,e.limit)}}),Mc=U.object({version:U.literal(1),platformUrl:U.url(),applicationId:U.string().min(1).optional(),workspaceId:U.uuid()});function defaultConfigPath(){return Ur(process.cwd(),`tailor.config.ts`)}function contextPath(e){return Vr(zr(e),Ze(),`${Rr(e)}.context.json`)}async function loadWorkspaceContext(e,t=defaultConfigPath(),n){let r;try{r=await Di(contextPath(t),`utf8`)}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return;throw e}let i;try{i=JSON.parse(r)}catch{return}let a=Mc.safeParse(i);if(!(!a.success||a.data.platformUrl!==e||n!==void 0&&a.data.applicationId!==n))return a.data}async function saveWorkspaceContext(e,t=defaultConfigPath(),n){let r=Mc.safeParse({...e,...n===void 0?{}:{applicationId:n}});if(!r.success)throw c(`workspace context`,r.error);let i=r.data,a=Vr(zr(t),Ze()),o=contextPath(t),s=`${JSON.stringify(i,null,2)}\n`;try{if(await Di(o,`utf8`)===s)return}catch{}let l=`${o}.${process.pid}.${mi()}.tmp`;await Ei(a,{recursive:!0});try{await ji(l,s,{mode:384}),await Oi(l,o)}catch(e){throw await ki(l,{force:!0}).catch(()=>void 0),e}}function suggestedWorkspaceName(){let e=Rr(process.cwd()).toLowerCase().replaceAll(/[^a-z0-9-]+/g,`-`).replaceAll(/^-+|-+$/g,``).slice(0,63).replace(/-+$/,``);return validateWorkspaceName(e)===!0?e:`my-workspace`}function executableAction(e){return{command:`tailor`,args:e}}function deployArgs(e){return e.deployArgs??[`deploy`]}function workspaceCommandArgs(e){return e.workspaceCommandArgs??[]}function organizationArgs(e){return e.organizationId===void 0?e.locationResolved?[`--organization-id`,`<organization-id>`]:[]:[`--organization-id`,e.organizationId]}function createDeployArgs(e,t,n){return[...deployArgs(e),`--create-workspace`,`--workspace-name`,t,`--workspace-region`,n,...organizationArgs(e),...e.folderId?[`--folder-id`,e.folderId]:[]]}function selectDeployArgs(e){return[...deployArgs(e),`--workspace-id`,`<workspace-id>`]}function userDefaultsDiagnostics(e,t){let n=e.userDefaults;return n?{suggestion:`${t} ${userDefaultsTarget(n)}`,context:userDefaultsContext(n)}:{suggestion:t,context:{}}}function workspaceLabel(e){let t=e.organizationId??`personal`;return`${workspaceDisplayName(e)} (${e.region}, org: ${t}, id: ${e.id})`}function workspaceMatchesRequestedIdentity(e,t){return t.workspaceName===e.name&&t.workspaceRegion===e.region&&t.organizationId===e.organizationId&&t.folderId===e.folderId}function workspaceIdentity(e){let{id:t,name:n,region:r,organizationId:i,folderId:a}=e;return{id:t,name:n,region:r,organizationId:i,folderId:a}}function projectContextTargets(e){if(e)return[...new Map(e.map(e=>[e.configPath,e])).values()]}async function loadProjectContexts(e,t){let n=projectContextTargets(t);if(!n||n.length===0){let t=await loadWorkspaceContext(e);return t?[t]:[]}return(await Promise.all(n.map(({configPath:t,applicationId:n})=>loadWorkspaceContext(e,t,n)))).filter(e=>e!==void 0)}async function persistWorkspaceContext(e,t){let n=projectContextTargets(t);if(!n||n.length===0){await saveWorkspaceContext(e);return}let r=(await Promise.allSettled(n.map(({configPath:t,applicationId:n})=>saveWorkspaceContext(e,t,n)))).filter(e=>e.status===`rejected`);if(r.length>0)throw E({code:`WORKSPACE_CONTEXT_SAVE_FAILED`,message:r.map(({reason:e})=>e instanceof Error?e.message:String(e)).join(`; `)})}async function rememberWorkspaceContext(e,t,n=`error-on-partial`){if(!t.dryRun)try{await persistWorkspaceContext(e,t.contextTargets)}catch(r){if((projectContextTargets(t.contextTargets)?.length??0)>1&&n===`error-on-partial`)throw E({code:`WORKSPACE_CONTEXT_SAVE_FAILED`,message:`The workspace selection could not be saved for every configuration file.`,details:r instanceof Error?r.message:String(r),suggestion:`Fix project state permissions, then rerun deploy with the workspace ID.`,next:executableAction([...deployArgs(t),...Se({workspaceId:e.workspaceId})]),context:{workspaceId:e.workspaceId,configPaths:t.contextTargets?.map(({configPath:e})=>e)}});C.warn(`Could not save the project workspace selection (${r instanceof Error?r.message:String(r)}). Continue with --workspace-id ${e.workspaceId} on later runs.`)}}async function useWorkspace(e,t,n,r,i=`error-on-partial`){return await rememberWorkspaceContext({version:1,platformUrl:t,workspaceId:n.id},r,i),C.info(`Using workspace: ${workspaceLabel(n)}`),{client:e,workspaceId:n.id}}function useRememberedWorkspace(e,t){return C.warn(`Using saved workspace selection: ${workspaceLabel(t)}`),{client:e,workspaceId:t.id}}const Nc=`create-new-workspace`;async function chooseWorkspace(e,t,n,r){let i=await X.select({message:`Select a workspace`,choices:[...n.map(e=>({name:workspaceLabel(e),value:e.id})),{name:`Create new workspace`,value:Nc}]});if(i===Nc)return createWorkspaceForDeploy(e,t,r,!0);let a=n.find(({id:e})=>e===i);if(!a)throw b(`Selected workspace was not found`);return useWorkspace(e,t,a,r)}function invalidCreateOptionsError(e,t,n,r){return E({code:`WORKSPACE_CREATE_OPTIONS_INVALID`,message:`Workspace creation options are invalid.`,details:r,suggestion:`Correct the workspace creation options and rerun deploy.`,next:executableAction(createDeployArgs(e,t,n))})}async function promptOrganization(e){let{userOrganizations:t}=await e.listUserOrganizations({});if(t.length===0)throw E({code:`WORKSPACE_ORGANIZATION_REQUIRED`,message:`A workspace must be created in an organization, and this user belongs to none.`,suggestion:`Ask an organization admin to add this user, then rerun deploy.`});return X.select({message:`Organization`,choices:t.map(({organizationId:e,organizationName:t})=>({name:`${t} (${e})`,value:e}))})}async function resolveCreationOrganization(e,t,n){return t.organizationId!==void 0||!n||t.dryRun?t:{...t,organizationId:await promptOrganization(e)}}async function createWorkspace(e,t,n,r,i,a){let o=await resolveCreationOrganization(e,n,r),s=o.workspaceName,c=o.workspaceRegion;if(r)s??=await X.text({message:`Workspace name`,default:suggestedWorkspaceName(),validate:validateWorkspaceName}),c??=await X.select({message:`Workspace region`,choices:i.map(e=>({name:e,value:e}))});else{let e=[...s===void 0?[`--workspace-name`]:[],...c===void 0?[`--workspace-region`]:[]];if(e.length>0)throw E({code:`WORKSPACE_CREATE_OPTIONS_REQUIRED`,message:`Workspace creation requires a name and region in non-interactive mode.`,suggestion:`Provide every workspace creation option and rerun deploy.`,next:executableAction(createDeployArgs(o,s??`<name>`,c??`<region>`)),context:{missingOptions:e}})}if(!s||!c)throw b(`Workspace creation options were not resolved`);let l=a;if(!l){try{l=validateCreateWorkspaceOptions({name:s,region:c,organizationId:o.organizationId,folderId:o.folderId})}catch(e){throw invalidCreateOptionsError(o,s,c,e instanceof Error?e.message:String(e))}if(!i.includes(c))throw invalidCreateOptionsError(o,s,c,`Region must be one of: ${i.join(`, `)}.`)}if(o.userDefaults&&announceUserDefaults(o.userDefaults),r){let e=[o.organizationId?`organization: ${o.organizationId}`:void 0,o.folderId?`folder: ${o.folderId}`:void 0].filter(e=>e!==void 0);if(!await X.confirm({message:`Create workspace "${s}" in ${c}${e.length>0?` (${e.join(`, `)})`:``}?`,default:!0}))throw E({code:`WORKSPACE_CREATION_CANCELLED`,message:`Workspace creation was cancelled.`})}let u;try{u=await createValidatedWorkspaceWithClient(e,l)}catch(e){throw e instanceof q&&![K.Canceled,K.Unknown,K.DeadlineExceeded,K.Aborted,K.Internal,K.Unavailable,K.DataLoss].includes(e.code)?(o.userDefaults&&pointAtUserDefaults(e,o.userDefaults),e):E({code:`WORKSPACE_CREATION_FAILED`,message:`Workspace creation did not complete successfully.`,details:e instanceof Error?e.message:String(e),suggestion:`The outcome may be uncertain. List workspaces before retrying creation to avoid duplicates.`,next:executableAction([`workspace`,`list`,...workspaceCommandArgs(o),`--json`])})}return await rememberWorkspaceContext({version:1,platformUrl:t,workspaceId:u.id},o),C.success(`Created workspace: ${workspaceLabel(u)}`),C.info(`Reuse this workspace by running ${w({command:`tailor`,args:[`deploy`,...Se({workspaceId:u.id,profile:o.profile})]})}`),C.info(`Or set TAILOR_PLATFORM_WORKSPACE_ID=${u.id}.`),{client:e,workspaceId:u.id}}async function createWorkspaceForDeploy(e,t,n,r,i,a){let o=i??(await e.listAvailableWorkspaceRegions({})).regions;if(n.dryRun)throw E({code:`WORKSPACE_CREATION_DISABLED_IN_DRY_RUN`,message:`Dry-run cannot create the workspace required to build a deployment plan.`,suggestion:`Create a workspace explicitly, then rerun the same dry-run with its workspace ID.`,context:{availableRegions:o}});return createWorkspace(e,t,n,r,o,a)}async function resolveDeployWorkspace(e={}){let t=e,n=[t.workspaceName===void 0?void 0:`--workspace-name`,t.workspaceRegion===void 0?void 0:`--workspace-region`].filter(e=>e!==void 0);if(!t.createWorkspace&&n.length>0)throw E({code:`WORKSPACE_CREATE_FLAG_REQUIRED`,message:`Workspace creation options require --create-workspace.`,suggestion:`Add --create-workspace or remove the workspace creation options.`,next:executableAction(createDeployArgs(t,t.workspaceName??`<name>`,t.workspaceRegion??`<region>`)),context:{options:n}});if(t.createWorkspace&&t.workspaceName!==void 0){let e=validateWorkspaceName(t.workspaceName);if(e!==!0)throw invalidCreateOptionsError(t,t.workspaceName,t.workspaceRegion??`<region>`,e)}if(t.createWorkspace&&t.workspaceRegion===``)throw invalidCreateOptionsError(t,t.workspaceName??`<name>`,t.workspaceRegion,`Region must not be empty.`);let r=await ne({workspaceId:t.workspaceId,profile:t.profile}),i=await A({profile:t.profile}),a=await De({profile:t.profile,allowMissingProfile:r!==void 0}),o=Ct(a),s=await N(i,a);if(r){let workspaceNotFoundError=()=>{let e=[`workspace`,`list`,...workspaceCommandArgs(t)];return E({code:`WORKSPACE_NOT_FOUND`,message:`Workspace "${r}" was not found.`,suggestion:`Check the workspace ID; run ${w({command:`tailor`,args:e})} to see the workspaces you can access.`,next:executableAction([...e,`--json`])})},e;try{e=await s.getWorkspace({workspaceId:r})}catch(e){throw e instanceof q&&e.code===K.NotFound?workspaceNotFoundError():e}if(!e.workspace)throw workspaceNotFoundError();return useWorkspace(s,o,workspaceInfo(e.workspace),t,`warn`)}let c=await resolveWorkspaceCreationLocation(t);t={...t,organizationId:c.organizationId,folderId:c.folderId,userDefaults:c.defaults,locationResolved:!0};let l=canPrompt();t.createWorkspace&&(t=await resolveCreationOrganization(s,t,l));let u;if(t.createWorkspace&&t.workspaceName!==void 0&&t.workspaceRegion!==void 0)try{u=validateCreateWorkspaceOptions({name:t.workspaceName,region:t.workspaceRegion,organizationId:t.organizationId,folderId:t.folderId})}catch(e){throw invalidCreateOptionsError(t,t.workspaceName,t.workspaceRegion,e instanceof Error?e.message:String(e))}let[d,f]=await Promise.all([loadProjectContexts(o,t.contextTargets),listWorkspacesWithClient(s)]),p=new Set(d.map(({workspaceId:e})=>e)),m=p.size===1?f.find(({id:e})=>p.has(e)):void 0;if(m&&(!t.createWorkspace||workspaceMatchesRequestedIdentity(m,t))){let e=projectContextTargets(t.contextTargets)?.length??1;return d.length===e?useRememberedWorkspace(s,m):useWorkspace(s,o,m,t)}let h=f.length===1?f[0]:void 0,g=h!==void 0&&u!==void 0&&workspaceMatchesRequestedIdentity(h,t),_;if(u&&!g&&(_=await s.listAvailableWorkspaceRegions({}),!_.regions.includes(u.region)))throw invalidCreateOptionsError(t,u.name,u.region,`Region must be one of: ${_.regions.join(`, `)}.`);if(f.length===0&&(l||t.createWorkspace||d.length===0)){let e=_?.regions??(await s.listAvailableWorkspaceRegions({})).regions;if(t.dryRun||l||t.createWorkspace)return createWorkspaceForDeploy(s,o,t,l,e,u);let n=userDefaultsDiagnostics(t,`Create one during deploy by providing the workspace name and one of the available regions.`);throw E({code:`WORKSPACE_NOT_FOUND`,message:`No workspaces are available for this account.`,suggestion:n.suggestion,next:executableAction(createDeployArgs(t,`<name>`,`<region>`)),context:{availableRegions:e,...n.context}})}if(p.size>1){let e=t.createWorkspace===!0&&t.workspaceName!==void 0&&t.workspaceRegion!==void 0&&f.length===0;if(!l&&!e)throw E({code:`WORKSPACE_CONTEXT_CONFLICT`,message:`The deployed configuration files are linked to different workspaces.`,suggestion:`Choose one workspace explicitly for the combined deployment.`,next:executableAction(selectDeployArgs(t)),context:{savedWorkspaceIds:[...p]}});if(f.length>0&&!t.createWorkspace)return chooseWorkspace(s,o,f,t)}if(!m&&d.length>0){let e=t.createWorkspace===!0&&t.workspaceName!==void 0&&t.workspaceRegion!==void 0&&f.length<=1;if(!l&&!e)throw E({code:`WORKSPACE_CONTEXT_STALE`,message:`The saved project workspace is no longer available.`,suggestion:`Choose an available workspace explicitly before deploying.`,next:executableAction(selectDeployArgs(t)),context:{savedWorkspaceIds:[...p],workspaces:f.map(workspaceIdentity)}});if(f.length>0&&l&&!t.createWorkspace)return chooseWorkspace(s,o,f,t)}if(f.length===1){let[e]=f;if(!e)throw b(`Workspace discovery returned an invalid result`);if(t.createWorkspace&&!workspaceMatchesRequestedIdentity(e,t)){let n=userDefaultsDiagnostics(t,`Use the existing workspace, or run the explicit workspace create command to create another one.`);throw E({code:`WORKSPACE_CREATE_CONFLICT`,message:`The existing workspace does not match the requested workspace.`,suggestion:n.suggestion,next:executableAction([`workspace`,`create`,...workspaceCommandArgs(t),...t.workspaceCommandJson?[`--json`]:[],`--name`,t.workspaceName??`<name>`,`--region`,t.workspaceRegion??`<region>`,...organizationArgs(t),...t.folderId?[`--folder-id`,t.folderId]:[]]),context:{existingWorkspace:workspaceIdentity(e),...n.context}})}return l&&!t.createWorkspace?chooseWorkspace(s,o,f,t):useWorkspace(s,o,e,t)}if(f.length>1){if(!l)throw E({code:`WORKSPACE_SELECTION_REQUIRED`,message:`Multiple workspaces are available.`,suggestion:`Choose one explicitly for non-interactive deployment.`,next:executableAction(selectDeployArgs(t)),context:{workspaces:f.map(workspaceIdentity)}});return chooseWorkspace(s,o,f,t)}throw b(`Workspace discovery returned an invalid result`)}const Pc=/* @__PURE__ */ new Set([`tailorDB`,`secretManager`,`aiGateway`,`staticWebsite`,`workflowExecutionPolicy`,`idp`,`auth`]);function collectExpectedLocalStaticWebsiteNames(e){let t=/* @__PURE__ */ new Set;for(let n of e)for(let e of n.application.staticWebsiteServices)t.add(e.name);return t}function collectExpectedLocalStaticWebsiteNamesFromConfigs(e){let t=/* @__PURE__ */ new Set;for(let{config:n}of e)for(let e of n.staticWebsites??[])t.add(e.name);return t}async function shouldForceApplyAll(e,t,n,r){let i=(await buildMetaRequest({trn:resourceTrn(t,`application`,n.name),appName:n.name,appId:n.id})).labels,a=/* @__PURE__ */ new Set;n.subgraphs.length>0&&a.add(resourceTrn(t,`application`,n.name)),n.staticWebsiteServices.forEach(e=>{a.add(resourceTrn(t,`staticwebsite`,e.name))}),n.aiGatewayServices.forEach(e=>{a.add(resourceTrn(t,`aigateway`,e.name))}),n.resolverServices.forEach(e=>{a.add(resourceTrn(t,`pipeline`,e.namespace))}),n.idpServices.forEach(e=>{a.add(resourceTrn(t,`idp`,e.name))}),n.authService&&a.add(resourceTrn(t,`auth`,n.authService.config.name)),Object.values(n.executorService?.executors??{}).forEach(e=>{a.add(resourceTrn(t,`executor`,e.name))}),Object.values(n.workflowService?.workflows??{}).forEach(e=>{a.add(resourceTrn(t,`workflow`,e.name))}),n.tailorDBServices.forEach(e=>{a.add(resourceTrn(t,`tailordb`,e.namespace))}),n.secrets.forEach(e=>{a.add(resourceTrn(t,`vault`,e.vaultName))}),r.forEach(e=>{a.add(resourceTrn(t,`function_registry`,e.name))});let o=await Promise.allSettled([...a].map(t=>P(async()=>{let{metadata:n}=await e.getMetadata({trn:t});return n})));if(o.some(e=>e.status===`fulfilled`&&e.value?.labels[`sdk-name`]===n.name&&!hasMatchingSdkVersion(e.value.labels,i)))return!0;let s=o.find(e=>e.status===`rejected`);if(s)throw s.reason;return!1}function recoveryEnvironmentArgs(e,t){return[...(t?.envFiles??[]).flatMap(e=>[`--env-file`,H.resolve(process.cwd(),e)]),...(t?.envFilesIfExists??[]).flatMap(e=>[`--env-file-if-exists`,H.resolve(process.cwd(),e)]),...Se({profile:e?.profile})]}function recoveryOutputArgs(e){return[...e?.verbose?[`--verbose`]:[],...e?.json||C.jsonMode?[`--json`]:[]]}function migrationSkipStepsArgs(e){let t=formatMigrationSkipSteps(e?.migrationSkipSteps);return t===void 0?[]:[`--migration-skip-steps`,t]}function retryDeployArgs(e,t,n){return[`deploy`,`--config`,t.join(`,`),...recoveryEnvironmentArgs(e,n),...e?.dryRun?[`--dry-run`]:[],...e?.yes?[`--yes`]:[],...e?.noSchemaCheck?[`--no-schema-check`]:[],...migrationSkipStepsArgs(e),...e?.noValidate?[`--no-validate`]:[],...e?.noCache?[`--no-cache`]:[],...e?.cleanCache?[`--clean-cache`]:[],...recoveryOutputArgs(n)]}function workspaceRecoveryArgs(e,t){return[...recoveryEnvironmentArgs(e,t),...t?.verbose?[`--verbose`]:[]]}function collectPlannedExternalTailorDBServices(e,t){let n=new Set(e.application.externalTailorDBNamespaces);return n.size===0?[]:t.flatMap(e=>e.application.tailorDBServices.filter(e=>n.has(e.namespace)))}function collectExternalAuthIdpConfigNames(e){let t=/* @__PURE__ */ new Map;for(let n of e){let e=n.application.authService;if(!e)continue;let{name:r}=e.config,i=e.config.idProvider?.name;if(t.has(r)&&t.get(r)!==i)throw E({code:`AUTH_NAMESPACE_CONFLICT`,message:`Auth namespace "${r}" is defined by multiple config files with different IdP configs. Auth namespace names must be unique across all configs in a single deploy.`});t.set(r,i)}return t}function collectDeployRunPlanInputs(e,t){let n=collectEventSubscriptions(e);return assertRecordableDependencies(n,t),{eventSubscriptions:n,runAppIds:new Set(e.map(e=>e.application.id).filter(e=>e!==void 0)),expectedLocalStaticWebsiteNames:collectExpectedLocalStaticWebsiteNames(e),externalAuthIdpConfigNames:collectExternalAuthIdpConfigNames(e)}}async function planDeploymentTarget(e){let{target:t,targets:n,runInputs:r,client:i,workspaceId:a,noSchemaCheck:o,migrationSkipSteps:s,migrationRecoveryArgs:c,migrationTestBaselines:l,migrationTestSnapshots:u,migrationMachineUserOverride:d,skip:f,previous:p}=e,{config:m,application:h,workflowBuildResult:g,httpAdapterBuildResult:_,bundledScripts:v}=t,y=ownedSubscriptions(r.eventSubscriptions,t),b=h.tailorDBServices.map(e=>{let t=u?.get(e.namespace);return t?{...e,types:t.tables,typeSourceInfo:{}}:e});f?.has(`tailorDB`)&&p||await B(`plan.validateTailorDBTypeNames`,()=>Ue({client:i,workspaceId:a,tailorDBServices:b,externalTailorDBNamespaces:h.externalTailorDBNamespaces,plannedExternalTailorDBServices:collectPlannedExternalTailorDBServices(t,n)}));let x=h.workflowService,S=collectFunctionEntries(h,filterBundledWorkflowJobs(x?.jobs??[],g?.usedJobNames??[]),v),C=p?p.forceApplyAll:await B(`plan.detectSdkVersionChange`,()=>shouldForceApplyAll(i,a,h,S));return B(`plan`,async()=>{let e=n.map(e=>e.application),v=collectVisibleTailorDBTypeNamespaces(h,e),b=collectVisibleResolverNamespaces(h,e),w=collectVisibleIdpNames(h,e),T={client:i,workspaceId:a,application:h,forRemoval:!1,config:m,noSchemaCheck:o,migrationSkipSteps:s,migrationRecoveryArgs:c,migrationTestBaselines:l,migrationTestSnapshots:u,migrationMachineUserOverride:d,forceApplyAll:C,...r,idpUserTriggerTargets:subscribedIdps(y),executorUsedTailorDBTables:subscribedTailorDBTables(y),executorUsedResolvers:subscribedResolvers(y),dependentApps:collectDependentApps(y),tailorDBTypeNamespaces:v,resolverNamespaces:b,idpNames:w},E=await B(`plan.functionRegistry`,()=>planFunctionRegistry(i,a,h.name,h.id,S,p?.functionRegistry.existingMap)),D=collectWorkflowJobStates(E.changeSet),[O,ee,te,ne,k,re,ie,ae,oe,se,ce]=await Promise.all([f?.has(`tailorDB`)&&p?p.tailorDB:B(`plan.tailorDB`,()=>planTailorDB(T)),f?.has(`staticWebsite`)&&p?p.staticWebsite:B(`plan.staticWebsite`,()=>planStaticWebsite(T)),f?.has(`aiGateway`)&&p?p.aiGateway:B(`plan.aiGateway`,()=>planAIGateway(T)),f?.has(`idp`)&&p?p.idp:B(`plan.idp`,()=>planIdP(T)),f?.has(`auth`)&&p?p.auth:B(`plan.auth`,()=>planAuth(T)),B(`plan.pipeline`,()=>planPipeline(T,p&&{existingServices:p.pipeline.existingServices,existingResolvers:p.pipeline.existingResolvers})),B(`plan.application`,()=>planApplication(T,_,p&&{existingApplications:p.app.existingApplications,existingLabels:p.app.existingLabels})),B(`plan.executor`,()=>planExecutor(T,p?.executor.existingExecutors)),B(`plan.workflow`,()=>planWorkflow(i,a,h.name,h.id,x?.workflows??{},g?.mainJobDeps??{},D.unchanged,{...subscribedWorkflows(y),jobPublishEvents:collectWorkflowJobPublishEvents(t),dependentApps:T.dependentApps,runAppIds:T.runAppIds},p&&{existingJobFunctions:p.workflow.existingJobFunctions,existingWorkflows:p.workflow.existingWorkflows},D.forcedBySdkVersion)),f?.has(`workflowExecutionPolicy`)&&p?p.workflowExecutionPolicy:B(`plan.workflowExecutionPolicy`,()=>planWorkflowJobFunctionExecutionPolicy(i,a,h.name,h.id,m.workflow?.executionPolicies??{})),f?.has(`secretManager`)&&p?p.secretManager:B(`plan.secretManager`,()=>planSecretManager(T))]);return{application:h,forceApplyAll:C,functionRegistry:E,tailorDB:O,staticWebsite:ee,aiGateway:te,idp:ne,auth:k,pipeline:re,app:ie,executor:ae,workflow:oe,workflowExecutionPolicy:se,secretManager:ce}})}async function planDeploymentTargets(e){let{targets:t,planTarget:n=planDeploymentTarget,previousDeployments:r,...i}=e,a=new Map(r?.map(e=>[e.application.name,e]));return Promise.all(t.map(e=>n({...i,target:e,targets:t,previous:a.get(e.application.name)})))}function confirmationKey(e,t){return JSON.stringify([e.application.name,t])}function collectConfirmations(e,t=/* @__PURE__ */ new Set){let n=deploymentPlanResults(e),isNew=n=>!t.has(confirmationKey(e,n));return{checkpointRepairs:e.tailorDB.context.checkpointRepairs.filter(isNew),conflicts:collectOwnerConflicts(n).filter(isNew),unmanaged:collectUnmanagedResources(n).filter(isNew),importantDeletions:collectImportantResourceDeletions(n).filter(isNew)}}async function confirmDeploymentPlans(e){let{deployments:t,yes:n,dryRun:r=!1,missingDependentApps:i=[],confirmedDeployments:a=[]}=e,o=r?`dry-run`:n?`yes`:`prompt`,s=new Set(a.flatMap(e=>Object.values(collectConfirmations(e)).flat().map(t=>confirmationKey(e,t)))),c=t.map(e=>({deployment:e,...collectConfirmations(e,s)}));await confirmMigrationCheckpointRepairs(c.flatMap(e=>e.checkpointRepairs),o),await confirmMissingDependentApps(i,o);for(let{deployment:e,conflicts:t,unmanaged:n}of c)await confirmOwnerConflict(t,e.application.name,o,e.application.id),await confirmUnmanagedResources(n,e.application.name,o);await confirmImportantResourceDeletion(c.flatMap(e=>e.importantDeletions),o)}async function validateDeploymentPlans(e){for(let t of e)await validatePlan(deploymentPlanResults(t))}async function reviewDeploymentPlans(e){let{deployments:t,dryRun:n,noValidate:r,pendingDeployedHooks:i,missingDependentApps:a}=e;scheduleRenamedAppDeletes(t),r?C.warn(`Client-side validation skipped (--no-validate).`):await validateDeploymentPlans(t);let o=printDeploymentPlans(t,{dryRun:n,pendingDeployedHooks:i,missingDependentApps:a});return await B(`confirm`,()=>confirmDeploymentPlans(e)),o}function needsEnvRebuild(e,t){return e.some(e=>Object.values(e.application.env).some(e=>It(e)&&t.has(Tt(e))))}function assertEnvResolvedAfterRebuild(e,t){if(needsEnvRebuild(e,t))throw E({code:`STATIC_WEBSITE_URL_NOT_RESOLVED`,message:`A static website referenced by env still has no URL after rebuilding to pick up this deploy's own config changes.`,suggestion:`Re-run the deploy; the static website's URL may not be assigned yet.`})}function adjustApplicationForMigrationTest(e,t){if(!t?.migrationTestSnapshots)return e;let n=t.migrationTestBaselines!==void 0,r=n&&e.authService?{...e.authService,userProfile:void 0}:e.authService,i={...e,executorService:n?void 0:e.executorService,authService:r,staticWebsiteServices:e.staticWebsiteServices.map(e=>({...e,customDomains:void 0})),get applications(){return[i]}};return i}async function deployInternal(t,n,r){return B(`deploy`,async i=>{i.setAttribute(`deploy.dry_run`,t?.dryRun??!1),St(),e();let a=parseDeployConfigPaths(t?.configPath),o=t?.dryRun??!1,s=t?.buildOnly??p(process.env.TAILOR_DEPLOY_BUILD_ONLY)===!0,c=s?[]:await B(`config.preflight`,()=>loadDeployConfigs({configPaths:a,dryRun:o,buildOnly:s})),l=c.map(({config:e})=>e.path),u=c.map(({config:e})=>({configPath:e.path,applicationId:e.id??`name:${e.name}`})),d=s?void 0:await resolveDeployWorkspace({workspaceId:t?.workspaceId,profile:t?.profile,createWorkspace:t?.createWorkspace,workspaceName:t?.workspaceName,workspaceRegion:t?.workspaceRegion,organizationId:t?.organizationId,folderId:t?.folderId,dryRun:o,contextTargets:u,deployArgs:retryDeployArgs(t,l,n),workspaceCommandArgs:workspaceRecoveryArgs(t,n),workspaceCommandJson:n?.json||C.jsonMode}),f=collectExpectedLocalStaticWebsiteNamesFromConfigs(c),m=t?.noCache??!1,h=H.resolve(Ze(),`cache`);t?.cleanCache&&(W.rmSync(h,{recursive:!0,force:!0}),C.info(`Bundle cache cleaned`));let build=e=>B(`build`,async()=>{let t=await Rt();return buildDeploymentTargets({configPaths:a,loadedConfigs:s?void 0:c,dryRun:o,buildOnly:s,noCache:m,packageVersion:t.version??`unknown`,cacheDir:h,client:d?.client,workspaceId:d?.workspaceId,expectedLocalStaticWebsiteNames:f,previousTargets:e})}),g=await build();if(s)return{bundledScripts:mergeBundledScripts(g),httpAdapterScripts:collectHttpAdapterScripts(g)};if(assertUniqueGlobalResourceNames(g),!d)throw b(`Workspace was not resolved`);let{client:_,workspaceId:v}=d;i.setAttribute(`app.name`,g.map(e=>e.application.name).join(`,`)),i.setAttribute(`workspace.id`,v);let y,plan=async(e,i)=>{let a=e.map(e=>({...e,application:adjustApplicationForMigrationTest(e.application,r)})),o=i&&y?y:await B(`plan.metadataLookup`,()=>createMetadataLookupClient({client:_,workspaceId:v,applications:a.map(({application:e})=>e)}));y=o;let s=collectDeployRunPlanInputs(a,!t?.dryRun),c=await planDeploymentTargets({targets:a,runInputs:s,client:o,workspaceId:v,noSchemaCheck:t?.noSchemaCheck,migrationSkipSteps:t?.migrationSkipSteps,migrationRecoveryArgs:recoveryEnvironmentArgs(t,n),migrationTestBaselines:r?.migrationTestBaselines,migrationTestSnapshots:r?.migrationTestSnapshots,migrationMachineUserOverride:r?.migrationMachineUserOverride,skip:i?.skip,previousDeployments:i?.previousDeployments});return dropCrossDeploymentManagedDeletes(c),assertNoSingleRunTransferHandoff(c),{planTargets:a,metadataClient:o,runInputs:s,deployments:c}},{planTargets:x,metadataClient:S,runInputs:w,deployments:T}=await plan(g);assertSkipNamespacesKnown(t?.migrationSkipSteps??/* @__PURE__ */ new Map,new Set(T.flatMap(e=>e.tailorDB.context.tailorDBInputs.map(e=>e.namespace))));let D=(await Promise.all(x.map(e=>fetchMissingDependentApps({client:S,workspaceId:v,application:e.application,runAppIds:w.runAppIds??/* @__PURE__ */ new Set,subscribedKeys:subscribedResourceKeys(w.eventSubscriptions,e),jobsByWorkflow:e.workflowBuildResult?.mainJobDeps??{}})))).flat(),O=needsEnvRebuild(T,f),ee=r?.skipDeployedHooks?[]:g.flatMap(e=>e.plugins.filter(e=>e.onDeployed).map(t=>({application:e.application.name,pluginId:t.id}))),te={yes:t?.yes??!1,noValidate:t?.noValidate},ne=await reviewDeploymentPlans({...te,deployments:T,dryRun:o,missingDependentApps:D,pendingDeployedHooks:ee});if(o){for(let{application:e,pluginId:t}of ee)C.info(`Hook to run after apply: "${t}" (app "${e}")`);C.info(`Dry run enabled. No changes applied.`);return}await preflightAllTailorDB(_,T),await applyPrerequisiteResources(_,T);let k;if(O){C.info(`A static website was just created; rebuilding so env resolves to its real URL before the rest of this deploy applies.`);let e=await build(g);assertUniqueGlobalResourceNames(e);let t=await plan(e,{skip:Pc,previousDeployments:T});assertEnvResolvedAfterRebuild(t.deployments,f),ne=await reviewDeploymentPlans({...te,deployments:t.deployments,confirmedDeployments:T}),k=await applyRemainingResources(_,v,t.deployments)}else k=await applyRemainingResources(_,v,T);let re=C.jsonMode&&!r?.suppressResultOutput?await loadDeployedApplications({client:_,workspaceId:v,targets:g}).catch(e=>{throw ee.length?deployedHookLoadFailure(e,ee.map(({application:e,pluginId:t})=>`${t} (app: ${e})`)):E({code:`DEPLOY_RESULT_LOAD_FAILED`,message:`Platform resources were applied successfully, but loading the deployed application information failed.`,details:e instanceof Error?e.message:String(e),suggestion:`Fix the error and run tailor deploy again. Unchanged resources are not re-applied.`,cause:e})}):void 0,ie=r?.skipDeployedHooks?[]:await runDeployedHooks({client:_,workspaceId:v,targets:g,applications:re});r?.suppressResultOutput||(C.jsonMode?C.out({summary:ne,status:`applied`,workspaceId:v,applications:re,...k.length?{tailordbMaintenance:k}:{},...ie.length?{deployedHooks:ie}:{}}):C.success(`Successfully applied changes.`))})}function deploy(e){return deployInternal(e)}function deployMigrationTestBaseline(e,t,n){return deployInternal(e,void 0,{migrationTestBaselines:t,migrationTestSnapshots:n,suppressResultOutput:!0,skipDeployedHooks:!0})}function deployMigrationTestTarget(e,t,n){return deployInternal(e,void 0,{migrationTestSnapshots:t,migrationMachineUserOverride:n,suppressResultOutput:!0,skipDeployedHooks:!0})}function deployFromCLI(e,t){return deployInternal(e,t)}function generateSeedScriptContent(e){return M`
|
|
192
|
+
`,args:U.strictObject({name:V(Cc,{alias:`n`,description:`Workspace name`}),region:V(U.string(),{alias:`r`,description:`Workspace region (${Mc.join(`, `)})`}),"delete-protection":V(U.boolean().default(!1),{alias:`d`,description:`Enable delete protection`}),"organization-id":V(U.string().optional(),{alias:`o`,description:`Organization ID to workspace associate with`,env:`TAILOR_PLATFORM_ORGANIZATION_ID`}),"folder-id":V(U.string().optional(),{alias:`f`,description:`Folder ID to workspace associate with`,env:`TAILOR_PLATFORM_FOLDER_ID`}),ttl:V(kc.optional(),{description:`Record on the workspace itself when it becomes prunable, such as 30m, 24h, or 7d (${Oc}). \`workspace prune --expired\` deletes it once that has passed`}),"profile-name":V(U.string().optional(),{alias:`p`,description:`Profile name to create`}),profile:V(xc.optional(),{description:`Workspace profile used for authentication and Platform selection`,env:`TAILOR_PLATFORM_PROFILE`}),"profile-user":V(U.string().optional(),{description:`User email address or machine user client ID for the profile (defaults to current user)`}),permission:V(U.enum([`write`,`read`]).default(`write`),{description:`Profile permission (requires --profile-name). 'read' blocks all write commands while the profile is active.`})}),run:async e=>{await assertWritable({profile:e.profile});let t=e[`profile-name`],n;if(t){let r=await Oe();if(r.profiles[t])throw E({code:`PROFILE_EXISTS`,message:`Profile "${t}" already exists.`});let i=e.profile,a=i?r.profiles[i]:void 0,o=a?ye(a):void 0,s=e[`profile-user`]||a?.user||r.current_user;if(!s)throw E({code:`USER_NOT_SET`,message:`Current user not found.`,suggestion:`Log in or specify --profile-user to create a profile.`,command:`workspace create`});let c=ke(r,s,o);if(!c)throw E({code:`USER_NOT_FOUND`,message:`User "${s}" not found.`,suggestion:`Verify the user name and log in.`,next:{command:`tailor`,args:[`login`,...Se({profile:i})]}});n={name:t,user:c,platformSettings:profilePlatformSettings(o)}}let{client:r,validated:i,defaults:a}=await prepareWorkspaceCreation({name:e.name,region:e.region,deleteProtection:e[`delete-protection`],...fe(e),ttl:e.ttl,profile:e.profile}),o;try{a&&!e.json&&announceUserDefaults(a),o=await createValidatedWorkspaceWithClient(r,i)}catch(e){throw a&&pointAtUserDefaults(e,a),e}let s;if(n){let t=await Oe(),r=n.platformSettings;t.profiles[n.name]={user:n.user,workspace_id:o.id,...e.permission===`read`?{readonly:!0}:{},...r},ce(t),s={name:n.name,user:n.user,workspaceId:o.id,permission:e.permission,...r.platform_url?{platformUrl:r.platform_url}:{},...r.oauth2_client_id?{oauth2ClientId:r.oauth2_client_id}:{},...r.console_url?{consoleUrl:r.console_url}:{}},e.json||C.success(`Profile "${n.name}" created successfully.`)}let{ttl:c,...l}=o;if(e.json||(C.success(`Workspace "${workspaceDisplayName(o)}" created successfully.`),c?.state===`written`&&C.info(`Workspace becomes prunable at ${c.expiresAt.toISOString()}.`)),e.json?C.out({...l,...c?{ttl:ttlOutput(c)}:{},...s?{profile:s}:{}}):(C.out(l,{display:{name:Nc,folderName:null}}),s&&(C.out(`Profile:`),C.out(s))),c?.state===`unconfirmed`)throw E({code:`WORKSPACE_TTL_WRITE_FAILED`,message:`Workspace "${workspaceDisplayName(o)}" was created, but --ttl could not be confirmed: ${c.message}`,details:`The workspace exists. Whether it records the expiry is unknown — the write may have landed. Set the expiry again to be sure.`,context:{workspaceId:o.id,requestedExpiresAt:c.expiresAt.toISOString(),...s?{profileCreated:s.name}:{}},next:{command:`tailor`,args:[`workspace`,`ttl`,`set`,`--ttl`,c.requested,...Se({workspaceId:o.id,profile:e.profile})]}})}});async function listWorkspaces(e){let t=parseOptions(xc.optional(),e?.profile),n=await A({profile:t}),r=await De({profile:t});return listWorkspacesWithClient(await N(n,r),e)}async function listWorkspacesWithExpiry(e){let t=parseOptions(xc.optional(),e?.profile),n=await A({profile:t}),r=await De({profile:t}),i=await N(n,r),a=await fetchWithinLimit(e?.limit,t=>fetchWorkspaces(i,{...e,limit:t})),o=await workspaceInfosWithFolderNames(i,a.items),s=await fetchReportedExpiries(i,o.map(({id:e})=>e),/* @__PURE__ */ new Date);return{items:o.map((e,t)=>{let n=s[t];return{...e,expiresAt:n===void 0?`unavailable`:n}}),truncated:a.truncated}}async function listWorkspacesWithClient(e,t){return workspaceInfosWithFolderNames(e,await fetchWorkspaces(e,t))}async function fetchWorkspaces(e,t){let n=Ce(t?.order);return Pt(async(t,r)=>{let{workspaces:i,nextPageToken:a}=await e.listWorkspaces({pageToken:t,pageSize:r,pageDirection:n});return[i,a]},{limit:t?.limit})}const Ic=Y({name:`list`,description:`List all Tailor Platform workspaces.`,args:U.strictObject({...pe(),profile:V(xc.optional(),{description:`Workspace profile used for authentication and Platform selection`,env:`TAILOR_PLATFORM_PROFILE`})}),run:async e=>{let t=await listWorkspacesWithExpiry({order:e.order,limit:e.limit,profile:e.profile});C.out(t.items,{display:{name:Nc,folderName:null,organizationId:null,folderId:null,updatedAt:null}}),await reportTruncation(t,e.limit)}}),Lc=U.object({version:U.literal(1),platformUrl:U.url(),applicationId:U.string().min(1).optional(),workspaceId:U.uuid()});function defaultConfigPath(){return Kr(process.cwd(),`tailor.config.ts`)}function contextPath(e){return Wr(Hr(e),Qe(),`${Vr(e)}.context.json`)}async function loadWorkspaceContext(e,t=defaultConfigPath(),n){let r;try{r=await Ai(contextPath(t),`utf8`)}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return;throw e}let i;try{i=JSON.parse(r)}catch{return}let a=Lc.safeParse(i);if(!(!a.success||a.data.platformUrl!==e||n!==void 0&&a.data.applicationId!==n))return a.data}async function saveWorkspaceContext(e,t=defaultConfigPath(),n){let r=Lc.safeParse({...e,...n===void 0?{}:{applicationId:n}});if(!r.success)throw c(`workspace context`,r.error);let i=r.data,a=Wr(Hr(t),Qe()),o=contextPath(t),s=`${JSON.stringify(i,null,2)}\n`;try{if(await Ai(o,`utf8`)===s)return}catch{}let l=`${o}.${process.pid}.${_i()}.tmp`;await ki(a,{recursive:!0});try{await Pi(l,s,{mode:384}),await ji(l,o)}catch(e){throw await Mi(l,{force:!0}).catch(()=>void 0),e}}function suggestedWorkspaceName(){let e=Vr(process.cwd()).toLowerCase().replaceAll(/[^a-z0-9-]+/g,`-`).replaceAll(/^-+|-+$/g,``).slice(0,63).replace(/-+$/,``);return validateWorkspaceName(e)===!0?e:`my-workspace`}function executableAction(e){return{command:`tailor`,args:e}}function deployArgs(e){return e.deployArgs??[`deploy`]}function workspaceCommandArgs(e){return e.workspaceCommandArgs??[]}function organizationArgs(e){return e.organizationId===void 0?e.locationResolved?[`--organization-id`,`<organization-id>`]:[]:[`--organization-id`,e.organizationId]}function createDeployArgs(e,t,n){return[...deployArgs(e),`--create-workspace`,`--workspace-name`,t,`--workspace-region`,n,...organizationArgs(e),...e.folderId?[`--folder-id`,e.folderId]:[]]}function selectDeployArgs(e){return[...deployArgs(e),`--workspace-id`,`<workspace-id>`]}function userDefaultsDiagnostics(e,t){let n=e.userDefaults;return n?{suggestion:`${t} ${userDefaultsTarget(n)}`,context:userDefaultsContext(n)}:{suggestion:t,context:{}}}function workspaceLabel(e){return`${workspaceDisplayName(e)} (${e.region}, org: ${e.organizationId}, id: ${e.id})`}function workspaceMatchesRequestedIdentity(e,t){return t.workspaceName===e.name&&t.workspaceRegion===e.region&&t.organizationId===e.organizationId&&t.folderId===e.folderId}function workspaceIdentity(e){let{id:t,name:n,region:r,organizationId:i,folderId:a}=e;return{id:t,name:n,region:r,organizationId:i,folderId:a}}function projectContextTargets(e){if(e)return[...new Map(e.map(e=>[e.configPath,e])).values()]}async function loadProjectContexts(e,t){let n=projectContextTargets(t);if(!n||n.length===0){let t=await loadWorkspaceContext(e);return t?[t]:[]}return(await Promise.all(n.map(({configPath:t,applicationId:n})=>loadWorkspaceContext(e,t,n)))).filter(e=>e!==void 0)}async function persistWorkspaceContext(e,t){let n=projectContextTargets(t);if(!n||n.length===0){await saveWorkspaceContext(e);return}let r=(await Promise.allSettled(n.map(({configPath:t,applicationId:n})=>saveWorkspaceContext(e,t,n)))).filter(e=>e.status===`rejected`);if(r.length>0)throw E({code:`WORKSPACE_CONTEXT_SAVE_FAILED`,message:r.map(({reason:e})=>e instanceof Error?e.message:String(e)).join(`; `)})}async function rememberWorkspaceContext(e,t,n=`error-on-partial`){if(!t.dryRun)try{await persistWorkspaceContext(e,t.contextTargets)}catch(r){if((projectContextTargets(t.contextTargets)?.length??0)>1&&n===`error-on-partial`)throw E({code:`WORKSPACE_CONTEXT_SAVE_FAILED`,message:`The workspace selection could not be saved for every configuration file.`,details:r instanceof Error?r.message:String(r),suggestion:`Fix project state permissions, then rerun deploy with the workspace ID.`,next:executableAction([...deployArgs(t),...Se({workspaceId:e.workspaceId})]),context:{workspaceId:e.workspaceId,configPaths:t.contextTargets?.map(({configPath:e})=>e)}});C.warn(`Could not save the project workspace selection (${r instanceof Error?r.message:String(r)}). Continue with --workspace-id ${e.workspaceId} on later runs.`)}}async function useWorkspace(e,t,n,r,i=`error-on-partial`){return await rememberWorkspaceContext({version:1,platformUrl:t,workspaceId:n.id},r,i),C.info(`Using workspace: ${workspaceLabel(n)}`),{client:e,workspaceId:n.id}}function useRememberedWorkspace(e,t){return C.warn(`Using saved workspace selection: ${workspaceLabel(t)}`),{client:e,workspaceId:t.id}}const Rc=`create-new-workspace`;async function chooseWorkspace(e,t,n,r){let i=await X.select({message:`Select a workspace`,choices:[...n.map(e=>({name:workspaceLabel(e),value:e.id})),{name:`Create new workspace`,value:Rc}]});if(i===Rc)return createWorkspaceForDeploy(e,t,r,!0);let a=n.find(({id:e})=>e===i);if(!a)throw b(`Selected workspace was not found`);return useWorkspace(e,t,a,r)}function invalidCreateOptionsError(e,t,n,r){return E({code:`WORKSPACE_CREATE_OPTIONS_INVALID`,message:`Workspace creation options are invalid.`,details:r,suggestion:`Correct the workspace creation options and rerun deploy.`,next:executableAction(createDeployArgs(e,t,n))})}async function promptOrganization(e){let{userOrganizations:t}=await e.listUserOrganizations({});if(t.length===0)throw E({code:`WORKSPACE_ORGANIZATION_REQUIRED`,message:`A workspace must be created in an organization, and this user belongs to none.`,suggestion:`Ask an organization admin to add this user, then rerun deploy.`});return X.select({message:`Organization`,choices:t.map(({organizationId:e,organizationName:t})=>({name:`${t} (${e})`,value:e}))})}async function resolveCreationOrganization(e,t,n){return t.organizationId!==void 0||!n||t.dryRun?t:{...t,organizationId:await promptOrganization(e)}}async function createWorkspace(e,t,n,r,i,a){let o=await resolveCreationOrganization(e,n,r),s=o.workspaceName,c=o.workspaceRegion;if(r)s??=await X.text({message:`Workspace name`,default:suggestedWorkspaceName(),validate:validateWorkspaceName}),c??=await X.select({message:`Workspace region`,choices:i.map(e=>({name:e,value:e}))});else{let e=[...s===void 0?[`--workspace-name`]:[],...c===void 0?[`--workspace-region`]:[]];if(e.length>0)throw E({code:`WORKSPACE_CREATE_OPTIONS_REQUIRED`,message:`Workspace creation requires a name and region in non-interactive mode.`,suggestion:`Provide every workspace creation option and rerun deploy.`,next:executableAction(createDeployArgs(o,s??`<name>`,c??`<region>`)),context:{missingOptions:e}})}if(!s||!c)throw b(`Workspace creation options were not resolved`);let l=a;if(!l){try{l=validateCreateWorkspaceOptions({name:s,region:c,organizationId:o.organizationId,folderId:o.folderId})}catch(e){throw invalidCreateOptionsError(o,s,c,e instanceof Error?e.message:String(e))}if(!i.includes(c))throw invalidCreateOptionsError(o,s,c,`Region must be one of: ${i.join(`, `)}.`)}if(o.userDefaults&&announceUserDefaults(o.userDefaults),r){let e=[o.organizationId?`organization: ${o.organizationId}`:void 0,o.folderId?`folder: ${o.folderId}`:void 0].filter(e=>e!==void 0);if(!await X.confirm({message:`Create workspace "${s}" in ${c}${e.length>0?` (${e.join(`, `)})`:``}?`,default:!0}))throw E({code:`WORKSPACE_CREATION_CANCELLED`,message:`Workspace creation was cancelled.`})}let u;try{u=await createValidatedWorkspaceWithClient(e,l)}catch(e){throw e instanceof q&&![K.Canceled,K.Unknown,K.DeadlineExceeded,K.Aborted,K.Internal,K.Unavailable,K.DataLoss].includes(e.code)?(o.userDefaults&&pointAtUserDefaults(e,o.userDefaults),e):E({code:`WORKSPACE_CREATION_FAILED`,message:`Workspace creation did not complete successfully.`,details:e instanceof Error?e.message:String(e),suggestion:`The outcome may be uncertain. List workspaces before retrying creation to avoid duplicates.`,next:executableAction([`workspace`,`list`,...workspaceCommandArgs(o),`--json`])})}return await rememberWorkspaceContext({version:1,platformUrl:t,workspaceId:u.id},o),C.success(`Created workspace: ${workspaceLabel(u)}`),C.info(`Reuse this workspace by running ${w({command:`tailor`,args:[`deploy`,...Se({workspaceId:u.id,profile:o.profile})]})}`),C.info(`Or set TAILOR_PLATFORM_WORKSPACE_ID=${u.id}.`),{client:e,workspaceId:u.id}}async function createWorkspaceForDeploy(e,t,n,r,i,a){let o=i??(await e.listAvailableWorkspaceRegions({})).regions;if(n.dryRun)throw E({code:`WORKSPACE_CREATION_DISABLED_IN_DRY_RUN`,message:`Dry-run cannot create the workspace required to build a deployment plan.`,suggestion:`Create a workspace explicitly, then rerun the same dry-run with its workspace ID.`,context:{availableRegions:o}});return createWorkspace(e,t,n,r,o,a)}async function resolveDeployWorkspace(e={}){let t=e,n=[t.workspaceName===void 0?void 0:`--workspace-name`,t.workspaceRegion===void 0?void 0:`--workspace-region`].filter(e=>e!==void 0);if(!t.createWorkspace&&n.length>0)throw E({code:`WORKSPACE_CREATE_FLAG_REQUIRED`,message:`Workspace creation options require --create-workspace.`,suggestion:`Add --create-workspace or remove the workspace creation options.`,next:executableAction(createDeployArgs(t,t.workspaceName??`<name>`,t.workspaceRegion??`<region>`)),context:{options:n}});if(t.createWorkspace&&t.workspaceName!==void 0){let e=validateWorkspaceName(t.workspaceName);if(e!==!0)throw invalidCreateOptionsError(t,t.workspaceName,t.workspaceRegion??`<region>`,e)}if(t.createWorkspace&&t.workspaceRegion===``)throw invalidCreateOptionsError(t,t.workspaceName??`<name>`,t.workspaceRegion,`Region must not be empty.`);let r=await re({workspaceId:t.workspaceId,profile:t.profile}),i=await A({profile:t.profile}),a=await De({profile:t.profile,allowMissingProfile:r!==void 0}),o=Et(a),s=await N(i,a);if(r){let workspaceNotFoundError=()=>{let e=[`workspace`,`list`,...workspaceCommandArgs(t)];return E({code:`WORKSPACE_NOT_FOUND`,message:`Workspace "${r}" was not found.`,suggestion:`Check the workspace ID; run ${w({command:`tailor`,args:e})} to see the workspaces you can access.`,next:executableAction([...e,`--json`])})},e;try{e=await s.getWorkspace({workspaceId:r})}catch(e){throw e instanceof q&&e.code===K.NotFound?workspaceNotFoundError():e}if(!e.workspace)throw workspaceNotFoundError();return useWorkspace(s,o,workspaceInfo(e.workspace),t,`warn`)}let c=await resolveWorkspaceCreationLocation(t);t={...t,organizationId:c.organizationId,folderId:c.folderId,userDefaults:c.defaults,locationResolved:!0};let l=canPrompt();t.createWorkspace&&(t=await resolveCreationOrganization(s,t,l));let u;if(t.createWorkspace&&t.workspaceName!==void 0&&t.workspaceRegion!==void 0)try{u=validateCreateWorkspaceOptions({name:t.workspaceName,region:t.workspaceRegion,organizationId:t.organizationId,folderId:t.folderId})}catch(e){throw invalidCreateOptionsError(t,t.workspaceName,t.workspaceRegion,e instanceof Error?e.message:String(e))}let[d,f]=await Promise.all([loadProjectContexts(o,t.contextTargets),listWorkspacesWithClient(s)]),p=new Set(d.map(({workspaceId:e})=>e)),m=p.size===1?f.find(({id:e})=>p.has(e)):void 0;if(m&&(!t.createWorkspace||workspaceMatchesRequestedIdentity(m,t))){let e=projectContextTargets(t.contextTargets)?.length??1;return d.length===e?useRememberedWorkspace(s,m):useWorkspace(s,o,m,t)}let h=f.length===1?f[0]:void 0,g=h!==void 0&&u!==void 0&&workspaceMatchesRequestedIdentity(h,t),_;if(u&&!g&&(_=await s.listAvailableWorkspaceRegions({}),!_.regions.includes(u.region)))throw invalidCreateOptionsError(t,u.name,u.region,`Region must be one of: ${_.regions.join(`, `)}.`);if(f.length===0&&(l||t.createWorkspace||d.length===0)){let e=_?.regions??(await s.listAvailableWorkspaceRegions({})).regions;if(t.dryRun||l||t.createWorkspace)return createWorkspaceForDeploy(s,o,t,l,e,u);let n=userDefaultsDiagnostics(t,`Create one during deploy by providing the workspace name and one of the available regions.`);throw E({code:`WORKSPACE_NOT_FOUND`,message:`No workspaces are available for this account.`,suggestion:n.suggestion,next:executableAction(createDeployArgs(t,`<name>`,`<region>`)),context:{availableRegions:e,...n.context}})}if(p.size>1){let e=t.createWorkspace===!0&&t.workspaceName!==void 0&&t.workspaceRegion!==void 0&&f.length===0;if(!l&&!e)throw E({code:`WORKSPACE_CONTEXT_CONFLICT`,message:`The deployed configuration files are linked to different workspaces.`,suggestion:`Choose one workspace explicitly for the combined deployment.`,next:executableAction(selectDeployArgs(t)),context:{savedWorkspaceIds:[...p]}});if(f.length>0&&!t.createWorkspace)return chooseWorkspace(s,o,f,t)}if(!m&&d.length>0){let e=t.createWorkspace===!0&&t.workspaceName!==void 0&&t.workspaceRegion!==void 0&&f.length<=1;if(!l&&!e)throw E({code:`WORKSPACE_CONTEXT_STALE`,message:`The saved project workspace is no longer available.`,suggestion:`Choose an available workspace explicitly before deploying.`,next:executableAction(selectDeployArgs(t)),context:{savedWorkspaceIds:[...p],workspaces:f.map(workspaceIdentity)}});if(f.length>0&&l&&!t.createWorkspace)return chooseWorkspace(s,o,f,t)}if(f.length===1){let[e]=f;if(!e)throw b(`Workspace discovery returned an invalid result`);if(t.createWorkspace&&!workspaceMatchesRequestedIdentity(e,t)){let n=userDefaultsDiagnostics(t,`Use the existing workspace, or run the explicit workspace create command to create another one.`);throw E({code:`WORKSPACE_CREATE_CONFLICT`,message:`The existing workspace does not match the requested workspace.`,suggestion:n.suggestion,next:executableAction([`workspace`,`create`,...workspaceCommandArgs(t),...t.workspaceCommandJson?[`--json`]:[],`--name`,t.workspaceName??`<name>`,`--region`,t.workspaceRegion??`<region>`,...organizationArgs(t),...t.folderId?[`--folder-id`,t.folderId]:[]]),context:{existingWorkspace:workspaceIdentity(e),...n.context}})}return l&&!t.createWorkspace?chooseWorkspace(s,o,f,t):useWorkspace(s,o,e,t)}if(f.length>1){if(!l)throw E({code:`WORKSPACE_SELECTION_REQUIRED`,message:`Multiple workspaces are available.`,suggestion:`Choose one explicitly for non-interactive deployment.`,next:executableAction(selectDeployArgs(t)),context:{workspaces:f.map(workspaceIdentity)}});return chooseWorkspace(s,o,f,t)}throw b(`Workspace discovery returned an invalid result`)}const zc=/* @__PURE__ */ new Set([`tailorDB`,`secretManager`,`aiGateway`,`staticWebsite`,`workflowExecutionPolicy`,`idp`,`auth`]);function collectExpectedLocalStaticWebsiteNames(e){let t=/* @__PURE__ */ new Set;for(let n of e)for(let e of n.application.staticWebsiteServices)t.add(e.name);return t}function collectExpectedLocalStaticWebsiteNamesFromConfigs(e){let t=/* @__PURE__ */ new Set;for(let{config:n}of e)for(let e of n.staticWebsites??[])t.add(e.name);return t}async function shouldForceApplyAll(e,t,n,r){let i=(await buildMetaRequest({trn:resourceTrn(t,`application`,n.name),appName:n.name,appId:n.id})).labels,a=/* @__PURE__ */ new Set;n.subgraphs.length>0&&a.add(resourceTrn(t,`application`,n.name)),n.staticWebsiteServices.forEach(e=>{a.add(resourceTrn(t,`staticwebsite`,e.name))}),n.aiGatewayServices.forEach(e=>{a.add(resourceTrn(t,`aigateway`,e.name))}),n.resolverServices.forEach(e=>{a.add(resourceTrn(t,`pipeline`,e.namespace))}),n.idpServices.forEach(e=>{a.add(resourceTrn(t,`idp`,e.name))}),n.authService&&a.add(resourceTrn(t,`auth`,n.authService.config.name)),Object.values(n.executorService?.executors??{}).forEach(e=>{a.add(resourceTrn(t,`executor`,e.name))}),Object.values(n.workflowService?.workflows??{}).forEach(e=>{a.add(resourceTrn(t,`workflow`,e.name))}),n.tailorDBServices.forEach(e=>{a.add(resourceTrn(t,`tailordb`,e.namespace))}),n.secrets.forEach(e=>{a.add(resourceTrn(t,`vault`,e.vaultName))}),r.forEach(e=>{a.add(resourceTrn(t,`function_registry`,e.name))});let o=await Promise.allSettled([...a].map(t=>P(async()=>{let{metadata:n}=await e.getMetadata({trn:t});return n})));if(o.some(e=>e.status===`fulfilled`&&e.value?.labels[`sdk-name`]===n.name&&!hasMatchingSdkVersion(e.value.labels,i)))return!0;let s=o.find(e=>e.status===`rejected`);if(s)throw s.reason;return!1}function recoveryEnvironmentArgs(e,t){return[...(t?.envFiles??[]).flatMap(e=>[`--env-file`,H.resolve(process.cwd(),e)]),...(t?.envFilesIfExists??[]).flatMap(e=>[`--env-file-if-exists`,H.resolve(process.cwd(),e)]),...Se({profile:e?.profile})]}function recoveryOutputArgs(e){return[...e?.verbose?[`--verbose`]:[],...e?.json||C.jsonMode?[`--json`]:[]]}function migrationSkipStepsArgs(e){let t=formatMigrationSkipSteps(e?.migrationSkipSteps);return t===void 0?[]:[`--migration-skip-steps`,t]}function retryDeployArgs(e,t,n){return[`deploy`,`--config`,t.join(`,`),...recoveryEnvironmentArgs(e,n),...e?.dryRun?[`--dry-run`]:[],...e?.yes?[`--yes`]:[],...e?.noSchemaCheck?[`--no-schema-check`]:[],...migrationSkipStepsArgs(e),...e?.noValidate?[`--no-validate`]:[],...e?.noCache?[`--no-cache`]:[],...e?.cleanCache?[`--clean-cache`]:[],...recoveryOutputArgs(n)]}function workspaceRecoveryArgs(e,t){return[...recoveryEnvironmentArgs(e,t),...t?.verbose?[`--verbose`]:[]]}function collectPlannedExternalTailorDBServices(e,t){let n=new Set(e.application.externalTailorDBNamespaces);return n.size===0?[]:t.flatMap(e=>e.application.tailorDBServices.filter(e=>n.has(e.namespace)))}function collectExternalAuthIdpConfigNames(e){let t=/* @__PURE__ */ new Map;for(let n of e){let e=n.application.authService;if(!e)continue;let{name:r}=e.config,i=e.config.idProvider?.name;if(t.has(r)&&t.get(r)!==i)throw E({code:`AUTH_NAMESPACE_CONFLICT`,message:`Auth namespace "${r}" is defined by multiple config files with different IdP configs. Auth namespace names must be unique across all configs in a single deploy.`});t.set(r,i)}return t}function collectPlannedMachineUsers(e){let t=/* @__PURE__ */ new Map;for(let n of e){let e=n.application.authService;if(!e)continue;let{name:r}=e.config,i=t.get(r)??/* @__PURE__ */ new Set;for(let t of Object.keys(e.config.machineUsers??{}))i.add(t);t.set(r,i)}return t}function collectDeployRunPlanInputs(e,t){let n=collectEventSubscriptions(e);return assertRecordableDependencies(n,t),{eventSubscriptions:n,runAppIds:new Set(e.map(e=>e.application.id).filter(e=>e!==void 0)),expectedLocalStaticWebsiteNames:collectExpectedLocalStaticWebsiteNames(e),externalAuthIdpConfigNames:collectExternalAuthIdpConfigNames(e),plannedMachineUsers:collectPlannedMachineUsers(e)}}async function planDeploymentTarget(e){let{target:t,targets:n,runInputs:r,client:i,workspaceId:a,noSchemaCheck:o,migrationSkipSteps:s,migrationRecoveryArgs:c,migrationTestBaselines:l,migrationTestSnapshots:u,migrationMachineUserOverride:d,skip:f,previous:p}=e,{config:m,application:h,workflowBuildResult:g,httpAdapterBuildResult:_,bundledScripts:v}=t,y=ownedSubscriptions(r.eventSubscriptions,t),b=h.tailorDBServices.map(e=>{let t=u?.get(e.namespace);return t?{...e,types:t.tables,typeSourceInfo:{}}:e});f?.has(`tailorDB`)&&p||await B(`plan.validateTailorDBTypeNames`,()=>We({client:i,workspaceId:a,tailorDBServices:b,externalTailorDBNamespaces:h.externalTailorDBNamespaces,plannedExternalTailorDBServices:collectPlannedExternalTailorDBServices(t,n)}));let x=h.workflowService,S=collectFunctionEntries(h,filterBundledWorkflowJobs(x?.jobs??[],g?.usedJobNames??[]),v),C=p?p.forceApplyAll:await B(`plan.detectSdkVersionChange`,()=>shouldForceApplyAll(i,a,h,S));return B(`plan`,async()=>{let e=n.map(e=>e.application),v=collectVisibleTailorDBTypeNamespaces(h,e),b=collectVisibleResolverNamespaces(h,e),w=collectVisibleIdpNames(h,e),T={client:i,workspaceId:a,application:h,forRemoval:!1,config:m,noSchemaCheck:o,migrationSkipSteps:s,migrationRecoveryArgs:c,migrationTestBaselines:l,migrationTestSnapshots:u,migrationMachineUserOverride:d,forceApplyAll:C,...r,idpUserTriggerTargets:subscribedIdps(y),executorUsedTailorDBTables:subscribedTailorDBTables(y),executorUsedResolvers:subscribedResolvers(y),dependentApps:collectDependentApps(y),tailorDBTypeNamespaces:v,resolverNamespaces:b,idpNames:w},E=await B(`plan.functionRegistry`,()=>planFunctionRegistry(i,a,h.name,h.id,S,p?.functionRegistry.existingMap)),ee=collectWorkflowJobStates(E.changeSet),[D,te,ne,re,O,ie,k,ae,oe,se,ce]=await Promise.all([f?.has(`tailorDB`)&&p?p.tailorDB:B(`plan.tailorDB`,()=>planTailorDB(T)),f?.has(`staticWebsite`)&&p?p.staticWebsite:B(`plan.staticWebsite`,()=>planStaticWebsite(T)),f?.has(`aiGateway`)&&p?p.aiGateway:B(`plan.aiGateway`,()=>planAIGateway(T)),f?.has(`idp`)&&p?p.idp:B(`plan.idp`,()=>planIdP(T)),f?.has(`auth`)&&p?p.auth:B(`plan.auth`,()=>planAuth(T)),B(`plan.pipeline`,()=>planPipeline(T,p&&{existingServices:p.pipeline.existingServices,existingResolvers:p.pipeline.existingResolvers})),B(`plan.application`,()=>planApplication(T,_,p&&{existingApplications:p.app.existingApplications,existingLabels:p.app.existingLabels})),B(`plan.executor`,()=>planExecutor(T,p?.executor.existingExecutors)),B(`plan.workflow`,()=>planWorkflow(i,a,h.name,h.id,x?.workflows??{},g?.mainJobDeps??{},ee.unchanged,{...subscribedWorkflows(y),jobPublishEvents:collectWorkflowJobPublishEvents(t),dependentApps:T.dependentApps,runAppIds:T.runAppIds},p&&{existingJobFunctions:p.workflow.existingJobFunctions,existingWorkflows:p.workflow.existingWorkflows},ee.forcedBySdkVersion)),f?.has(`workflowExecutionPolicy`)&&p?p.workflowExecutionPolicy:B(`plan.workflowExecutionPolicy`,()=>planWorkflowJobFunctionExecutionPolicy(i,a,h.name,h.id,m.workflow?.executionPolicies??{})),f?.has(`secretManager`)&&p?p.secretManager:B(`plan.secretManager`,()=>planSecretManager(T))]);return{application:h,forceApplyAll:C,functionRegistry:E,tailorDB:D,staticWebsite:te,aiGateway:ne,idp:re,auth:O,pipeline:ie,app:k,executor:ae,workflow:oe,workflowExecutionPolicy:se,secretManager:ce}})}async function planDeploymentTargets(e){let{targets:t,planTarget:n=planDeploymentTarget,previousDeployments:r,...i}=e,a=new Map(r?.map(e=>[e.application.name,e]));return Promise.all(t.map(e=>n({...i,target:e,targets:t,previous:a.get(e.application.name)})))}function confirmationKey(e,t){return JSON.stringify([e.application.name,t])}function collectConfirmations(e,t=/* @__PURE__ */ new Set){let n=deploymentPlanResults(e),isNew=n=>!t.has(confirmationKey(e,n));return{checkpointRepairs:e.tailorDB.context.checkpointRepairs.filter(isNew),conflicts:collectOwnerConflicts(n).filter(isNew),unmanaged:collectUnmanagedResources(n).filter(isNew),importantDeletions:collectImportantResourceDeletions(n).filter(isNew)}}async function confirmDeploymentPlans(e){let{deployments:t,yes:n,dryRun:r=!1,missingDependentApps:i=[],confirmedDeployments:a=[]}=e,o=r?`dry-run`:n?`yes`:`prompt`,s=new Set(a.flatMap(e=>Object.values(collectConfirmations(e)).flat().map(t=>confirmationKey(e,t)))),c=t.map(e=>({deployment:e,...collectConfirmations(e,s)}));await confirmMigrationCheckpointRepairs(c.flatMap(e=>e.checkpointRepairs),o),await confirmMissingDependentApps(i,o);for(let{deployment:e,conflicts:t,unmanaged:n}of c)await confirmOwnerConflict(t,e.application.name,o,e.application.id),await confirmUnmanagedResources(n,e.application.name,o);await confirmImportantResourceDeletion(c.flatMap(e=>e.importantDeletions),o)}async function validateDeploymentPlans(e){for(let t of e)await validatePlan(deploymentPlanResults(t))}async function reviewDeploymentPlans(e){let{deployments:t,dryRun:n,noValidate:r,pendingDeployedHooks:i,missingDependentApps:a}=e;scheduleRenamedAppDeletes(t),r?C.warn(`Client-side validation skipped (--no-validate).`):await validateDeploymentPlans(t);let o=printDeploymentPlans(t,{dryRun:n,pendingDeployedHooks:i,missingDependentApps:a});return await B(`confirm`,()=>confirmDeploymentPlans(e)),o}function needsEnvRebuild(e,t){return e.some(e=>Object.values(e.application.env).some(e=>Rt(e)&&t.has(kt(e))))}function assertEnvResolvedAfterRebuild(e,t){if(needsEnvRebuild(e,t))throw E({code:`STATIC_WEBSITE_URL_NOT_RESOLVED`,message:`A static website referenced by env still has no URL after rebuilding to pick up this deploy's own config changes.`,suggestion:`Re-run the deploy; the static website's URL may not be assigned yet.`})}function adjustApplicationForMigrationTest(e,t){if(!t?.migrationTestSnapshots)return e;let n=t.migrationTestBaselines!==void 0,r=n&&e.authService?{...e.authService,userProfile:void 0}:e.authService,i={...e,executorService:n?void 0:e.executorService,authService:r,staticWebsiteServices:e.staticWebsiteServices.map(e=>({...e,customDomains:void 0})),get applications(){return[i]}};return i}async function deployInternal(t,n,r){return B(`deploy`,async i=>{i.setAttribute(`deploy.dry_run`,t?.dryRun??!1),wt(),e();let a=parseDeployConfigPaths(t?.configPath),o=t?.dryRun??!1,s=t?.buildOnly??p(process.env.TAILOR_DEPLOY_BUILD_ONLY)===!0,c=s?[]:await B(`config.preflight`,()=>loadDeployConfigs({configPaths:a,dryRun:o,buildOnly:s})),l=c.map(({config:e})=>e.path),u=c.map(({config:e})=>({configPath:e.path,applicationId:e.id??`name:${e.name}`})),d=s?void 0:await resolveDeployWorkspace({workspaceId:t?.workspaceId,profile:t?.profile,createWorkspace:t?.createWorkspace,workspaceName:t?.workspaceName,workspaceRegion:t?.workspaceRegion,organizationId:t?.organizationId,folderId:t?.folderId,dryRun:o,contextTargets:u,deployArgs:retryDeployArgs(t,l,n),workspaceCommandArgs:workspaceRecoveryArgs(t,n),workspaceCommandJson:n?.json||C.jsonMode}),f=collectExpectedLocalStaticWebsiteNamesFromConfigs(c),m=t?.noCache??!1,h=H.resolve(Qe(),`cache`);t?.cleanCache&&(W.rmSync(h,{recursive:!0,force:!0}),C.info(`Bundle cache cleaned`));let build=e=>B(`build`,async()=>{let t=await Vt();return buildDeploymentTargets({configPaths:a,loadedConfigs:s?void 0:c,dryRun:o,buildOnly:s,noCache:m,packageVersion:t.version??`unknown`,cacheDir:h,client:d?.client,workspaceId:d?.workspaceId,expectedLocalStaticWebsiteNames:f,previousTargets:e})}),g=await build();if(s)return{bundledScripts:mergeBundledScripts(g),httpAdapterScripts:collectHttpAdapterScripts(g)};if(assertUniqueGlobalResourceNames(g),!d)throw b(`Workspace was not resolved`);let{client:_,workspaceId:v}=d;i.setAttribute(`app.name`,g.map(e=>e.application.name).join(`,`)),i.setAttribute(`workspace.id`,v);let y,plan=async(e,i)=>{let a=e.map(e=>({...e,application:adjustApplicationForMigrationTest(e.application,r)})),o=i&&y?y:await B(`plan.metadataLookup`,()=>createMetadataLookupClient({client:_,workspaceId:v,applications:a.map(({application:e})=>e)}));y=o;let s=collectDeployRunPlanInputs(a,!t?.dryRun),c=await planDeploymentTargets({targets:a,runInputs:s,client:o,workspaceId:v,noSchemaCheck:t?.noSchemaCheck,migrationSkipSteps:t?.migrationSkipSteps,migrationRecoveryArgs:recoveryEnvironmentArgs(t,n),migrationTestBaselines:r?.migrationTestBaselines,migrationTestSnapshots:r?.migrationTestSnapshots,migrationMachineUserOverride:r?.migrationMachineUserOverride,skip:i?.skip,previousDeployments:i?.previousDeployments});return dropCrossDeploymentManagedDeletes(c),assertNoSingleRunTransferHandoff(c),{planTargets:a,metadataClient:o,runInputs:s,deployments:c}},{planTargets:x,metadataClient:S,runInputs:w,deployments:T}=await plan(g);assertSkipNamespacesKnown(t?.migrationSkipSteps??/* @__PURE__ */ new Map,new Set(T.flatMap(e=>e.tailorDB.context.tailorDBInputs.map(e=>e.namespace))));let ee=(await Promise.all(x.map(e=>fetchMissingDependentApps({client:S,workspaceId:v,application:e.application,runAppIds:w.runAppIds??/* @__PURE__ */ new Set,subscribedKeys:subscribedResourceKeys(w.eventSubscriptions,e),jobsByWorkflow:e.workflowBuildResult?.mainJobDeps??{}})))).flat(),D=needsEnvRebuild(T,f),te=r?.skipDeployedHooks?[]:g.flatMap(e=>e.plugins.filter(e=>e.onDeployed).map(t=>({application:e.application.name,pluginId:t.id}))),ne={yes:t?.yes??!1,noValidate:t?.noValidate},re=await reviewDeploymentPlans({...ne,deployments:T,dryRun:o,missingDependentApps:ee,pendingDeployedHooks:te});if(o){for(let{application:e,pluginId:t}of te)C.info(`Hook to run after apply: "${t}" (app "${e}")`);C.info(`Dry run enabled. No changes applied.`);return}await preflightAllTailorDB(_,T),await applyPrerequisiteResources(_,T);let O;if(D){C.info(`A static website was just created; rebuilding so env resolves to its real URL before the rest of this deploy applies.`);let e=await build(g);assertUniqueGlobalResourceNames(e);let t=await plan(e,{skip:zc,previousDeployments:T});assertEnvResolvedAfterRebuild(t.deployments,f),re=await reviewDeploymentPlans({...ne,deployments:t.deployments,confirmedDeployments:T}),O=await applyRemainingResources(_,v,t.deployments)}else O=await applyRemainingResources(_,v,T);let ie=C.jsonMode&&!r?.suppressResultOutput?await loadDeployedApplications({client:_,workspaceId:v,targets:g}).catch(e=>{throw te.length?deployedHookLoadFailure(e,te.map(({application:e,pluginId:t})=>`${t} (app: ${e})`)):E({code:`DEPLOY_RESULT_LOAD_FAILED`,message:`Platform resources were applied successfully, but loading the deployed application information failed.`,details:e instanceof Error?e.message:String(e),suggestion:`Fix the error and run tailor deploy again. Unchanged resources are not re-applied.`,cause:e})}):void 0,k=r?.skipDeployedHooks?[]:await runDeployedHooks({client:_,workspaceId:v,targets:g,applications:ie});r?.suppressResultOutput||(C.jsonMode?C.out({summary:re,status:`applied`,workspaceId:v,applications:ie,...O.length?{tailordbMaintenance:O}:{},...k.length?{deployedHooks:k}:{}}):C.success(`Successfully applied changes.`))})}function deploy(e){return deployInternal(e)}function deployMigrationTestBaseline(e,t,n){return deployInternal(e,void 0,{migrationTestBaselines:t,migrationTestSnapshots:n,suppressResultOutput:!0,skipDeployedHooks:!0})}function deployMigrationTestTarget(e,t,n){return deployInternal(e,void 0,{migrationTestSnapshots:t,migrationMachineUserOverride:n,suppressResultOutput:!0,skipDeployedHooks:!0})}function deployFromCLI(e,t){return deployInternal(e,t)}function generateSeedScriptContent(e){return M`
|
|
193
193
|
import { Kysely, TailordbDialect } from "@tailor-platform/sdk/kysely";
|
|
194
194
|
|
|
195
195
|
type SeedInput = {
|
|
@@ -328,13 +328,11 @@ export {};
|
|
|
328
328
|
.filter((record): record is Record<string, unknown> => record !== undefined);
|
|
329
329
|
}
|
|
330
330
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
> = {};
|
|
337
|
-
const errors: string[] = [];
|
|
331
|
+
async function seedTables(
|
|
332
|
+
db: ReturnType<typeof getDB>,
|
|
333
|
+
input: SeedInput,
|
|
334
|
+
): Promise<SeedResult["processed"]> {
|
|
335
|
+
const processed: SeedResult["processed"] = {};
|
|
338
336
|
const BATCH_SIZE = ${`100`};
|
|
339
337
|
const upsert = input.upsert === true;
|
|
340
338
|
|
|
@@ -417,16 +415,24 @@ export {};
|
|
|
417
415
|
}
|
|
418
416
|
} catch (error) {
|
|
419
417
|
const message = error instanceof Error ? error.message : String(error);
|
|
420
|
-
errors.push(\`\${tableName}: \${message}\`);
|
|
421
418
|
console.error(\`[${e}] \${tableName}: failed - \${message}\`);
|
|
419
|
+
throw new Error(\`\${tableName}: \${message}\`, { cause: error });
|
|
422
420
|
}
|
|
423
421
|
}
|
|
424
422
|
|
|
425
|
-
return
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
423
|
+
return processed;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
export async function main(input: SeedInput): Promise<SeedResult> {
|
|
427
|
+
try {
|
|
428
|
+
const processed = await getDB("${e}")
|
|
429
|
+
.transaction()
|
|
430
|
+
.execute((db) => seedTables(db, input));
|
|
431
|
+
return { success: true, processed, errors: [] };
|
|
432
|
+
} catch (error) {
|
|
433
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
434
|
+
return { success: false, processed: {}, errors: [message] };
|
|
435
|
+
}
|
|
430
436
|
}
|
|
431
437
|
`}function generateSeedDumpScriptContent(e){return M`
|
|
432
438
|
import { Kysely, TailordbDialect } from "@tailor-platform/sdk/kysely";
|
|
@@ -484,12 +490,12 @@ export {};
|
|
|
484
490
|
return { success: false, rows: [], cursor: null, errors: [message] };
|
|
485
491
|
}
|
|
486
492
|
}
|
|
487
|
-
`}async function bundleSeedScript(e,t,n=process.cwd()){return{namespace:e,bundledCode:await bundleGeneratedEntry({entryFileName:`seed_${e}.entry.ts`,entryContent:generateSeedScriptContent(e),baseDir:n}),typesIncluded:t}}async function bundleSeedDumpScript(e,t=process.cwd()){return{namespace:e,bundledCode:await bundleGeneratedEntry({entryFileName:`seed_dump_${e}.entry.ts`,entryContent:generateSeedDumpScriptContent(e),baseDir:t})}}async function bundleGeneratedEntry(e){let{entryFileName:t,entryContent:n,baseDir:r}=e,i=H.resolve(Ze(),`seed`);W.mkdirSync(i,{recursive:!0});let a=H.join(i,t);W.writeFileSync(a,n);let o;try{o=await Gr(r)}catch{o=void 0}let s=Be({tsconfig:o}),c=await xi.build({plugins:[ze(a,r),Ye(),qe],input:a,write:!1,output:{format:`esm`,sourcemap:!1,minify:!1,codeSplitting:!1,globals:{tailordb:`tailordb`}},external:[`tailordb`],resolve:{conditionNames:[`node`,`import`]},tsconfig:o,treeshake:{moduleSideEffects:!1,annotations:!0,unknownGlobalSideEffects:!1},...s.options});return s.assertAllResolved(),c.output[0].code}async function waitForExecution(e,t,n,r=1e3){for(;;){let{execution:i}=await e.getFunctionExecution({workspaceId:t,executionId:n});if(!i)throw Error(`Execution '${n}' not found.`);if(isFunctionExecutionTerminalStatus(i.status))return{status:i.status,logs:joinFunctionLogMessages(i.logEntries),result:i.result};await new Promise(e=>setTimeout(e,r))}}async function executeScript(e){let{client:t,workspaceId:n,name:r,code:i,arg:a,invoker:o,pollInterval:s}=e,c=await t.execScript({workspaceId:n,name:r,code:i,arg:JSON.stringify(a===void 0?{}:a),invoker:o}),l=c.executionId,u=await waitForExecution(t,n,l,s);return u.status===On.SUCCESS?{success:!0,logs:u.logs,result:u.result}:{success:!1,logs:u.logs,result:u.result||c.result,error:u.result||c.result||(u.status===On.CANCELED?`Script execution was canceled`:`Script execution failed with unknown error`)}}function chunkSeedData(e){let{data:t,order:n,codeByteSize:r,maxMessageSize:i=3670016}=e,o=i-r-1024;if(o<=0)throw Error(`Code size (${r} bytes) exceeds the message size limit (${i} bytes). No space left for seed data.`);let s=n.filter(e=>(t[e]?.length??0)>0);if(s.length===0)return[];if(byteSize(JSON.stringify({data:t,order:n}))<=o)return[{data:t,order:n,index:0,total:1}];let c=[],l={},u=[];for(let e of s){let n=a(t[e],`seed data missing for type: ${e}`);if(u.length>0){let t={...l,[e]:n},r=[...u,e];byteSize(JSON.stringify({data:t,order:r}))>o&&(c.push({data:l,order:u,index:c.length}),l={},u=[])}if(byteSize(JSON.stringify({data:{[e]:n},order:[e]}))<=o){l[e]=n,u.push(e);continue}u.length>0&&(c.push({data:l,order:u,index:c.length}),l={},u=[]);let r=[];for(let t of n){if(byteSize(JSON.stringify({data:{[e]:[t]},order:[e]}))>o){let n=byteSize(JSON.stringify(t));throw Error(`A single record in table "${e}" (${n} bytes) exceeds the message size budget (${o} bytes). Consider increasing maxMessageSize or reducing the record size.`)}let n=[...r,t],i={...l,[e]:n},a=u.includes(e)?u:[...u,e];byteSize(JSON.stringify({data:i,order:a}))>o&&r.length>0?(l[e]=r,u.includes(e)||u.push(e),c.push({data:l,order:u,index:c.length}),l={},u=[],r=[t]):r=n}r.length>0&&(l[e]=r,u.includes(e)||u.push(e))}u.length>0&&c.push({data:l,order:u,index:c.length});let d=c.length;return c.map(e=>({...e,total:d}))}function byteSize(e){return new TextEncoder().encode(e).length}function processSeedTypeInfo(e,t){let n=/* @__PURE__ */ new Set,r=[],i=Object.create(null);for(let[t,a]of Object.entries(e.fields)){let o=a.relation?.targetType??a.config.foreignKeyType;o&&(o===e.name?(r.push(t),i[t]=a.relation?.key??a.config.foreignKeyField??`id`):n.add(o))}for(let[t,a]of Object.entries(e.fields))if(a.config.fields)for(let o of collectForeignKeyReferences(a.config.fields)){if(o.table!==e.name){n.add(o.table);continue}let a=`${t}.${o.path}`;r.push(a),i[a]=o.field??`id`}return{name:e.name,namespace:t,dependencies:Array.from(n),selfRefFields:r,selfRefKeys:i,dataFile:`data/${e.name}.jsonl`}}function collectRelationTargetKeys(e){let t=/* @__PURE__ */ new Map;for(let n of e)for(let e of Object.values(n.tables)){let addTarget=(e,n)=>{if(!e||!n)return;let r=t.get(e)??/* @__PURE__ */ new Set;r.add(n),t.set(e,r)};for(let t of Object.values(e.fields)){addTarget(t.relation?.targetType??t.config.foreignKeyType,t.relation?.key??t.config.foreignKeyField);for(let e of collectForeignKeyReferences(t.config.fields??{}))addTarget(e.table,e.field)}}return t}function buildSeedNamespaceConfigs(e){let t=collectRelationTargetKeys(e);return e.map(e=>{let n=[],r={},i=[],o={},s={},c={},l={};for(let[u,d]of Object.entries(e.tables)){let f=processSeedTypeInfo(d,e.namespace);n.push(f.name),r[f.name]=f.dependencies,o[f.name]=f.selfRefFields,s[f.name]=f.selfRefKeys,f.selfRefFields.length>0&&i.push(f.name);let p=a(e.sourceInfo.get(u),`source info missing for table: ${u}`),m=Dr(d,p),h=t.get(f.name);l[f.name]=h?m.omitFields.filter(e=>!h.has(e)):m.omitFields,c[f.name]=Object.entries(d.fields).filter(([e,t])=>t.config.required!==!1&&!m.optionalFields.includes(e)&&!m.omitFields.includes(e)).map(([e])=>e)}return{namespace:e.namespace,types:n,dependencies:r,selfRefTypes:i,selfRefFields:o,selfRefKeys:s,requiredFields:c,omitFields:l}})}function resolvePluginConfig(e,t){return e.find(e=>e.id===t)?.pluginConfig}function getAuthInput(e){let t=e.authService;if(!t)return;let n=t.config,r=t.userProfile;return{name:n.name,userProfile:r?{tableName:r.type.name,namespace:r.namespace,usernameField:r.usernameField}:void 0,machineUsers:n.machineUsers,oauth2Clients:n.oauth2Clients,idProvider:n.idProvider}}async function loadApplicationNamespaces(e={}){let{config:t,plugins:n}=await loadConfig(e.configPath);await generateUserTypes({config:t,configPath:t.path});let r=n.length>0?new Cr(n):void 0,i=pt({config:t,pluginManager:r}),a=typeof e.namespaces==`function`?e.namespaces(t,n):e.namespaces,o=a?new Set(a):void 0,s=o?i.tailorDBServices.filter(e=>o.has(e.namespace)):i.tailorDBServices;if(o&&s.length!==o.size){let e=new Set(s.map(e=>e.namespace)),t=[...o].filter(t=>!e.has(t)).join(`, `),n=i.tailorDBServices.map(e=>e.namespace).join(`, `);throw Error(`TailorDB namespace "${t}" not found in local config.db.`+(n?` Available owned namespaces: ${n}`:``))}let c=[];for(let e of s)await e.loadTypes(),await e.processNamespacePlugins(),c.push({namespace:e.namespace,tables:{...e.types},sourceInfo:new Map(Object.entries(e.typeSourceInfo)),pluginAttachments:e.pluginAttachments});return{config:t,plugins:n,application:i,namespaces:c}}async function loadTailorDBNamespaces(e={}){let{config:t,plugins:n,namespaces:r}=await loadApplicationNamespaces(e);return{config:t,plugins:n,namespaces:r}}async function loadSeedContext(e={}){let{config:t,plugins:n,application:r,namespaces:i}=await loadApplicationNamespaces({configPath:e.configPath});Fe({tailorDBServices:r.tailorDBServices});let a=resolvePluginConfig(n,kr);if(!a)throw Error(`seedPlugin is not configured in ${t.path}. Add seedPlugin({ distPath: "./seed" }) from "@tailor-platform/sdk/plugin/seed" to definePlugins().`);if(typeof a.distPath!=`string`||a.distPath===``)throw Error(`seedPlugin in ${t.path} has no distPath option. Pass seedPlugin({ distPath: "./seed" }) so seed data has a location.`);await r.authService?.resolveNamespaces();let o=getAuthInput(r),s=o?Or(o):void 0,c=s?{idpNamespace:s.idpNamespace,seedScriptCode:wr(s.idpNamespace),listScriptCode:Tr(s.idpNamespace),truncateScriptCode:Er(s.idpNamespace)}:null;return{config:t,distPath:H.resolve(a.distPath),machineUserName:a.machineUserName,datasets:parseDatasets(a.datasets,t.path),namespaces:buildSeedNamespaceConfigs(i),idpUser:c}}const Fc=/^[A-Za-z0-9][A-Za-z0-9_-]*$/;function assertDatasetName(e,t){if(!Fc.test(e))throw Error(`Dataset name "${e}" in the seedPlugin datasets option of ${t} is invalid. Use letters, digits, \`-\` and \`_\`, starting with a letter or digit.`)}function parseDatasets(e,t){if(e===void 0)return{};if(typeof e!=`object`||!e||Array.isArray(e))throw Error(`seedPlugin datasets must map names to lists of dataset directory names in ${t}.`);let n={};for(let[r,i]of Object.entries(e)){if(assertDatasetName(r,t),!Array.isArray(i))throw Error(`seedPlugin datasets.${r} must be an array of dataset directory names in ${t}.`);if(i.length===0)throw Error(`seedPlugin datasets.${r} lists no dataset directories in ${t}.`);for(let e of i){if(typeof e!=`string`)throw Error(`seedPlugin datasets.${r} must be an array of dataset directory names in ${t}.`);assertDatasetName(e,t)}n[r]=i}return n}function colorizeExecutorJobStatus(e){switch(e){case`PENDING`:return h.dim(e);case`RUNNING`:return h.info(e);case`SUCCESS`:return h.success(e);case`FAILED`:return h.error(e);case`CANCELED`:return h.warning(e);default:return e}}const Ic={[qn.UNSPECIFIED]:`transient`,[qn.PENDING]:`transient`,[qn.RUNNING]:`transient`,[qn.SUCCESS]:`success`,[qn.FAILED]:`failure`,[qn.CANCELED]:`failure`};function classifyExecutorJobStatus(e){return protoEnumLookup(Ic,e,`transient`)}const Lc=protoEnumNames(qn).filter(e=>e!==`UNSPECIFIED`);function parseExecutorJobStatus(e){let t=parseProtoEnumName(qn,e,[qn.UNSPECIFIED]);if(t===void 0)throw E({code:`EXECUTOR_STATUS_INVALID`,message:`Invalid status: ${e}. Valid values: ${Lc.join(`, `)}`});return t}const Rc={[I.UNSPECIFIED]:`UNSPECIFIED`,[I.WEBHOOK]:`WEBHOOK`,[I.TAILOR_GRAPHQL]:`GRAPHQL`,[I.FUNCTION]:`FUNCTION`,[I.JOB_FUNCTION]:`JOB_FUNCTION`,[I.WORKFLOW]:`WORKFLOW`};function executorTargetTypeToString(e){return protoEnumLookup(Rc,e,`UNSPECIFIED`)}function executorTriggerTypeToString(e){return protoEnumName(tr,e)??`UNSPECIFIED`}function executorJobStatusToString(e){return protoEnumName(qn,e)??`UNSPECIFIED`}function toExecutorJobListInfo(e){return{id:e.id,executorName:e.executorName,status:executorJobStatusToString(e.status),createdAt:e.createdAt?G(e.createdAt).toISOString():`N/A`}}function toExecutorJobInfo(e){return{id:e.id,executorName:e.executorName,status:executorJobStatusToString(e.status),scheduledAt:e.scheduledAt?G(e.scheduledAt).toISOString():`N/A`,createdAt:e.createdAt?G(e.createdAt).toISOString():`N/A`,updatedAt:e.updatedAt?G(e.updatedAt).toISOString():`N/A`}}function toExecutorJobAttemptInfo(e){return{id:e.id,jobId:e.jobId,status:executorJobStatusToString(e.status),error:e.error||``,startedAt:e.startedAt?G(e.startedAt).toISOString():`N/A`,finishedAt:e.finishedAt?G(e.finishedAt).toISOString():`N/A`,operationReference:e.operationReference||``}}function formatSubjectEvent(e,t){let n=t.map(e=>e.split(`.`).at(-1)??e).join(`, `);return n?`event: ${e} ${n}`:`event: ${e}`}function formatTypedEventTrigger(e){let t=e.typedConfig;if(t.case===void 0)return null;switch(t.case){case`tailordb`:return formatSubjectEvent(t.value.typeName,t.value.eventTypes);case`pipeline`:return formatSubjectEvent(t.value.resolverName,t.value.eventTypes);case`idp`:return formatSubjectEvent(`idp user`,t.value.eventTypes);case`auth`:return formatSubjectEvent(`auth access_token`,t.value.eventTypes);default:return null}}function formatTriggerType(e){let t=e.triggerConfig?.config;if(!t||t.case===void 0)return executorTriggerTypeToString(e.triggerType);switch(t.case){case`schedule`:return`schedule: ${t.value.frequency} (${t.value.timezone})`;case`event`:{let n=formatTypedEventTrigger(t.value);if(n)return n;let r=readLegacyEventTriggerConfig(t.value);return r.eventType?formatEventTrigger(r.eventType,r.condition):executorTriggerTypeToString(e.triggerType)}case`incomingWebhook`:return`webhook`;default:return executorTriggerTypeToString(e.triggerType)}}function readLegacyEventTriggerConfig(e){return{eventType:e.eventType,condition:e.condition?.expr}}function formatEventTrigger(e,t){let n=e.split(`.`);if(n.length<3)return`event: ${e}`;let[r,i,a]=n;if(t){let e=t.match(/args\.typeName\s*===?\s*["']([^"']+)["']/);if(e)return`event: ${e[1]} ${a}`;let n=t.match(/args\.resolverName\s*===?\s*["']([^"']+)["']/);if(n)return`event: ${n[1]} ${a}`}return`event: ${r} ${i} ${a}`}function formatTriggerConfig(e){let t=e.triggerConfig?.config;if(!t||t.case===void 0)return{};switch(t.case){case`schedule`:return{timezone:t.value.timezone,frequency:t.value.frequency};case`event`:return formatEventTriggerConfig(t.value);case`incomingWebhook`:return{secret:t.value.secret?`***`:``};default:return{}}}function formatEventTriggerConfig(e){let t=e.typedConfig;if(t.case===void 0){let t=readLegacyEventTriggerConfig(e);return{eventType:t.eventType,condition:t.condition||``}}if(t.case===`workflow`)return{kind:t.case,eventTypes:t.value.eventTypes,condition:t.value.condition?.expr||``,...t.value.workflowName&&{workflowName:t.value.workflowName}};let n={kind:t.case,eventTypes:t.value.eventTypes,namespaceName:t.value.namespaceName,condition:t.value.condition?.expr||``};switch(t.case){case`tailordb`:return{...n,typeName:t.value.typeName};case`pipeline`:return{...n,resolverName:t.value.resolverName};default:return n}}function formatTargetConfig(e){let t=e.targetConfig?.config;if(!t||t.case===void 0)return{};switch(t.case){case`webhook`:return{url:t.value.url?.expr||``,headers:t.value.headers.length};case`tailorGraphql`:return{appName:t.value.appName,query:t.value.query};case`function`:return{name:t.value.name};case`workflow`:return{workflowName:t.value.workflowName};default:return{}}}function toExecutorListInfo(e){return{name:e.name,triggerType:formatTriggerType(e),targetType:executorTargetTypeToString(e.targetType),disabled:e.disabled}}function toExecutorInfo(e){return{name:e.name,description:e.description,triggerType:formatTriggerType(e),targetType:executorTargetTypeToString(e.targetType),disabled:e.disabled,triggerConfig:formatTriggerConfig(e),targetConfig:formatTargetConfig(e)}}const zc={name:V(U.string(),{positional:!0,description:`Executor name`})};async function resolveExecutor(e,t,n){let{executor:r}=await e.getExecutorExecutor({workspaceId:t,name:n});if(!r)throw E({code:`EXECUTOR_NOT_FOUND`,message:`Executor '${n}' not found.`});return r}async function getExecutor(e){let t=e.executor.name,{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId});try{return toExecutorInfo(await resolveExecutor(n,r,t))}catch(e){throw e instanceof q&&e.code===K.NotFound?E({code:`EXECUTOR_NOT_FOUND`,message:`Executor '${t}' not found.`,cause:e}):e}}const Bc=Y({name:`get`,description:`Get executor details`,args:U.strictObject({...j,...zc}),run:async e=>{let t=await getExecutor({executor:{name:e.name},workspaceId:e[`workspace-id`],profile:e.profile});C.out(t,{display:{triggerConfig:null,targetConfig:null}})}}),Vc=U.enum([`success`,`suspended`,`terminal`]),Hc={name:V(U.string(),{positional:!0,description:`Workflow name`})},Uc={interval:V(re.default(`3s`),{alias:`i`,description:`Polling interval when waiting (e.g., '3s', '500ms', '1m')`}),timeout:V(re.default(`10m`),{alias:`t`,description:`Maximum time to wait (e.g., '30s', '10m')`}),until:V(Vc.default(`terminal`),{alias:`u`,description:`Wait target (success, suspended, terminal)`}),logs:V(U.boolean().default(!1),{alias:`l`,description:`Display job execution logs after completion`})},Wc={wait:V(U.boolean().default(!1),{alias:`W`,description:`Wait for execution to complete`}),...Uc};function workflowExecutionStatusToString(e){return protoEnumName(R,e)??`UNSPECIFIED`}function workflowJobExecutionStatusToString(e){return protoEnumName(z,e)??`UNSPECIFIED`}function toWorkflowListInfo(e){return{name:e.name,mainJob:e.mainJobFunctionName,jobFunctions:Object.keys(e.jobFunctions).length,updatedAt:e.updatedAt?G(e.updatedAt):null}}function toWorkflowInfo(e){let t={};for(let[n,r]of Object.entries(e.jobFunctions))t[n]=r.toString();return{name:e.name,id:e.id,mainJob:e.mainJobFunctionName,jobFunctions:t,createdAt:e.createdAt?G(e.createdAt):null,updatedAt:e.updatedAt?G(e.updatedAt):null}}function toWorkflowJobExecutionInfo(e){return{id:e.id,stackedJobName:e.stackedJobName,status:workflowJobExecutionStatusToString(e.status),executionId:e.executionId,startedAt:e.startedAt?G(e.startedAt):null,finishedAt:e.finishedAt?G(e.finishedAt):null}}function toWorkflowExecutionInfo(e){return{id:e.id,workflowName:e.workflowName,status:workflowExecutionStatusToString(e.status),jobExecutions:e.jobExecutions.length,startedAt:e.startedAt?G(e.startedAt):null,finishedAt:e.finishedAt?G(e.finishedAt):null}}function formatTime$1(e){return e.toLocaleTimeString(`en-US`,{hour12:!1})}function colorizeStatus(e){let t=R[e];switch(e){case R.PENDING:case R.UNSPECIFIED:return h.dim(t);case R.PENDING_RESUME:case R.PENDING_RETRY:case R.WAITING:return h.warning(t);case R.RUNNING:return h.info(t);case R.SUCCESS:return h.success(t);case R.FAILED:case R.CANCELED:return h.error(t);default:return t}}function getActiveJobs(e){return e.jobExecutions.filter(e=>e.status===z.RUNNING||e.status===z.SUSPEND||e.status===z.WAITING).map(e=>e.stackedJobName).join(`, `)}function createWorkflowWaitResult(e){let t=Date.now()-e.startedAt;if(e.execution){let n=classifyWorkflowExecutionStatus(e.execution);return{...toWorkflowExecutionInfo(e.execution),statusClass:n.statusClass,elapsedMs:t,attempts:e.attempts,timedOut:e.timedOut,lastError:e.lastError}}return{id:e.executionId,workflowName:``,status:`UNKNOWN`,statusClass:`unknown`,jobExecutions:0,startedAt:null,finishedAt:null,elapsedMs:t,attempts:e.attempts,timedOut:e.timedOut,lastError:e.lastError}}async function waitForWorkflowExecution(e){let t=e.interval??3e3,n=e.until??`terminal`,r=Date.now(),i=e.showProgress?spinner({indent:2}).start(`Waiting for workflow to complete...`):null,a=0,o,s=null,c,l;try{for(;;){let u=Date.now()-r,d=e.timeout===void 0?void 0:e.timeout-u;if(d!==void 0&&d<=0)return i?.fail(`Workflow wait timed out.`),createWorkflowWaitResult({executionId:e.executionId,execution:o,startedAt:r,attempts:a,timedOut:!0,lastError:s});try{a+=1;let{execution:t}=await e.client.getWorkflowExecution({workspaceId:e.workspaceId,executionId:e.executionId});if(!t)throw i?.fail(`Execution '${e.executionId}' not found.`),E({code:`WORKFLOW_EXECUTION_NOT_FOUND`,message:`Execution '${e.executionId}' not found.`});o=t,s=null;let u=classifyWorkflowExecutionStatus(t),d=colorizeStatus(t.status);if(t.status!==c&&(e.showProgress&&(i?.stop(),C.info(`Status: ${d}`,{mode:`stream`,indent:2}),i?.start(`Waiting for workflow to complete...`)),c=t.status),e.trackJobs){let n=getActiveJobs(t);n&&n!==l&&(e.showProgress&&(i?.stop(),C.info(`Job | ${n}: ${d}`,{mode:`stream`,indent:2}),i?.start(`Waiting for workflow to complete...`)),l=n)}if(i&&(i.text=`Waiting for workflow to complete... (${formatTime$1(/* @__PURE__ */ new Date)})`),hasReachedWorkflowWaitTarget(u,n)||u.statusClass===`failure`||n===`suspended`&&u.statusClass===`success`)return t.status===R.SUCCESS?i?.succeed(`Completed: ${d}`):isWorkflowExecutionFailureStatus(t.status)?i?.fail(`Completed: ${d}`):isWorkflowExecutionSuspendedStatus(t.status)?i?.warn(`Completed: ${d}`):i?.succeed(`Completed: ${d}`),createWorkflowWaitResult({executionId:e.executionId,execution:t,startedAt:r,attempts:a,timedOut:!1,lastError:s})}catch(t){if(!isRetryableWaitError(t))throw t;s=formatWaitError(t),e.showProgress&&i&&(i.text=`Retrying workflow status poll... (${formatTime$1(/* @__PURE__ */ new Date)})`)}let f=Date.now()-r,p=e.timeout===void 0?void 0:e.timeout-f;if(p!==void 0&&p<=0)return i?.fail(`Workflow wait timed out.`),createWorkflowWaitResult({executionId:e.executionId,execution:o,startedAt:r,attempts:a,timedOut:!0,lastError:s});await Mi(p===void 0?t:Math.min(t,p))}}finally{i?.stop()}}async function waitForWorkflowExecutionById(e){let{client:t,workspaceId:n}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId});return await waitForWorkflowExecution({client:t,workspaceId:n,executionId:e.executionId,interval:e.interval,timeout:e.timeout,until:e.until,showProgress:e.showProgress,trackJobs:e.trackJobs})}function getWorkflowWaitFailure(e,t){let n={executionId:e.id,status:e.status};if(e.timedOut)return E({code:`WORKFLOW_WAIT_TIMEOUT`,message:`Timed out waiting for workflow execution '${e.id}' to reach ${t}. Last status: ${e.status}.`,context:n});if(e.status===`FAILED`)return E({code:`WORKFLOW_EXECUTION_FAILED`,message:`Workflow execution '${e.id}' failed.`,context:n});if(e.status===`CANCELED`)return E({code:`WORKFLOW_EXECUTION_CANCELED`,message:`Workflow execution '${e.id}' was canceled.`,context:n});if(t===`success`&&e.statusClass!==`success`)return E({code:`WORKFLOW_EXECUTION_NOT_SUCCESSFUL`,message:`Workflow execution '${e.id}' reached ${e.status} before success.`,context:n});if(t===`suspended`&&e.statusClass!==`suspended`)return E({code:`WORKFLOW_EXECUTION_NOT_SUSPENDED`,message:`Workflow execution '${e.id}' reached ${e.status} before suspension.`,context:n})}function parseStatus(e){let t=parseProtoEnumName(R,e);if(t===void 0)throw E({code:`WORKFLOW_STATUS_INVALID`,message:`Invalid status: ${e}. Valid values: ${protoEnumNames(R).join(`, `)}`,command:`workflow executions`});return t}async function listWorkflowExecutions(e){let t=e?.workflow?.name,{client:a,workspaceId:o}=await loadOperatorWorkspaceContext({profile:e?.profile,workspaceId:e?.workspaceId}),s=[];if(e?.status){let t=parseStatus(e.status);s.push(Kr(r,{condition:Kr(i,{field:`status`,operator:n.EQ,value:{kind:{case:`numberValue`,value:t}}})}))}let c=s.length>0?Kr(r,{and:s}):void 0,l=Ce(e?.order??`desc`);return(await Mt(async(e,n)=>{let{executions:r,nextPageToken:i}=await a.listWorkflowExecutions({workspaceId:o,workflowName:t??``,pageToken:e,pageSize:n,pageDirection:l,filter:c});return[r,i]},{limit:e?.limit})).map(toWorkflowExecutionInfo)}async function getWorkflowExecution(e){let{client:t,workspaceId:n}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId});async function fetchFunctionExecution(e){try{let{execution:r}=await t.getFunctionExecution({workspaceId:n,executionId:e});return r}catch(t){t instanceof q&&t.code===K.NotFound||C.warn(`Could not fetch logs for function execution '${e}': ${t instanceof Error?t.message:String(t)}`);return}}async function fetchExecutionWithLogs(e,r){let{execution:i}=await t.getWorkflowExecution({workspaceId:n,executionId:e});if(!i)throw E({code:`WORKFLOW_EXECUTION_NOT_FOUND`,message:`Execution '${e}' not found.`});let a=toWorkflowExecutionInfo(i);return r&&i.jobExecutions.length>0&&(a.jobDetails=await Promise.all(i.jobExecutions.map(async e=>{let t=toWorkflowJobExecutionInfo(e);if(e.executionId){let n=await fetchFunctionExecution(e.executionId);if(n)return{...t,...collectFunctionExecutionLogs(n.logEntries),result:n.result||void 0}}return t}))),a}async function waitForCompletion(){let r=e.interval??3e3,i=await waitForWorkflowExecution({client:t,workspaceId:n,executionId:e.executionId,interval:r,timeout:e.timeout,until:e.until??`terminal`});return{...await fetchExecutionWithLogs(e.executionId,e.logs??!1),statusClass:i.statusClass,elapsedMs:i.elapsedMs,attempts:i.attempts,timedOut:i.timedOut,lastError:i.lastError}}return{execution:await fetchExecutionWithLogs(e.executionId,e.logs??!1),wait:waitForCompletion}}function printExecutionWithLogs(e){let formatDate=e=>e?e.toISOString():`N/A`,t=[[`id`,e.id],[`workflowName`,e.workflowName],[`status`,e.status],[`jobExecutions`,e.jobExecutions.toString()],[`startedAt`,formatDate(e.startedAt)],[`finishedAt`,formatDate(e.finishedAt)]];if(C.out(formatKeyValueTable(t)),e.jobDetails&&e.jobDetails.length>0){C.log(h.bold(`
|
|
493
|
+
`}async function bundleSeedScript(e,t,n=process.cwd(),r={}){return{namespace:e,bundledCode:await bundleGeneratedEntry({entryFileName:`seed_${e}.entry.ts`,entryContent:generateSeedScriptContent(e),baseDir:n,buildOptions:r}),typesIncluded:t}}async function bundleSeedDumpScript(e,t=process.cwd(),n={}){return{namespace:e,bundledCode:await bundleGeneratedEntry({entryFileName:`seed_dump_${e}.entry.ts`,entryContent:generateSeedDumpScriptContent(e),baseDir:t,buildOptions:n})}}async function bundleGeneratedEntry(e){let{entryFileName:t,entryContent:n,baseDir:r,buildOptions:i}=e,a=mt(i.inlineSourcemap),o=H.resolve(Qe(),`seed`);W.mkdirSync(o,{recursive:!0});let s=H.join(o,t);W.writeFileSync(s,n);let c;try{c=await Jr(r)}catch{c=void 0}let l=Be({tsconfig:c}),u=await wi.build({plugins:[ze(s,r),Xe(),Je],input:s,write:!1,output:{format:`esm`,sourcemap:a,minify:!a||{mangle:{keepNames:!0}},codeSplitting:!1,globals:{tailordb:`tailordb`}},external:[`tailordb`],resolve:{conditionNames:[`node`,`import`]},tsconfig:c,treeshake:{moduleSideEffects:!1,annotations:!0,unknownGlobalSideEffects:!1},...l.options});return l.assertAllResolved(),Ve({chunk:u.output[0],inlineSourcemap:a,dependencySources:i.inlineSourcemapDependencySources??!1})}async function waitForExecution(e,t,n,r=1e3){for(;;){let{execution:i}=await e.getFunctionExecution({workspaceId:t,executionId:n});if(!i)throw Error(`Execution '${n}' not found.`);if(isFunctionExecutionTerminalStatus(i.status))return{status:i.status,logs:joinFunctionLogMessages(i.logEntries),result:i.result};await new Promise(e=>setTimeout(e,r))}}async function executeScript(e){let{client:t,workspaceId:n,name:r,code:i,arg:a,invoker:o,pollInterval:s}=e,c=await t.execScript({workspaceId:n,name:r,code:i,arg:JSON.stringify(a===void 0?{}:a),invoker:o}),l=c.executionId,u=await waitForExecution(t,n,l,s);return u.status===jn.SUCCESS?{success:!0,logs:u.logs,result:u.result}:{success:!1,logs:u.logs,result:u.result||c.result,error:u.result||c.result||(u.status===jn.CANCELED?`Script execution was canceled`:`Script execution failed with unknown error`)}}function chunkSeedData(e){let{data:t,order:n,codeByteSize:r,maxMessageSize:i=3670016}=e,o=i-r-1024;if(o<=0)throw Error(`Code size (${r} bytes) exceeds the message size limit (${i} bytes). No space left for seed data.`);let s=n.filter(e=>(t[e]?.length??0)>0);if(s.length===0)return[];if(byteSize(JSON.stringify({data:t,order:n}))<=o)return[{data:t,order:n,index:0,total:1}];let c=[],l={},u=[];for(let e of s){let n=a(t[e],`seed data missing for type: ${e}`);if(u.length>0){let t={...l,[e]:n},r=[...u,e];byteSize(JSON.stringify({data:t,order:r}))>o&&(c.push({data:l,order:u,index:c.length}),l={},u=[])}if(byteSize(JSON.stringify({data:{[e]:n},order:[e]}))<=o){l[e]=n,u.push(e);continue}u.length>0&&(c.push({data:l,order:u,index:c.length}),l={},u=[]);let r=byteSize(JSON.stringify({data:{[e]:[]},order:[e]})),i=[],s=r;for(let t of n){let n=byteSize(JSON.stringify(t));if(r+n>o)throw Error(`A single record in table "${e}" (${n} bytes) exceeds the message size budget (${o} bytes). Consider increasing maxMessageSize or reducing the record size.`);let a=+(i.length>0);s+a+n>o?(c.push({data:{[e]:i},order:[e],index:c.length}),i=[t],s=r+n):(i.push(t),s+=a+n)}i.length>0&&(l[e]=i,u.push(e))}u.length>0&&c.push({data:l,order:u,index:c.length});let d=c.length;return c.map(e=>({...e,total:d}))}const Bc=/[<>&\u2028\u2029]/g;function platformEncoded(e){return e.replace(Bc,e=>`\\u${e.charCodeAt(0).toString(16).padStart(4,`0`)}`)}function byteSize(e){return new TextEncoder().encode(platformEncoded(e)).length}function processSeedTypeInfo(e,t){let n=/* @__PURE__ */ new Set,r=[],i=Object.create(null);for(let[t,a]of Object.entries(e.fields)){let o=a.relation?.targetType??a.config.foreignKeyType;o&&(o===e.name?(r.push(t),i[t]=a.relation?.key??a.config.foreignKeyField??`id`):n.add(o))}for(let[t,a]of Object.entries(e.fields))if(a.config.fields)for(let o of collectForeignKeyReferences(a.config.fields)){if(o.table!==e.name){n.add(o.table);continue}let a=`${t}.${o.path}`;r.push(a),i[a]=o.field??`id`}return{name:e.name,namespace:t,dependencies:Array.from(n),selfRefFields:r,selfRefKeys:i,dataFile:`data/${e.name}.jsonl`}}function collectRelationTargetKeys(e){let t=/* @__PURE__ */ new Map;for(let n of e)for(let e of Object.values(n.tables)){let addTarget=(e,n)=>{if(!e||!n)return;let r=t.get(e)??/* @__PURE__ */ new Set;r.add(n),t.set(e,r)};for(let t of Object.values(e.fields)){addTarget(t.relation?.targetType??t.config.foreignKeyType,t.relation?.key??t.config.foreignKeyField);for(let e of collectForeignKeyReferences(t.config.fields??{}))addTarget(e.table,e.field)}}return t}function buildSeedNamespaceConfigs(e){let t=collectRelationTargetKeys(e);return e.map(e=>{let n=[],r={},i=[],o={},s={},c={},l={};for(let[u,d]of Object.entries(e.tables)){let f=processSeedTypeInfo(d,e.namespace);n.push(f.name),r[f.name]=f.dependencies,o[f.name]=f.selfRefFields,s[f.name]=f.selfRefKeys,f.selfRefFields.length>0&&i.push(f.name);let p=a(e.sourceInfo.get(u),`source info missing for table: ${u}`),m=Ar(d,p),h=t.get(f.name);l[f.name]=h?m.omitFields.filter(e=>!h.has(e)):m.omitFields,c[f.name]=Object.entries(d.fields).filter(([e,t])=>t.config.required!==!1&&!m.optionalFields.includes(e)&&!m.omitFields.includes(e)).map(([e])=>e)}return{namespace:e.namespace,types:n,dependencies:r,selfRefTypes:i,selfRefFields:o,selfRefKeys:s,requiredFields:c,omitFields:l}})}function resolvePluginConfig(e,t){return e.find(e=>e.id===t)?.pluginConfig}function getAuthInput(e){let t=e.authService;if(!t)return;let n=t.config,r=t.userProfile;return{name:n.name,userProfile:r?{tableName:r.type.name,namespace:r.namespace,usernameField:r.usernameField}:void 0,machineUsers:n.machineUsers,oauth2Clients:n.oauth2Clients,idProvider:n.idProvider}}async function loadApplicationNamespaces(e={}){let{config:t,plugins:n}=await loadConfig(e.configPath);await generateUserTypes({config:t,configPath:t.path});let r=n.length>0?new Er(n):void 0,i=ht({config:t,pluginManager:r}),a=typeof e.namespaces==`function`?e.namespaces(t,n):e.namespaces,o=a?new Set(a):void 0,s=o?i.tailorDBServices.filter(e=>o.has(e.namespace)):i.tailorDBServices;if(o&&s.length!==o.size){let e=new Set(s.map(e=>e.namespace)),t=[...o].filter(t=>!e.has(t)).join(`, `),n=i.tailorDBServices.map(e=>e.namespace).join(`, `);throw Error(`TailorDB namespace "${t}" not found in local config.db.`+(n?` Available owned namespaces: ${n}`:``))}let c=[];for(let e of s)await e.loadTypes(),await e.processNamespacePlugins(),c.push({namespace:e.namespace,tables:{...e.types},sourceInfo:new Map(Object.entries(e.typeSourceInfo)),pluginAttachments:e.pluginAttachments});return{config:t,plugins:n,application:i,namespaces:c}}async function loadTailorDBNamespaces(e={}){let{config:t,plugins:n,namespaces:r}=await loadApplicationNamespaces(e);return{config:t,plugins:n,namespaces:r}}async function loadSeedContext(e={}){let{config:t,plugins:n,application:r,namespaces:i}=await loadApplicationNamespaces({configPath:e.configPath});Fe({tailorDBServices:r.tailorDBServices});let a=resolvePluginConfig(n,Mr);if(!a)throw Error(`seedPlugin is not configured in ${t.path}. Add seedPlugin({ distPath: "./seed" }) from "@tailor-platform/sdk/plugin/seed" to definePlugins().`);if(typeof a.distPath!=`string`||a.distPath===``)throw Error(`seedPlugin in ${t.path} has no distPath option. Pass seedPlugin({ distPath: "./seed" }) so seed data has a location.`);await r.authService?.resolveNamespaces();let o=getAuthInput(r),s=o?jr(o):void 0,c=s?{idpNamespace:s.idpNamespace,seedScriptCode:Dr(s.idpNamespace),listScriptCode:Or(s.idpNamespace),truncateScriptCode:kr(s.idpNamespace)}:null;return{config:t,distPath:H.resolve(a.distPath),machineUserName:a.machineUserName,datasets:parseDatasets(a.datasets,t.path),namespaces:buildSeedNamespaceConfigs(i),idpUser:c}}const Vc=/^[A-Za-z0-9][A-Za-z0-9_-]*$/;function assertDatasetName(e,t){if(!Vc.test(e))throw Error(`Dataset name "${e}" in the seedPlugin datasets option of ${t} is invalid. Use letters, digits, \`-\` and \`_\`, starting with a letter or digit.`)}function parseDatasets(e,t){if(e===void 0)return{};if(typeof e!=`object`||!e||Array.isArray(e))throw Error(`seedPlugin datasets must map names to lists of dataset directory names in ${t}.`);let n={};for(let[r,i]of Object.entries(e)){if(assertDatasetName(r,t),!Array.isArray(i))throw Error(`seedPlugin datasets.${r} must be an array of dataset directory names in ${t}.`);if(i.length===0)throw Error(`seedPlugin datasets.${r} lists no dataset directories in ${t}.`);for(let e of i){if(typeof e!=`string`)throw Error(`seedPlugin datasets.${r} must be an array of dataset directory names in ${t}.`);assertDatasetName(e,t)}n[r]=i}return n}function colorizeExecutorJobStatus(e){switch(e){case`PENDING`:return h.dim(e);case`RUNNING`:return h.info(e);case`SUCCESS`:return h.success(e);case`FAILED`:return h.error(e);case`CANCELED`:return h.warning(e);default:return e}}const Hc={[Xn.UNSPECIFIED]:`transient`,[Xn.PENDING]:`transient`,[Xn.RUNNING]:`transient`,[Xn.SUCCESS]:`success`,[Xn.FAILED]:`failure`,[Xn.CANCELED]:`failure`};function classifyExecutorJobStatus(e){return protoEnumLookup(Hc,e,`transient`)}const Uc=protoEnumNames(Xn).filter(e=>e!==`UNSPECIFIED`);function parseExecutorJobStatus(e){let t=parseProtoEnumName(Xn,e,[Xn.UNSPECIFIED]);if(t===void 0)throw E({code:`EXECUTOR_STATUS_INVALID`,message:`Invalid status: ${e}. Valid values: ${Uc.join(`, `)}`});return t}const Wc={[I.UNSPECIFIED]:`UNSPECIFIED`,[I.WEBHOOK]:`WEBHOOK`,[I.TAILOR_GRAPHQL]:`GRAPHQL`,[I.FUNCTION]:`FUNCTION`,[I.JOB_FUNCTION]:`JOB_FUNCTION`,[I.WORKFLOW]:`WORKFLOW`};function executorTargetTypeToString(e){return protoEnumLookup(Wc,e,`UNSPECIFIED`)}function executorTriggerTypeToString(e){return protoEnumName(ir,e)??`UNSPECIFIED`}function executorJobStatusToString(e){return protoEnumName(Xn,e)??`UNSPECIFIED`}function toExecutorJobListInfo(e){return{id:e.id,executorName:e.executorName,status:executorJobStatusToString(e.status),createdAt:e.createdAt?G(e.createdAt).toISOString():`N/A`}}function toExecutorJobInfo(e){return{id:e.id,executorName:e.executorName,status:executorJobStatusToString(e.status),scheduledAt:e.scheduledAt?G(e.scheduledAt).toISOString():`N/A`,createdAt:e.createdAt?G(e.createdAt).toISOString():`N/A`,updatedAt:e.updatedAt?G(e.updatedAt).toISOString():`N/A`}}function toExecutorJobAttemptInfo(e){return{id:e.id,jobId:e.jobId,status:executorJobStatusToString(e.status),error:e.error||``,startedAt:e.startedAt?G(e.startedAt).toISOString():`N/A`,finishedAt:e.finishedAt?G(e.finishedAt).toISOString():`N/A`,operationReference:e.operationReference||``}}function formatSubjectEvent(e,t){let n=t.map(e=>e.split(`.`).at(-1)??e).join(`, `);return n?`event: ${e} ${n}`:`event: ${e}`}function formatTypedEventTrigger(e){let t=e.typedConfig;if(t.case===void 0)return null;switch(t.case){case`tailordb`:return formatSubjectEvent(t.value.typeName,t.value.eventTypes);case`pipeline`:return formatSubjectEvent(t.value.resolverName,t.value.eventTypes);case`idp`:return formatSubjectEvent(`idp user`,t.value.eventTypes);case`auth`:return formatSubjectEvent(`auth access_token`,t.value.eventTypes);default:return null}}function formatTriggerType(e){let t=e.triggerConfig?.config;if(!t||t.case===void 0)return executorTriggerTypeToString(e.triggerType);switch(t.case){case`schedule`:return`schedule: ${t.value.frequency} (${t.value.timezone})`;case`event`:{let n=formatTypedEventTrigger(t.value);if(n)return n;let r=readLegacyEventTriggerConfig(t.value);return r.eventType?formatEventTrigger(r.eventType,r.condition):executorTriggerTypeToString(e.triggerType)}case`incomingWebhook`:return`webhook`;default:return executorTriggerTypeToString(e.triggerType)}}function readLegacyEventTriggerConfig(e){return{eventType:e.eventType,condition:e.condition?.expr}}function formatEventTrigger(e,t){let n=e.split(`.`);if(n.length<3)return`event: ${e}`;let[r,i,a]=n;if(t){let e=t.match(/args\.typeName\s*===?\s*["']([^"']+)["']/);if(e)return`event: ${e[1]} ${a}`;let n=t.match(/args\.resolverName\s*===?\s*["']([^"']+)["']/);if(n)return`event: ${n[1]} ${a}`}return`event: ${r} ${i} ${a}`}function formatTriggerConfig(e){let t=e.triggerConfig?.config;if(!t||t.case===void 0)return{};switch(t.case){case`schedule`:return{timezone:t.value.timezone,frequency:t.value.frequency};case`event`:return formatEventTriggerConfig(t.value);case`incomingWebhook`:return{secret:t.value.secret?`***`:``};default:return{}}}function formatEventTriggerConfig(e){let t=e.typedConfig;if(t.case===void 0){let t=readLegacyEventTriggerConfig(e);return{eventType:t.eventType,condition:t.condition||``}}if(t.case===`workflow`)return{kind:t.case,eventTypes:t.value.eventTypes,condition:t.value.condition?.expr||``,...t.value.workflowName&&{workflowName:t.value.workflowName}};let n={kind:t.case,eventTypes:t.value.eventTypes,namespaceName:t.value.namespaceName,condition:t.value.condition?.expr||``};switch(t.case){case`tailordb`:return{...n,typeName:t.value.typeName};case`pipeline`:return{...n,resolverName:t.value.resolverName};default:return n}}function formatTargetConfig(e){let t=e.targetConfig?.config;if(!t||t.case===void 0)return{};switch(t.case){case`webhook`:return{url:t.value.url?.expr||``,headers:t.value.headers.length};case`tailorGraphql`:return{appName:t.value.appName,query:t.value.query};case`function`:return{name:t.value.name};case`workflow`:return{workflowName:t.value.workflowName};default:return{}}}function toExecutorListInfo(e){return{name:e.name,triggerType:formatTriggerType(e),targetType:executorTargetTypeToString(e.targetType),disabled:e.disabled}}function toExecutorInfo(e){return{name:e.name,description:e.description,triggerType:formatTriggerType(e),targetType:executorTargetTypeToString(e.targetType),disabled:e.disabled,triggerConfig:formatTriggerConfig(e),targetConfig:formatTargetConfig(e)}}const Gc={name:V(U.string(),{positional:!0,description:`Executor name`})};async function resolveExecutor(e,t,n){let{executor:r}=await e.getExecutorExecutor({workspaceId:t,name:n});if(!r)throw E({code:`EXECUTOR_NOT_FOUND`,message:`Executor '${n}' not found.`});return r}async function getExecutor(e){let t=e.executor.name,{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId});try{return toExecutorInfo(await resolveExecutor(n,r,t))}catch(e){throw e instanceof q&&e.code===K.NotFound?E({code:`EXECUTOR_NOT_FOUND`,message:`Executor '${t}' not found.`,cause:e}):e}}const Kc=Y({name:`get`,description:`Get executor details`,args:U.strictObject({...j,...Gc}),run:async e=>{let t=await getExecutor({executor:{name:e.name},workspaceId:e[`workspace-id`],profile:e.profile});C.out(t,{display:{triggerConfig:null,targetConfig:null}})}}),qc=U.enum([`success`,`suspended`,`terminal`]),Jc={name:V(U.string(),{positional:!0,description:`Workflow name`})},Yc={interval:V(ie.default(`3s`),{alias:`i`,description:`Polling interval when waiting (e.g., '3s', '500ms', '1m')`}),timeout:V(ie.default(`10m`),{alias:`t`,description:`Maximum time to wait (e.g., '30s', '10m')`}),until:V(qc.default(`terminal`),{alias:`u`,description:`Wait target (success, suspended, terminal)`}),logs:V(U.boolean().default(!1),{alias:`l`,description:`Display job execution logs after completion`})},Xc={wait:V(U.boolean().default(!1),{alias:`W`,description:`Wait for execution to complete`}),...Yc};function workflowExecutionStatusToString(e){return protoEnumName(R,e)??`UNSPECIFIED`}function workflowJobExecutionStatusToString(e){return protoEnumName(z,e)??`UNSPECIFIED`}function toWorkflowListInfo(e){return{name:e.name,mainJob:e.mainJobFunctionName,jobFunctions:Object.keys(e.jobFunctions).length,updatedAt:e.updatedAt?G(e.updatedAt):null}}function toWorkflowInfo(e){let t={};for(let[n,r]of Object.entries(e.jobFunctions))t[n]=r.toString();return{name:e.name,id:e.id,mainJob:e.mainJobFunctionName,jobFunctions:t,createdAt:e.createdAt?G(e.createdAt):null,updatedAt:e.updatedAt?G(e.updatedAt):null}}function toWorkflowJobExecutionInfo(e){return{id:e.id,stackedJobName:e.stackedJobName,status:workflowJobExecutionStatusToString(e.status),executionId:e.executionId,startedAt:e.startedAt?G(e.startedAt):null,finishedAt:e.finishedAt?G(e.finishedAt):null}}function toWorkflowExecutionInfo(e){return{id:e.id,workflowName:e.workflowName,status:workflowExecutionStatusToString(e.status),jobExecutions:e.jobExecutions.length,startedAt:e.startedAt?G(e.startedAt):null,finishedAt:e.finishedAt?G(e.finishedAt):null}}function formatTime$1(e){return e.toLocaleTimeString(`en-US`,{hour12:!1})}function colorizeStatus(e){let t=R[e];switch(e){case R.PENDING:case R.UNSPECIFIED:return h.dim(t);case R.PENDING_RESUME:case R.PENDING_RETRY:case R.WAITING:return h.warning(t);case R.RUNNING:return h.info(t);case R.SUCCESS:return h.success(t);case R.FAILED:case R.CANCELED:return h.error(t);default:return t}}function getActiveJobs(e){return e.jobExecutions.filter(e=>e.status===z.RUNNING||e.status===z.SUSPEND||e.status===z.WAITING).map(e=>e.stackedJobName).join(`, `)}function createWorkflowWaitResult(e){let t=Date.now()-e.startedAt;if(e.execution){let n=classifyWorkflowExecutionStatus(e.execution);return{...toWorkflowExecutionInfo(e.execution),statusClass:n.statusClass,elapsedMs:t,attempts:e.attempts,timedOut:e.timedOut,lastError:e.lastError}}return{id:e.executionId,workflowName:``,status:`UNKNOWN`,statusClass:`unknown`,jobExecutions:0,startedAt:null,finishedAt:null,elapsedMs:t,attempts:e.attempts,timedOut:e.timedOut,lastError:e.lastError}}async function waitForWorkflowExecution(e){let t=e.interval??3e3,n=e.until??`terminal`,r=Date.now(),i=e.showProgress?spinner({indent:2}).start(`Waiting for workflow to complete...`):null,a=0,o,s=null,c,l;try{for(;;){let u=Date.now()-r,d=e.timeout===void 0?void 0:e.timeout-u;if(d!==void 0&&d<=0)return i?.fail(`Workflow wait timed out.`),createWorkflowWaitResult({executionId:e.executionId,execution:o,startedAt:r,attempts:a,timedOut:!0,lastError:s});try{a+=1;let{execution:t}=await e.client.getWorkflowExecution({workspaceId:e.workspaceId,executionId:e.executionId});if(!t)throw i?.fail(`Execution '${e.executionId}' not found.`),E({code:`WORKFLOW_EXECUTION_NOT_FOUND`,message:`Execution '${e.executionId}' not found.`});o=t,s=null;let u=classifyWorkflowExecutionStatus(t),d=colorizeStatus(t.status);if(t.status!==c&&(e.showProgress&&(i?.stop(),C.info(`Status: ${d}`,{mode:`stream`,indent:2}),i?.start(`Waiting for workflow to complete...`)),c=t.status),e.trackJobs){let n=getActiveJobs(t);n&&n!==l&&(e.showProgress&&(i?.stop(),C.info(`Job | ${n}: ${d}`,{mode:`stream`,indent:2}),i?.start(`Waiting for workflow to complete...`)),l=n)}if(i&&(i.text=`Waiting for workflow to complete... (${formatTime$1(/* @__PURE__ */ new Date)})`),hasReachedWorkflowWaitTarget(u,n)||u.statusClass===`failure`||n===`suspended`&&u.statusClass===`success`)return t.status===R.SUCCESS?i?.succeed(`Completed: ${d}`):isWorkflowExecutionFailureStatus(t.status)?i?.fail(`Completed: ${d}`):isWorkflowExecutionSuspendedStatus(t.status)?i?.warn(`Completed: ${d}`):i?.succeed(`Completed: ${d}`),createWorkflowWaitResult({executionId:e.executionId,execution:t,startedAt:r,attempts:a,timedOut:!1,lastError:s})}catch(t){if(!isRetryableWaitError(t))throw t;s=formatWaitError(t),e.showProgress&&i&&(i.text=`Retrying workflow status poll... (${formatTime$1(/* @__PURE__ */ new Date)})`)}let f=Date.now()-r,p=e.timeout===void 0?void 0:e.timeout-f;if(p!==void 0&&p<=0)return i?.fail(`Workflow wait timed out.`),createWorkflowWaitResult({executionId:e.executionId,execution:o,startedAt:r,attempts:a,timedOut:!0,lastError:s});await Fi(p===void 0?t:Math.min(t,p))}}finally{i?.stop()}}async function waitForWorkflowExecutionById(e){let{client:t,workspaceId:n}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId});return await waitForWorkflowExecution({client:t,workspaceId:n,executionId:e.executionId,interval:e.interval,timeout:e.timeout,until:e.until,showProgress:e.showProgress,trackJobs:e.trackJobs})}function getWorkflowWaitFailure(e,t){let n={executionId:e.id,status:e.status};if(e.timedOut)return E({code:`WORKFLOW_WAIT_TIMEOUT`,message:`Timed out waiting for workflow execution '${e.id}' to reach ${t}. Last status: ${e.status}.`,context:n});if(e.status===`FAILED`)return E({code:`WORKFLOW_EXECUTION_FAILED`,message:`Workflow execution '${e.id}' failed.`,context:n});if(e.status===`CANCELED`)return E({code:`WORKFLOW_EXECUTION_CANCELED`,message:`Workflow execution '${e.id}' was canceled.`,context:n});if(t===`success`&&e.statusClass!==`success`)return E({code:`WORKFLOW_EXECUTION_NOT_SUCCESSFUL`,message:`Workflow execution '${e.id}' reached ${e.status} before success.`,context:n});if(t===`suspended`&&e.statusClass!==`suspended`)return E({code:`WORKFLOW_EXECUTION_NOT_SUSPENDED`,message:`Workflow execution '${e.id}' reached ${e.status} before suspension.`,context:n})}function parseStatus(e){let t=parseProtoEnumName(R,e);if(t===void 0)throw E({code:`WORKFLOW_STATUS_INVALID`,message:`Invalid status: ${e}. Valid values: ${protoEnumNames(R).join(`, `)}`,command:`workflow executions`});return t}async function listWorkflowExecutions(e){let t=e?.workflow?.name,{client:a,workspaceId:o}=await loadOperatorWorkspaceContext({profile:e?.profile,workspaceId:e?.workspaceId}),s=[];if(e?.status){let t=parseStatus(e.status);s.push(Yr(r,{condition:Yr(i,{field:`status`,operator:n.EQ,value:{kind:{case:`numberValue`,value:t}}})}))}let c=s.length>0?Yr(r,{and:s}):void 0,l=Ce(e?.order??`desc`);return(await Pt(async(e,n)=>{let{executions:r,nextPageToken:i}=await a.listWorkflowExecutions({workspaceId:o,workflowName:t??``,pageToken:e,pageSize:n,pageDirection:l,filter:c});return[r,i]},{limit:e?.limit})).map(toWorkflowExecutionInfo)}async function getWorkflowExecution(e){let{client:t,workspaceId:n}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId});async function fetchFunctionExecution(e){try{let{execution:r}=await t.getFunctionExecution({workspaceId:n,executionId:e});return r}catch(t){t instanceof q&&t.code===K.NotFound||C.warn(`Could not fetch logs for function execution '${e}': ${t instanceof Error?t.message:String(t)}`);return}}async function fetchExecutionWithLogs(e,r){let{execution:i}=await t.getWorkflowExecution({workspaceId:n,executionId:e});if(!i)throw E({code:`WORKFLOW_EXECUTION_NOT_FOUND`,message:`Execution '${e}' not found.`});let a=toWorkflowExecutionInfo(i);return r&&i.jobExecutions.length>0&&(a.jobDetails=await Promise.all(i.jobExecutions.map(async e=>{let t=toWorkflowJobExecutionInfo(e);if(e.executionId){let n=await fetchFunctionExecution(e.executionId);if(n)return{...t,...collectFunctionExecutionLogs(n.logEntries),result:n.result||void 0}}return t}))),a}async function waitForCompletion(){let r=e.interval??3e3,i=await waitForWorkflowExecution({client:t,workspaceId:n,executionId:e.executionId,interval:r,timeout:e.timeout,until:e.until??`terminal`});return{...await fetchExecutionWithLogs(e.executionId,e.logs??!1),statusClass:i.statusClass,elapsedMs:i.elapsedMs,attempts:i.attempts,timedOut:i.timedOut,lastError:i.lastError}}return{execution:await fetchExecutionWithLogs(e.executionId,e.logs??!1),wait:waitForCompletion}}function printExecutionWithLogs(e){let formatDate=e=>e?e.toISOString():`N/A`,t=[[`id`,e.id],[`workflowName`,e.workflowName],[`status`,e.status],[`jobExecutions`,e.jobExecutions.toString()],[`startedAt`,formatDate(e.startedAt)],[`finishedAt`,formatDate(e.finishedAt)]];if(C.out(formatKeyValueTable(t)),e.jobDetails&&e.jobDetails.length>0){C.log(h.bold(`
|
|
488
494
|
Job Executions:`));for(let t of e.jobDetails){C.log(h.info(`\n--- ${t.stackedJobName} ---`)),C.log(` Status: ${t.status}`),C.log(` Started: ${formatDate(t.startedAt)}`),C.log(` Finished: ${formatDate(t.finishedAt)}`);let e=formatFunctionLogLines(t.logEntries);if(e.length>0){C.log(h.warning(`
|
|
489
495
|
Logs:`));for(let t of e)C.log(` ${t}`)}if(t.result){C.log(h.success(`
|
|
490
496
|
Result:`));try{let e=JSON.parse(t.result);C.log(` ${JSON.stringify(e,null,2).split(`
|
|
491
497
|
`).join(`
|
|
492
|
-
`)}`)}catch{C.log(` ${t.result}`)}}}}}const Gc=Y({name:`executions`,description:`List or get workflow executions.`,args:U.strictObject({...j,...me,"execution-id":V(U.string().optional(),{positional:!0,description:`Execution ID (if provided, shows details)`}),"workflow-name":V(U.string().regex(/^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$/,`Must be 3-63 lowercase alphanumeric characters or hyphens, starting and ending with alphanumeric`).optional(),{alias:`n`,description:`Filter by workflow name (list mode only)`}),status:V(U.string().optional(),{alias:`s`,description:`Filter by status (list mode only)`}),...Wc,logs:V(U.boolean().default(!1),{description:`Display job execution logs (detail mode only)`})}),run:async e=>{let t=C.jsonMode||e.json;if(e.executionId){let n=he(e.interval);if(t||C.info(`Execution ID: ${e.executionId}`,{mode:`stream`}),e.wait){let r=await waitForWorkflowExecutionById({executionId:e.executionId,workspaceId:e[`workspace-id`],profile:e.profile,interval:n,timeout:he(e.timeout),until:e.until,showProgress:!t,trackJobs:!0});if(e.logs&&!t){let{execution:t}=await getWorkflowExecution({executionId:e.executionId,workspaceId:e[`workspace-id`],profile:e.profile,logs:!0});printExecutionWithLogs(t)}else if(e.logs){let{execution:t}=await getWorkflowExecution({executionId:e.executionId,workspaceId:e[`workspace-id`],profile:e.profile,logs:!0}),n={...r,jobDetails:t.jobDetails};C.out(n)}else C.out(r);let i=getWorkflowWaitFailure(r,e.until);if(i)throw i;return}let{execution:r}=await getWorkflowExecution({executionId:e.executionId,workspaceId:e[`workspace-id`],profile:e.profile,interval:n,logs:e.logs});e.logs&&!t?printExecutionWithLogs(r):C.out(r)}else{let t=await fetchWithinLimit(e.limit,t=>listWorkflowExecutions({workspaceId:e[`workspace-id`],profile:e.profile,workflow:e[`workflow-name`]===void 0?void 0:{name:e[`workflow-name`]},status:e.status,order:e.order,limit:t})),n=t.items;C.out(n),await reportTruncation(t,e.limit)}}});async function resolveWorkflow(e,t,n){let{workflow:r}=await e.getWorkflowByName({workspaceId:t,workflowName:n});if(!r)throw E({code:`WORKFLOW_NOT_FOUND`,message:`Workflow '${n}' not found.`});return r}async function getWorkflow(e){let t=e.workflow.name,{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId});try{return toWorkflowInfo(await resolveWorkflow(n,r,t))}catch(e){throw e instanceof q&&e.code===K.NotFound?E({code:`WORKFLOW_NOT_FOUND`,message:`Workflow '${t}' not found.`,cause:e}):e}}const Kc=Y({name:`get`,description:`Get workflow details.`,args:U.strictObject({...j,...Hc}),run:async e=>{let t=await getWorkflow({workflow:{name:e.name},workspaceId:e[`workspace-id`],profile:e.profile});C.out(t)}});async function startWorkflowCore(e){let{client:t,workspaceId:n,workflowName:r}=e;try{let i=await resolveWorkflow(t,n,r),a=Kr(un,e.invoker),o=e.arg===void 0?void 0:typeof e.arg==`string`?e.arg:JSON.stringify(e.arg),{executionId:s}=await t.startWorkflow({workspaceId:n,workflowId:i.id,authInvoker:a,arg:o});return{executionId:s,wait:r=>waitForWorkflowExecution({client:t,workspaceId:n,executionId:s,interval:e.interval??3e3,timeout:r?.timeout,until:r?.until,showProgress:r?.showProgress,trackJobs:!0})}}catch(e){throw e instanceof q&&e.code===K.NotFound?E({code:`WORKFLOW_NOT_FOUND`,message:`Workflow '${r}' not found.`,cause:e}):e}}async function resolveApplicationAuthNamespace(e){let{config:t}=await loadConfig(e.configPath),{application:n}=await e.client.getApplication({workspaceId:e.workspaceId,applicationName:t.name}),r=n?.authNamespace||t.auth?.name;if(!r)throw E({code:`AUTH_CONFIG_REQUIRED`,message:`Application ${t.name} does not have an auth configuration.`});return r}async function startWorkflowByName(e){let t=await be({machineUser:e.machineUser,machineUserSource:e.machineUserSource,profile:e.profile});if(!t)throw E({code:`MACHINE_USER_REQUIRED`,message:`Machine user is required.`,suggestion:`Specify --machine-user, set TAILOR_PLATFORM_MACHINE_USER_NAME, or set a profile default with 'tailor profile update <profile> --machine-user <name>'.`});let{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId}),i=await resolveApplicationAuthNamespace({client:n,workspaceId:r,configPath:e.configPath});return await startWorkflowCore({client:n,workspaceId:r,workflowName:e.name,invoker:{namespace:i,machineUserName:t},arg:e.arg,interval:e.interval})}async function startWorkflow(e){let{client:t,workspaceId:n}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId}),r=await resolveApplicationAuthNamespace({client:t,workspaceId:n,configPath:e.configPath});return await startWorkflowCore({client:t,workspaceId:n,workflowName:e.workflow.name,invoker:{namespace:r,machineUserName:e.invoker},arg:e.arg,interval:e.interval})}const qc=Y({name:`start`,description:`Start a workflow execution.`,args:U.strictObject({...k,...Hc,"machine-user":V(U.string().optional(),{alias:`m`,description:`Machine user name. Falls back to the active profile's default machine user.`,env:`TAILOR_PLATFORM_MACHINE_USER_NAME`}),arg:V(U.string().optional(),{alias:`a`,description:`Workflow argument (JSON string)`}),...Wc}),run:async e=>{let{executionId:t,wait:n}=await startWorkflowByName({name:e.name,machineUser:e[`machine-user`],machineUserSource:_e(e[`machine-user`]),arg:e.arg,workspaceId:e[`workspace-id`],profile:e.profile,configPath:e.config,interval:he(e.interval)}),r=C.jsonMode;if(C.info(`Execution ID: ${t}`,{mode:`stream`}),e.wait){let i=await n({showProgress:!r,timeout:he(e.timeout),until:e.until});if(e.logs&&!r){let{execution:n}=await getWorkflowExecution({executionId:t,workspaceId:e[`workspace-id`],profile:e.profile,logs:!0});printExecutionWithLogs(n)}else if(e.logs){let{execution:n}=await getWorkflowExecution({executionId:t,workspaceId:e[`workspace-id`],profile:e.profile,logs:!0});C.out({...i,jobDetails:n.jobDetails})}else C.out(i);let a=getWorkflowWaitFailure(i,e.until);if(a)throw a}else C.out({executionId:t})}});function formatTime(e){return e.toLocaleTimeString(`en-US`,{hour12:!1})}function createUnknownExecutorJob(e,t){return{id:t,executorName:e,status:`UNKNOWN`,scheduledAt:`N/A`,createdAt:`N/A`,updatedAt:`N/A`}}async function listExecutorJobs(e){let t=e.executor.name,{client:a,workspaceId:o}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId}),s=[];if(e.status){let t=parseExecutorJobStatus(e.status);s.push(Kr(r,{condition:Kr(i,{field:`status`,operator:n.EQ,value:{kind:{case:`numberValue`,value:t}}})}))}let c=s.length>0?Kr(r,{and:s}):void 0,l=Ce(e.order??`desc`);try{return(await Mt(async(e,n)=>{let{jobs:r,nextPageToken:i}=await a.listExecutorJobs({workspaceId:o,executorName:t,pageToken:e,pageSize:n,pageDirection:l,filter:c});return[r,i]},{limit:e.limit})).map(toExecutorJobListInfo)}catch(e){throw e instanceof q&&e.code===K.NotFound?E({code:`EXECUTOR_NOT_FOUND`,message:`Executor '${t}' not found.`,cause:e}):e}}async function getExecutorJob(e){let n=e.executor.name,{client:r,workspaceId:i}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId});try{let{job:a}=await r.getExecutorJob({workspaceId:i,executorName:n,jobId:e.jobId});if(!a)throw E({code:`EXECUTOR_JOB_NOT_FOUND`,message:`Job '${e.jobId}' not found.`});let o=toExecutorJobInfo(a);if(e.attempts){let n=await jt(async(n,a)=>{let{attempts:o,nextPageToken:s}=await r.listExecutorJobAttempts({workspaceId:i,jobId:e.jobId,pageToken:n,pageSize:a,pageDirection:t.DESC});return[o,s]});return{...o,attempts:n.map(toExecutorJobAttemptInfo)}}return o}catch(t){throw t instanceof q&&t.code===K.NotFound?E({code:`EXECUTOR_JOB_NOT_FOUND`,message:`Job '${e.jobId}' not found for executor '${n}'.`,cause:t}):t}}async function watchExecutorJob(e){let n=e.executor.name,{client:r,workspaceId:i}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId}),a=e.interval??3e3,o=e.timeout,s=e.showProgress??!C.jsonMode,c=Date.now(),l=s?spinner().start(`Waiting for executor job to complete...`):null,u=0,d=null,remainingTimeout=()=>{if(o!==void 0)return o-(Date.now()-c)},withWaitMetadata=(e,t)=>({...e,elapsedMs:Date.now()-c,attempts:u,timedOut:t,lastError:d}),timeoutResult=(t,r)=>withWaitMetadata({job:r?toExecutorJobInfo(r):createUnknownExecutorJob(n,e.jobId),targetType:t},!0);try{let{executor:o}=await r.getExecutorExecutor({workspaceId:i,name:n});if(!o)throw E({code:`EXECUTOR_NOT_FOUND`,message:`Executor '${n}' not found.`});let c=o.targetType,f=executorTargetTypeToString(c),p;for(;;){let t=remainingTimeout();if(t!==void 0&&t<=0)return l?.fail(`Executor job wait timed out.`),timeoutResult(f,p);try{if(u+=1,p=(await r.getExecutorJob({workspaceId:i,executorName:n,jobId:e.jobId})).job,!p)throw E({code:`EXECUTOR_JOB_NOT_FOUND`,message:`Job '${e.jobId}' not found.`});if(d=null,classifyExecutorJobStatus(p.status)!==`transient`)break}catch(e){if(!isRetryableWaitError(e))throw e;d=formatWaitError(e),l&&(l.text=`Retrying executor job poll... (${formatTime(/* @__PURE__ */ new Date)})`)}let o=remainingTimeout();if(o!==void 0&&o<=0)return l?.fail(`Executor job wait timed out.`),timeoutResult(f,p);l&&(l.text=`Waiting for executor job... (${formatTime(/* @__PURE__ */ new Date)})`),await zi(o===void 0?a:Math.min(a,o))}let m=toExecutorJobInfo(p),h=colorizeExecutorJobStatus(m.status);p.status===qn.SUCCESS?l?.succeed(`Executor job completed: ${h}`):l?.fail(`Executor job completed: ${h}`);let g=(await jt(async(n,a)=>{let{attempts:o,nextPageToken:s}=await r.listExecutorJobAttempts({workspaceId:i,jobId:e.jobId,pageToken:n,pageSize:a,pageDirection:t.DESC});return[o,s]})).map(toExecutorJobAttemptInfo),_={...m,attempts:g},v=g[0]?.operationReference;if(v)switch(c){case I.WORKFLOW:l?.stop();try{let t=remainingTimeout();if(t!==void 0&&t<=0)return withWaitMetadata({job:_,targetType:f,workflowExecutionId:v},!0);let n=await waitForWorkflowExecution({client:r,workspaceId:i,executionId:v,interval:a,timeout:t,showProgress:s,trackJobs:!0});u+=n.attempts,d=n.lastError;let o;if(e.logs)try{let{execution:t}=await getWorkflowExecution({executionId:v,workspaceId:e.workspaceId,profile:e.profile,logs:!0});t.jobDetails&&(o=t.jobDetails.filter(e=>e.logs||e.result).map(e=>({jobName:e.stackedJobName||e.id,logs:e.logs,logEntries:e.logEntries,result:e.result})))}catch(e){C.warn(`Could not fetch workflow execution logs: ${e instanceof Error?e.message:e}`)}return withWaitMetadata({job:_,targetType:f,workflowExecutionId:v,workflowStatus:n.status,workflowJobLogs:o},n.timedOut)}catch(e){return C.warn(`Could not track workflow execution: ${e instanceof Error?e.message:e}`),withWaitMetadata({job:_,targetType:f,workflowExecutionId:v},!1)}case I.FUNCTION:case I.JOB_FUNCTION:l?.start(`Waiting for function execution ${v}...`);try{let t;for(;;){let n=remainingTimeout();if(n!==void 0&&n<=0)return l?.fail(`Function execution wait timed out.`),withWaitMetadata({job:_,targetType:f,functionExecutionId:v,functionStatus:t},!0);try{u+=1;let{execution:n}=await r.getFunctionExecution({workspaceId:i,executionId:v});if(!n)throw E({code:`FUNCTION_EXECUTION_NOT_FOUND`,message:`Function execution '${v}' not found.`});if(d=null,t=functionExecutionStatusToString(n.status),isFunctionExecutionTerminalStatus(n.status)){let r=colorizeFunctionExecutionStatus(t);n.status===On.SUCCESS?l?.succeed(`Function execution completed: ${r}`):l?.fail(`Function execution completed: ${r}`);let i=e.logs?collectFunctionExecutionLogs(n.logEntries):void 0;return withWaitMetadata({job:_,targetType:f,functionExecutionId:v,functionStatus:t,functionLogs:i?.logs,functionLogEntries:i?.logEntries},!1)}}catch(e){if(!isRetryableWaitError(e))throw e;d=formatWaitError(e),l&&(l.text=`Retrying function execution poll... (${formatTime(/* @__PURE__ */ new Date)})`)}let o=remainingTimeout();if(o!==void 0&&o<=0)return l?.fail(`Function execution wait timed out.`),withWaitMetadata({job:_,targetType:f,functionExecutionId:v,functionStatus:t},!0);l&&(l.text=`Waiting for function execution... (${formatTime(/* @__PURE__ */ new Date)})`),await zi(o===void 0?a:Math.min(a,o))}}catch(e){return l?.warn(`Could not track function execution: ${e instanceof Error?e.message:e}`),withWaitMetadata({job:_,targetType:f,functionExecutionId:v},!1)}}return withWaitMetadata({job:_,targetType:f},!1)}finally{l?.stop()}}function getExecutorWaitFailure(e){let t={jobId:e.job.id,status:e.job.status,workflowExecutionId:e.workflowExecutionId,functionExecutionId:e.functionExecutionId};if(e.timedOut)return E({code:`EXECUTOR_WAIT_TIMEOUT`,message:`Timed out waiting for executor job '${e.job.id}'. Last status: ${e.job.status}.`,context:t});if(e.job.status===`FAILED`||e.job.status===`CANCELED`)return E({code:`EXECUTOR_JOB_FAILED`,message:`Executor job '${e.job.id}' completed with status ${e.job.status}.`,context:t});if(e.workflowStatus===`FAILED`)return E({code:`WORKFLOW_EXECUTION_FAILED`,message:`Workflow execution '${e.workflowExecutionId}' failed.`,context:t});if(e.workflowStatus===`CANCELED`)return E({code:`WORKFLOW_EXECUTION_CANCELED`,message:`Workflow execution '${e.workflowExecutionId}' was canceled.`,context:t});if(e.functionStatus===`FAILED`)return E({code:`FUNCTION_EXECUTION_FAILED`,message:`Function execution '${e.functionExecutionId}' failed.`,context:t});if(e.functionStatus===`CANCELED`)return E({code:`FUNCTION_EXECUTION_CANCELED`,message:`Function execution '${e.functionExecutionId}' was canceled.`,context:t})}function getExecutorWaitFailureMessage(e){return getExecutorWaitFailure(e)?.message}function printJobWithAttempts(e){let t=[[`id`,e.id],[`executorName`,e.executorName],[`status`,e.status],[`scheduledAt`,e.scheduledAt],[`createdAt`,e.createdAt],[`updatedAt`,e.updatedAt]];if(C.log(formatKeyValueTable(t)),e.attempts&&e.attempts.length>0){C.log(h.bold(`
|
|
498
|
+
`)}`)}catch{C.log(` ${t.result}`)}}}}}const Zc=Y({name:`executions`,description:`List or get workflow executions.`,args:U.strictObject({...j,...me,"execution-id":V(U.string().optional(),{positional:!0,description:`Execution ID (if provided, shows details)`}),"workflow-name":V(U.string().regex(/^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$/,`Must be 3-63 lowercase alphanumeric characters or hyphens, starting and ending with alphanumeric`).optional(),{alias:`n`,description:`Filter by workflow name (list mode only)`}),status:V(U.string().optional(),{alias:`s`,description:`Filter by status (list mode only)`}),...Xc,logs:V(U.boolean().default(!1),{description:`Display job execution logs (detail mode only)`})}),run:async e=>{let t=C.jsonMode||e.json;if(e.executionId){let n=he(e.interval);if(t||C.info(`Execution ID: ${e.executionId}`,{mode:`stream`}),e.wait){let r=await waitForWorkflowExecutionById({executionId:e.executionId,workspaceId:e[`workspace-id`],profile:e.profile,interval:n,timeout:he(e.timeout),until:e.until,showProgress:!t,trackJobs:!0});if(e.logs&&!t){let{execution:t}=await getWorkflowExecution({executionId:e.executionId,workspaceId:e[`workspace-id`],profile:e.profile,logs:!0});printExecutionWithLogs(t)}else if(e.logs){let{execution:t}=await getWorkflowExecution({executionId:e.executionId,workspaceId:e[`workspace-id`],profile:e.profile,logs:!0}),n={...r,jobDetails:t.jobDetails};C.out(n)}else C.out(r);let i=getWorkflowWaitFailure(r,e.until);if(i)throw i;return}let{execution:r}=await getWorkflowExecution({executionId:e.executionId,workspaceId:e[`workspace-id`],profile:e.profile,interval:n,logs:e.logs});e.logs&&!t?printExecutionWithLogs(r):C.out(r)}else{let t=await fetchWithinLimit(e.limit,t=>listWorkflowExecutions({workspaceId:e[`workspace-id`],profile:e.profile,workflow:e[`workflow-name`]===void 0?void 0:{name:e[`workflow-name`]},status:e.status,order:e.order,limit:t})),n=t.items;C.out(n),await reportTruncation(t,e.limit)}}});async function resolveWorkflow(e,t,n){let{workflow:r}=await e.getWorkflowByName({workspaceId:t,workflowName:n});if(!r)throw E({code:`WORKFLOW_NOT_FOUND`,message:`Workflow '${n}' not found.`});return r}async function getWorkflow(e){let t=e.workflow.name,{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId});try{return toWorkflowInfo(await resolveWorkflow(n,r,t))}catch(e){throw e instanceof q&&e.code===K.NotFound?E({code:`WORKFLOW_NOT_FOUND`,message:`Workflow '${t}' not found.`,cause:e}):e}}const Qc=Y({name:`get`,description:`Get workflow details.`,args:U.strictObject({...j,...Jc}),run:async e=>{let t=await getWorkflow({workflow:{name:e.name},workspaceId:e[`workspace-id`],profile:e.profile});C.out(t)}});async function startWorkflowCore(e){let{client:t,workspaceId:n,workflowName:r}=e;try{let i=await resolveWorkflow(t,n,r),a=Yr(pn,e.invoker),o=e.arg===void 0?void 0:typeof e.arg==`string`?e.arg:JSON.stringify(e.arg),{executionId:s}=await t.startWorkflow({workspaceId:n,workflowId:i.id,authInvoker:a,arg:o});return{executionId:s,wait:r=>waitForWorkflowExecution({client:t,workspaceId:n,executionId:s,interval:e.interval??3e3,timeout:r?.timeout,until:r?.until,showProgress:r?.showProgress,trackJobs:!0})}}catch(e){throw e instanceof q&&e.code===K.NotFound?E({code:`WORKFLOW_NOT_FOUND`,message:`Workflow '${r}' not found.`,cause:e}):e}}async function resolveApplicationAuthNamespace(e){let{config:t}=await loadConfig(e.configPath),{application:n}=await e.client.getApplication({workspaceId:e.workspaceId,applicationName:t.name}),r=n?.authNamespace||t.auth?.name;if(!r)throw E({code:`AUTH_CONFIG_REQUIRED`,message:`Application ${t.name} does not have an auth configuration.`});return r}async function startWorkflowByName(e){let t=await be({machineUser:e.machineUser,machineUserSource:e.machineUserSource,profile:e.profile});if(!t)throw E({code:`MACHINE_USER_REQUIRED`,message:`Machine user is required.`,suggestion:`Specify --machine-user, set TAILOR_PLATFORM_MACHINE_USER_NAME, or set a profile default with 'tailor profile update <profile> --machine-user <name>'.`});let{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId}),i=await resolveApplicationAuthNamespace({client:n,workspaceId:r,configPath:e.configPath});return await startWorkflowCore({client:n,workspaceId:r,workflowName:e.name,invoker:{namespace:i,machineUserName:t},arg:e.arg,interval:e.interval})}async function startWorkflow(e){let{client:t,workspaceId:n}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId}),r=await resolveApplicationAuthNamespace({client:t,workspaceId:n,configPath:e.configPath});return await startWorkflowCore({client:t,workspaceId:n,workflowName:e.workflow.name,invoker:{namespace:r,machineUserName:e.invoker},arg:e.arg,interval:e.interval})}const $c=Y({name:`start`,description:`Start a workflow execution.`,args:U.strictObject({...O,...Jc,"machine-user":V(U.string().optional(),{alias:`m`,description:`Machine user name. Falls back to the active profile's default machine user.`,env:`TAILOR_PLATFORM_MACHINE_USER_NAME`}),arg:V(U.string().optional(),{alias:`a`,description:`Workflow argument (JSON string)`}),...Xc}),run:async e=>{let{executionId:t,wait:n}=await startWorkflowByName({name:e.name,machineUser:e[`machine-user`],machineUserSource:_e(e[`machine-user`]),arg:e.arg,workspaceId:e[`workspace-id`],profile:e.profile,configPath:e.config,interval:he(e.interval)}),r=C.jsonMode;if(C.info(`Execution ID: ${t}`,{mode:`stream`}),e.wait){let i=await n({showProgress:!r,timeout:he(e.timeout),until:e.until});if(e.logs&&!r){let{execution:n}=await getWorkflowExecution({executionId:t,workspaceId:e[`workspace-id`],profile:e.profile,logs:!0});printExecutionWithLogs(n)}else if(e.logs){let{execution:n}=await getWorkflowExecution({executionId:t,workspaceId:e[`workspace-id`],profile:e.profile,logs:!0});C.out({...i,jobDetails:n.jobDetails})}else C.out(i);let a=getWorkflowWaitFailure(i,e.until);if(a)throw a}else C.out({executionId:t})}});function formatTime(e){return e.toLocaleTimeString(`en-US`,{hour12:!1})}function createUnknownExecutorJob(e,t){return{id:t,executorName:e,status:`UNKNOWN`,scheduledAt:`N/A`,createdAt:`N/A`,updatedAt:`N/A`}}async function listExecutorJobs(e){let t=e.executor.name,{client:a,workspaceId:o}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId}),s=[];if(e.status){let t=parseExecutorJobStatus(e.status);s.push(Yr(r,{condition:Yr(i,{field:`status`,operator:n.EQ,value:{kind:{case:`numberValue`,value:t}}})}))}let c=s.length>0?Yr(r,{and:s}):void 0,l=Ce(e.order??`desc`);try{return(await Pt(async(e,n)=>{let{jobs:r,nextPageToken:i}=await a.listExecutorJobs({workspaceId:o,executorName:t,pageToken:e,pageSize:n,pageDirection:l,filter:c});return[r,i]},{limit:e.limit})).map(toExecutorJobListInfo)}catch(e){throw e instanceof q&&e.code===K.NotFound?E({code:`EXECUTOR_NOT_FOUND`,message:`Executor '${t}' not found.`,cause:e}):e}}async function getExecutorJob(e){let n=e.executor.name,{client:r,workspaceId:i}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId});try{let{job:a}=await r.getExecutorJob({workspaceId:i,executorName:n,jobId:e.jobId});if(!a)throw E({code:`EXECUTOR_JOB_NOT_FOUND`,message:`Job '${e.jobId}' not found.`});let o=toExecutorJobInfo(a);if(e.attempts){let n=await Nt(async(n,a)=>{let{attempts:o,nextPageToken:s}=await r.listExecutorJobAttempts({workspaceId:i,jobId:e.jobId,pageToken:n,pageSize:a,pageDirection:t.DESC});return[o,s]});return{...o,attempts:n.map(toExecutorJobAttemptInfo)}}return o}catch(t){throw t instanceof q&&t.code===K.NotFound?E({code:`EXECUTOR_JOB_NOT_FOUND`,message:`Job '${e.jobId}' not found for executor '${n}'.`,cause:t}):t}}async function watchExecutorJob(e){let n=e.executor.name,{client:r,workspaceId:i}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId}),a=e.interval??3e3,o=e.timeout,s=e.showProgress??!C.jsonMode,c=Date.now(),l=s?spinner().start(`Waiting for executor job to complete...`):null,u=0,d=null,remainingTimeout=()=>{if(o!==void 0)return o-(Date.now()-c)},withWaitMetadata=(e,t)=>({...e,elapsedMs:Date.now()-c,attempts:u,timedOut:t,lastError:d}),timeoutResult=(t,r)=>withWaitMetadata({job:r?toExecutorJobInfo(r):createUnknownExecutorJob(n,e.jobId),targetType:t},!0);try{let{executor:o}=await r.getExecutorExecutor({workspaceId:i,name:n});if(!o)throw E({code:`EXECUTOR_NOT_FOUND`,message:`Executor '${n}' not found.`});let c=o.targetType,f=executorTargetTypeToString(c),p;for(;;){let t=remainingTimeout();if(t!==void 0&&t<=0)return l?.fail(`Executor job wait timed out.`),timeoutResult(f,p);try{if(u+=1,p=(await r.getExecutorJob({workspaceId:i,executorName:n,jobId:e.jobId})).job,!p)throw E({code:`EXECUTOR_JOB_NOT_FOUND`,message:`Job '${e.jobId}' not found.`});if(d=null,classifyExecutorJobStatus(p.status)!==`transient`)break}catch(e){if(!isRetryableWaitError(e))throw e;d=formatWaitError(e),l&&(l.text=`Retrying executor job poll... (${formatTime(/* @__PURE__ */ new Date)})`)}let o=remainingTimeout();if(o!==void 0&&o<=0)return l?.fail(`Executor job wait timed out.`),timeoutResult(f,p);l&&(l.text=`Waiting for executor job... (${formatTime(/* @__PURE__ */ new Date)})`),await Hi(o===void 0?a:Math.min(a,o))}let m=toExecutorJobInfo(p),h=colorizeExecutorJobStatus(m.status);p.status===Xn.SUCCESS?l?.succeed(`Executor job completed: ${h}`):l?.fail(`Executor job completed: ${h}`);let g=(await Nt(async(n,a)=>{let{attempts:o,nextPageToken:s}=await r.listExecutorJobAttempts({workspaceId:i,jobId:e.jobId,pageToken:n,pageSize:a,pageDirection:t.DESC});return[o,s]})).map(toExecutorJobAttemptInfo),_={...m,attempts:g},v=g[0]?.operationReference;if(v)switch(c){case I.WORKFLOW:l?.stop();try{let t=remainingTimeout();if(t!==void 0&&t<=0)return withWaitMetadata({job:_,targetType:f,workflowExecutionId:v},!0);let n=await waitForWorkflowExecution({client:r,workspaceId:i,executionId:v,interval:a,timeout:t,showProgress:s,trackJobs:!0});u+=n.attempts,d=n.lastError;let o;if(e.logs)try{let{execution:t}=await getWorkflowExecution({executionId:v,workspaceId:e.workspaceId,profile:e.profile,logs:!0});t.jobDetails&&(o=t.jobDetails.filter(e=>e.logs||e.result).map(e=>({jobName:e.stackedJobName||e.id,logs:e.logs,logEntries:e.logEntries,result:e.result})))}catch(e){C.warn(`Could not fetch workflow execution logs: ${e instanceof Error?e.message:e}`)}return withWaitMetadata({job:_,targetType:f,workflowExecutionId:v,workflowStatus:n.status,workflowJobLogs:o},n.timedOut)}catch(e){return C.warn(`Could not track workflow execution: ${e instanceof Error?e.message:e}`),withWaitMetadata({job:_,targetType:f,workflowExecutionId:v},!1)}case I.FUNCTION:case I.JOB_FUNCTION:l?.start(`Waiting for function execution ${v}...`);try{let t;for(;;){let n=remainingTimeout();if(n!==void 0&&n<=0)return l?.fail(`Function execution wait timed out.`),withWaitMetadata({job:_,targetType:f,functionExecutionId:v,functionStatus:t},!0);try{u+=1;let{execution:n}=await r.getFunctionExecution({workspaceId:i,executionId:v});if(!n)throw E({code:`FUNCTION_EXECUTION_NOT_FOUND`,message:`Function execution '${v}' not found.`});if(d=null,t=functionExecutionStatusToString(n.status),isFunctionExecutionTerminalStatus(n.status)){let r=colorizeFunctionExecutionStatus(t);n.status===jn.SUCCESS?l?.succeed(`Function execution completed: ${r}`):l?.fail(`Function execution completed: ${r}`);let i=e.logs?collectFunctionExecutionLogs(n.logEntries):void 0;return withWaitMetadata({job:_,targetType:f,functionExecutionId:v,functionStatus:t,functionLogs:i?.logs,functionLogEntries:i?.logEntries},!1)}}catch(e){if(!isRetryableWaitError(e))throw e;d=formatWaitError(e),l&&(l.text=`Retrying function execution poll... (${formatTime(/* @__PURE__ */ new Date)})`)}let o=remainingTimeout();if(o!==void 0&&o<=0)return l?.fail(`Function execution wait timed out.`),withWaitMetadata({job:_,targetType:f,functionExecutionId:v,functionStatus:t},!0);l&&(l.text=`Waiting for function execution... (${formatTime(/* @__PURE__ */ new Date)})`),await Hi(o===void 0?a:Math.min(a,o))}}catch(e){return l?.warn(`Could not track function execution: ${e instanceof Error?e.message:e}`),withWaitMetadata({job:_,targetType:f,functionExecutionId:v},!1)}}return withWaitMetadata({job:_,targetType:f},!1)}finally{l?.stop()}}function getExecutorWaitFailure(e){let t={jobId:e.job.id,status:e.job.status,workflowExecutionId:e.workflowExecutionId,functionExecutionId:e.functionExecutionId};if(e.timedOut)return E({code:`EXECUTOR_WAIT_TIMEOUT`,message:`Timed out waiting for executor job '${e.job.id}'. Last status: ${e.job.status}.`,context:t});if(e.job.status===`FAILED`||e.job.status===`CANCELED`)return E({code:`EXECUTOR_JOB_FAILED`,message:`Executor job '${e.job.id}' completed with status ${e.job.status}.`,context:t});if(e.workflowStatus===`FAILED`)return E({code:`WORKFLOW_EXECUTION_FAILED`,message:`Workflow execution '${e.workflowExecutionId}' failed.`,context:t});if(e.workflowStatus===`CANCELED`)return E({code:`WORKFLOW_EXECUTION_CANCELED`,message:`Workflow execution '${e.workflowExecutionId}' was canceled.`,context:t});if(e.functionStatus===`FAILED`)return E({code:`FUNCTION_EXECUTION_FAILED`,message:`Function execution '${e.functionExecutionId}' failed.`,context:t});if(e.functionStatus===`CANCELED`)return E({code:`FUNCTION_EXECUTION_CANCELED`,message:`Function execution '${e.functionExecutionId}' was canceled.`,context:t})}function getExecutorWaitFailureMessage(e){return getExecutorWaitFailure(e)?.message}function printJobWithAttempts(e){let t=[[`id`,e.id],[`executorName`,e.executorName],[`status`,e.status],[`scheduledAt`,e.scheduledAt],[`createdAt`,e.createdAt],[`updatedAt`,e.updatedAt]];if(C.log(formatKeyValueTable(t)),e.attempts&&e.attempts.length>0){C.log(h.bold(`
|
|
493
499
|
Attempts:`));for(let t of e.attempts)if(C.log(h.info(`\n--- Attempt ${t.id} ---`)),C.log(` Status: ${t.status}`),C.log(` Started: ${t.startedAt}`),C.log(` Finished: ${t.finishedAt}`),t.error){C.log(h.error(`
|
|
494
500
|
Error:`));let e=t.error.split(`
|
|
495
501
|
`);for(let t of e)C.log(` ${t}`)}}}function printDownstreamExecution(e){if(e.workflowExecutionId&&(C.log(h.bold(`
|
|
@@ -497,21 +503,21 @@ Workflow Execution:`)),C.log(` ID: ${e.workflowExecutionId}`),e.workflowStatus&
|
|
|
497
503
|
`))C.log(` ${t}`)}if(t.result){C.log(h.dim(` Result:`));try{let e=JSON.parse(t.result),n=JSON.stringify(e,null,2);for(let e of n.split(`
|
|
498
504
|
`))C.log(` ${e}`)}catch{C.log(` ${t.result}`)}}}if(e.functionExecutionId){C.log(h.bold(`
|
|
499
505
|
Function Execution:`)),C.log(` ID: ${e.functionExecutionId}`),e.functionStatus&&C.log(` Status: ${e.functionStatus}`);let t=formatFunctionLogMessages(e.functionLogEntries);if(t){C.log(h.dim(` Logs:`));for(let e of t.split(`
|
|
500
|
-
`))C.log(` ${e}`)}}}const Jc=Y({name:`jobs`,description:`List or get executor jobs.`,examples:[{cmd:`my-executor`,desc:`List jobs for an executor (default: 50 jobs)`},{cmd:`my-executor --limit 10`,desc:`Limit the number of jobs`},{cmd:`my-executor -s RUNNING`,desc:`Filter by status`},{cmd:`my-executor <job-id>`,desc:`Get job details`},{cmd:`my-executor <job-id> --attempts`,desc:`Get job details with attempts`},{cmd:`my-executor <job-id> -W`,desc:`Wait for job to complete`},{cmd:`my-executor <job-id> -W -l`,desc:`Wait for job with logs`}],args:U.strictObject({...j,"executor-name":V(U.string(),{positional:!0,description:`Executor name`}),"job-id":V(U.string().optional(),{positional:!0,description:`Job ID (if provided, shows job details)`}),status:V(U.string().optional(),{alias:`s`,description:`Filter by status (${Lc.join(`, `)}) (list mode only)`}),attempts:V(U.boolean().default(!1),{description:`Show job attempts (only with job ID) (detail mode only)`}),wait:V(U.boolean().default(!1),{alias:`W`,description:`Wait for job completion and downstream execution (workflow/function) if applicable (detail mode only)`}),interval:V(re.default(`3s`),{alias:`i`,description:`Polling interval when using --wait (e.g., '3s', '500ms', '1m')`}),timeout:V(re.default(`5m`),{alias:`t`,description:`Maximum time to wait when using --wait (e.g., '30s', '5m')`}),...me,limit:V(ae.default(50),{description:`Maximum number of jobs to list (0: unlimited, default: 50) (list mode only)`}),logs:V(U.boolean().default(!1),{alias:`l`,description:`Display function execution logs after completion (requires --wait)`})}),run:async e=>{let t=C.jsonMode||e.json;if(e.jobId){if(e.wait){let n=await watchExecutorJob({executor:{name:e.executorName},jobId:e.jobId,workspaceId:e[`workspace-id`],profile:e.profile,interval:he(e.interval),timeout:he(e.timeout),logs:e.logs,showProgress:!t});t?C.out(n):(C.log(h.bold(`Target Type: ${n.targetType}\n`)),printJobWithAttempts(n.job),printDownstreamExecution(n));let r=getExecutorWaitFailure(n);if(r)throw r;return}let n=await getExecutorJob({executor:{name:e.executorName},jobId:e.jobId,attempts:e.attempts,workspaceId:e[`workspace-id`],profile:e.profile});e.attempts&&!t?printJobWithAttempts(n):C.out(n)}else{e.wait&&C.warn(`--wait flag is ignored in list mode. Specify a job ID to wait.`);let t=await fetchWithinLimit(e.limit,t=>listExecutorJobs({executor:{name:e.executorName},status:e.status,order:e.order,limit:t,workspaceId:e[`workspace-id`],profile:e.profile})),n=t.items;C.out(n),await reportTruncation(t,e.limit)}}});async function listExecutors(e){let{client:t,workspaceId:n}=await loadOperatorWorkspaceContext({profile:e?.profile,workspaceId:e?.workspaceId}),r=Ce(e?.order);return(await Mt(async(e,i)=>{let{executors:a,nextPageToken:o}=await t.listExecutorExecutors({workspaceId:n,pageToken:e,pageSize:i,pageDirection:r});return[a,o]},{limit:e?.limit})).map(e=>toExecutorListInfo(e))}const Yc=Y({name:`list`,description:`List all executors`,args:U.strictObject({...j,...pe()}),run:async e=>{let t=C.jsonMode,n=await fetchWithinLimit(e.limit,t=>listExecutors({workspaceId:e[`workspace-id`],profile:e.profile,order:e.order,limit:t})),r=n.items;if(r.length===0)C.info(`No executors found.`),t&&C.out([]);else if(C.out(r,{display:{disabled:e=>e?h.warning(`true`):h.dim(`false`)}}),await reportTruncation(n,e.limit),!t&&r.some(e=>e.triggerType===`webhook`)){let t={command:`tailor`,args:[`executor`,`webhook`,`list`,...Se({profile:e.profile,workspaceId:e[`workspace-id`]})]};C.info(`To see webhook URLs, run ${w(t)}`)}}}),Xc=U.string().transform(e=>{try{return JSON.parse(e)}catch{throw E({code:`EXECUTOR_DATA_INVALID`,message:`Invalid JSON data: ${e}. Please provide a valid JSON string.`,command:`executor trigger`})}}).refine(e=>typeof e==`object`&&!!e&&!Array.isArray(e),{message:`JSON data must be an object, not an array or primitive value`}),Zc=U.string().superRefine((e,t)=>{e.includes(`:`)||t.addIssue({code:`custom`,message:`Invalid header format: '${e}'. Expected format: 'Key: Value'`})}).transform(e=>{let t=e.indexOf(`:`);return{key:e.slice(0,t).trim(),value:e.slice(t+1).trim()}}).refine(e=>e.key.length>0,{message:`Header name cannot be empty`});async function triggerExecutorByName(e){let{client:t,workspaceId:n}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId});try{return{jobId:(await t.triggerExecutor({workspaceId:n,executorName:e.executorName,payload:e.payload})).jobId}}catch(t){throw t instanceof q&&t.code===K.NotFound?E({code:`EXECUTOR_NOT_FOUND`,message:`Executor '${e.executorName}' not found.`,cause:t}):t instanceof q&&t.code===K.InvalidArgument?E({code:`EXECUTOR_ARGUMENT_INVALID`,message:`Invalid argument: ${t.message}`,cause:t}):t}}async function triggerExecutor(e){if(e.executor.trigger.kind!==`incomingWebhook`&&e.payload!==void 0)throw E({code:`EXECUTOR_TRIGGER_UNSUPPORTED`,message:`Executor '${e.executor.name}' has '${e.executor.trigger.kind}' trigger type. The payload is only available for 'incomingWebhook' trigger type.`});return await triggerExecutorByName({executorName:e.executor.name,payload:e.payload,workspaceId:e.workspaceId,profile:e.profile})}const Qc=Y({name:`trigger`,description:`Trigger an executor manually.`,notes:"Only executors with `INCOMING_WEBHOOK` or `SCHEDULE` trigger types can be triggered manually.\nExecutors with `EVENT` trigger types (such as `recordCreated`, `recordUpdated`, `recordDeleted`) cannot be triggered manually.\n\nThe `--data` and `--header` options are only available for `INCOMING_WEBHOOK` trigger type.\n\n**Downstream Execution Tracking**\n\nWhen using `--wait`, the CLI tracks not only the executor job but also any downstream executions:\n\n- **Workflow targets**: Waits for the workflow execution to complete (SUCCESS, FAILED, or PENDING_RESUME). Shows real-time status changes and currently running job names during execution (same output as `workflow start --wait`).\n- **Function targets**: Waits for the function execution to complete\n- **Webhook/GraphQL targets**: Only waits for the executor job itself\n\nThe `--logs` option displays logs from the downstream execution when available.",examples:[{cmd:`my-executor`,desc:`Trigger an executor`},{cmd:`my-executor -d '{"message": "hello"}'`,desc:`Trigger with data`},{cmd:`my-executor -d '{"message": "hello"}' -H "X-Custom: value" -H "X-Another: value2"`,desc:`Trigger with data and headers`},{cmd:`my-executor -W`,desc:`Trigger and wait for completion`},{cmd:`my-executor -W -l`,desc:`Trigger, wait, and show logs`}],args:U.strictObject({...j,"executor-name":V(U.string(),{positional:!0,description:`Executor name`}),data:V(Xc.optional(),{alias:`d`,description:`Request body (JSON string)`}),header:V(Zc.array().optional(),{alias:`H`,overrideBuiltinAlias:!0,description:`Request header (format: 'Key: Value', can be specified multiple times)`}),wait:V(U.boolean().default(!1),{alias:`W`,description:`Wait for job completion and downstream execution (workflow/function) if applicable`}),interval:V(re.default(`3s`),{alias:`i`,description:`Polling interval when using --wait (e.g., '3s', '500ms', '1m')`}),timeout:V(re.default(`5m`),{alias:`t`,description:`Maximum time to wait when using --wait (e.g., '30s', '5m')`}),logs:V(U.boolean().default(!1),{alias:`l`,description:`Display function execution logs after completion (requires --wait)`})}),run:async e=>{let t=C.jsonMode||e.json;await assertWritable({profile:e.profile});let{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e[`workspace-id`]}),{executor:i}=await n.getExecutorExecutor({workspaceId:r,name:e.executorName});if(!i)throw E({code:`EXECUTOR_NOT_FOUND`,message:`Executor '${e.executorName}' not found.`});if(i.triggerType===tr.EVENT)throw E({code:`EXECUTOR_TRIGGER_UNSUPPORTED`,message:`Executor '${e.executorName}' has '${executorTriggerTypeToString(i.triggerType)}' trigger type and cannot be triggered manually. Only executors with 'INCOMING_WEBHOOK' or 'SCHEDULE' triggers can be triggered manually.`});if(i.triggerType===tr.SCHEDULE&&(e.data||e.header))throw E({code:`EXECUTOR_TRIGGER_OPTIONS_INVALID`,message:`Executor '${e.executorName}' has 'SCHEDULE' trigger type. The --data and --header options are only available for 'INCOMING_WEBHOOK' trigger type.`,command:`executor trigger`});let a,o=e.data,s={};if(e.header)for(let t of e.header)s[t.key]=t.value;(o!==void 0||Object.keys(s).length>0)&&(a={body:o??{},headers:s});let c=await triggerExecutorByName({executorName:e.executorName,payload:a,workspaceId:e[`workspace-id`],profile:e.profile});if(!c.jobId)C.success(`Executor '${e.executorName}' triggered successfully.`),e.wait&&C.warn(`Cannot watch: job ID not available. The API may need to be updated.`);else if(C.success(`Executor '${e.executorName}' triggered successfully. Job ID: ${c.jobId}`),e.wait){let n=await watchExecutorJob({executor:{name:e.executorName},jobId:c.jobId,workspaceId:e[`workspace-id`],profile:e.profile,interval:he(e.interval),timeout:he(e.timeout),logs:e.logs,showProgress:!t});t?C.out(n):(C.log(h.bold(`\nTarget Type: ${n.targetType}`)),C.log(`Job Status: ${n.job.status}`),printDownstreamExecution(n));let r=getExecutorWaitFailure(n);if(r)throw r}}});async function listWebhookExecutors(e){let{client:t,workspaceId:n}=await loadOperatorWorkspaceContext({profile:e?.profile,workspaceId:e?.workspaceId}),r=Ce(e?.order);return(await Mt(async(e,i)=>{let{webhooks:a,nextPageToken:o}=await t.listExecutorIncomingWebhooks({workspaceId:n,pageToken:e,pageSize:i,pageDirection:r});return[a,o]},{limit:e?.limit})).map(e=>({name:e.executorName,webhookUrl:e.url,disabled:e.disabled}))}const $c=Y({name:`list`,description:`List executors with incoming webhook triggers`,args:U.strictObject({...j,...pe()}),run:async e=>{let t=C.jsonMode,n=await fetchWithinLimit(e.limit,t=>listWebhookExecutors({workspaceId:e[`workspace-id`],profile:e.profile,order:e.order,limit:t})),r=n.items;if(r.length===0)C.info(`No webhook executors found.`),t&&C.out([]);else if(C.out(r,{display:{disabled:e=>e?h.warning(`true`):h.dim(`false`)}}),await reportTruncation(n,e.limit),!t){let t={command:`tailor`,args:[`executor`,`trigger`,`<name>`,`-d`,`{"key":"value"}`,...Se({profile:e.profile,workspaceId:e[`workspace-id`]})]};C.info(`To test a webhook, run ${w(t)}`)}}}),el=Lr({name:`webhook`,description:`Manage executor webhooks`,subCommands:{list:$c},defaultSubCommand:`list`}),functionRegistryInfo=e=>({name:e.name,description:e.description,sizeBytes:e.sizeBytes.toString(),contentHash:e.contentHash,createdAt:formatTimestamp(e.createdAt),updatedAt:formatTimestamp(e.updatedAt)}),tl=U.object({workspaceId:U.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:U.string().optional(),name:U.string().min(1,{message:`name is required`})});async function loadOptions$12(e){let t=parseOptions(tl,e),{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:t.profile,workspaceId:t.workspaceId});return{client:n,workspaceId:r,name:t.name}}async function getFunctionRegistry(e){let{client:t,workspaceId:n,name:r}=await loadOptions$12(e),i=`Function registry "${r}" not found.`;try{let e=await t.getFunctionRegistry({workspaceId:n,name:r});if(!e.function)throw E({code:`FUNCTION_NOT_FOUND`,message:i});return functionRegistryInfo(e.function)}catch(e){throw e instanceof q&&e.code===K.NotFound?E({code:`FUNCTION_NOT_FOUND`,message:i,cause:e}):e}}const nl=Y({name:`get`,description:`Get a function registry by name`,args:U.strictObject({...j,name:V(U.string(),{description:`Function name`,alias:`n`})}),run:async e=>{let t=await getFunctionRegistry({workspaceId:e[`workspace-id`],profile:e.profile,name:e.name}),n=e.json?t:{...t,createdAt:humanizeRelativeTime(t.createdAt),updatedAt:humanizeRelativeTime(t.updatedAt)};C.out(n)}}),rl=U.object({workspaceId:U.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:U.string().optional(),order:U.enum([`asc`,`desc`]).optional(),limit:U.coerce.number().int().nonnegative().optional()});async function loadOptions$11(e){let t=parseOptions(rl,e),{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:t.profile,workspaceId:t.workspaceId});return{client:n,workspaceId:r,order:t.order,limit:t.limit}}async function listFunctionRegistries(e){let{client:t,workspaceId:n,order:r,limit:i}=await loadOptions$11(e),a=Ce(r);return(await Mt(async(e,r)=>{try{let{functions:i,nextPageToken:o}=await t.listFunctionRegistries({workspaceId:n,pageToken:e,pageSize:r,sortBy:`updated_at`,pageDirection:a});return[i,o]}catch(e){if(e instanceof q&&e.code===K.NotFound)return[[],``];throw e}},{limit:i})).map(functionRegistryInfo)}const il=Y({name:`list`,description:`List function registries in a workspace`,args:U.strictObject({...j,...pe()}),run:async e=>{let t=C.jsonMode,n=await fetchWithinLimit(e.limit,t=>listFunctionRegistries({workspaceId:e[`workspace-id`],profile:e.profile,order:e.order,limit:t})),r=n.items,i=t?r:r.map(({createdAt:e,updatedAt:t,...n})=>({...n,createdAt:humanizeRelativeTime(e),updatedAt:humanizeRelativeTime(t)}));C.out(i),await reportTruncation(n,e.limit)}});function extractAllNamespaces(e){let t=/* @__PURE__ */ new Set;if(e.db)for(let n of Object.keys(e.db))t.add(n);return Array.from(t)}function extractOwnedNamespaces(e){let t=/* @__PURE__ */ new Set;if(e.db)for(let[n,r]of Object.entries(e.db))`external`in r||t.add(n);return Array.from(t)}function redactStringValues(e,t){if(typeof t==`string`)return S(t);if(typeof t==`number`||typeof t==`boolean`||t===null){let e=JSON.stringify(t),n=y(e);return n===e?t:n}return t}function errorToJson(e,t){let n=buildErrorEnvelope(e,t);try{return plainRedactedCopy(n)}catch{let{context:e,stack:t,...r}=n.error;return plainRedactedCopy({error:r})}}function plainRedactedCopy(e){return JSON.parse(JSON.stringify(e,redactStringValues))}function buildErrorEnvelope(e,t){let n=baseErrorEnvelope(e,t);if(!(e instanceof Error))return n;let{causes:r,context:i,location:a,...o}=s(e);return{error:{...n.error,...o,...i||r?{context:{...i,...Object.fromEntries(Object.entries(r??{}).map(([e,n])=>[e,errorToJson(n,t).error]))}}:{}}}}function baseErrorEnvelope(e,t){if(m(e))return{error:{code:e.code||`CLI_ERROR`,message:e.message,...e.details?{details:e.details}:{},...e.suggestion?{suggestion:e.suggestion}:{},...e.command?{help:executableHelpAction(e.command)}:{},...e.next?{next:e.next}:{},...e.context?{context:e.context}:{},...t?.includeStack&&e.stack?{stack:e.stack}:{}}};if(e instanceof q){let n=K[e.code];return{error:{code:`RPC_${typeof n==`string`?n.replaceAll(/([a-z0-9])([A-Z])/g,`$1_$2`).toUpperCase():`CODE_${e.code}`}`,message:e.message,...t?.includeStack&&e.stack?{stack:e.stack}:{}}}}if(e instanceof Error){let n=g(e);return{error:{code:e.name===`CIPromptError`?`INTERACTIVE_PROMPT_REQUIRED`:`UNEXPECTED_ERROR`,message:e.message,...n?{suggestion:n}:{},...t?.includeStack&&e.stack?{stack:e.stack}:{}}}}return{error:{code:`UNKNOWN_ERROR`,message:String(e)}}}function serializeError(e,t){return JSON.stringify(errorToJson(e,t))}function executableHelpAction(e){return{command:`tailor`,args:[...e.split(/\s+/).filter(Boolean),`--help`]}}function createGenerationManager(e){let{application:t,config:n,pluginManager:r}=e,i=H.join(Ze(),`generated`);W.mkdirSync(i,{recursive:!0});let o={tailordb:{},resolver:{},executor:{}},s=r?.getPluginsWithGenerationHooks()??[];function buildTailorDBData(){return Object.entries(o.tailordb).map(([e,t])=>({namespace:e,tables:t.types,sourceInfo:new Map(Object.entries(t.sourceInfo)),pluginAttachments:t.pluginAttachments}))}function buildResolverData(){return Object.entries(o.resolver).map(([e,t])=>({namespace:e,resolvers:t}))}async function runPluginPhaseHook(e,r){if(!e[r])return;let s=H.join(i,e.id),c=getAuthInput(t),l=buildTailorDBData(),u;switch(r){case`onTailorDBReady`:u=await a(e.onTailorDBReady,`plugin.onTailorDBReady hook missing`)({tailordb:l,auth:c,baseDir:s,configPath:n.path,pluginConfig:e.pluginConfig});break;case`onResolverReady`:u=await a(e.onResolverReady,`plugin.onResolverReady hook missing`)({tailordb:l,resolvers:buildResolverData(),auth:c,baseDir:s,configPath:n.path,pluginConfig:e.pluginConfig});break;case`onExecutorReady`:u=await a(e.onExecutorReady,`plugin.onExecutorReady hook missing`)({tailordb:l,resolvers:buildResolverData(),executors:{...o.executor},auth:c,baseDir:s,configPath:n.path,pluginConfig:e.pluginConfig})}await writeGeneratedFiles(e.id,u)}async function runPluginHook(e){let t=s.filter(t=>t[e]!=null);if(t.length===0)return;let n=(await Promise.allSettled(t.map(async t=>{try{await runPluginPhaseHook(t,e)}catch(n){throw C.error(`Error processing plugin ${h.bold(t.id)} (${e})`),C.error(String(n)),n}}))).flatMap((e,n)=>e.status===`rejected`?[{plugin:a(t[n],`Plugin result has no matching plugin`).id,reason:e.reason}]:[]);if(n.length>0)throw E({code:`PLUGIN_GENERATION_FAILED`,message:`Plugin generation failed during ${e}.`,details:n.map(({plugin:e,reason:t})=>`${e}: ${m(t)?S(t.format()):String(t)}`).join(`
|
|
501
|
-
`),context:{hook:e,failures:n.map(({plugin:e,reason:t})=>({plugin:e,error:errorToJson(t,{includeStack:C.verbose}).error}))}})}async function writeGeneratedFiles(e,t){await Promise.all(t.files.map(async t=>(W.mkdirSync(H.dirname(t.path),{recursive:!0}),new Promise((n,r)=>{if(t.skipIfExists&&W.existsSync(t.path)){let r=H.relative(process.cwd(),t.path);return C.debug(`${e} | skip existing: ${r}`),n()}W.writeFile(t.path,t.content,i=>{if(i){let e=H.relative(process.cwd(),t.path);C.error(`Error writing file ${h.bold(e)}`),C.error(String(i)),r(i)}else{let r=H.relative(process.cwd(),t.path);C.debug(`${e} | generate: ${h.success(r)}`),n()}})})))),t.files.length>0&&C.log(`${e} | generation complete`)}return{application:t,baseDir:i,services:o,async generate(){C.newline(),C.log(`Generation for application: ${h.highlight(t.config.name)}`);let e=t;await B(`generate.loadTailorDBTypes`,async t=>{t.setAttribute(`generate.namespace_count`,e.tailorDBServices.length);for(let t of e.tailorDBServices){let e=t.namespace;await B(`generate.loadTypes.${e}`,async()=>{try{await t.loadTypes(),await t.processNamespacePlugins(),o.tailordb[e]={types:t.types,sourceInfo:t.typeSourceInfo,pluginAttachments:t.pluginAttachments}}catch(t){throw C.error(`Error loading tables for TailorDB service ${h.bold(e)}`),C.error(String(t)),t}})}try{Fe({tailorDBServices:e.tailorDBServices})}catch(e){throw C.error(`Error validating TailorDB table names`),C.error(String(e)),e}});let i=[...e.resolverServices,...lt(n,r)],{pluginExecutorFiles:a,executorService:c}=await B(`generate.pluginFiles`,async()=>{let t=ft(r,e.tailorDBServices,n.path);return{pluginExecutorFiles:t,executorService:e.executorService??(t.length>0?bt({config:{files:[]},baseDir:H.dirname(n.path)}):void 0)}});if(e.authService){let t=e.authService;await B(`generate.resolveAuthNamespaces`,async()=>t.resolveNamespaces())}(e.tailorDBServices.length>0||a.length>0)&&C.newline(),s.some(e=>e.onTailorDBReady!=null)&&(await B(`generate.onTailorDBReady`,async()=>{await runPluginHook(`onTailorDBReady`)}),C.newline()),await B(`generate.loadResolvers`,async()=>{for(let e of i){let t=e.namespace;await B(`generate.loadResolvers.${t}`,async()=>{try{await e.loadResolvers();let n={};o.resolver[t]=n,Object.entries(e.resolvers).forEach(([e,t])=>{n[t.name]=t})}catch(e){throw C.error(`Error loading resolvers for Resolver service ${h.bold(t)}`),C.error(String(e)),e}})}}),s.some(e=>e.onResolverReady!=null)&&(await B(`generate.onResolversReady`,async()=>{await runPluginHook(`onResolverReady`)}),C.newline()),await B(`generate.loadExecutors`,async()=>{c&&(await c.loadExecutors(),a.length>0&&await c.loadPluginExecutorFiles([...a]));let e=c?.executors??{};Object.entries(e).forEach(([e,t])=>{o.executor[e]=t})}),s.some(e=>e.onExecutorReady!=null)&&(await B(`generate.onExecutorsReady`,async()=>{await runPluginHook(`onExecutorReady`)}),C.newline())}}}async function generate$1(e){return B(`generate`,async t=>{let{config:n,plugins:r}=await B(`generate.loadConfig`,async()=>loadConfig(e?.configPath));await B(`generate.generateUserTypes`,async()=>generateUserTypes({config:n,configPath:n.path}));let i;r.length>0&&(i=new Cr(r));let a=pt({config:n,pluginManager:i});t.setAttribute(`app.name`,a.config.name),await createGenerationManager({application:a,config:n,pluginManager:i}).generate()})}function machineUserInfo(e){return{id:e.id,name:e.name,clientId:e.clientId,createdAt:e.createdAt?G(e.createdAt):null,updatedAt:e.updatedAt?G(e.updatedAt):null,attributes:Object.fromEntries(Object.entries(e.attributeMap).map(([e,t])=>[e,Yr(ai,t)]))}}async function listMachineUsers(e){let{client:t,workspaceId:n}=await loadOperatorWorkspaceContext({profile:e?.profile,workspaceId:e?.workspaceId}),{config:r}=await loadConfig(e?.configPath),{application:i}=await t.getApplication({workspaceId:n,applicationName:r.name});if(!i?.authNamespace)throw E({code:`AUTH_CONFIG_REQUIRED`,message:`Application ${r.name} does not have an auth configuration.`});let a=Ce(e?.order);return(await Mt(async(e,r)=>{let{machineUsers:o,nextPageToken:s}=await t.listAuthMachineUsers({workspaceId:n,pageToken:e,pageSize:r,authNamespace:i.authNamespace,pageDirection:a});return[o,s]},{limit:e?.limit})).map(machineUserInfo)}const al=Y({name:`list`,description:`List all machine users in the application.`,args:U.strictObject({...k,...pe()}),run:async e=>{let t=await fetchWithinLimit(e.limit,t=>listMachineUsers({workspaceId:e[`workspace-id`],profile:e.profile,configPath:e.config,order:e.order,limit:t})),n=t.items;C.out(n,{display:{createdAt:null,updatedAt:null}}),await reportTruncation(t,e.limit)}});async function getMachineUserTokenInternal(e){let t=await be({machineUser:e.name,machineUserSource:e.nameSource,profile:e.profile});if(!t)throw E({code:`MACHINE_USER_REQUIRED`,message:`Machine user is required.`,suggestion:`Provide the NAME positional argument, set TAILOR_PLATFORM_MACHINE_USER_NAME, or set a profile default with 'tailor profile update <profile> --machine-user <name>'.`,command:`machineuser token`});let{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId}),{config:i}=await loadConfig(e.configPath),{application:a}=await n.getApplication({workspaceId:r,applicationName:i.name});if(!a?.authNamespace)throw E({code:`AUTH_CONFIG_REQUIRED`,message:`Application ${i.name} does not have an auth configuration.`});let{machineUser:o}=await n.getAuthMachineUser({workspaceId:r,authNamespace:a.authNamespace,name:t});if(!o)throw E({code:`MACHINE_USER_NOT_FOUND`,message:`Machine user ${t} not found.`});let s=await Pt(a.url,o.clientId,o.clientSecret),c=/* @__PURE__ */ new Date;return c.setSeconds(c.getSeconds()+s.expires_in),{accessToken:s.access_token,tokenType:s.token_type,expiresAt:c.toISOString()}}async function getMachineUserToken(e){return await getMachineUserTokenInternal(e)}const ol=Y({name:`token`,description:`Get an access token for a machine user.`,args:U.strictObject({...k,name:V(U.string().optional(),{positional:!0,description:`Machine user name. Falls back to TAILOR_PLATFORM_MACHINE_USER_NAME, then the active profile's default machine user.`})}),run:async e=>{let t=await getMachineUserTokenInternal({name:e.name,nameSource:_e(e.name,process.argv.slice(2),{valueIsExplicit:e.name!==void 0}),workspaceId:e[`workspace-id`],profile:e.profile,configPath:e.config}),n={access_token:t.accessToken,token_type:t.tokenType,expires_at:t.expiresAt};C.out(n)}}),sl={[Qt.UNSPECIFIED]:`unknown`,[Qt.AUTHORIZATION_CODE]:`authorization_code`,[Qt.REFRESH_TOKEN]:`refresh_token`},grantTypeToString=e=>protoEnumLookup(sl,e,`unknown`);function toOAuth2ClientInfo(e){return{name:e.name,description:e.description,clientId:e.clientId,grantTypes:e.grantTypes.map(grantTypeToString),redirectUris:e.redirectUris,createdAt:e.createdAt?G(e.createdAt):null}}function toOAuth2ClientCredentials(e){return C.registerSecret(e.clientSecret),{name:e.name,description:e.description,clientId:e.clientId,clientSecret:e.clientSecret,grantTypes:e.grantTypes.map(grantTypeToString),redirectUris:e.redirectUris,createdAt:e.createdAt?G(e.createdAt):null}}async function getOAuth2Client(e){let{client:t,workspaceId:n}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId}),{config:r}=await loadConfig(e.configPath),{application:i}=await t.getApplication({workspaceId:n,applicationName:r.name});if(!i?.authNamespace)throw E({code:`AUTH_CONFIG_REQUIRED`,message:`Application ${r.name} does not have an auth configuration.`});try{let{oauth2Client:r}=await t.getAuthOAuth2Client({workspaceId:n,namespaceName:i.authNamespace,name:e.name});return toOAuth2ClientCredentials(a(r,`oauth2Client missing in response`))}catch(t){throw t instanceof q&&t.code===K.NotFound?E({code:`OAUTH2_CLIENT_NOT_FOUND`,message:`OAuth2 client '${e.name}' not found.`,cause:t}):t}}const cl=Y({name:`get`,description:`Get OAuth2 client credentials (including client secret).`,args:U.strictObject({...k,name:V(U.string(),{positional:!0,description:`OAuth2 client name`})}),run:async e=>{let t=await getOAuth2Client({name:e.name,workspaceId:e[`workspace-id`],profile:e.profile,configPath:e.config});C.out(t)}});async function listOAuth2Clients(e){let{client:t,workspaceId:n}=await loadOperatorWorkspaceContext({profile:e?.profile,workspaceId:e?.workspaceId}),{config:r}=await loadConfig(e?.configPath),{application:i}=await t.getApplication({workspaceId:n,applicationName:r.name});if(!i?.authNamespace)throw E({code:`AUTH_CONFIG_REQUIRED`,message:`Application ${r.name} does not have an auth configuration.`});let a=Ce(e?.order);return(await Mt(async(e,r)=>{let{oauth2Clients:o,nextPageToken:s}=await t.listAuthOAuth2Clients({workspaceId:n,pageToken:e,pageSize:r,namespaceName:i.authNamespace,pageDirection:a});return[o,s]},{limit:e?.limit})).map(toOAuth2ClientInfo)}const ll=Y({name:`list`,description:`List all OAuth2 clients in the application.`,args:U.strictObject({...k,...pe()}),run:async e=>{let t=await fetchWithinLimit(e.limit,t=>listOAuth2Clients({workspaceId:e[`workspace-id`],profile:e.profile,configPath:e.config,order:e.order,limit:t})),n=t.items;C.out(n),await reportTruncation(t,e.limit)}}),userOrganizationInfo=e=>({organizationId:e.organizationId,organizationName:e.organizationName,rootFolderId:e.rootFolderId,rootFolderName:e.rootFolderName,displayName:e.displayName}),organizationInfo=e=>({id:e.id,name:e.name,createdAt:formatTimestamp(e.createTime),updatedAt:formatTimestamp(e.updateTime)}),folderListInfo=e=>({id:e.id,name:e.name,organizationId:e.organizationId,parentFolderId:e.parentFolderId,hasChildren:e.hasChildren,createdAt:formatTimestamp(e.createTime)}),folderInfo=e=>({...folderListInfo(e),updatedAt:formatTimestamp(e.updateTime)}),ul=U.object({organizationId:U.uuid({message:`organization-id must be a valid UUID`}),parentFolderId:U.string().optional(),name:U.string().min(1,`Name must not be empty`)});async function createFolder(e){let t=parseOptions(ul,e),n=await A(),r=await(await N(n)).createOrganizationFolder({organizationId:t.organizationId,parentFolderId:t.parentFolderId??``,folderName:t.name});if(!r.folder)throw b(`Failed to create folder.`);return folderInfo(r.folder)}const dl=Y({name:`create`,description:`Create a new folder in an organization.`,args:U.strictObject({...ie,"parent-folder-id":V(U.string().optional(),{description:`Parent folder ID`}),name:V(U.string(),{alias:`n`,description:`Folder name`})}),run:async e=>{await assertWritable();let t=await createFolder({organizationId:e[`organization-id`],parentFolderId:e[`parent-folder-id`],name:e.name});e.json||C.success(`Folder "${t.name}" created successfully.`),C.out(t)}}),fl=U.object({organizationId:U.uuid({message:`organization-id must be a valid UUID`}),folderId:U.uuid({message:`folder-id must be a valid UUID`})});async function deleteFolder(e){let t=parseOptions(fl,e),n=await A();await(await N(n)).deleteOrganizationFolder({organizationId:t.organizationId,folderId:t.folderId})}const pl=Y({name:`delete`,description:`Delete a folder from an organization.`,args:U.strictObject({...ie,...ue,...se}),run:async e=>{await assertWritable();let t=await A(),n=await N(t),r;try{r=await n.getOrganizationFolder({organizationId:e[`organization-id`],folderId:e[`folder-id`]})}catch(t){throw t instanceof q&&t.code===K.NotFound?E({code:`FOLDER_NOT_FOUND`,message:`Folder "${e[`folder-id`]}" not found.`,cause:t}):t}if(!r.folder)throw E({code:`FOLDER_NOT_FOUND`,message:`Folder "${e[`folder-id`]}" not found.`});let i=r.folder.name;if(!e.yes&&!await X.confirm({message:`Are you sure you want to delete folder "${i}"?`}))throw E({code:`FOLDER_DELETION_CANCELLED`,message:`Folder deletion cancelled.`});await n.deleteOrganizationFolder({organizationId:e[`organization-id`],folderId:e[`folder-id`]}),C.success(`Folder "${i}" deleted successfully.`),printMutationResult({changed:!0,organizationId:e[`organization-id`],folderId:e[`folder-id`],name:i})}}),ml=U.object({organizationId:U.uuid({message:`organization-id must be a valid UUID`}),folderId:U.uuid({message:`folder-id must be a valid UUID`})});async function getFolder(e){let t=parseOptions(ml,e),n=await A(),r=await(await N(n)).getOrganizationFolder({organizationId:t.organizationId,folderId:t.folderId});if(!r.folder)throw E({code:`FOLDER_NOT_FOUND`,message:`Folder "${t.folderId}" not found.`});return folderInfo(r.folder)}const hl=Y({name:`get`,description:`Show detailed information about a folder.`,args:U.strictObject({...ie,...ue}),run:async e=>{let t=await getFolder({organizationId:e[`organization-id`],folderId:e[`folder-id`]}),n=e.json?t:{...t,createdAt:humanizeRelativeTime(t.createdAt),updatedAt:humanizeRelativeTime(t.updatedAt)};C.out(n)}}),gl=U.object({organizationId:U.uuid({message:`organization-id must be a valid UUID`}),parentFolderId:U.string().optional(),order:Te.optional(),limit:U.number().int().nonnegative().optional()});async function listFolders(e){let{organizationId:t,parentFolderId:n,order:r,limit:i}=parseOptions(gl,e),a=await A(),o=await N(a),s=Ce(r);return(await Mt(async(e,r)=>{let i=await o.listOrganizationFolders({organizationId:t,...n?{parentFolderId:n}:{},pageToken:e,pageSize:r,pageDirection:s});return[i.folders,i.nextPageToken]},{limit:i})).map(folderListInfo)}const _l=Y({name:`list`,description:`List folders in an organization.`,args:U.strictObject({...ie,"parent-folder-id":V(U.string().optional(),{description:`Parent folder ID to list children of`}),...pe()}),run:async e=>{let t=await fetchWithinLimit(e.limit,t=>listFolders({organizationId:e[`organization-id`],parentFolderId:e[`parent-folder-id`],order:e.order,limit:t})),n=t.items;C.out(n,{display:{updatedAt:null}}),await reportTruncation(t,e.limit)}}),vl=U.object({organizationId:U.uuid({message:`organization-id must be a valid UUID`}),folderId:U.uuid({message:`folder-id must be a valid UUID`}),name:U.string().min(1,`Name must not be empty`)});async function updateFolder(e){let t=parseOptions(vl,e),n=await A(),r=await(await N(n)).updateOrganizationFolder({organizationId:t.organizationId,folderId:t.folderId,folderName:t.name});if(!r.folder)throw b(`Failed to update folder "${t.folderId}".`);return folderInfo(r.folder)}const yl=Y({name:`update`,description:`Update a folder's name.`,args:U.strictObject({...ie,...ue,name:V(U.string(),{alias:`n`,description:`New folder name`})}),run:async e=>{await assertWritable();let t=await updateFolder({organizationId:e[`organization-id`],folderId:e[`folder-id`],name:e.name});e.json||C.success(`Folder "${t.name}" updated successfully.`),C.out(t)}}),bl=U.object({organizationId:U.uuid({message:`organization-id must be a valid UUID`})});async function getOrganization(e){let t=parseOptions(bl,e),n=await A(),r=await(await N(n)).getOrganization({organizationId:t.organizationId});if(!r.organization)throw E({code:`ORGANIZATION_NOT_FOUND`,message:`Organization "${t.organizationId}" not found.`});return organizationInfo(r.organization)}const xl=Y({name:`get`,description:`Show detailed information about an organization.`,args:U.strictObject({...ie}),run:async e=>{let t=await getOrganization({organizationId:e[`organization-id`]}),n=e.json?t:{...t,createdAt:humanizeRelativeTime(t.createdAt),updatedAt:humanizeRelativeTime(t.updatedAt)};C.out(n)}});async function listOrganizations(e){let t=e?.limit,n=await A(),{userOrganizations:r}=await(await N(n)).listUserOrganizations({}),i=r.map(userOrganizationInfo);return t===void 0?i:i.slice(0,t)}const Sl=Y({name:`list`,description:`List organizations you belong to.`,args:U.strictObject({limit:V(le.optional(),{alias:`l`,description:`Maximum number of organizations to list`})}),run:async e=>{let t=await fetchWithinLimit(e.limit,e=>listOrganizations({limit:e}));C.out(t.items),await reportTruncation(t,e.limit)}});async function fetchChildFolders(e,t,n,r,i){if(i!==void 0&&r>=i)return[];let a=await jt(async(r,i)=>{let a=await e.listOrganizationFolders({organizationId:t,parentFolderId:n,pageToken:r,pageSize:i});return[a.folders,a.nextPageToken]}),o=[];for(let n of a){let a=n.hasChildren?await fetchChildFolders(e,t,n.id,r+1,i):[];o.push({name:n.name,children:a})}return o}async function buildFolderTreeJson(e,t,n,r,i){if(i!==void 0&&r>=i)return[];let a=await jt(async(r,i)=>{let a=await e.listOrganizationFolders({organizationId:t,parentFolderId:n,pageToken:r,pageSize:i});return[a.folders,a.nextPageToken]}),o=[];for(let n of a){let a=n.hasChildren?await buildFolderTreeJson(e,t,n.id,r+1,i):[];o.push({id:n.id,name:n.name,children:a})}return o}function renderTree(e,t){let n=``;for(let[r,i]of e.entries()){let a=r===e.length-1,o=a?`└── `:`├── `,s=a?` `:`│ `;n+=`${t}${o}${i.name}\n`,i.children.length>0&&(n+=renderTree(i.children,t+s))}return n}async function buildOrgTree(e,t,n){let r=await fetchChildFolders(e,t.organizationId,t.rootFolderId,0,n),i=`${t.organizationName}\n`;return i+=renderTree(r,``),i}async function organizationTree(e){let t=await A(),n=await N(t),r;if(e?.organizationId){if(r=(await listOrganizations()).filter(t=>t.organizationId===e.organizationId),r.length===0)throw E({code:`ORGANIZATION_NOT_FOUND`,message:`Organization "${e.organizationId}" not found.`})}else r=await listOrganizations();let i=e?.depth,a=[];for(let e of r){let t=await buildFolderTreeJson(n,e.organizationId,e.rootFolderId,0,i);a.push({organizationId:e.organizationId,organizationName:e.organizationName,folders:t})}return a}const Cl=Y({name:`tree`,description:`Display organization folder hierarchy as a tree.`,args:U.strictObject({"organization-id":V(U.string().optional(),{alias:`o`,description:`Organization ID (show all if omitted)`,env:`TAILOR_PLATFORM_ORGANIZATION_ID`}),depth:V(le.optional(),{alias:`d`,description:`Maximum folder depth to display`})}),run:async e=>{let t=await A(),n=await N(t),r;if(e[`organization-id`]){if(r=(await listOrganizations()).filter(t=>t.organizationId===e[`organization-id`]),r.length===0)throw E({code:`ORGANIZATION_NOT_FOUND`,message:`Organization "${e[`organization-id`]}" not found.`})}else r=await listOrganizations();if(e.json){let t=[];for(let i of r){let r=await buildFolderTreeJson(n,i.organizationId,i.rootFolderId,0,e.depth);t.push({organizationId:i.organizationId,organizationName:i.organizationName,folders:r})}C.out(t);return}let i=[];for(let t of r)i.push(await buildOrgTree(n,t,e.depth));C.log(i.join(`
|
|
502
|
-
`))}}),
|
|
503
|
-
`)),l.every(e=>e.deletes.length===0)?{removed:!1,leftBehind:s}:(i&&await i(),await applyWorkflow(e,o.workflow,`delete`),await applyWorkflowJobFunctionExecutionPolicy(e,o.workflowExecutionPolicy,`delete`),await applyExecutor(e,o.executor,`delete`),await applyStaticWebsite(e,o.staticWebsite,`delete`),await applyAIGateway(e,o.aiGateway,`delete`),await applyApplication(e,o.app,`delete`),await applyPipeline(e,o.pipeline,`delete-resources`),await applyPipeline(e,o.pipeline,`delete-services`),await applyAuth(e,o.auth,`delete-resources`),await applyAuth(e,o.auth,`delete-services`),await applyIdP(e,o.idp,`delete-resources`),await applyIdP(e,o.idp,`delete-services`),await applyTailorDB(e,o.tailorDB,`delete-resources`),await applyTailorDB(e,o.tailorDB,`delete-services`),await applyFunctionRegistry(e,t,o.functionRegistry,`delete`),await applySecretManager(e,o.secretManager,`delete`),{removed:!0,leftBehind:s})}async function remove(e){let{client:t,workspaceId:n,application:r,config:i}=await loadOptions$10(e);await execRemove(t,n,r,i)}const
|
|
506
|
+
`))C.log(` ${e}`)}}}const el=Y({name:`jobs`,description:`List or get executor jobs.`,examples:[{cmd:`my-executor`,desc:`List jobs for an executor (default: 50 jobs)`},{cmd:`my-executor --limit 10`,desc:`Limit the number of jobs`},{cmd:`my-executor -s RUNNING`,desc:`Filter by status`},{cmd:`my-executor <job-id>`,desc:`Get job details`},{cmd:`my-executor <job-id> --attempts`,desc:`Get job details with attempts`},{cmd:`my-executor <job-id> -W`,desc:`Wait for job to complete`},{cmd:`my-executor <job-id> -W -l`,desc:`Wait for job with logs`}],args:U.strictObject({...j,"executor-name":V(U.string(),{positional:!0,description:`Executor name`}),"job-id":V(U.string().optional(),{positional:!0,description:`Job ID (if provided, shows job details)`}),status:V(U.string().optional(),{alias:`s`,description:`Filter by status (${Uc.join(`, `)}) (list mode only)`}),attempts:V(U.boolean().default(!1),{description:`Show job attempts (only with job ID) (detail mode only)`}),wait:V(U.boolean().default(!1),{alias:`W`,description:`Wait for job completion and downstream execution (workflow/function) if applicable (detail mode only)`}),interval:V(ie.default(`3s`),{alias:`i`,description:`Polling interval when using --wait (e.g., '3s', '500ms', '1m')`}),timeout:V(ie.default(`5m`),{alias:`t`,description:`Maximum time to wait when using --wait (e.g., '30s', '5m')`}),...me,limit:V(ae.default(50),{description:`Maximum number of jobs to list (0: unlimited, default: 50) (list mode only)`}),logs:V(U.boolean().default(!1),{alias:`l`,description:`Display function execution logs after completion (requires --wait)`})}),run:async e=>{let t=C.jsonMode||e.json;if(e.jobId){if(e.wait){let n=await watchExecutorJob({executor:{name:e.executorName},jobId:e.jobId,workspaceId:e[`workspace-id`],profile:e.profile,interval:he(e.interval),timeout:he(e.timeout),logs:e.logs,showProgress:!t});t?C.out(n):(C.log(h.bold(`Target Type: ${n.targetType}\n`)),printJobWithAttempts(n.job),printDownstreamExecution(n));let r=getExecutorWaitFailure(n);if(r)throw r;return}let n=await getExecutorJob({executor:{name:e.executorName},jobId:e.jobId,attempts:e.attempts,workspaceId:e[`workspace-id`],profile:e.profile});e.attempts&&!t?printJobWithAttempts(n):C.out(n)}else{e.wait&&C.warn(`--wait flag is ignored in list mode. Specify a job ID to wait.`);let t=await fetchWithinLimit(e.limit,t=>listExecutorJobs({executor:{name:e.executorName},status:e.status,order:e.order,limit:t,workspaceId:e[`workspace-id`],profile:e.profile})),n=t.items;C.out(n),await reportTruncation(t,e.limit)}}});async function listExecutors(e){let{client:t,workspaceId:n}=await loadOperatorWorkspaceContext({profile:e?.profile,workspaceId:e?.workspaceId}),r=Ce(e?.order);return(await Pt(async(e,i)=>{let{executors:a,nextPageToken:o}=await t.listExecutorExecutors({workspaceId:n,pageToken:e,pageSize:i,pageDirection:r});return[a,o]},{limit:e?.limit})).map(e=>toExecutorListInfo(e))}const tl=Y({name:`list`,description:`List all executors`,args:U.strictObject({...j,...pe()}),run:async e=>{let t=C.jsonMode,n=await fetchWithinLimit(e.limit,t=>listExecutors({workspaceId:e[`workspace-id`],profile:e.profile,order:e.order,limit:t})),r=n.items;if(r.length===0)C.info(`No executors found.`),t&&C.out([]);else if(C.out(r,{display:{disabled:e=>e?h.warning(`true`):h.dim(`false`)}}),await reportTruncation(n,e.limit),!t&&r.some(e=>e.triggerType===`webhook`)){let t={command:`tailor`,args:[`executor`,`webhook`,`list`,...Se({profile:e.profile,workspaceId:e[`workspace-id`]})]};C.info(`To see webhook URLs, run ${w(t)}`)}}}),nl=U.string().transform(e=>{try{return JSON.parse(e)}catch{throw E({code:`EXECUTOR_DATA_INVALID`,message:`Invalid JSON data: ${e}. Please provide a valid JSON string.`,command:`executor trigger`})}}).refine(e=>typeof e==`object`&&!!e&&!Array.isArray(e),{message:`JSON data must be an object, not an array or primitive value`}),rl=U.string().superRefine((e,t)=>{e.includes(`:`)||t.addIssue({code:`custom`,message:`Invalid header format: '${e}'. Expected format: 'Key: Value'`})}).transform(e=>{let t=e.indexOf(`:`);return{key:e.slice(0,t).trim(),value:e.slice(t+1).trim()}}).refine(e=>e.key.length>0,{message:`Header name cannot be empty`});async function triggerExecutorByName(e){let{client:t,workspaceId:n}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId});try{return{jobId:(await t.triggerExecutor({workspaceId:n,executorName:e.executorName,payload:e.payload})).jobId}}catch(t){throw t instanceof q&&t.code===K.NotFound?E({code:`EXECUTOR_NOT_FOUND`,message:`Executor '${e.executorName}' not found.`,cause:t}):t instanceof q&&t.code===K.InvalidArgument?E({code:`EXECUTOR_ARGUMENT_INVALID`,message:`Invalid argument: ${t.message}`,cause:t}):t}}async function triggerExecutor(e){if(e.executor.trigger.kind!==`incomingWebhook`&&e.payload!==void 0)throw E({code:`EXECUTOR_TRIGGER_UNSUPPORTED`,message:`Executor '${e.executor.name}' has '${e.executor.trigger.kind}' trigger type. The payload is only available for 'incomingWebhook' trigger type.`});return await triggerExecutorByName({executorName:e.executor.name,payload:e.payload,workspaceId:e.workspaceId,profile:e.profile})}const il=Y({name:`trigger`,description:`Trigger an executor manually.`,notes:"Only executors with `INCOMING_WEBHOOK` or `SCHEDULE` trigger types can be triggered manually.\nExecutors with `EVENT` trigger types (such as `recordCreated`, `recordUpdated`, `recordDeleted`) cannot be triggered manually.\n\nThe `--data` and `--header` options are accepted only for `INCOMING_WEBHOOK` trigger type.\n\nThe executor receives the `--data` JSON as `body`, with empty `headers` and no `rawBody`. `--header` values are not passed to the executor. To test an executor that reads headers or verifies a signature over `rawBody`, send the request to its webhook URL, which `executor webhook list` shows.\n\n**Downstream Execution Tracking**\n\nWhen using `--wait`, the CLI tracks not only the executor job but also any downstream executions:\n\n- **Workflow targets**: Waits for the workflow execution to complete (SUCCESS, FAILED, or PENDING_RESUME). Shows real-time status changes and currently running job names during execution (same output as `workflow start --wait`).\n- **Function targets**: Waits for the function execution to complete\n- **Webhook/GraphQL targets**: Only waits for the executor job itself\n\nThe `--logs` option displays logs from the downstream execution when available.",examples:[{cmd:`my-executor`,desc:`Trigger an executor`},{cmd:`my-executor -d '{"message": "hello"}'`,desc:`Trigger with data`},{cmd:`my-executor -W`,desc:`Trigger and wait for completion`},{cmd:`my-executor -W -l`,desc:`Trigger, wait, and show logs`}],args:U.strictObject({...j,"executor-name":V(U.string(),{positional:!0,description:`Executor name`}),data:V(nl.optional(),{alias:`d`,description:`Request body (JSON string)`}),header:V(rl.array().optional(),{alias:`H`,overrideBuiltinAlias:!0,description:`Ignored, as the executor receives empty headers (format: 'Key: Value', can be specified multiple times)`}),wait:V(U.boolean().default(!1),{alias:`W`,description:`Wait for job completion and downstream execution (workflow/function) if applicable`}),interval:V(ie.default(`3s`),{alias:`i`,description:`Polling interval when using --wait (e.g., '3s', '500ms', '1m')`}),timeout:V(ie.default(`5m`),{alias:`t`,description:`Maximum time to wait when using --wait (e.g., '30s', '5m')`}),logs:V(U.boolean().default(!1),{alias:`l`,description:`Display function execution logs after completion (requires --wait)`})}),run:async e=>{let t=C.jsonMode||e.json;await assertWritable({profile:e.profile});let{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e[`workspace-id`]}),{executor:i}=await n.getExecutorExecutor({workspaceId:r,name:e.executorName});if(!i)throw E({code:`EXECUTOR_NOT_FOUND`,message:`Executor '${e.executorName}' not found.`});if(i.triggerType===ir.EVENT)throw E({code:`EXECUTOR_TRIGGER_UNSUPPORTED`,message:`Executor '${e.executorName}' has '${executorTriggerTypeToString(i.triggerType)}' trigger type and cannot be triggered manually. Only executors with 'INCOMING_WEBHOOK' or 'SCHEDULE' triggers can be triggered manually.`});if(i.triggerType===ir.SCHEDULE&&(e.data||e.header))throw E({code:`EXECUTOR_TRIGGER_OPTIONS_INVALID`,message:`Executor '${e.executorName}' has 'SCHEDULE' trigger type. The --data and --header options are only available for 'INCOMING_WEBHOOK' trigger type.`,command:`executor trigger`});if(e.header){let t={command:`tailor`,args:[`executor`,`webhook`,`list`,...Se({profile:e.profile,workspaceId:e[`workspace-id`]})]};C.warn(`--header values are not passed to the executor, which receives empty headers. Remove --header, or if the executor needs headers, send the request to its webhook URL (${w(t)} lists it).`)}let a=await triggerExecutorByName({executorName:e.executorName,payload:e.data,workspaceId:e[`workspace-id`],profile:e.profile});if(!a.jobId)C.success(`Executor '${e.executorName}' triggered successfully.`),e.wait&&C.warn(`Cannot watch: job ID not available. The API may need to be updated.`);else if(C.success(`Executor '${e.executorName}' triggered successfully. Job ID: ${a.jobId}`),e.wait){let n=await watchExecutorJob({executor:{name:e.executorName},jobId:a.jobId,workspaceId:e[`workspace-id`],profile:e.profile,interval:he(e.interval),timeout:he(e.timeout),logs:e.logs,showProgress:!t});t?C.out(n):(C.log(h.bold(`\nTarget Type: ${n.targetType}`)),C.log(`Job Status: ${n.job.status}`),printDownstreamExecution(n));let r=getExecutorWaitFailure(n);if(r)throw r}}});async function listWebhookExecutors(e){let{client:t,workspaceId:n}=await loadOperatorWorkspaceContext({profile:e?.profile,workspaceId:e?.workspaceId}),r=Ce(e?.order);return(await Pt(async(e,i)=>{let{webhooks:a,nextPageToken:o}=await t.listExecutorIncomingWebhooks({workspaceId:n,pageToken:e,pageSize:i,pageDirection:r});return[a,o]},{limit:e?.limit})).map(e=>({name:e.executorName,webhookUrl:e.url,disabled:e.disabled}))}const al=Y({name:`list`,description:`List executors with incoming webhook triggers`,args:U.strictObject({...j,...pe()}),run:async e=>{let t=C.jsonMode,n=await fetchWithinLimit(e.limit,t=>listWebhookExecutors({workspaceId:e[`workspace-id`],profile:e.profile,order:e.order,limit:t})),r=n.items;if(r.length===0)C.info(`No webhook executors found.`),t&&C.out([]);else if(C.out(r,{display:{disabled:e=>e?h.warning(`true`):h.dim(`false`)}}),await reportTruncation(n,e.limit),!t){let t={command:`tailor`,args:[`executor`,`trigger`,`<name>`,`-d`,`{"key":"value"}`,...Se({profile:e.profile,workspaceId:e[`workspace-id`]})]};C.info(`To test a webhook, run ${w(t)}`)}}}),ol=Br({name:`webhook`,description:`Manage executor webhooks`,subCommands:{list:al},defaultSubCommand:`list`}),functionRegistryInfo=e=>({name:e.name,description:e.description,sizeBytes:e.sizeBytes.toString(),contentHash:e.contentHash,createdAt:formatTimestamp(e.createdAt),updatedAt:formatTimestamp(e.updatedAt)}),sl=U.object({workspaceId:U.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:U.string().optional(),name:U.string().min(1,{message:`name is required`})});async function loadOptions$12(e){let t=parseOptions(sl,e),{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:t.profile,workspaceId:t.workspaceId});return{client:n,workspaceId:r,name:t.name}}async function getFunctionRegistry(e){let{client:t,workspaceId:n,name:r}=await loadOptions$12(e),i=`Function registry "${r}" not found.`;try{let e=await t.getFunctionRegistry({workspaceId:n,name:r});if(!e.function)throw E({code:`FUNCTION_NOT_FOUND`,message:i});return functionRegistryInfo(e.function)}catch(e){throw e instanceof q&&e.code===K.NotFound?E({code:`FUNCTION_NOT_FOUND`,message:i,cause:e}):e}}const cl=Y({name:`get`,description:`Get a function registry by name`,args:U.strictObject({...j,name:V(U.string(),{description:`Function name`,alias:`n`})}),run:async e=>{let t=await getFunctionRegistry({workspaceId:e[`workspace-id`],profile:e.profile,name:e.name}),n=e.json?t:{...t,createdAt:humanizeRelativeTime(t.createdAt),updatedAt:humanizeRelativeTime(t.updatedAt)};C.out(n)}}),ll=U.object({workspaceId:U.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:U.string().optional(),order:U.enum([`asc`,`desc`]).optional(),limit:U.coerce.number().int().nonnegative().optional()});async function loadOptions$11(e){let t=parseOptions(ll,e),{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:t.profile,workspaceId:t.workspaceId});return{client:n,workspaceId:r,order:t.order,limit:t.limit}}async function listFunctionRegistries(e){let{client:t,workspaceId:n,order:r,limit:i}=await loadOptions$11(e),a=Ce(r);return(await Pt(async(e,r)=>{try{let{functions:i,nextPageToken:o}=await t.listFunctionRegistries({workspaceId:n,pageToken:e,pageSize:r,sortBy:`updated_at`,pageDirection:a});return[i,o]}catch(e){if(e instanceof q&&e.code===K.NotFound)return[[],``];throw e}},{limit:i})).map(functionRegistryInfo)}const ul=Y({name:`list`,description:`List function registries in a workspace`,args:U.strictObject({...j,...pe()}),run:async e=>{let t=C.jsonMode,n=await fetchWithinLimit(e.limit,t=>listFunctionRegistries({workspaceId:e[`workspace-id`],profile:e.profile,order:e.order,limit:t})),r=n.items,i=t?r:r.map(({createdAt:e,updatedAt:t,...n})=>({...n,createdAt:humanizeRelativeTime(e),updatedAt:humanizeRelativeTime(t)}));C.out(i),await reportTruncation(n,e.limit)}});function extractAllNamespaces(e){let t=/* @__PURE__ */ new Set;if(e.db)for(let n of Object.keys(e.db))t.add(n);return Array.from(t)}function extractOwnedNamespaces(e){let t=/* @__PURE__ */ new Set;if(e.db)for(let[n,r]of Object.entries(e.db))`external`in r||t.add(n);return Array.from(t)}function redactStringValues(e,t){if(typeof t==`string`)return S(t);if(typeof t==`number`||typeof t==`boolean`||t===null){let e=JSON.stringify(t),n=y(e);return n===e?t:n}return t}function errorToJson(e,t){let n=buildErrorEnvelope(e,t);try{return plainRedactedCopy(n)}catch{let{context:e,stack:t,...r}=n.error;return plainRedactedCopy({error:r})}}function plainRedactedCopy(e){return JSON.parse(JSON.stringify(e,redactStringValues))}function buildErrorEnvelope(e,t){let n=baseErrorEnvelope(e,t);if(!(e instanceof Error))return n;let{causes:r,context:i,location:a,...o}=s(e);return{error:{...n.error,...o,...i||r?{context:{...i,...Object.fromEntries(Object.entries(r??{}).map(([e,n])=>[e,errorToJson(n,t).error]))}}:{}}}}function baseErrorEnvelope(e,t){if(m(e))return{error:{code:e.code||`CLI_ERROR`,message:e.message,...e.details?{details:e.details}:{},...e.suggestion?{suggestion:e.suggestion}:{},...e.command?{help:executableHelpAction(e.command)}:{},...e.next?{next:e.next}:{},...e.context?{context:e.context}:{},...t?.includeStack&&e.stack?{stack:e.stack}:{}}};if(e instanceof q){let n=K[e.code];return{error:{code:`RPC_${typeof n==`string`?n.replaceAll(/([a-z0-9])([A-Z])/g,`$1_$2`).toUpperCase():`CODE_${e.code}`}`,message:e.message,...t?.includeStack&&e.stack?{stack:e.stack}:{}}}}if(e instanceof Error){let n=g(e);return{error:{code:e.name===`CIPromptError`?`INTERACTIVE_PROMPT_REQUIRED`:`UNEXPECTED_ERROR`,message:e.message,...n?{suggestion:n}:{},...t?.includeStack&&e.stack?{stack:e.stack}:{}}}}return{error:{code:`UNKNOWN_ERROR`,message:String(e)}}}function serializeError(e,t){return JSON.stringify(errorToJson(e,t))}function executableHelpAction(e){return{command:`tailor`,args:[...e.split(/\s+/).filter(Boolean),`--help`]}}function createGenerationManager(e){let{application:t,config:n,pluginManager:r}=e,i=H.join(Qe(),`generated`);W.mkdirSync(i,{recursive:!0});let o={tailordb:{},resolver:{},executor:{}},s=r?.getPluginsWithGenerationHooks()??[];function buildTailorDBData(){return Object.entries(o.tailordb).map(([e,t])=>({namespace:e,tables:t.types,sourceInfo:new Map(Object.entries(t.sourceInfo)),pluginAttachments:t.pluginAttachments}))}function buildResolverData(){return Object.entries(o.resolver).map(([e,t])=>({namespace:e,resolvers:t}))}async function runPluginPhaseHook(e,r){if(!e[r])return;let s=H.join(i,e.id),c=getAuthInput(t),l=buildTailorDBData(),u;switch(r){case`onTailorDBReady`:u=await a(e.onTailorDBReady,`plugin.onTailorDBReady hook missing`)({tailordb:l,auth:c,baseDir:s,configPath:n.path,pluginConfig:e.pluginConfig});break;case`onResolverReady`:u=await a(e.onResolverReady,`plugin.onResolverReady hook missing`)({tailordb:l,resolvers:buildResolverData(),auth:c,baseDir:s,configPath:n.path,pluginConfig:e.pluginConfig});break;case`onExecutorReady`:u=await a(e.onExecutorReady,`plugin.onExecutorReady hook missing`)({tailordb:l,resolvers:buildResolverData(),executors:{...o.executor},auth:c,baseDir:s,configPath:n.path,pluginConfig:e.pluginConfig})}await writeGeneratedFiles(e.id,u)}async function runPluginHook(e){let t=s.filter(t=>t[e]!=null);if(t.length===0)return;let n=(await Promise.allSettled(t.map(async t=>{try{await runPluginPhaseHook(t,e)}catch(n){throw C.error(`Error processing plugin ${h.bold(t.id)} (${e})`),C.error(String(n)),n}}))).flatMap((e,n)=>e.status===`rejected`?[{plugin:a(t[n],`Plugin result has no matching plugin`).id,reason:e.reason}]:[]);if(n.length>0)throw E({code:`PLUGIN_GENERATION_FAILED`,message:`Plugin generation failed during ${e}.`,details:n.map(({plugin:e,reason:t})=>`${e}: ${m(t)?S(t.format()):String(t)}`).join(`
|
|
507
|
+
`),context:{hook:e,failures:n.map(({plugin:e,reason:t})=>({plugin:e,error:errorToJson(t,{includeStack:C.verbose}).error}))}})}async function writeGeneratedFiles(e,t){await Promise.all(t.files.map(async t=>(W.mkdirSync(H.dirname(t.path),{recursive:!0}),new Promise((n,r)=>{if(t.skipIfExists&&W.existsSync(t.path)){let r=H.relative(process.cwd(),t.path);return C.debug(`${e} | skip existing: ${r}`),n()}W.writeFile(t.path,t.content,i=>{if(i){let e=H.relative(process.cwd(),t.path);C.error(`Error writing file ${h.bold(e)}`),C.error(String(i)),r(i)}else{let r=H.relative(process.cwd(),t.path);C.debug(`${e} | generate: ${h.success(r)}`),n()}})})))),t.files.length>0&&C.log(`${e} | generation complete`)}return{application:t,baseDir:i,services:o,async generate(){C.newline(),C.log(`Generation for application: ${h.highlight(t.config.name)}`);let e=t;await B(`generate.loadTailorDBTypes`,async t=>{t.setAttribute(`generate.namespace_count`,e.tailorDBServices.length);for(let t of e.tailorDBServices){let e=t.namespace;await B(`generate.loadTypes.${e}`,async()=>{try{await t.loadTypes(),await t.processNamespacePlugins(),o.tailordb[e]={types:t.types,sourceInfo:t.typeSourceInfo,pluginAttachments:t.pluginAttachments}}catch(t){throw C.error(`Error loading tables for TailorDB service ${h.bold(e)}`),C.error(String(t)),t}})}try{Fe({tailorDBServices:e.tailorDBServices})}catch(e){throw C.error(`Error validating TailorDB table names`),C.error(String(e)),e}});let i=[...e.resolverServices,...ut(n,r)],{pluginExecutorFiles:a,executorService:c}=await B(`generate.pluginFiles`,async()=>{let t=pt(r,e.tailorDBServices,n.path);return{pluginExecutorFiles:t,executorService:e.executorService??(t.length>0?St({config:{files:[]},baseDir:H.dirname(n.path)}):void 0)}});if(e.authService){let t=e.authService;await B(`generate.resolveAuthNamespaces`,async()=>t.resolveNamespaces())}(e.tailorDBServices.length>0||a.length>0)&&C.newline(),s.some(e=>e.onTailorDBReady!=null)&&(await B(`generate.onTailorDBReady`,async()=>{await runPluginHook(`onTailorDBReady`)}),C.newline()),await B(`generate.loadResolvers`,async()=>{for(let e of i){let t=e.namespace;await B(`generate.loadResolvers.${t}`,async()=>{try{await e.loadResolvers();let n={};o.resolver[t]=n,Object.entries(e.resolvers).forEach(([e,t])=>{n[t.name]=t})}catch(e){throw C.error(`Error loading resolvers for Resolver service ${h.bold(t)}`),C.error(String(e)),e}})}}),s.some(e=>e.onResolverReady!=null)&&(await B(`generate.onResolversReady`,async()=>{await runPluginHook(`onResolverReady`)}),C.newline()),await B(`generate.loadExecutors`,async()=>{c&&(await c.loadExecutors(),a.length>0&&await c.loadPluginExecutorFiles([...a]));let e=c?.executors??{};Object.entries(e).forEach(([e,t])=>{o.executor[e]=t})}),s.some(e=>e.onExecutorReady!=null)&&(await B(`generate.onExecutorsReady`,async()=>{await runPluginHook(`onExecutorReady`)}),C.newline())}}}async function generate$1(e){return B(`generate`,async t=>{let{config:n,plugins:r}=await B(`generate.loadConfig`,async()=>loadConfig(e?.configPath));await B(`generate.generateUserTypes`,async()=>generateUserTypes({config:n,configPath:n.path}));let i;r.length>0&&(i=new Er(r));let a=ht({config:n,pluginManager:i});t.setAttribute(`app.name`,a.config.name),await createGenerationManager({application:a,config:n,pluginManager:i}).generate()})}function machineUserInfo(e){return{id:e.id,name:e.name,clientId:e.clientId,createdAt:e.createdAt?G(e.createdAt):null,updatedAt:e.updatedAt?G(e.updatedAt):null,attributes:Object.fromEntries(Object.entries(e.attributeMap).map(([e,t])=>[e,Qr(ci,t)]))}}async function listMachineUsers(e){let{client:t,workspaceId:n}=await loadOperatorWorkspaceContext({profile:e?.profile,workspaceId:e?.workspaceId}),{config:r}=await loadConfig(e?.configPath),{application:i}=await t.getApplication({workspaceId:n,applicationName:r.name});if(!i?.authNamespace)throw E({code:`AUTH_CONFIG_REQUIRED`,message:`Application ${r.name} does not have an auth configuration.`});let a=Ce(e?.order);return(await Pt(async(e,r)=>{let{machineUsers:o,nextPageToken:s}=await t.listAuthMachineUsers({workspaceId:n,pageToken:e,pageSize:r,authNamespace:i.authNamespace,pageDirection:a});return[o,s]},{limit:e?.limit})).map(machineUserInfo)}const dl=Y({name:`list`,description:`List all machine users in the application.`,args:U.strictObject({...O,...pe()}),run:async e=>{let t=await fetchWithinLimit(e.limit,t=>listMachineUsers({workspaceId:e[`workspace-id`],profile:e.profile,configPath:e.config,order:e.order,limit:t})),n=t.items;C.out(n,{display:{createdAt:null,updatedAt:null}}),await reportTruncation(t,e.limit)}});async function getMachineUserTokenInternal(e){let t=await be({machineUser:e.name,machineUserSource:e.nameSource,profile:e.profile});if(!t)throw E({code:`MACHINE_USER_REQUIRED`,message:`Machine user is required.`,suggestion:`Provide the NAME positional argument, set TAILOR_PLATFORM_MACHINE_USER_NAME, or set a profile default with 'tailor profile update <profile> --machine-user <name>'.`,command:`machineuser token`});let{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId}),{config:i}=await loadConfig(e.configPath),{application:a}=await n.getApplication({workspaceId:r,applicationName:i.name});if(!a?.authNamespace)throw E({code:`AUTH_CONFIG_REQUIRED`,message:`Application ${i.name} does not have an auth configuration.`});let{machineUser:o}=await n.getAuthMachineUser({workspaceId:r,authNamespace:a.authNamespace,name:t});if(!o)throw E({code:`MACHINE_USER_NOT_FOUND`,message:`Machine user ${t} not found.`});let s=await It(a.url,o.clientId,o.clientSecret),c=/* @__PURE__ */ new Date;return c.setSeconds(c.getSeconds()+s.expires_in),{accessToken:s.access_token,tokenType:s.token_type,expiresAt:c.toISOString()}}async function getMachineUserToken(e){return await getMachineUserTokenInternal(e)}const fl=Y({name:`token`,description:`Get an access token for a machine user.`,args:U.strictObject({...O,name:V(U.string().optional(),{positional:!0,description:`Machine user name. Falls back to TAILOR_PLATFORM_MACHINE_USER_NAME, then the active profile's default machine user.`})}),run:async e=>{let t=await getMachineUserTokenInternal({name:e.name,nameSource:_e(e.name,process.argv.slice(2),{valueIsExplicit:e.name!==void 0}),workspaceId:e[`workspace-id`],profile:e.profile,configPath:e.config}),n={access_token:t.accessToken,token_type:t.tokenType,expires_at:t.expiresAt};C.out(n)}}),pl={[tn.UNSPECIFIED]:`unknown`,[tn.AUTHORIZATION_CODE]:`authorization_code`,[tn.REFRESH_TOKEN]:`refresh_token`},grantTypeToString=e=>protoEnumLookup(pl,e,`unknown`);function toOAuth2ClientInfo(e){return{name:e.name,description:e.description,clientId:e.clientId,grantTypes:e.grantTypes.map(grantTypeToString),redirectUris:e.redirectUris,createdAt:e.createdAt?G(e.createdAt):null}}function toOAuth2ClientCredentials(e){return C.registerSecret(e.clientSecret),{name:e.name,description:e.description,clientId:e.clientId,clientSecret:e.clientSecret,grantTypes:e.grantTypes.map(grantTypeToString),redirectUris:e.redirectUris,createdAt:e.createdAt?G(e.createdAt):null}}async function getOAuth2Client(e){let{client:t,workspaceId:n}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId}),{config:r}=await loadConfig(e.configPath),{application:i}=await t.getApplication({workspaceId:n,applicationName:r.name});if(!i?.authNamespace)throw E({code:`AUTH_CONFIG_REQUIRED`,message:`Application ${r.name} does not have an auth configuration.`});try{let{oauth2Client:r}=await t.getAuthOAuth2Client({workspaceId:n,namespaceName:i.authNamespace,name:e.name});return toOAuth2ClientCredentials(a(r,`oauth2Client missing in response`))}catch(t){throw t instanceof q&&t.code===K.NotFound?E({code:`OAUTH2_CLIENT_NOT_FOUND`,message:`OAuth2 client '${e.name}' not found.`,cause:t}):t}}const ml=Y({name:`get`,description:`Get OAuth2 client credentials (including client secret).`,args:U.strictObject({...O,name:V(U.string(),{positional:!0,description:`OAuth2 client name`})}),run:async e=>{let t=await getOAuth2Client({name:e.name,workspaceId:e[`workspace-id`],profile:e.profile,configPath:e.config});C.out(t)}});async function listOAuth2Clients(e){let{client:t,workspaceId:n}=await loadOperatorWorkspaceContext({profile:e?.profile,workspaceId:e?.workspaceId}),{config:r}=await loadConfig(e?.configPath),{application:i}=await t.getApplication({workspaceId:n,applicationName:r.name});if(!i?.authNamespace)throw E({code:`AUTH_CONFIG_REQUIRED`,message:`Application ${r.name} does not have an auth configuration.`});let a=Ce(e?.order);return(await Pt(async(e,r)=>{let{oauth2Clients:o,nextPageToken:s}=await t.listAuthOAuth2Clients({workspaceId:n,pageToken:e,pageSize:r,namespaceName:i.authNamespace,pageDirection:a});return[o,s]},{limit:e?.limit})).map(toOAuth2ClientInfo)}const hl=Y({name:`list`,description:`List all OAuth2 clients in the application.`,args:U.strictObject({...O,...pe()}),run:async e=>{let t=await fetchWithinLimit(e.limit,t=>listOAuth2Clients({workspaceId:e[`workspace-id`],profile:e.profile,configPath:e.config,order:e.order,limit:t})),n=t.items;C.out(n),await reportTruncation(t,e.limit)}}),userOrganizationInfo=e=>({organizationId:e.organizationId,organizationName:e.organizationName,rootFolderId:e.rootFolderId,rootFolderName:e.rootFolderName,displayName:e.displayName}),organizationInfo=e=>({id:e.id,name:e.name,createdAt:formatTimestamp(e.createTime),updatedAt:formatTimestamp(e.updateTime)}),folderListInfo=e=>({id:e.id,name:e.name,organizationId:e.organizationId,parentFolderId:e.parentFolderId,hasChildren:e.hasChildren,createdAt:formatTimestamp(e.createTime)}),folderInfo=e=>({...folderListInfo(e),updatedAt:formatTimestamp(e.updateTime)}),gl=U.object({organizationId:U.uuid({message:`organization-id must be a valid UUID`}),parentFolderId:U.string().optional(),name:U.string().min(1,`Name must not be empty`)});async function createFolder(e){let t=parseOptions(gl,e),n=await A(),r=await(await N(n)).createOrganizationFolder({organizationId:t.organizationId,parentFolderId:t.parentFolderId??``,folderName:t.name});if(!r.folder)throw b(`Failed to create folder.`);return folderInfo(r.folder)}const _l=Y({name:`create`,description:`Create a new folder in an organization.`,args:U.strictObject({...k,"parent-folder-id":V(U.string().optional(),{description:`Parent folder ID`}),name:V(U.string(),{alias:`n`,description:`Folder name`})}),run:async e=>{await assertWritable();let t=await createFolder({organizationId:e[`organization-id`],parentFolderId:e[`parent-folder-id`],name:e.name});e.json||C.success(`Folder "${t.name}" created successfully.`),C.out(t)}}),vl=U.object({organizationId:U.uuid({message:`organization-id must be a valid UUID`}),folderId:U.uuid({message:`folder-id must be a valid UUID`})});async function deleteFolder(e){let t=parseOptions(vl,e),n=await A();await(await N(n)).deleteOrganizationFolder({organizationId:t.organizationId,folderId:t.folderId})}const yl=Y({name:`delete`,description:`Delete a folder from an organization.`,args:U.strictObject({...k,...ue,...se}),run:async e=>{await assertWritable();let t=await A(),n=await N(t),r;try{r=await n.getOrganizationFolder({organizationId:e[`organization-id`],folderId:e[`folder-id`]})}catch(t){throw t instanceof q&&t.code===K.NotFound?E({code:`FOLDER_NOT_FOUND`,message:`Folder "${e[`folder-id`]}" not found.`,cause:t}):t}if(!r.folder)throw E({code:`FOLDER_NOT_FOUND`,message:`Folder "${e[`folder-id`]}" not found.`});let i=r.folder.name;if(!e.yes&&!await X.confirm({message:`Are you sure you want to delete folder "${i}"?`}))throw E({code:`FOLDER_DELETION_CANCELLED`,message:`Folder deletion cancelled.`});await n.deleteOrganizationFolder({organizationId:e[`organization-id`],folderId:e[`folder-id`]}),C.success(`Folder "${i}" deleted successfully.`),printMutationResult({changed:!0,organizationId:e[`organization-id`],folderId:e[`folder-id`],name:i})}}),bl=U.object({organizationId:U.uuid({message:`organization-id must be a valid UUID`}),folderId:U.uuid({message:`folder-id must be a valid UUID`})});async function getFolder(e){let t=parseOptions(bl,e),n=await A(),r=await(await N(n)).getOrganizationFolder({organizationId:t.organizationId,folderId:t.folderId});if(!r.folder)throw E({code:`FOLDER_NOT_FOUND`,message:`Folder "${t.folderId}" not found.`});return folderInfo(r.folder)}const xl=Y({name:`get`,description:`Show detailed information about a folder.`,args:U.strictObject({...k,...ue}),run:async e=>{let t=await getFolder({organizationId:e[`organization-id`],folderId:e[`folder-id`]}),n=e.json?t:{...t,createdAt:humanizeRelativeTime(t.createdAt),updatedAt:humanizeRelativeTime(t.updatedAt)};C.out(n)}}),Sl=U.object({organizationId:U.uuid({message:`organization-id must be a valid UUID`}),parentFolderId:U.string().optional(),order:Te.optional(),limit:U.number().int().nonnegative().optional()});async function listFolders(e){let{organizationId:t,parentFolderId:n,order:r,limit:i}=parseOptions(Sl,e),a=await A(),o=await N(a),s=Ce(r);return(await Pt(async(e,r)=>{let i=await o.listOrganizationFolders({organizationId:t,...n?{parentFolderId:n}:{},pageToken:e,pageSize:r,pageDirection:s});return[i.folders,i.nextPageToken]},{limit:i})).map(folderListInfo)}const Cl=Y({name:`list`,description:`List folders in an organization.`,args:U.strictObject({...k,"parent-folder-id":V(U.string().optional(),{description:`Parent folder ID to list children of`}),...pe()}),run:async e=>{let t=await fetchWithinLimit(e.limit,t=>listFolders({organizationId:e[`organization-id`],parentFolderId:e[`parent-folder-id`],order:e.order,limit:t})),n=t.items;C.out(n,{display:{updatedAt:null}}),await reportTruncation(t,e.limit)}}),wl=U.object({organizationId:U.uuid({message:`organization-id must be a valid UUID`}),folderId:U.uuid({message:`folder-id must be a valid UUID`}),name:U.string().min(1,`Name must not be empty`)});async function updateFolder(e){let t=parseOptions(wl,e),n=await A(),r=await(await N(n)).updateOrganizationFolder({organizationId:t.organizationId,folderId:t.folderId,folderName:t.name});if(!r.folder)throw b(`Failed to update folder "${t.folderId}".`);return folderInfo(r.folder)}const Tl=Y({name:`update`,description:`Update a folder's name.`,args:U.strictObject({...k,...ue,name:V(U.string(),{alias:`n`,description:`New folder name`})}),run:async e=>{await assertWritable();let t=await updateFolder({organizationId:e[`organization-id`],folderId:e[`folder-id`],name:e.name});e.json||C.success(`Folder "${t.name}" updated successfully.`),C.out(t)}}),El=U.object({organizationId:U.uuid({message:`organization-id must be a valid UUID`})});async function getOrganization(e){let t=parseOptions(El,e),n=await A(),r=await(await N(n)).getOrganization({organizationId:t.organizationId});if(!r.organization)throw E({code:`ORGANIZATION_NOT_FOUND`,message:`Organization "${t.organizationId}" not found.`});return organizationInfo(r.organization)}const Dl=Y({name:`get`,description:`Show detailed information about an organization.`,args:U.strictObject({...k}),run:async e=>{let t=await getOrganization({organizationId:e[`organization-id`]}),n=e.json?t:{...t,createdAt:humanizeRelativeTime(t.createdAt),updatedAt:humanizeRelativeTime(t.updatedAt)};C.out(n)}});async function listOrganizations(e){let t=e?.limit,n=await A(),{userOrganizations:r}=await(await N(n)).listUserOrganizations({}),i=r.map(userOrganizationInfo);return t===void 0?i:i.slice(0,t)}const Ol=Y({name:`list`,description:`List organizations you belong to.`,args:U.strictObject({limit:V(le.optional(),{alias:`l`,description:`Maximum number of organizations to list`})}),run:async e=>{let t=await fetchWithinLimit(e.limit,e=>listOrganizations({limit:e}));C.out(t.items),await reportTruncation(t,e.limit)}});async function fetchChildFolders(e,t,n,r,i){if(i!==void 0&&r>=i)return[];let a=await Nt(async(r,i)=>{let a=await e.listOrganizationFolders({organizationId:t,parentFolderId:n,pageToken:r,pageSize:i});return[a.folders,a.nextPageToken]}),o=[];for(let n of a){let a=n.hasChildren?await fetchChildFolders(e,t,n.id,r+1,i):[];o.push({name:n.name,children:a})}return o}async function buildFolderTreeJson(e,t,n,r,i){if(i!==void 0&&r>=i)return[];let a=await Nt(async(r,i)=>{let a=await e.listOrganizationFolders({organizationId:t,parentFolderId:n,pageToken:r,pageSize:i});return[a.folders,a.nextPageToken]}),o=[];for(let n of a){let a=n.hasChildren?await buildFolderTreeJson(e,t,n.id,r+1,i):[];o.push({id:n.id,name:n.name,children:a})}return o}function renderTree(e,t){let n=``;for(let[r,i]of e.entries()){let a=r===e.length-1,o=a?`└── `:`├── `,s=a?` `:`│ `;n+=`${t}${o}${i.name}\n`,i.children.length>0&&(n+=renderTree(i.children,t+s))}return n}async function buildOrgTree(e,t,n){let r=await fetchChildFolders(e,t.organizationId,t.rootFolderId,0,n),i=`${t.organizationName}\n`;return i+=renderTree(r,``),i}async function organizationTree(e){let t=await A(),n=await N(t),r;if(e?.organizationId){if(r=(await listOrganizations()).filter(t=>t.organizationId===e.organizationId),r.length===0)throw E({code:`ORGANIZATION_NOT_FOUND`,message:`Organization "${e.organizationId}" not found.`})}else r=await listOrganizations();let i=e?.depth,a=[];for(let e of r){let t=await buildFolderTreeJson(n,e.organizationId,e.rootFolderId,0,i);a.push({organizationId:e.organizationId,organizationName:e.organizationName,folders:t})}return a}const kl=Y({name:`tree`,description:`Display organization folder hierarchy as a tree.`,args:U.strictObject({"organization-id":V(U.string().optional(),{alias:`o`,description:`Organization ID (show all if omitted)`,env:`TAILOR_PLATFORM_ORGANIZATION_ID`}),depth:V(le.optional(),{alias:`d`,description:`Maximum folder depth to display`})}),run:async e=>{let t=await A(),n=await N(t),r;if(e[`organization-id`]){if(r=(await listOrganizations()).filter(t=>t.organizationId===e[`organization-id`]),r.length===0)throw E({code:`ORGANIZATION_NOT_FOUND`,message:`Organization "${e[`organization-id`]}" not found.`})}else r=await listOrganizations();if(e.json){let t=[];for(let i of r){let r=await buildFolderTreeJson(n,i.organizationId,i.rootFolderId,0,e.depth);t.push({organizationId:i.organizationId,organizationName:i.organizationName,folders:r})}C.out(t);return}let i=[];for(let t of r)i.push(await buildOrgTree(n,t,e.depth));C.log(i.join(`
|
|
508
|
+
`))}}),Al=U.object({organizationId:U.uuid({message:`organization-id must be a valid UUID`}),name:U.string().min(1,`Name must not be empty`)});async function updateOrganization(e){let t=parseOptions(Al,e),n=await A(),r=await(await N(n)).updateOrganization({organizationId:t.organizationId,organizationName:t.name});if(!r.organization)throw b(`Failed to update organization "${t.organizationId}".`);return organizationInfo(r.organization)}const jl=Y({name:`update`,description:`Update an organization's name.`,args:U.strictObject({...k,name:V(U.string(),{alias:`n`,description:`New organization name`})}),run:async e=>{await assertWritable();let t=await updateOrganization({organizationId:e[`organization-id`],name:e.name});e.json||C.success(`Organization "${t.name}" updated successfully.`),C.out(t)}});async function resolveRemoveConfigId(e){let t=findAppIdLock(e.path);if(t===null)return warnMissingAppId(e.id),e;let n=await resolveLockedAppIds({lock:t,mode:`read`,entries:[{configPath:e.path,configId:e.id}]});return{...e,id:n.entries[0]?.id}}async function loadOptions$10(e){let{client:t,workspaceId:n}=await loadOperatorWorkspaceContext({profile:e?.profile,workspaceId:e?.workspaceId}),{config:r}=await loadConfig(e?.configPath),i=await resolveRemoveConfigId(r);return{client:t,workspaceId:n,application:ht({config:i}),config:i}}async function execRemove(e,t,n,r,i){let a={client:e,workspaceId:t,application:n,forRemoval:!0,config:r},o={tailorDB:await planTailorDB(a),staticWebsite:await planStaticWebsite(a),aiGateway:await planAIGateway(a),idp:await planIdP(a),auth:await planAuth(a),pipeline:await planPipeline(a),app:await planApplication(a),executor:await planExecutor(a),workflow:await planWorkflow(e,t,n.name,n.id,{},{}),workflowExecutionPolicy:await planWorkflowJobFunctionExecutionPolicy(e,t,n.name,n.id,{}),functionRegistry:await planFunctionRegistry(e,t,n.name,n.id,[]),secretManager:await planSecretManager(a)};assertStaticWebsiteDeletesNotOffered(o.staticWebsite);let s=Object.values(o).some(e=>`resourceOwners`in e&&e.resourceOwners.has(n.name)),c=createChangeSet(`Workflow job functions`);c.deletes.push(...o.workflow.jobFunctionDeletes.map(e=>({name:e.jobFunctionName})));let l=[o.functionRegistry.changeSet,o.staticWebsite.changeSet,o.aiGateway.changeSet,o.app,o.tailorDB.changeSet.service,o.tailorDB.changeSet.type,o.tailorDB.changeSet.gqlPermission,o.pipeline.changeSet.service,o.pipeline.changeSet.resolver,o.executor.changeSet,o.workflow.changeSet,c,o.workflowExecutionPolicy.changeSet,o.idp.changeSet.service,o.idp.changeSet.client,o.auth.changeSet.service,o.auth.changeSet.idpConfig,o.auth.changeSet.userProfileConfig,o.auth.changeSet.tenantConfig,o.auth.changeSet.machineUser,o.auth.changeSet.oauth2Client,o.auth.changeSet.authHook,o.auth.changeSet.scim,o.auth.changeSet.scimResource,o.auth.changeSet.connection,o.secretManager.vaultChangeSet,o.secretManager.secretChangeSet],u=l.flatMap(e=>e.lines());return u.length>0&&C.log(u.join(`
|
|
509
|
+
`)),l.every(e=>e.deletes.length===0)?{removed:!1,leftBehind:s}:(i&&await i(),await applyWorkflow(e,o.workflow,`delete`),await applyWorkflowJobFunctionExecutionPolicy(e,o.workflowExecutionPolicy,`delete`),await applyExecutor(e,o.executor,`delete`),await applyStaticWebsite(e,o.staticWebsite,`delete`),await applyAIGateway(e,o.aiGateway,`delete`),await applyApplication(e,o.app,`delete`),await applyPipeline(e,o.pipeline,`delete-resources`),await applyPipeline(e,o.pipeline,`delete-services`),await applyAuth(e,o.auth,`delete-resources`),await applyAuth(e,o.auth,`delete-services`),await applyIdP(e,o.idp,`delete-resources`),await applyIdP(e,o.idp,`delete-services`),await applyTailorDB(e,o.tailorDB,`delete-resources`),await applyTailorDB(e,o.tailorDB,`delete-services`),await applyFunctionRegistry(e,t,o.functionRegistry,`delete`),await applySecretManager(e,o.secretManager,`delete`),{removed:!0,leftBehind:s})}async function remove(e){let{client:t,workspaceId:n,application:r,config:i}=await loadOptions$10(e);await execRemove(t,n,r,i)}const Ml=Y({name:`remove`,description:`Remove all resources managed by the application from the workspace.`,args:U.strictObject({...O,...se}),run:async e=>{await assertWritable({profile:e.profile});let{client:t,workspaceId:n,application:r,config:i}=await loadOptions$10({workspaceId:e[`workspace-id`],profile:e.profile,configPath:e.config});C.info(`Planning removal of resources managed by "${r.name}"...`),C.newline();let a=await execRemove(t,n,r,i,async()=>{if(e.yes)C.success(`Removing all resources (--yes flag specified)...`);else if(!await X.confirm({message:`Are you sure you want to remove all resources?`,default:!1}))throw E({code:`REMOVE_CANCELLED`,message:M`
|
|
504
510
|
Remove cancelled. No resources were deleted.
|
|
505
511
|
To override, run again and confirm, or use --yes flag.
|
|
506
512
|
`})});printMutationResult({changed:a.removed,workspaceId:n,application:r.name,complete:!a.leftBehind}),a.leftBehind?C.warn(M`
|
|
507
513
|
Resources tagged with "${r.name}" were left in place: they carry an application id this config does not match.
|
|
508
514
|
Record that id for this config (in .github/tailor.lock, or the config's 'id'), or run deploy to take them over first, then remove again.
|
|
509
|
-
`):C.success(`Successfully removed all resources managed by "${r.name}".`)}});function applicationInfo(e){return{name:e.name,domain:e.domain,url:e.url,auth:e.authNamespace,cors:e.cors,allowedIpAddresses:e.allowedIpAddresses,disableIntrospection:e.disableIntrospection,createdAt:e.createTime?G(e.createTime):null,updatedAt:e.updateTime?G(e.updateTime):null}}async function fetchAIGateways(e,t,n){return(await Promise.all(n.map(async n=>{let r=await P(()=>e.getAIGateway({workspaceId:t,aigatewayName:n}));return r?.aigateway?{name:r.aigateway.name,url:r.aigateway.url}:void 0}))).filter(e=>e!==void 0)}async function fetchStaticWebsites(e,t,n){return(await Promise.all(n.map(async n=>{let r=(await P(()=>e.getStaticWebsite({workspaceId:t,name:n})))?.staticwebsite;return r?{name:r.name,url:r.url,description:r.description}:void 0}))).filter(e=>e!==void 0)}function oauth2ClientNames(e){return!e||`external`in e?[]:Object.keys(e.oauth2Clients??{})}async function fetchOAuth2Clients(e,t,n,r){if(!n||r.length===0)return[];let i;try{i=await F(async(r,i)=>{let{oauth2Clients:a,nextPageToken:o}=await e.listAuthOAuth2Clients({workspaceId:t,namespaceName:n,pageToken:r,pageSize:i});return[a,o]})}catch(e){if(e instanceof q&&e.code===K.PermissionDenied)return C.warn(`The current credentials cannot list OAuth2 clients in auth namespace "${n}", so oauth2Clients is null.`),null;throw e}let a=/* @__PURE__ */ new Map;for(let e of i)C.registerSecret(e.clientSecret),a.set(e.name,e.clientId);return r.flatMap(e=>{let t=a.get(e);return t===void 0?[]:[{name:e,clientId:t}]})}async function show(e){let{client:t,workspaceId:n}=await loadOperatorWorkspaceContext({profile:e?.profile,workspaceId:e?.workspaceId}),{config:r}=await loadConfig(e?.configPath),i=r.aiGateways?.length?[...new Set(r.aiGateways.map(e=>e.name))]:[],o=r.staticWebsites?.length?[...new Set(r.staticWebsites.map(e=>e.name))]:[],s=t.getApplication({workspaceId:n,applicationName:r.name}),[c,l,u,d,f]=await Promise.all([t.getWorkspace({workspaceId:n}),s,fetchAIGateways(t,n,i),fetchStaticWebsites(t,n,o),s.then(({application:e})=>fetchOAuth2Clients(t,n,e?.authNamespace??``,oauth2ClientNames(r.auth)))]),{name:p,...m}=applicationInfo(a(l.application,`application "${r.name}" not found in workspace`)),h=c.workspace,g=h?await resolveWorkspaceFolderName(t,h):``;return{name:p,workspaceId:n,workspaceName:h?.name??``,...g?{workspaceFolderName:g}:{},workspaceRegion:h?.region??``,...m,aiGateways:u,staticWebsites:d,oauth2Clients:f}}const Dl=createWorkspaceNameTransformer(`workspaceName`,`workspaceFolderName`),Ol=Y({name:`show`,description:`Show information about the deployed application.`,args:U.strictObject({...k}),run:async e=>{let t=await show({workspaceId:e[`workspace-id`],profile:e.profile,configPath:e.config});C.out(t,{display:{workspaceName:Dl,workspaceFolderName:null}})}});function logBetaWarning(e){C.warn(`The '${e}' command is a beta feature and may introduce breaking changes in future releases.`),C.newline()}function normalizeEditorCommand(e){let t=e?.trim();return t&&t.length>0?t:void 0}function getConfiguredEditorCommand(){return normalizeEditorCommand(process.env.VISUAL)??normalizeEditorCommand(process.env.EDITOR)}function getEditorCommand(){return getConfiguredEditorCommand()??`editor`}function parseEditorCommand(e){let[t,...n]=e.trim().split(/\s+/);if(!t)throw Error(`Editor command is empty.`);return{command:t,args:n}}async function openInEditor(e,t=getEditorCommand()){let{command:n,args:r}=parseEditorCommand(t);return await new Promise((t,i)=>{let a=Fi(n,[...r,e],{stdio:`inherit`,detached:!1});a.once(`error`,e=>i(e)),a.once(`close`,e=>{e==null||e===0?t():i(/* @__PURE__ */ Error(`Editor exited with code ${e}.`))})}),!0}async function openInConfiguredEditor(e){let t=getConfiguredEditorCommand();return t?await openInEditor(e,t):!1}function fieldKey(e,t){return`${e}.${t}`}function buildTempFieldName(e,t){let n=`${e}Migrate`;for(let e=1;e<=t.size+1;e++){let r=e===1?n:`${n}${e}`;if(r.length>63)break;if(!t.has(r))return r}throw E({code:`MIGRATION_EXPAND_CONTRACT_NAME_UNAVAILABLE`,message:`Cannot derive a temporary field name for "${e}": every candidate is taken or exceeds 63 characters.`})}function isExpandContractCandidate(e){return e.kind===`field_type_modified`||e.kind===`field_modified`&&hasFieldShapeChange(e.before,e.after)}function canConvertField(e){return getExpandContractEligibility(e).eligible}function getExpandContractEligibility(e){let{previous:t,current:n,tableName:r,fieldName:i}=e,a=t.tables[r]?.fields[i],o=n.tables[r]?.fields[i];if(!a||!o)return{eligible:!1,reason:`the field does not exist in both schemas`};let s=getExpandContractFieldChangeEligibility(a,o);return s.eligible?isFieldReferenced(t.tables[r],i)||isFieldReferenced(n.tables[r],i)?{eligible:!1,reason:`another schema feature references the field`}:{eligible:!0}:s}function typeMemberNames(e){return e?[...Object.keys(e.fields),...Object.keys(e.files??{}),...Object.keys(e.forwardRelationships??{}),...Object.keys(e.backwardRelationships??{})]:[]}function staticPropertyName(e,t){if(!t&&e.type===`Identifier`)return e.name;if(e.type===`Literal`&&typeof e.value==`string`)return e.value;if(e.type===`TemplateLiteral`&&e.expressions.length===0)return e.quasis[0]?.value.cooked??void 0}const kl=/* @__PURE__ */ new Set([`input`,`newRecord`,`oldRecord`,`invoker`,`now`]);function walkScriptAst(e,t,n=[]){if(!e)return;t(e,n);let r=[...n,e],i=e;for(let[e,n]of Object.entries(i))if(e!==`type`&&e!==`parent`){if(Array.isArray(n))for(let e of n)e&&typeof e==`object`&&`type`in e&&walkScriptAst(e,t,r);else n&&typeof n==`object`&&`type`in n&&walkScriptAst(n,t,r)}}function unwrapFunction(e){return e.type===`ParenthesizedExpression`?unwrapFunction(e.expression):e}function collectIssueBindings(e){let t=/* @__PURE__ */ new Set([`__issues`]);walkScriptAst(e,e=>{if(e.type!==`CallExpression`)return;let n=unwrapFunction(e.callee);if(n.type!==`ArrowFunctionExpression`&&n.type!==`FunctionExpression`||e.arguments[1]?.type!==`Identifier`||e.arguments[1].name!==`__issues`)return;let r=n.params[1];r?.type===`Identifier`&&t.add(r.name)});let n;do{let r=t.size;walkScriptAst(e,e=>{e.type===`VariableDeclarator`&&e.id.type===`Identifier`&&e.init?.type===`Identifier`&&t.has(e.init.name)&&t.add(e.id.name)}),n=t.size>r}while(n);return t}function isWrapperArgumentProperty(e,t){if(e.type!==`Property`)return!1;let n=staticPropertyName(e.key,e.computed);if(!n||!kl.has(n))return!1;let r=t.at(-1),i=t.at(-2);return r?.type!==`ObjectExpression`||i?.type!==`CallExpression`?!1:i.arguments[0]===r&&[`ArrowFunctionExpression`,`FunctionExpression`].includes(unwrapFunction(i.callee).type)}function isWrapperParameterProperty(e,t){if(e.type!==`Property`)return!1;let n=staticPropertyName(e.key,e.computed);if(!n||!kl.has(n))return!1;let r=t.at(-1);if(r?.type!==`ObjectPattern`)return!1;for(let e=t.length-2;e>=0;e--){let i=t[e];if(i&&(i.type===`ArrowFunctionExpression`||i.type===`FunctionExpression`)&&i.params[0]===r)return t.slice(0,e).some(e=>e.type===`CallExpression`&&unwrapFunction(e.callee)===i&&e.arguments[0]?.type===`ObjectExpression`&&e.arguments[0].properties.some(e=>e.type===`Property`&&staticPropertyName(e.key,e.computed)===n))}return!1}function isIssueMessage(e,t,n){let r=t.at(-1);return r?.type===`CallExpression`&&r.callee.type===`Identifier`&&n.has(r.callee.name)&&r.arguments.findIndex(t=>t===e)>0}function scriptReferencesField(e,t){try{let{program:n,errors:r}=Ci(`expand-contract-reference.js`,e,{sourceType:`module`});if(r.length>0)return!0;let i=collectIssueBindings(n),a=!1;return walkScriptAst(n,(e,n)=>{a||(e.type===`MemberExpression`&&(staticPropertyName(e.property,e.computed)===t||e.computed&&staticPropertyName(e.property,!0)===void 0)||e.type===`Property`&&(staticPropertyName(e.key,e.computed)===t||e.computed&&staticPropertyName(e.key,!0)===void 0)&&(e.computed||!isWrapperArgumentProperty(e,n)&&!isWrapperParameterProperty(e,n))||e.type===`CallExpression`&&e.callee.type===`Identifier`&&i.has(e.callee.name)&&e.arguments[0]!==void 0&&e.arguments[0].type!==`SpreadElement`&&staticPropertyName(e.arguments[0],!0)===t?a=!0:e.type!==`Literal`&&e.type!==`TemplateLiteral`||staticPropertyName(e,!0)!==t||isIssueMessage(e,n,i)||(a=!0))}),a}catch{return!0}}function permissionsReferenceField(e,t){return e?[...e.record?Object.values(e.record).flatMap(e=>e):[],...e.gql??[]].some(e=>e.conditions.some(e=>{let[n,,r]=e;return[n,r].some(e=>isSnapshotFieldRefOperand(e)&&(`record`in e&&e.record===t||`newRecord`in e&&e.newRecord===t||`oldRecord`in e&&e.oldRecord===t))})):!1}function isFieldReferenced(e,t){return e?Object.values(e.indexes??{}).some(e=>e.fields.includes(t))||[...Object.values(e.forwardRelationships??{}),...Object.values(e.backwardRelationships??{})].some(e=>e.sourceField===t||e.targetField===t)||permissionsReferenceField(e.permissions,t)?!0:[e.typeHookExpr?.create,e.typeHookExpr?.update,e.typeValidateExpr].filter(e=>e!==void 0).some(e=>scriptReferencesField(e,t)):!1}function planExpandContract(e){let{previous:t,current:n,diff:r,confirmed:i}=e,a=[],o=/* @__PURE__ */ new Set;for(let e of r.changes){if(!isExpandContractCandidate(e))continue;let r=fieldKey(e.tableName,e.fieldName);if(!i.has(r)||!canConvertField({previous:t,current:n,tableName:e.tableName,fieldName:e.fieldName}))continue;let s=/* @__PURE__ */ new Set([...typeMemberNames(t.tables[e.tableName]),...typeMemberNames(n.tables[e.tableName]),...a.filter(t=>t.tableName===e.tableName).map(e=>e.tempFieldName)]);a.push({tableName:e.tableName,fieldName:e.fieldName,tempFieldName:buildTempFieldName(e.fieldName,s),before:e.before,after:e.after}),o.add(r)}return{plans:a,blocked:r.breakingChanges.filter(e=>e.unsupported&&!(e.fieldName&&o.has(fieldKey(e.tableName,e.fieldName))))}}function extractBreakingChangeFields(e){let t=/* @__PURE__ */ new Map,n=/* @__PURE__ */ new Map,r=/* @__PURE__ */ new Map,i=/* @__PURE__ */ new Map,o=/* @__PURE__ */ new Map;for(let s of e.changes)if(s.kind===`field_modified`||s.kind===`field_type_modified`){let{before:e,after:n}=s;if(!e.required&&n.required&&(t.has(s.tableName)||t.set(s.tableName,/* @__PURE__ */ new Set),a(t.get(s.tableName),`optionalToRequired entry missing`).add(s.fieldName)),e.type===`enum`&&n.type===`enum`){let t=(e.allowedValues??[]).map(e=>e.value),i=(n.allowedValues??[]).map(e=>e.value),o=new Set(t),c=new Set(i);(t.some(e=>!c.has(e))||i.some(e=>!o.has(e)))&&(r.has(s.tableName)||r.set(s.tableName,/* @__PURE__ */ new Map),a(r.get(s.tableName),`enumValueChanges entry missing`).set(s.fieldName,{beforeValues:t,afterValues:i,afterRequired:n.required}))}}else if(s.kind===`field_added`){let{after:e}=s;e.required&&(n.has(s.tableName)||n.set(s.tableName,/* @__PURE__ */ new Map),a(n.get(s.tableName),`addedRequiredFields entry missing`).set(s.fieldName,e))}else s.kind===`field_renamed`?(i.has(s.tableName)||i.set(s.tableName,/* @__PURE__ */ new Map),a(i.get(s.tableName),`renamedFields entry missing`).set(s.fieldName,s.after)):s.kind===`table_renamed`&&o.set(s.tableName,s.after);return{optionalToRequired:t,addedRequiredFields:n,enumValueChanges:r,renamedFields:i,clearedFields:/* @__PURE__ */ new Map,renamedTypes:o}}function generateDbTypesFromSnapshot(e,t,n=[],r=!1){let i=t?extractBreakingChangeFields(t):{optionalToRequired:/* @__PURE__ */ new Map,addedRequiredFields:/* @__PURE__ */ new Map,enumValueChanges:/* @__PURE__ */ new Map,renamedFields:/* @__PURE__ */ new Map,clearedFields:/* @__PURE__ */ new Map,renamedTypes:/* @__PURE__ */ new Map};for(let e of n){let t=i.renamedFields.get(e.tableName)??/* @__PURE__ */ new Map;t.set(e.tempFieldName,{...e.after,required:!1,unique:!1}),i.renamedFields.set(e.tableName,t);let n=i.clearedFields.get(e.tableName)??/* @__PURE__ */ new Set;n.add(e.fieldName),i.clearedFields.set(e.tableName,n)}let a=[...Object.values(e.tables),...i.renamedTypes.values()];if(a.length===0)return generateEmptyDbTypes(e.namespace);let o=/* @__PURE__ */ new Set,s=!1,c=!1,l=!1,u=[];for(let e of a){let t=generateTableType(e,i,r);for(let e of t.usedUtilityTypes)o.add(e);s||=t.usedColumnType,c||=t.usedArrayColumnType,l||=t.usesTemporalNamespace,u.push(t.typeDef)}let d=[`type Transaction as KyselyTransaction`,`type Generated`];return s&&d.unshift(`type ColumnType`),c&&d.push(`type ArrayColumnType`),o.has(`Timestamp`)&&d.push(`type Timestamp`),o.has(`Serial`)&&d.push(`type Serial`),o.has(`TemporalDate`)&&d.push(`type TemporalDate`),o.has(`TemporalInstant`)&&d.push(`type TemporalInstant`),o.has(`TemporalTime`)&&d.push(`type TemporalTime`),l&&d.push(`type Temporal`),[`/**`,` * Auto-generated Kysely types for migration script.`,` * These types reflect the database schema state at this migration point.`,` *`,` * DO NOT EDIT - This file is auto-generated by the migration system.`,` */`,``,`import { ${d.join(`, `)} } from "@tailor-platform/sdk/kysely";`,`import type { Env } from "@tailor-platform/sdk";`,``,`export interface Database {`,...u,`}`,``,`export type Transaction = KyselyTransaction<Database>;`,``,...Al].join(`
|
|
515
|
+
`):C.success(`Successfully removed all resources managed by "${r.name}".`)}});function applicationInfo(e){return{name:e.name,domain:e.domain,url:e.url,auth:e.authNamespace,cors:e.cors,allowedIpAddresses:e.allowedIpAddresses,disableIntrospection:e.disableIntrospection,createdAt:e.createTime?G(e.createTime):null,updatedAt:e.updateTime?G(e.updateTime):null}}async function fetchAIGateways(e,t,n){return(await Promise.all(n.map(async n=>{let r=await P(()=>e.getAIGateway({workspaceId:t,aigatewayName:n}));return r?.aigateway?{name:r.aigateway.name,url:r.aigateway.url}:void 0}))).filter(e=>e!==void 0)}async function fetchStaticWebsites(e,t,n){return(await Promise.all(n.map(async n=>{let r=(await P(()=>e.getStaticWebsite({workspaceId:t,name:n})))?.staticwebsite;return r?{name:r.name,url:r.url,description:r.description}:void 0}))).filter(e=>e!==void 0)}function oauth2ClientNames(e){return!e||`external`in e?[]:Object.keys(e.oauth2Clients??{})}async function fetchOAuth2Clients(e,t,n,r){if(!n||r.length===0)return[];let i;try{i=await F(async(r,i)=>{let{oauth2Clients:a,nextPageToken:o}=await e.listAuthOAuth2Clients({workspaceId:t,namespaceName:n,pageToken:r,pageSize:i});return[a,o]})}catch(e){if(e instanceof q&&e.code===K.PermissionDenied)return C.warn(`The current credentials cannot list OAuth2 clients in auth namespace "${n}", so oauth2Clients is null.`),null;throw e}let a=/* @__PURE__ */ new Map;for(let e of i)C.registerSecret(e.clientSecret),a.set(e.name,e.clientId);return r.flatMap(e=>{let t=a.get(e);return t===void 0?[]:[{name:e,clientId:t}]})}async function show(e){let{client:t,workspaceId:n}=await loadOperatorWorkspaceContext({profile:e?.profile,workspaceId:e?.workspaceId}),{config:r}=await loadConfig(e?.configPath),i=r.aiGateways?.length?[...new Set(r.aiGateways.map(e=>e.name))]:[],o=r.staticWebsites?.length?[...new Set(r.staticWebsites.map(e=>e.name))]:[],s=t.getApplication({workspaceId:n,applicationName:r.name}),[c,l,u,d,f]=await Promise.all([t.getWorkspace({workspaceId:n}),s,fetchAIGateways(t,n,i),fetchStaticWebsites(t,n,o),s.then(({application:e})=>fetchOAuth2Clients(t,n,e?.authNamespace??``,oauth2ClientNames(r.auth)))]),{name:p,...m}=applicationInfo(a(l.application,`application "${r.name}" not found in workspace`)),h=c.workspace,g=h?await resolveWorkspaceFolderName(t,h):``;return{name:p,workspaceId:n,workspaceName:h?.name??``,...g?{workspaceFolderName:g}:{},workspaceRegion:h?.region??``,...m,aiGateways:u,staticWebsites:d,oauth2Clients:f}}const Nl=createWorkspaceNameTransformer(`workspaceName`,`workspaceFolderName`),Pl=Y({name:`show`,description:`Show information about the deployed application.`,args:U.strictObject({...O}),run:async e=>{let t=await show({workspaceId:e[`workspace-id`],profile:e.profile,configPath:e.config});C.out(t,{display:{workspaceName:Nl,workspaceFolderName:null}})}});function logBetaWarning(e){C.warn(`The '${e}' command is a beta feature and may introduce breaking changes in future releases.`),C.newline()}function normalizeEditorCommand(e){let t=e?.trim();return t&&t.length>0?t:void 0}function getConfiguredEditorCommand(){return normalizeEditorCommand(process.env.VISUAL)??normalizeEditorCommand(process.env.EDITOR)}function getEditorCommand(){return getConfiguredEditorCommand()??`editor`}function parseEditorCommand(e){let[t,...n]=e.trim().split(/\s+/);if(!t)throw Error(`Editor command is empty.`);return{command:t,args:n}}async function openInEditor(e,t=getEditorCommand()){let{command:n,args:r}=parseEditorCommand(t);return await new Promise((t,i)=>{let a=Ri(n,[...r,e],{stdio:`inherit`,detached:!1});a.once(`error`,e=>i(e)),a.once(`close`,e=>{e==null||e===0?t():i(/* @__PURE__ */ Error(`Editor exited with code ${e}.`))})}),!0}async function openInConfiguredEditor(e){let t=getConfiguredEditorCommand();return t?await openInEditor(e,t):!1}function fieldKey(e,t){return`${e}.${t}`}function buildTempFieldName(e,t){let n=`${e}Migrate`;for(let e=1;e<=t.size+1;e++){let r=e===1?n:`${n}${e}`;if(r.length>63)break;if(!t.has(r))return r}throw E({code:`MIGRATION_EXPAND_CONTRACT_NAME_UNAVAILABLE`,message:`Cannot derive a temporary field name for "${e}": every candidate is taken or exceeds 63 characters.`})}function isExpandContractCandidate(e){return e.kind===`field_type_modified`||e.kind===`field_modified`&&hasFieldShapeChange(e.before,e.after)}function canConvertField(e){return getExpandContractEligibility(e).eligible}function getExpandContractEligibility(e){let{previous:t,current:n,tableName:r,fieldName:i}=e,a=t.tables[r]?.fields[i],o=n.tables[r]?.fields[i];if(!a||!o)return{eligible:!1,reason:`the field does not exist in both schemas`};let s=getExpandContractFieldChangeEligibility(a,o);return s.eligible?isFieldReferenced(t.tables[r],i)||isFieldReferenced(n.tables[r],i)?{eligible:!1,reason:`another schema feature references the field`}:{eligible:!0}:s}function typeMemberNames(e){return e?[...Object.keys(e.fields),...Object.keys(e.files??{}),...Object.keys(e.forwardRelationships??{}),...Object.keys(e.backwardRelationships??{})]:[]}function staticPropertyName(e,t){if(!t&&e.type===`Identifier`)return e.name;if(e.type===`Literal`&&typeof e.value==`string`)return e.value;if(e.type===`TemplateLiteral`&&e.expressions.length===0)return e.quasis[0]?.value.cooked??void 0}const Fl=/* @__PURE__ */ new Set([`input`,`newRecord`,`oldRecord`,`invoker`,`now`]);function walkScriptAst(e,t,n=[]){if(!e)return;t(e,n);let r=[...n,e],i=e;for(let[e,n]of Object.entries(i))if(e!==`type`&&e!==`parent`){if(Array.isArray(n))for(let e of n)e&&typeof e==`object`&&`type`in e&&walkScriptAst(e,t,r);else n&&typeof n==`object`&&`type`in n&&walkScriptAst(n,t,r)}}function unwrapFunction(e){return e.type===`ParenthesizedExpression`?unwrapFunction(e.expression):e}function collectIssueBindings(e){let t=/* @__PURE__ */ new Set([`__issues`]);walkScriptAst(e,e=>{if(e.type!==`CallExpression`)return;let n=unwrapFunction(e.callee);if(n.type!==`ArrowFunctionExpression`&&n.type!==`FunctionExpression`||e.arguments[1]?.type!==`Identifier`||e.arguments[1].name!==`__issues`)return;let r=n.params[1];r?.type===`Identifier`&&t.add(r.name)});let n;do{let r=t.size;walkScriptAst(e,e=>{e.type===`VariableDeclarator`&&e.id.type===`Identifier`&&e.init?.type===`Identifier`&&t.has(e.init.name)&&t.add(e.id.name)}),n=t.size>r}while(n);return t}function isWrapperArgumentProperty(e,t){if(e.type!==`Property`)return!1;let n=staticPropertyName(e.key,e.computed);if(!n||!Fl.has(n))return!1;let r=t.at(-1),i=t.at(-2);return r?.type!==`ObjectExpression`||i?.type!==`CallExpression`?!1:i.arguments[0]===r&&[`ArrowFunctionExpression`,`FunctionExpression`].includes(unwrapFunction(i.callee).type)}function isWrapperParameterProperty(e,t){if(e.type!==`Property`)return!1;let n=staticPropertyName(e.key,e.computed);if(!n||!Fl.has(n))return!1;let r=t.at(-1);if(r?.type!==`ObjectPattern`)return!1;for(let e=t.length-2;e>=0;e--){let i=t[e];if(i&&(i.type===`ArrowFunctionExpression`||i.type===`FunctionExpression`)&&i.params[0]===r)return t.slice(0,e).some(e=>e.type===`CallExpression`&&unwrapFunction(e.callee)===i&&e.arguments[0]?.type===`ObjectExpression`&&e.arguments[0].properties.some(e=>e.type===`Property`&&staticPropertyName(e.key,e.computed)===n))}return!1}function isIssueMessage(e,t,n){let r=t.at(-1);return r?.type===`CallExpression`&&r.callee.type===`Identifier`&&n.has(r.callee.name)&&r.arguments.findIndex(t=>t===e)>0}function scriptReferencesField(e,t){try{let{program:n,errors:r}=Ei(`expand-contract-reference.js`,e,{sourceType:`module`});if(r.length>0)return!0;let i=collectIssueBindings(n),a=!1;return walkScriptAst(n,(e,n)=>{a||(e.type===`MemberExpression`&&(staticPropertyName(e.property,e.computed)===t||e.computed&&staticPropertyName(e.property,!0)===void 0)||e.type===`Property`&&(staticPropertyName(e.key,e.computed)===t||e.computed&&staticPropertyName(e.key,!0)===void 0)&&(e.computed||!isWrapperArgumentProperty(e,n)&&!isWrapperParameterProperty(e,n))||e.type===`CallExpression`&&e.callee.type===`Identifier`&&i.has(e.callee.name)&&e.arguments[0]!==void 0&&e.arguments[0].type!==`SpreadElement`&&staticPropertyName(e.arguments[0],!0)===t?a=!0:e.type!==`Literal`&&e.type!==`TemplateLiteral`||staticPropertyName(e,!0)!==t||isIssueMessage(e,n,i)||(a=!0))}),a}catch{return!0}}function permissionsReferenceField(e,t){return e?[...e.record?Object.values(e.record).flatMap(e=>e):[],...e.gql??[]].some(e=>e.conditions.some(e=>{let[n,,r]=e;return[n,r].some(e=>isSnapshotFieldRefOperand(e)&&(`record`in e&&e.record===t||`newRecord`in e&&e.newRecord===t||`oldRecord`in e&&e.oldRecord===t))})):!1}function isFieldReferenced(e,t){return e?Object.values(e.indexes??{}).some(e=>e.fields.includes(t))||[...Object.values(e.forwardRelationships??{}),...Object.values(e.backwardRelationships??{})].some(e=>e.sourceField===t||e.targetField===t)||permissionsReferenceField(e.permissions,t)?!0:[e.typeHookExpr?.create,e.typeHookExpr?.update,e.typeValidateExpr].filter(e=>e!==void 0).some(e=>scriptReferencesField(e,t)):!1}function planExpandContract(e){let{previous:t,current:n,diff:r,confirmed:i}=e,a=[],o=/* @__PURE__ */ new Set;for(let e of r.changes){if(!isExpandContractCandidate(e))continue;let r=fieldKey(e.tableName,e.fieldName);if(!i.has(r)||!canConvertField({previous:t,current:n,tableName:e.tableName,fieldName:e.fieldName}))continue;let s=/* @__PURE__ */ new Set([...typeMemberNames(t.tables[e.tableName]),...typeMemberNames(n.tables[e.tableName]),...a.filter(t=>t.tableName===e.tableName).map(e=>e.tempFieldName)]);a.push({tableName:e.tableName,fieldName:e.fieldName,tempFieldName:buildTempFieldName(e.fieldName,s),before:e.before,after:e.after}),o.add(r)}return{plans:a,blocked:r.breakingChanges.filter(e=>e.unsupported&&!(e.fieldName&&o.has(fieldKey(e.tableName,e.fieldName))))}}function extractBreakingChangeFields(e){let t=/* @__PURE__ */ new Map,n=/* @__PURE__ */ new Map,r=/* @__PURE__ */ new Map,i=/* @__PURE__ */ new Map,o=/* @__PURE__ */ new Map;for(let s of e.changes)if(s.kind===`field_modified`||s.kind===`field_type_modified`){let{before:e,after:n}=s;if(!e.required&&n.required&&(t.has(s.tableName)||t.set(s.tableName,/* @__PURE__ */ new Set),a(t.get(s.tableName),`optionalToRequired entry missing`).add(s.fieldName)),e.type===`enum`&&n.type===`enum`){let t=(e.allowedValues??[]).map(e=>e.value),i=(n.allowedValues??[]).map(e=>e.value),o=new Set(t),c=new Set(i);(t.some(e=>!c.has(e))||i.some(e=>!o.has(e)))&&(r.has(s.tableName)||r.set(s.tableName,/* @__PURE__ */ new Map),a(r.get(s.tableName),`enumValueChanges entry missing`).set(s.fieldName,{beforeValues:t,afterValues:i,afterRequired:n.required}))}}else if(s.kind===`field_added`){let{after:e}=s;e.required&&(n.has(s.tableName)||n.set(s.tableName,/* @__PURE__ */ new Map),a(n.get(s.tableName),`addedRequiredFields entry missing`).set(s.fieldName,e))}else s.kind===`field_renamed`?(i.has(s.tableName)||i.set(s.tableName,/* @__PURE__ */ new Map),a(i.get(s.tableName),`renamedFields entry missing`).set(s.fieldName,s.after)):s.kind===`table_renamed`&&o.set(s.tableName,s.after);return{optionalToRequired:t,addedRequiredFields:n,enumValueChanges:r,renamedFields:i,clearedFields:/* @__PURE__ */ new Map,renamedTypes:o}}function generateDbTypesFromSnapshot(e,t,n=[],r=!1){let i=t?extractBreakingChangeFields(t):{optionalToRequired:/* @__PURE__ */ new Map,addedRequiredFields:/* @__PURE__ */ new Map,enumValueChanges:/* @__PURE__ */ new Map,renamedFields:/* @__PURE__ */ new Map,clearedFields:/* @__PURE__ */ new Map,renamedTypes:/* @__PURE__ */ new Map};for(let e of n){let t=i.renamedFields.get(e.tableName)??/* @__PURE__ */ new Map;t.set(e.tempFieldName,{...e.after,required:!1,unique:!1}),i.renamedFields.set(e.tableName,t);let n=i.clearedFields.get(e.tableName)??/* @__PURE__ */ new Set;n.add(e.fieldName),i.clearedFields.set(e.tableName,n)}let a=[...Object.values(e.tables),...i.renamedTypes.values()];if(a.length===0)return generateEmptyDbTypes(e.namespace);let o=/* @__PURE__ */ new Set,s=!1,c=!1,l=!1,u=[];for(let e of a){let t=generateTableType(e,i,r);for(let e of t.usedUtilityTypes)o.add(e);s||=t.usedColumnType,c||=t.usedArrayColumnType,l||=t.usesTemporalNamespace,u.push(t.typeDef)}let d=[`type Transaction as KyselyTransaction`,`type Generated`];return s&&d.unshift(`type ColumnType`),c&&d.push(`type ArrayColumnType`),o.has(`Timestamp`)&&d.push(`type Timestamp`),o.has(`Serial`)&&d.push(`type Serial`),o.has(`TemporalDate`)&&d.push(`type TemporalDate`),o.has(`TemporalInstant`)&&d.push(`type TemporalInstant`),o.has(`TemporalTime`)&&d.push(`type TemporalTime`),l&&d.push(`type Temporal`),[`/**`,` * Auto-generated Kysely types for migration script.`,` * These types reflect the database schema state at this migration point.`,` *`,` * DO NOT EDIT - This file is auto-generated by the migration system.`,` */`,``,`import { ${d.join(`, `)} } from "@tailor-platform/sdk/kysely";`,`import type { Env } from "@tailor-platform/sdk";`,``,`export interface Database {`,...u,`}`,``,`export type Transaction = KyselyTransaction<Database>;`,``,...Il].join(`
|
|
510
516
|
`)+`
|
|
511
|
-
`}const
|
|
517
|
+
`}const Il=["/** Context passed as the second argument to the migration's `main` function and to each step. */",`export type MigrationContext = {`,` env: keyof Env extends never ? Record<string, string | number | boolean> : Env;`,`};`,``,`/** One step of a multi-step migration. Each step runs in its own transaction. */`,`export type MigrationStep = {`,` /** Steps that must complete before this one starts. */`,` dependsOn?: readonly string[];`,` run: (trx: Transaction, context: MigrationContext) => Promise<unknown>;`,`};`,``,"/** Steps a migration exports as `steps` instead of `main`, keyed by step name. */",`export type MigrationSteps = Record<string, MigrationStep>;`,``,`/**`,` * Marks a value or a step the migration script still needs. The generated script calls it`," * where a decision is yours to make, so the migration fails, and `tailor tailordb migration"," * validate` and `tailor deploy` reject it, until you replace every call.",` */`,`export function TODO(message: string): never {`," throw new Error(`TODO: ${message}`);",`}`];function generateEmptyDbTypes(e){return[`/**`,` * Auto-generated Kysely types for migration script.`,` * Namespace: ${e}`,` *`,` * DO NOT EDIT - This file is auto-generated by the migration system.`,` */`,``,`import { type Transaction as KyselyTransaction } from "@tailor-platform/sdk/kysely";`,`import type { Env } from "@tailor-platform/sdk";`,``,`// eslint-disable-next-line @typescript-eslint/no-empty-object-type`,`export interface Database {}`,``,`export type Transaction = KyselyTransaction<Database>;`,``,...Il].join(`
|
|
512
518
|
`)+`
|
|
513
519
|
`}function generateTableType(e,t,n=!1){let r=[],i=/* @__PURE__ */ new Set,a=!1,o=!1,s=!1;r.push(` id: Generated<string>;`);let c=t.optionalToRequired.get(e.name)||/* @__PURE__ */ new Set,l=t.addedRequiredFields.get(e.name)||/* @__PURE__ */ new Map,u=t.enumValueChanges.get(e.name)||/* @__PURE__ */ new Map,d=t.clearedFields.get(e.name)??/* @__PURE__ */ new Set;for(let[t,l]of Object.entries(e.fields)){if(t===`id`)continue;let e=generateFieldType(l,c.has(t),u.get(t),n),f=d.has(t),p=f?generateClearableFieldType(l,n):void 0;r.push(` ${t}: ${(p??e).type};`),!f&&e.usedUtilityType&&i.add(e.usedUtilityType),a=a||e.usedColumnType||f,o||=!f&&e.usedArrayColumnType,s||=f?p?.usesTemporalNamespace??!1:e.usesTemporalNamespace}for(let[e,t]of l){let c=generateFieldType(t,!0,void 0,n);r.push(` ${e}: ${c.type};`),c.usedUtilityType&&i.add(c.usedUtilityType),a||=c.usedColumnType,o||=c.usedArrayColumnType,s||=c.usesTemporalNamespace}let f=t.renamedFields.get(e.name)||/* @__PURE__ */ new Map;for(let[e,t]of f){let c=generateFieldType(t,t.required,void 0,n);r.push(` ${e}: ${c.type};`),c.usedUtilityType&&i.add(c.usedUtilityType),a||=c.usedColumnType,o||=c.usedArrayColumnType,s||=c.usesTemporalNamespace}return{typeDef:` ${e.name}: {\n${r.join(`
|
|
514
|
-
`)}\n }`,usedUtilityTypes:i,usedColumnType:a,usedArrayColumnType:o,usesTemporalNamespace:s}}function mapToTsType(e,t,n=!1){if(e===`nested`)return{type:`Record<string, unknown>`};if(e===`enum`&&t&&t.length>0)return{type:`(${formatEnumUnion(t.map(e=>e.value))})`};if(e===`enum`)return{type:`string`};let r=
|
|
520
|
+
`)}\n }`,usedUtilityTypes:i,usedColumnType:a,usedArrayColumnType:o,usesTemporalNamespace:s}}function mapToTsType(e,t,n=!1){if(e===`nested`)return{type:`Record<string, unknown>`};if(e===`enum`&&t&&t.length>0)return{type:`(${formatEnumUnion(t.map(e=>e.value))})`};if(e===`enum`)return{type:`string`};let r=Ir(e,n);return{type:r,usedUtilityType:Fr.has(r)?r:void 0}}function formatEnumUnion(e){return e.map(e=>`"${e}"`).join(` | `)}function formatEnumSlot(e,t,n){if(e.length===0)return t?n?`never[] | null`:`never[]`:n?`null`:`never`;let r=formatEnumUnion(e);return t?n?`(${r})[] | null`:`(${r})[]`:n?`(${r}) | null`:r}function generateEnumChangeColumnType(e,t){let n=t.array??!1,r=[.../* @__PURE__ */ new Set([...e.beforeValues,...e.afterValues])],i=!e.afterRequired,a=formatEnumSlot(r,n,!t.required||i),o=formatEnumSlot(e.afterValues,n,i);return`ColumnType<${a}, ${o}, ${o}>`}const Ll=/* @__PURE__ */ new Set([`TemporalDate`,`TemporalInstant`,`TemporalTime`]);function generateClearableFieldType(e,t=!1){let{type:n}=mapToTsType(e.type,e.allowedValues,t),r=Ll.has(n),i=Fr.get(n);if(i){let t=e.array?`${i.select}[]`:i.select,n=e.array?`(${i.write})[]`:i.write;return{type:`ColumnType<${t} | null, ${n} | null, ${n} | null>`,usesTemporalNamespace:r}}let a=e.array?`${n}[]`:n;return{type:`ColumnType<${a} | null, ${a} | null, ${a} | null>`,usesTemporalNamespace:r}}function generateOptionalToRequiredDateColumnType(e,t=!1){if(e.type!==`date`&&e.type!==`datetime`&&e.type!==`time`)return null;let n=Ir(e.type,t),r=Fr.get(n);if(!r)return null;let i=e.array?`${r.select}[]`:r.select,a=e.array?`(${r.write})[]`:r.write;return{type:`ColumnType<${i} | null, ${a}, ${a}>`,usesTemporalNamespace:Ll.has(n)}}function generateFieldType(e,t,n,r=!1){if(n)return{type:generateEnumChangeColumnType(n,e),usedColumnType:!0,usedArrayColumnType:!1,usesTemporalNamespace:!1};let i,a;if(e.type===`enum`){let t=e.allowedValues?.map(e=>e.value)??[];i=t.length>0?formatEnumUnion(t):`string`}else{let t=mapToTsType(e.type,void 0,r);i=t.type,a=t.usedUtilityType}if(t){let t=generateOptionalToRequiredDateColumnType(e,r);if(t)return{type:t.type,usedColumnType:!0,usedArrayColumnType:!1,usesTemporalNamespace:t.usesTemporalNamespace}}let o=i;if(e.array){if(Fr.has(i)){let t=`ArrayColumnType<${i}>`;return{type:e.required?t:`${t} | null`,usedUtilityType:a,usedColumnType:!1,usedArrayColumnType:!0,usesTemporalNamespace:!1}}o=e.type===`enum`&&e.allowedValues&&e.allowedValues.length>0?`(${i})[]`:`${i}[]`}return t?{type:`ColumnType<${o} | null, ${o}, ${o}>`,usedUtilityType:a,usedColumnType:!0,usedArrayColumnType:!1,usesTemporalNamespace:!1}:(e.required||(o=`${o} | null`),{type:o,usedUtilityType:a,usedColumnType:!1,usedArrayColumnType:!1,usesTemporalNamespace:!1})}async function writeDbTypesFile(e,t,n,r,i=[],a=!1){let o=generateDbTypesFromSnapshot(e,r,i,a),s=getMigrationFilePath(t,n,`db`);return await J.writeFile(s,o),s}function toDDLTable(e){return{name:e.name,fields:e.fields,indexes:e.indexes}}function retargets(e,t){return e.foreignKeyType!==void 0&&(e.foreignKeyType!==t.foreignKeyType||e.foreignKeyField!==t.foreignKeyField)}function retargetedMembers(e){let t=/* @__PURE__ */ new Map;for(let n of e.changes){if(n.kind!==`field_modified`)continue;let e=[];retargets(n.before,n.after)&&e.push([]);for(let t of collectNestedMemberChanges(n.before,n.after))t.kind===`modified`&&retargets(t.before,t.after)&&e.push(t.path);if(e.length===0)continue;let r=t.get(n.tableName)??/* @__PURE__ */ new Map;r.set(n.fieldName,e),t.set(n.tableName,r)}return t}function withoutReferenceAt(e,t){let[n,...r]=t;if(n===void 0)return Lr(e);let i=e.fields?.[n];return!e.fields||!i?e:{...e,fields:{...e.fields,[n]:withoutReferenceAt(i,r)}}}function buildPreMigrationTables(e,t){let n=retargetedMembers(t),r=Object.values(buildPreMigrationSnapshot(e,t).tables).map(e=>{let t=n.get(e.name);return t?{...toDDLTable(e),fields:Object.fromEntries(Object.entries(e.fields).map(([e,n])=>[e,(t.get(e)??[]).reduce(withoutReferenceAt,n)]))}:toDDLTable(e)});return Nr(r)}function generateMigrationPgliteSchema(e,t){return Pr([{namespace:e.namespace,tables:buildPreMigrationTables(e,t)}],{generatedBy:`the migration system`})}async function writePgliteSchemaFile(e,t,n,r){let i=getMigrationFilePath(n,r,`pgliteSchema`);return await J.writeFile(i,generateMigrationPgliteSchema(e,t)),i}async function tryWritePgliteSchemaFile(e,t,n,r){try{return{pgliteSchemaPath:await writePgliteSchemaFile(e,t,n,r)}}catch(e){return{pgliteSchemaError:e instanceof Error?e.message:String(e)}}}async function recordRuntimeModes(e,t,n){let r=JSON.parse(await J.readFile(e,`utf-8`)),i=!1;t?(r.temporal=!0,i=!0):Object.hasOwn(r,`temporal`)&&(delete r.temporal,i=!0),n===`legacy`?Object.hasOwn(r,`dateRepresentation`)&&(delete r.dateRepresentation,i=!0):(r.dateRepresentation=n,i=!0),(t||n!==`legacy`)&&(typeof r.version!=`number`||r.version<8)&&(r.version=8),i&&await J.writeFile(e,JSON.stringify(r,null,2))}async function writeMigrationTypeFiles(e){let{previousSnapshot:t,diff:n,migrationsDir:r,migrationNumber:i,expandPlans:a=[],temporal:o=!1,dateDefault:s=`legacy`}=e,c=await writeDbTypesFile(t,r,i,n,a,o);return await recordRuntimeModes(getMigrationFilePath(r,i,`diff`),o,s),{dbTypesPath:c,...await tryWritePgliteSchemaFile(t,n,r,i)}}async function fileExists(e){try{return await J.access(e),!0}catch{return!1}}async function ensureFileNotExists(e){if(await fileExists(e))throw E({code:`MIGRATION_FILE_EXISTS`,message:`Migration file already exists: ${e}`})}async function generateSchemaFile(e,t,n){let r=getMigrationDirPath(t,n);await J.mkdir(r,{recursive:!0});let i=getMigrationFilePath(t,n,`schema`);return await ensureFileNotExists(i),await J.writeFile(i,JSON.stringify(e,null,2)),{filePath:i,migrationNumber:n}}async function generateDiffFiles(e,t,n,r,i,a=[],o=!1,s=`legacy`,c=[]){let l=getMigrationDirPath(t,n);await J.mkdir(l,{recursive:!0});let u=getMigrationFilePath(t,n,`diff`),d=getMigrationFilePath(t,n,`migrate`),f=getMigrationFilePath(t,n,`db`),p=getMigrationFilePath(t,n,`pgliteSchema`),m=e.requiresMigrationScript;await ensureFileNotExists(u),m&&(await ensureFileNotExists(d),await ensureFileNotExists(f),await ensureFileNotExists(p));let h=i?{...e,description:i}:e;await J.writeFile(u,JSON.stringify(h,null,2));let g={diffFilePath:u,migrationNumber:n};if(m){let e=generateMigrationScript(h,a,c);await J.writeFile(d,e),g.migrateFilePath=d;let i=await writeMigrationTypeFiles({previousSnapshot:r,diff:h,migrationsDir:t,migrationNumber:n,expandPlans:a,temporal:o,dateDefault:s});g.dbTypesFilePath=i.dbTypesPath,g.pgliteSchemaFilePath=i.pgliteSchemaPath,g.pgliteSchemaError=i.pgliteSchemaError}return g}async function generateDataOnlyMigrationFiles(e){let{migrationsDir:t,migrationNumber:n,snapshot:r,description:i,temporal:a=!1,dateDefault:o=`legacy`}=e,s=getMigrationDirPath(t,n);await J.mkdir(s,{recursive:!0});let c=getMigrationFilePath(t,n,`diff`),l=getMigrationFilePath(t,n,`migrate`),u=getMigrationFilePath(t,n,`db`);await ensureFileNotExists(c),await ensureFileNotExists(l),await ensureFileNotExists(u),await ensureFileNotExists(getMigrationFilePath(t,n,`pgliteSchema`));let d=i?{...e.diff,description:i}:e.diff;await J.writeFile(c,JSON.stringify(d,null,2)),await J.writeFile(l,generateDataOnlyMigrationScript(d.namespace));let f=await writeMigrationTypeFiles({previousSnapshot:r,diff:d,migrationsDir:t,migrationNumber:n,temporal:a,dateDefault:o});return{diffFilePath:c,migrateFilePath:l,dbTypesFilePath:u,pgliteSchemaFilePath:f.pgliteSchemaPath,pgliteSchemaError:f.pgliteSchemaError,migrationNumber:n}}function generateDataOnlyMigrationScript(e){return`/**
|
|
515
521
|
* Data-only migration script for ${e}
|
|
516
522
|
*
|
|
517
523
|
* This migration carries no schema change; it exists to run this script.
|
|
@@ -525,10 +531,10 @@ ${renderScript(` void TODO("implement the data transformation for this migratio
|
|
|
525
531
|
* fails after a step committed resumes from the steps that have not completed, so
|
|
526
532
|
* write every step to be safe to run again. Split a step into several steps
|
|
527
533
|
* where the work divides, and order them with \`dependsOn\`.
|
|
528
|
-
* See "Splitting a migration into steps" in the TailorDB migration docs.`}const
|
|
534
|
+
* See "Splitting a migration into steps" in the TailorDB migration docs.`}const Rl=[`renameNestedMember`],capitalize=e=>e.charAt(0).toUpperCase()+e.slice(1);function foreignKeyTargets(e,t){return collectForeignKeyTargets(e).filter(e=>e!==t)}function copiedLater(e,t){let n=new Set(t.flatMap(e=>e.kind===`table_renamed`?[e.tableName]:[]));return foreignKeyTargets(e.after.fields,e.tableName).filter(e=>n.has(e))}function cycleCopyTodo(e,t){let n=t.join(`, `),r=t.length===1?`copy ${e.tableName} with the foreign key to ${n} set to null, then fill it in after the copy of ${n}`:`copy ${e.tableName} with its foreign keys to ${n} set to null, then fill them in after the copies of ${n}`;return` // ${e.tableName} and ${n} reference each other, so neither copy can find the rows its foreign key points to.
|
|
529
535
|
void TODO(${JSON.stringify(r)});`}function orderTableRenames(e){let t=e.filter(e=>e.kind===`table_renamed`),parentsOf=e=>new Set(foreignKeyTargets(e.after.fields,e.tableName).filter(e=>t.some(t=>t.tableName===e))),n=[];for(;t.length>0;){let e=new Set(n.map(e=>e.tableName)),r=t.findIndex(t=>[...parentsOf(t)].every(t=>e.has(t)));n.push(...t.splice(Math.max(r,0),1))}let r=0;return e.map(e=>e.kind===`table_renamed`?n[r++]??e:e)}function describeChange(e){let t=capitalize(e.tableName);switch(e.kind){case`field_added`:return{preferredName:`populate${t}${capitalize(e.fieldName)}`,touches:[{table:e.tableName,field:e.fieldName}]};case`field_renamed`:return{preferredName:`rename${t}${capitalize(e.fieldName)}`,touches:[{table:e.tableName,field:e.previousFieldName},{table:e.tableName,field:e.fieldName}]};case`table_renamed`:return{preferredName:`copy${capitalize(e.previousTableName)}To${t}`,touches:[{table:e.previousTableName,field:`*`},{table:e.tableName,field:`*`},...foreignKeyTargets(e.after.fields,e.tableName).map(e=>({table:e,field:`id`}))]};case`field_modified`:case`field_type_modified`:{let n=e.after.foreignKeyType;return{preferredName:`update${t}${capitalize(e.fieldName)}`,touches:[{table:e.tableName,field:e.fieldName},...n&&n!==e.before.foreignKeyType?[{table:n,field:e.after.foreignKeyField??`id`}]:[]]}}case`index_added`:case`index_modified`:return{preferredName:`resolve${t}${capitalize(e.indexName)}`,touches:e.after.fields.map(t=>({table:e.tableName,field:t}))};default:return{preferredName:``,touches:[{table:e.tableName,field:`*`}]}}}function overwritesExistingValues(e,t){switch(e.kind){case`index_added`:case`index_modified`:case`field_type_modified`:return!0;case`field_modified`:return!(e.memberRenames?.length&&t===1);default:return!1}}const touchesOverlap=(e,t)=>e.some(e=>t.some(t=>e.table===t.table&&(e.field===`*`||t.field===`*`||e.field===t.field)));function generateChangeStatements(e,t,n){let r=generateDecimalScaleChangeScript(e),i=generateChangeScripts(e,r!==null,t,n);if(r){i.push(r);let t=generateUniqueConstraintScript(e);t&&i.push(t)}return i}function buildScriptSteps(e,t,n,r){let i=t.map((e,t)=>({preferredName:`convert${capitalize(e.tableName)}${capitalize(e.fieldName)}`,fallbackName:`expand${t+1}`,body:generateExpandConversionScript(e),overwritesExistingValues:!0,touches:[{table:e.tableName,field:e.fieldName},{table:e.tableName,field:e.tempFieldName}]})),a=orderTableRenames(e.changes);a.forEach((e,t)=>{let o=generateChangeStatements(e,n,r);if(o.length===0)return;if(e.kind===`table_renamed`){let n=copiedLater(e,a.slice(t+1));n.length>0&&o.unshift(cycleCopyTodo(e,n))}let{preferredName:s,touches:c}=describeChange(e);i.push({preferredName:s,fallbackName:`change${t+1}`,body:[...o].join(`
|
|
530
536
|
|
|
531
|
-
`),touches:c,overwritesExistingValues:overwritesExistingValues(e,o.length)})});let o=new Set(
|
|
537
|
+
`),touches:c,overwritesExistingValues:overwritesExistingValues(e,o.length)})});let o=new Set(Rl),s=[];return i.map(e=>{let t=Gt(e.preferredName)&&!o.has(e.preferredName)?e.preferredName:e.fallbackName;o.add(t);let n=s.filter(t=>touchesOverlap(t.touches,e.touches)).map(e=>e.name);return s.push({name:t,touches:e.touches}),{name:t,body:e.body,dependsOn:n,overwritesExistingValues:e.overwritesExistingValues}})}function renderScript(e,t,n=[]){let r=n.length>0?n:[{name:`migrate`,body:e,dependsOn:[]}],i=r.map(e=>`${e.overwritesExistingValues?`// Overwrites existing values. Once this step commits it cannot be undone,
|
|
532
538
|
// so check the values it writes before you deploy.
|
|
533
539
|
`:``}async function ${e.name}(trx: Transaction): Promise<void> {
|
|
534
540
|
${e.body}
|
|
@@ -542,7 +548,7 @@ ${i}
|
|
|
542
548
|
export const steps = {
|
|
543
549
|
${a}
|
|
544
550
|
} satisfies MigrationSteps;
|
|
545
|
-
`}function generateMigrationScript(e,t=[],n=[]){let r=buildScriptSteps(e,t,new Map(e.changes.filter(e=>e.kind===`table_renamed`).map(e=>[e.previousTableName,e.tableName])),n),i=[e.changes.some(e=>e.kind===`field_modified`&&e.memberRenames?.length)?
|
|
551
|
+
`}function generateMigrationScript(e,t=[],n=[]){let r=buildScriptSteps(e,t,new Map(e.changes.filter(e=>e.kind===`table_renamed`).map(e=>[e.previousTableName,e.tableName])),n),i=[e.changes.some(e=>e.kind===`field_modified`&&e.memberRenames?.length)?zl:``,e.changes.some(e=>e.kind===`table_renamed`&&nestedSelfReferencePaths(e).size>0)?Bl:``].filter(e=>e!==``).map(e=>`\n${e}`).join(``);return`/**
|
|
546
552
|
* Migration script for ${e.namespace}
|
|
547
553
|
*
|
|
548
554
|
* This script runs between the Pre-migration and Post-migration phases of
|
|
@@ -783,7 +789,7 @@ ${a}
|
|
|
783
789
|
}
|
|
784
790
|
lastId = rows[rows.length - 1]!.id;
|
|
785
791
|
}
|
|
786
|
-
}`}const
|
|
792
|
+
}`}const zl=`/**
|
|
787
793
|
* Return a copy of a nested value with the member at \`path\` also stored under
|
|
788
794
|
* \`newName\`, descending into arrays at every level.
|
|
789
795
|
*
|
|
@@ -818,7 +824,7 @@ function renameNestedMember(value: unknown, path: readonly string[], newName: st
|
|
|
818
824
|
});
|
|
819
825
|
return copy;
|
|
820
826
|
}
|
|
821
|
-
`,
|
|
827
|
+
`,Bl=`/**
|
|
822
828
|
* Return a copy of a nested value with the members at the dotted \`paths\` set to
|
|
823
829
|
* null, descending into arrays at every level.
|
|
824
830
|
*/
|
|
@@ -1020,12 +1026,12 @@ ${n===`throw`?` if (records.length > 1) {
|
|
|
1020
1026
|
}
|
|
1021
1027
|
lastId = rows[rows.length - 1]!.id;
|
|
1022
1028
|
}
|
|
1023
|
-
}`}function markMigrationScriptSkipped(e){let{migrationsDir:t,migrationNumber:n,reason:r}=e,i=formatMigrationNumber(n),a=r.trim();if(!a)throw E({code:`MIGRATION_SCRIPT_REASON_REQUIRED`,message:`Migration script skip reason must not be empty.`,command:`tailordb migration script`});let o=getMigrationFilePath(t,n,`diff`);if(!W.existsSync(o))throw E({code:`MIGRATION_NOT_FOUND`,message:`Migration ${i} not found in ${t}. Expected ${o}.`});let s=loadDiff(o);if(!s.requiresMigrationScript&&!s.hasWarnings)throw E({code:`MIGRATION_SCRIPT_NOT_REQUIRED`,message:`Migration ${i} does not require a migration script and has no data-loss warnings; nothing to skip.`});if(s.scriptSkipped)throw E({code:`MIGRATION_SCRIPT_SKIP_EXISTS`,message:`Migration ${i} already has a script skip recorded (${s.scriptSkipped.acknowledgedAt}: ${s.scriptSkipped.reason}).`});let c=getMigrationFilePath(t,n,`migrate`);if(W.existsSync(c))throw E({code:`MIGRATION_SCRIPT_EXISTS`,message:`Migration script exists at ${c}.`,suggestion:`Delete migrate.ts first if this migration should run without a script.`});let l={reason:a,acknowledgedAt:(/* @__PURE__ */ new Date()).toISOString()},u=JSON.parse(W.readFileSync(o,`utf-8`));return u.scriptSkipped=l,W.writeFileSync(o,JSON.stringify(u,null,2)),l}function clearMigrationScriptSkipped(e){let t=JSON.parse(W.readFileSync(e,`utf-8`));Object.hasOwn(t,`scriptSkipped`)&&(delete t.scriptSkipped,W.writeFileSync(e,JSON.stringify(t,null,2)))}async function addMigrationScriptFiles(e){let{migrationsDir:t,migrationNumber:n,withTest:r=!1,pgliteAvailable:i=!1,temporal:a=!1,dateDefault:o=`legacy`}=e,s=formatMigrationNumber(n),c=getMigrationFilePath(t,n,`diff`);if(!W.existsSync(c))throw E({code:`MIGRATION_NOT_FOUND`,message:`Migration ${s} not found in ${t}. Expected ${c}.`});let l=loadDiff(c),u=getMigrationFilePath(t,n,`migrate`),d=W.existsSync(u),f={};if(d&&l.scriptSkipped){if(clearMigrationScriptSkipped(c),f.clearedScriptSkip=!0,!r)return f}else if(d&&!r)throw E({code:`MIGRATION_SCRIPT_EXISTS`,message:`Migration script already exists at ${u}.`});let p=getMigrationFilePath(t,n,`test`),m=getMigrationFilePath(t,n,`pgliteTest`),h=getMigrationFilePath(t,n,`pgliteSchema`),g=r&&!W.existsSync(p),_=r&&i&&!W.existsSync(m);if(r&&!g&&!_)throw E({code:`MIGRATION_TEST_EXISTS`,message:i?`Migration tests already exist at ${p} and ${m}.`:`Migration test already exists at ${p}.`});if(d&&r){let e=getMigrationFilePath(t,n,`db`);if(!W.existsSync(e))throw E({code:`GENERATED_TYPES_NOT_FOUND`,message:`Generated types not found at ${e}.`,suggestion:`The test scaffold imports Database from ./db; restore db.ts before adding a test.`})}let v=!d||r&&!W.existsSync(h),y=v?reconstructSnapshotFromMigrations(t,n-1):null;if(v&&!y)throw E({code:`MIGRATION_HISTORY_INVALID`,message:`Could not reconstruct previous schema for migration ${s}.`,suggestion:`Make sure migration 0 exists.`});let b=d?analyzeMigrationScript(u).kind:`steps`;if(!d&&y){await J.writeFile(u,generateMigrationScript(l)),f.migratePath=u;let e=await writeMigrationTypeFiles({previousSnapshot:y,diff:l,migrationsDir:t,migrationNumber:n,temporal:a,dateDefault:o});f.dbTypesPath=e.dbTypesPath,f.pgliteSchemaPath=e.pgliteSchemaPath,f.pgliteSchemaError=e.pgliteSchemaError,clearMigrationScriptSkipped(c),l.scriptSkipped&&(f.clearedScriptSkip=!0)}else r&&y&&Object.assign(f,await tryWritePgliteSchemaFile(y,l,t,n));return g&&(await J.writeFile(p,generateMigrationTestScript(loadDiff(c),b)),f.testPath=p),f.pgliteTestRequested=_,_&&W.existsSync(h)&&(await J.writeFile(m,generateMigrationPgliteTestScript(loadDiff(c),b)),f.pgliteTestPath=m),f}function isPgliteAvailable(e){let t=H.resolve(e);for(;;){if(W.existsSync(H.join(t,`node_modules`,`@electric-sql`,`pglite`,`package.json`)))return!0;let e=H.dirname(t);if(e===t)return!1;t=e}}async function script(e){logBetaWarning(`tailordb migration`);let t=parseMigrationNumberArg(e.number);if(t===0)throw E({code:`MIGRATION_SCRIPT_NOT_ALLOWED`,message:`Migration ${e.number} is the initial schema snapshot and cannot have a migration script.`});let{config:n,plugins:r}=await loadConfig(e.configPath),i=H.dirname(n.path),o=resolvePluginConfig(r,`@tailor-platform/kysely-type`)?.temporal??!1,s=et(n),c=getNamespacesWithMigrations(n,i);if(c.length===0)throw migrationConfigNotFoundError();let l=resolveTargetNamespace(c,e.namespace),{migrationsDir:u}=a(c.find(e=>e.namespace===l),`namespace with migrations not found`);if(e.noScript){if(e.withTest)throw E({code:`MIGRATION_SCRIPT_OPTIONS_CONFLICT`,message:`--with-test cannot be used together with --no-script.`,command:`tailordb migration script`});let n=e.reason?.trim();if(!n)throw E({code:`MIGRATION_SCRIPT_REASON_REQUIRED`,message:`--reason is required with --no-script.`,command:`tailordb migration script`});let r=markMigrationScriptSkipped({migrationsDir:u,migrationNumber:t,reason:n});C.success(`Recorded that migration ${h.bold(e.number)} in namespace ${h.bold(l)} intentionally has no migration script`);let i=getMigrationFilePath(u,t,`diff`);C.info(` Reason: ${r.reason}`),C.info(` Diff file: ${i}`),printMutationResult({changed:!0,namespace:l,migrationNumber:t,scriptSkipped:{reason:r.reason,acknowledgedAt:r.acknowledgedAt},diffPath:i});return}if(e.reason!==void 0)throw E({code:`MIGRATION_SCRIPT_OPTIONS_CONFLICT`,message:`--reason can only be used together with --no-script.`,command:`tailordb migration script`});let d=isPgliteAvailable(u),f=await addMigrationScriptFiles({migrationsDir:u,migrationNumber:t,withTest:e.withTest,pgliteAvailable:d,temporal:o,dateDefault:s});if(printMutationResult({changed:!!(f.clearedScriptSkip||f.migratePath||f.pgliteSchemaPath||f.testPath||f.pgliteTestPath),namespace:l,migrationNumber:t,migratePath:f.migratePath??null,dbTypesPath:f.dbTypesPath??null,pgliteSchemaPath:f.pgliteSchemaPath??null,pgliteSchemaError:f.pgliteSchemaError??null,testPath:f.testPath??null,pgliteTestPath:f.pgliteTestPath??null,clearedScriptSkip:f.clearedScriptSkip??!1}),f.clearedScriptSkip&&!f.migratePath&&(C.success(`Cleared the stale script skip record for migration ${h.bold(e.number)} in namespace ${h.bold(l)}`),!f.testPath&&!f.pgliteTestRequested)){C.info(` Migration script: ${getMigrationFilePath(u,t,`migrate`)}`);return}let p=[f.testPath,f.pgliteTestPath].filter(Boolean).length,m=[f.migratePath&&`migration script`,p>0&&(p>1?`migration tests`:`migration test`)].filter(Boolean).join(` and `),g=`for migration ${h.bold(e.number)} in namespace ${h.bold(l)}`;m?C.success(`Added ${m} ${g}`):C.warn(`Added no files ${g}`),f.migratePath&&(C.info(` Migration script: ${f.migratePath}`),C.info(` DB types: ${f.dbTypesPath}`)),f.pgliteSchemaPath&&C.info(` PGlite schema: ${f.pgliteSchemaPath}`),f.pgliteSchemaError&&C.warn(` PGlite schema skipped: ${f.pgliteSchemaError}`),f.testPath&&C.info(` Migration test: ${f.testPath}`),f.pgliteTestPath?C.info(` PGlite test: ${f.pgliteTestPath}`):f.testPath&&!d?C.info(` Install @electric-sql/pglite as a devDependency to also scaffold a PGlite test (migrate.pglite.test.ts).`):f.pgliteTestRequested&&f.pgliteSchemaError&&C.info(` PGlite test skipped: it needs the db.pglite.ts that could not be generated.`),C.newline(),f.migratePath&&(C.log(`Edit the script to implement your data migration logic.`),C.log(`It will be executed by 'tailor deploy' between Pre and Post phases.`)),f.testPath&&C.log(`Fill in the test with the rows to stage and the statements to assert.`);let _=f.migratePath??f.testPath;if(!_)return;let v=getConfiguredEditorCommand();if(v&&canPrompt()){C.newline(),C.info(`Opening ${H.basename(_)} in ${v}...`);try{await openInConfiguredEditor(_)}catch{return}}}function resolveTargetNamespace(e,t){if(t){if(!e.some(e=>e.namespace===t))throw E({code:`TAILORDB_NAMESPACE_NOT_FOUND`,message:`Namespace "${t}" not found or does not have migrations configured`});return t}if(e.length===1){let[t]=e;return a(t,`namespace with migrations missing`).namespace}throw E({code:`MIGRATION_NAMESPACE_REQUIRED`,message:`Multiple TailorDB services found. Please specify namespace with --namespace flag: ${e.map(e=>e.namespace).join(`, `)}`,command:`tailordb migration script`})}const Fl=Y({name:`script`,description:`Add a migration script (migrate.ts) template to an existing migration directory, or record with --no-script that a migration intentionally has none.`,notes:"When `migrate.ts` already exists, running the command clears a previously recorded `--no-script` acknowledgment, and `--with-test` adds only the tests that do not exist yet (writing `db.pglite.ts` if it is missing). `migrate.pglite.test.ts` is scaffolded only when `@electric-sql/pglite` is installed in the project.",args:U.strictObject({...oe,number:V(U.string(),{positional:!0,description:`Migration number to add a script to (e.g., 0001 or 1)`}),namespace:V(U.string().optional(),{alias:`n`,description:`Target TailorDB namespace (required if multiple namespaces exist)`}),"no-script":V(U.boolean().optional(),{description:`Record that this migration intentionally runs without a migration script (requires --reason)`}),reason:V(U.string().optional(),{description:`Reason why no migration script is needed (used with --no-script)`}),"with-test":V(U.boolean().optional(),{description:`Also add the migrate.test.ts and migrate.pglite.test.ts scaffolds`})}),run:async e=>{await script({configPath:e.config,number:e.number,namespace:e.namespace,noScript:e[`no-script`],reason:e.reason,withTest:e[`with-test`]})}});function getUnsupportedMigrationHintLines(){return[`These changes require a manual 3-step migration process:`,` Migration 1: Add an optional temporary field with the desired structure`,` If the old field is required, make the old field optional`,` For each non-null old value, copy and convert it to the temporary field`,` and set the old field to null in the same update`,` Verify every old value is null before continuing`,` Migration 2: Remove the old field`,` Migration 3: Add the field with the original name and new structure,`,` migrate data from the temporary field, then remove it`,` Important: Reusing the name while stored old values remain can make subsequent reads fail`]}function assertNoNestedNamespaceMigrations(e,t){let realPath=e=>W.existsSync(e)?W.realpathSync(e):e,isInside=(e,t)=>H.relative(e,t).split(`/`)[0]!==`..`,n=realPath(e.migrationsDir),r=t.filter(({namespace:t,migrationsDir:r})=>t!==e.namespace&&(isInside(e.migrationsDir,r)||isInside(n,realPath(r))));if(r.length!==0)throw E({code:`MIGRATION_GENERATE_OPTIONS_CONFLICT`,message:`--init --namespace ${e.namespace} would also delete the migrations of ${r.map(({namespace:e})=>e).join(`, `)}, whose directories are inside ${e.migrationsDir}.`,suggestion:`Run --init without --namespace, or move the nested migration directories out.`,command:`tailordb migration generate`})}async function handleInitOption(e,t){let n=e.filter(({migrationsDir:e})=>W.existsSync(e));if(n.length===0)return C.info(`No existing migration directories found.`),[];C.newline(),C.warn(`This will DELETE all existing migration files:`);for(let{namespace:e,migrationsDir:t}of n)C.log(` - ${e}: ${t}`);if(C.newline(),!t){if(!await X.confirm({message:`Are you sure you want to delete these directories and start fresh?`,default:!1}))throw E({code:`MIGRATION_GENERATE_CANCELLED`,message:`Migration generation cancelled. No migration files were deleted.`});C.newline()}for(let{namespace:e,migrationsDir:t}of n)try{await J.rm(t,{recursive:!0,force:!0}),C.success(`Deleted migration directory for ${h.bold(e)}`)}catch(e){throw C.error(`Failed to delete ${t}: ${e}`),e}return C.newline(),C.info(`Migration directories cleared. Generating initial snapshot...`),C.newline(),n.map(({namespace:e})=>e)}function generatedMigration(e,t){return{namespace:e,migrationNumber:t.migrationNumber,schemaPath:null,diffPath:t.diffFilePath,migratePath:t.migrateFilePath??null,dbTypesPath:t.dbTypesFilePath??null,pgliteSchemaPath:t.pgliteSchemaFilePath??null,pgliteSchemaError:t.pgliteSchemaError??null}}async function generate(e){return generateMigrations(e)}async function generateMigrations(e){logBetaWarning(`tailordb migration`);let{config:t,plugins:n}=await loadConfig(e.configPath),r=H.dirname(t.path),i=resolvePluginConfig(n,`@tailor-platform/kysely-type`)?.temporal??!1,o=et(t),s=getNamespacesWithMigrations(t,r);if(s.length===0)return C.warn(`No TailorDB namespaces with migrations config found.`),C.info(`Add "migration: { directory: \\"./migrations\\" }" to your db config to enable migrations.`),{changed:!1,clearedNamespaces:[],skippedNamespaces:[],migrations:[]};let c=[],l=[],u=[];for(let t of e.renames??[]){let e=targetDepth(t);e>=2?u.push({raw:t,spec:parseNestedMemberRenameOption(t)}):e===1?c.push({raw:t,spec:parseRenameOption(t)}):l.push({raw:t,spec:parseTypeRenameOption(t)})}let d=[],f=[],p=[];for(let t of e.drops??[]){let e=targetDepth(t);e>=2?p.push({raw:t,spec:parseNestedMemberDropOption(t)}):e===1?d.push({raw:t,spec:parseDropOption(t)}):f.push({raw:t,spec:parseTypeDropOption(t)})}let m=(e.expandContracts??[]).map(e=>({raw:e,spec:parseExpandContractOption(e)})),g=c.length>0||l.length>0||u.length>0||d.length>0||f.length>0||p.length>0;if(e.init&&(g||m.length>0))throw E({code:`MIGRATION_GENERATE_OPTIONS_CONFLICT`,message:`--rename, --drop, and --expand-contract cannot be used together with --init.`,command:`tailordb migration generate`});if(assertNoRenameDropConflict(c.map(({spec:e})=>fieldKey(e.tableName,e.previousFieldName)),d.map(({spec:e})=>fieldKey(e.tableName,e.fieldName))),assertNoRenameDropConflict(u.map(({spec:e})=>nestedMemberKey({...e,path:e.previousPath})),p.map(({spec:e})=>nestedMemberKey(e))),assertNoRenameDropConflict(l.map(({spec:e})=>e.previousTableName),f.map(({spec:e})=>e.tableName)),e.namespace!==void 0&&!e.dataOnly&&!e.init)throw E({code:`MIGRATION_GENERATE_OPTIONS_CONFLICT`,message:`--namespace can only be used together with --data-only or --init.`,command:`tailordb migration generate`});if(e.dataOnly&&(e.init||g||m.length>0))throw E({code:`MIGRATION_GENERATE_OPTIONS_CONFLICT`,message:`--init, --rename, --drop, and --expand-contract cannot be used together with --data-only.`,command:`tailordb migration generate`});let _=e.dataOnly||e.namespace!==void 0?resolveTargetNamespace(s,e.namespace):void 0,v=_===void 0?s:s.filter(({namespace:e})=>e===_),y=e.init?v[0]:void 0;y&&_!==void 0&&assertNoNestedNamespaceMigrations(y,s);let b;n.length>0&&(b=new Cr(n));let{defineApplication:x}=await import(`./application-Bz80INH4.mjs`),S=x({config:t,pluginManager:b}),w=[];for(let{namespace:n,migrationsDir:r}of v){C.info(`Processing namespace: ${h.bold(n)}`),e.init||assertValidMigrationFiles(r,n,t.path);let i=S.tailorDBServices.find(e=>e.namespace===n);if(!i){C.warn(`No TailorDB service found for namespace "${n}"`);continue}await i.loadTypes(),await i.processNamespacePlugins();let a=i.types;w.push({namespace:n,migrationsDir:r,currentSnapshot:createSnapshotFromLocalTypes(a,n),previousSnapshot:e.init?null:reconstructSnapshotFromMigrations(r)})}if(e.dataOnly&&_!==void 0)return{changed:!0,clearedNamespaces:[],skippedNamespaces:[],migrations:[await generateDataOnlyMigration(w,_,e,i,o)]};let T=matchFlagsToNamespaces(c,w,renameSpecApplies,`--rename does not match a removed + added field pair`),D=matchFlagsToNamespaces(l,w,typeRenameSpecApplies,`--rename does not match a removed + added table pair`),O=matchFlagsToNamespaces(d,w,dropSpecApplies,`--drop does not match a removed field`),ee=matchFlagsToNamespaces(f,w,typeDropSpecApplies,`--drop does not match a removed table`),te=matchFlagsToNamespaces(u,w,nestedMemberRenameSpecApplies,`--rename does not match a removed + added nested member pair`),ne=matchFlagsToNamespaces(p,w,nestedMemberDropSpecApplies,`--drop does not match a removed nested member`),k=/* @__PURE__ */ new Map,re=/* @__PURE__ */ new Set,ie=[];for(let{namespace:e,previousSnapshot:t,currentSnapshot:n}of w){if(!t)continue;let r=[];for(let i of m){let{spec:a}=i,o=t.tables[a.tableName]?.fields[a.fieldName],s=n.tables[a.tableName]?.fields[a.fieldName];if(!o||!s||!hasFieldShapeChange(o,s))continue;re.add(i);let c=getExpandContractEligibility({previous:t,current:n,tableName:a.tableName,fieldName:a.fieldName});c.eligible?r.push(i):ie.push(`--expand-contract cannot convert ${i.raw} (namespace: ${e}): ${c.reason}`)}k.set(e,new Set(r.map(({spec:e})=>fieldKey(e.tableName,e.fieldName))))}let ae=m.filter(e=>!re.has(e));if(ae.length>0)throw E({code:`MIGRATION_EXPAND_CONTRACT_UNMATCHED`,message:`--expand-contract does not match a field whose type or array-ness changed: ${ae.map(e=>e.raw).join(`, `)}`,command:`tailordb migration generate`});if(ie.length>0)throw E({code:`MIGRATION_EXPAND_CONTRACT_INELIGIBLE`,message:ie.join(`
|
|
1024
|
-
`)});let oe=[];for(let t of w){let{namespace:n,previousSnapshot:r,currentSnapshot:i}=t;if(!r)continue;let a=compareSnapshots(r,i);if(!hasChanges(a)){t.diff=a;continue}let o=await resolveRenames(r,i,a,e,{fieldRenames:T.get(n)??[],typeRenames:
|
|
1029
|
+
}`}function markMigrationScriptSkipped(e){let{migrationsDir:t,migrationNumber:n,reason:r}=e,i=formatMigrationNumber(n),a=r.trim();if(!a)throw E({code:`MIGRATION_SCRIPT_REASON_REQUIRED`,message:`Migration script skip reason must not be empty.`,command:`tailordb migration script`});let o=getMigrationFilePath(t,n,`diff`);if(!W.existsSync(o))throw E({code:`MIGRATION_NOT_FOUND`,message:`Migration ${i} not found in ${t}. Expected ${o}.`});let s=loadDiff(o);if(!s.requiresMigrationScript&&!s.hasWarnings)throw E({code:`MIGRATION_SCRIPT_NOT_REQUIRED`,message:`Migration ${i} does not require a migration script and has no data-loss warnings; nothing to skip.`});if(s.scriptSkipped)throw E({code:`MIGRATION_SCRIPT_SKIP_EXISTS`,message:`Migration ${i} already has a script skip recorded (${s.scriptSkipped.acknowledgedAt}: ${s.scriptSkipped.reason}).`});let c=getMigrationFilePath(t,n,`migrate`);if(W.existsSync(c))throw E({code:`MIGRATION_SCRIPT_EXISTS`,message:`Migration script exists at ${c}.`,suggestion:`Delete migrate.ts first if this migration should run without a script.`});let l={reason:a,acknowledgedAt:(/* @__PURE__ */ new Date()).toISOString()},u=JSON.parse(W.readFileSync(o,`utf-8`));return u.scriptSkipped=l,W.writeFileSync(o,JSON.stringify(u,null,2)),l}function clearMigrationScriptSkipped(e){let t=JSON.parse(W.readFileSync(e,`utf-8`));Object.hasOwn(t,`scriptSkipped`)&&(delete t.scriptSkipped,W.writeFileSync(e,JSON.stringify(t,null,2)))}async function addMigrationScriptFiles(e){let{migrationsDir:t,migrationNumber:n,withTest:r=!1,pgliteAvailable:i=!1,temporal:a=!1,dateDefault:o=`legacy`}=e,s=formatMigrationNumber(n),c=getMigrationFilePath(t,n,`diff`);if(!W.existsSync(c))throw E({code:`MIGRATION_NOT_FOUND`,message:`Migration ${s} not found in ${t}. Expected ${c}.`});let l=loadDiff(c),u=getMigrationFilePath(t,n,`migrate`),d=W.existsSync(u),f={};if(d&&l.scriptSkipped){if(clearMigrationScriptSkipped(c),f.clearedScriptSkip=!0,!r)return f}else if(d&&!r)throw E({code:`MIGRATION_SCRIPT_EXISTS`,message:`Migration script already exists at ${u}.`});let p=getMigrationFilePath(t,n,`test`),m=getMigrationFilePath(t,n,`pgliteTest`),h=getMigrationFilePath(t,n,`pgliteSchema`),g=r&&!W.existsSync(p),_=r&&i&&!W.existsSync(m);if(r&&!g&&!_)throw E({code:`MIGRATION_TEST_EXISTS`,message:i?`Migration tests already exist at ${p} and ${m}.`:`Migration test already exists at ${p}.`});if(d&&r){let e=getMigrationFilePath(t,n,`db`);if(!W.existsSync(e))throw E({code:`GENERATED_TYPES_NOT_FOUND`,message:`Generated types not found at ${e}.`,suggestion:`The test scaffold imports Database from ./db; restore db.ts before adding a test.`})}let v=!d||r&&!W.existsSync(h),y=v?reconstructSnapshotFromMigrations(t,n-1):null;if(v&&!y)throw E({code:`MIGRATION_HISTORY_INVALID`,message:`Could not reconstruct previous schema for migration ${s}.`,suggestion:`Make sure migration 0 exists.`});let b=d?analyzeMigrationScript(u).kind:`steps`;if(!d&&y){await J.writeFile(u,generateMigrationScript(l)),f.migratePath=u;let e=await writeMigrationTypeFiles({previousSnapshot:y,diff:l,migrationsDir:t,migrationNumber:n,temporal:a,dateDefault:o});f.dbTypesPath=e.dbTypesPath,f.pgliteSchemaPath=e.pgliteSchemaPath,f.pgliteSchemaError=e.pgliteSchemaError,clearMigrationScriptSkipped(c),l.scriptSkipped&&(f.clearedScriptSkip=!0)}else r&&y&&Object.assign(f,await tryWritePgliteSchemaFile(y,l,t,n));return g&&(await J.writeFile(p,generateMigrationTestScript(loadDiff(c),b)),f.testPath=p),f.pgliteTestRequested=_,_&&W.existsSync(h)&&(await J.writeFile(m,generateMigrationPgliteTestScript(loadDiff(c),b)),f.pgliteTestPath=m),f}function isPgliteAvailable(e){let t=H.resolve(e);for(;;){if(W.existsSync(H.join(t,`node_modules`,`@electric-sql`,`pglite`,`package.json`)))return!0;let e=H.dirname(t);if(e===t)return!1;t=e}}async function script(e){logBetaWarning(`tailordb migration`);let t=parseMigrationNumberArg(e.number);if(t===0)throw E({code:`MIGRATION_SCRIPT_NOT_ALLOWED`,message:`Migration ${e.number} is the initial schema snapshot and cannot have a migration script.`});let{config:n,plugins:r}=await loadConfig(e.configPath),i=H.dirname(n.path),o=resolvePluginConfig(r,`@tailor-platform/kysely-type`)?.temporal??!1,s=tt(n),c=getNamespacesWithMigrations(n,i);if(c.length===0)throw migrationConfigNotFoundError();let l=resolveTargetNamespace(c,e.namespace),{migrationsDir:u}=a(c.find(e=>e.namespace===l),`namespace with migrations not found`);if(e.noScript){if(e.withTest)throw E({code:`MIGRATION_SCRIPT_OPTIONS_CONFLICT`,message:`--with-test cannot be used together with --no-script.`,command:`tailordb migration script`});let n=e.reason?.trim();if(!n)throw E({code:`MIGRATION_SCRIPT_REASON_REQUIRED`,message:`--reason is required with --no-script.`,command:`tailordb migration script`});let r=markMigrationScriptSkipped({migrationsDir:u,migrationNumber:t,reason:n});C.success(`Recorded that migration ${h.bold(e.number)} in namespace ${h.bold(l)} intentionally has no migration script`);let i=getMigrationFilePath(u,t,`diff`);C.info(` Reason: ${r.reason}`),C.info(` Diff file: ${i}`),printMutationResult({changed:!0,namespace:l,migrationNumber:t,scriptSkipped:{reason:r.reason,acknowledgedAt:r.acknowledgedAt},diffPath:i});return}if(e.reason!==void 0)throw E({code:`MIGRATION_SCRIPT_OPTIONS_CONFLICT`,message:`--reason can only be used together with --no-script.`,command:`tailordb migration script`});let d=isPgliteAvailable(u),f=await addMigrationScriptFiles({migrationsDir:u,migrationNumber:t,withTest:e.withTest,pgliteAvailable:d,temporal:o,dateDefault:s});if(printMutationResult({changed:!!(f.clearedScriptSkip||f.migratePath||f.pgliteSchemaPath||f.testPath||f.pgliteTestPath),namespace:l,migrationNumber:t,migratePath:f.migratePath??null,dbTypesPath:f.dbTypesPath??null,pgliteSchemaPath:f.pgliteSchemaPath??null,pgliteSchemaError:f.pgliteSchemaError??null,testPath:f.testPath??null,pgliteTestPath:f.pgliteTestPath??null,clearedScriptSkip:f.clearedScriptSkip??!1}),f.clearedScriptSkip&&!f.migratePath&&(C.success(`Cleared the stale script skip record for migration ${h.bold(e.number)} in namespace ${h.bold(l)}`),!f.testPath&&!f.pgliteTestRequested)){C.info(` Migration script: ${getMigrationFilePath(u,t,`migrate`)}`);return}let p=[f.testPath,f.pgliteTestPath].filter(Boolean).length,m=[f.migratePath&&`migration script`,p>0&&(p>1?`migration tests`:`migration test`)].filter(Boolean).join(` and `),g=`for migration ${h.bold(e.number)} in namespace ${h.bold(l)}`;m?C.success(`Added ${m} ${g}`):C.warn(`Added no files ${g}`),f.migratePath&&(C.info(` Migration script: ${f.migratePath}`),C.info(` DB types: ${f.dbTypesPath}`)),f.pgliteSchemaPath&&C.info(` PGlite schema: ${f.pgliteSchemaPath}`),f.pgliteSchemaError&&C.warn(` PGlite schema skipped: ${f.pgliteSchemaError}`),f.testPath&&C.info(` Migration test: ${f.testPath}`),f.pgliteTestPath?C.info(` PGlite test: ${f.pgliteTestPath}`):f.testPath&&!d?C.info(` Install @electric-sql/pglite as a devDependency to also scaffold a PGlite test (migrate.pglite.test.ts).`):f.pgliteTestRequested&&f.pgliteSchemaError&&C.info(` PGlite test skipped: it needs the db.pglite.ts that could not be generated.`),C.newline(),f.migratePath&&(C.log(`Edit the script to implement your data migration logic.`),C.log(`It will be executed by 'tailor deploy' between Pre and Post phases.`)),f.testPath&&C.log(`Fill in the test with the rows to stage and the statements to assert.`);let _=f.migratePath??f.testPath;if(!_)return;let v=getConfiguredEditorCommand();if(v&&canPrompt()){C.newline(),C.info(`Opening ${H.basename(_)} in ${v}...`);try{await openInConfiguredEditor(_)}catch{return}}}function resolveTargetNamespace(e,t){if(t){if(!e.some(e=>e.namespace===t))throw E({code:`TAILORDB_NAMESPACE_NOT_FOUND`,message:`Namespace "${t}" not found or does not have migrations configured`});return t}if(e.length===1){let[t]=e;return a(t,`namespace with migrations missing`).namespace}throw E({code:`MIGRATION_NAMESPACE_REQUIRED`,message:`Multiple TailorDB services found. Please specify namespace with --namespace flag: ${e.map(e=>e.namespace).join(`, `)}`,command:`tailordb migration script`})}const Vl=Y({name:`script`,description:`Add a migration script (migrate.ts) template to an existing migration directory, or record with --no-script that a migration intentionally has none.`,notes:"When `migrate.ts` already exists, running the command clears a previously recorded `--no-script` acknowledgment, and `--with-test` adds only the tests that do not exist yet (writing `db.pglite.ts` if it is missing). `migrate.pglite.test.ts` is scaffolded only when `@electric-sql/pglite` is installed in the project.",args:U.strictObject({...oe,number:V(U.string(),{positional:!0,description:`Migration number to add a script to (e.g., 0001 or 1)`}),namespace:V(U.string().optional(),{alias:`n`,description:`Target TailorDB namespace (required if multiple namespaces exist)`}),"no-script":V(U.boolean().optional(),{description:`Record that this migration intentionally runs without a migration script (requires --reason)`}),reason:V(U.string().optional(),{description:`Reason why no migration script is needed (used with --no-script)`}),"with-test":V(U.boolean().optional(),{description:`Also add the migrate.test.ts and migrate.pglite.test.ts scaffolds`})}),run:async e=>{await script({configPath:e.config,number:e.number,namespace:e.namespace,noScript:e[`no-script`],reason:e.reason,withTest:e[`with-test`]})}});function getUnsupportedMigrationHintLines(){return[`These changes require a manual 3-step migration process:`,` Migration 1: Add an optional temporary field with the desired structure`,` If the old field is required, make the old field optional`,` For each non-null old value, copy and convert it to the temporary field`,` and set the old field to null in the same update`,` Verify every old value is null before continuing`,` Migration 2: Remove the old field`,` Migration 3: Add the field with the original name and new structure,`,` migrate data from the temporary field, then remove it`,` Important: Reusing the name while stored old values remain can make subsequent reads fail`]}function assertNoNestedNamespaceMigrations(e,t){let realPath=e=>W.existsSync(e)?W.realpathSync(e):e,isInside=(e,t)=>H.relative(e,t).split(`/`)[0]!==`..`,n=realPath(e.migrationsDir),r=t.filter(({namespace:t,migrationsDir:r})=>t!==e.namespace&&(isInside(e.migrationsDir,r)||isInside(n,realPath(r))));if(r.length!==0)throw E({code:`MIGRATION_GENERATE_OPTIONS_CONFLICT`,message:`--init --namespace ${e.namespace} would also delete the migrations of ${r.map(({namespace:e})=>e).join(`, `)}, whose directories are inside ${e.migrationsDir}.`,suggestion:`Run --init without --namespace, or move the nested migration directories out.`,command:`tailordb migration generate`})}async function handleInitOption(e,t){let n=e.filter(({migrationsDir:e})=>W.existsSync(e));if(n.length===0)return C.info(`No existing migration directories found.`),[];C.newline(),C.warn(`This will DELETE all existing migration files:`);for(let{namespace:e,migrationsDir:t}of n)C.log(` - ${e}: ${t}`);if(C.newline(),!t){if(!await X.confirm({message:`Are you sure you want to delete these directories and start fresh?`,default:!1}))throw E({code:`MIGRATION_GENERATE_CANCELLED`,message:`Migration generation cancelled. No migration files were deleted.`});C.newline()}for(let{namespace:e,migrationsDir:t}of n)try{await J.rm(t,{recursive:!0,force:!0}),C.success(`Deleted migration directory for ${h.bold(e)}`)}catch(e){throw C.error(`Failed to delete ${t}: ${e}`),e}return C.newline(),C.info(`Migration directories cleared. Generating initial snapshot...`),C.newline(),n.map(({namespace:e})=>e)}function generatedMigration(e,t){return{namespace:e,migrationNumber:t.migrationNumber,schemaPath:null,diffPath:t.diffFilePath,migratePath:t.migrateFilePath??null,dbTypesPath:t.dbTypesFilePath??null,pgliteSchemaPath:t.pgliteSchemaFilePath??null,pgliteSchemaError:t.pgliteSchemaError??null}}async function generate(e){return generateMigrations(e)}async function generateMigrations(e){logBetaWarning(`tailordb migration`);let{config:t,plugins:n}=await loadConfig(e.configPath),r=H.dirname(t.path),i=resolvePluginConfig(n,`@tailor-platform/kysely-type`)?.temporal??!1,o=tt(t),s=getNamespacesWithMigrations(t,r);if(s.length===0)return C.warn(`No TailorDB namespaces with migrations config found.`),C.info(`Add "migration: { directory: \\"./migrations\\" }" to your db config to enable migrations.`),{changed:!1,clearedNamespaces:[],skippedNamespaces:[],migrations:[]};let c=[],l=[],u=[];for(let t of e.renames??[]){let e=targetDepth(t);e>=2?u.push({raw:t,spec:parseNestedMemberRenameOption(t)}):e===1?c.push({raw:t,spec:parseRenameOption(t)}):l.push({raw:t,spec:parseTypeRenameOption(t)})}let d=[],f=[],p=[];for(let t of e.drops??[]){let e=targetDepth(t);e>=2?p.push({raw:t,spec:parseNestedMemberDropOption(t)}):e===1?d.push({raw:t,spec:parseDropOption(t)}):f.push({raw:t,spec:parseTypeDropOption(t)})}let m=(e.expandContracts??[]).map(e=>({raw:e,spec:parseExpandContractOption(e)})),g=c.length>0||l.length>0||u.length>0||d.length>0||f.length>0||p.length>0;if(e.init&&(g||m.length>0))throw E({code:`MIGRATION_GENERATE_OPTIONS_CONFLICT`,message:`--rename, --drop, and --expand-contract cannot be used together with --init.`,command:`tailordb migration generate`});if(assertNoRenameDropConflict(c.map(({spec:e})=>fieldKey(e.tableName,e.previousFieldName)),d.map(({spec:e})=>fieldKey(e.tableName,e.fieldName))),assertNoRenameDropConflict(u.map(({spec:e})=>nestedMemberKey({...e,path:e.previousPath})),p.map(({spec:e})=>nestedMemberKey(e))),assertNoRenameDropConflict(l.map(({spec:e})=>e.previousTableName),f.map(({spec:e})=>e.tableName)),e.namespace!==void 0&&!e.dataOnly&&!e.init)throw E({code:`MIGRATION_GENERATE_OPTIONS_CONFLICT`,message:`--namespace can only be used together with --data-only or --init.`,command:`tailordb migration generate`});if(e.dataOnly&&(e.init||g||m.length>0))throw E({code:`MIGRATION_GENERATE_OPTIONS_CONFLICT`,message:`--init, --rename, --drop, and --expand-contract cannot be used together with --data-only.`,command:`tailordb migration generate`});let _=e.dataOnly||e.namespace!==void 0?resolveTargetNamespace(s,e.namespace):void 0,v=_===void 0?s:s.filter(({namespace:e})=>e===_),y=e.init?v[0]:void 0;y&&_!==void 0&&assertNoNestedNamespaceMigrations(y,s);let b;n.length>0&&(b=new Er(n));let{defineApplication:x}=await import(`./application-OeNMQzOC.mjs`),S=x({config:t,pluginManager:b}),w=[];for(let{namespace:n,migrationsDir:r}of v){C.info(`Processing namespace: ${h.bold(n)}`),e.init||assertValidMigrationFiles(r,n,t.path);let i=S.tailorDBServices.find(e=>e.namespace===n);if(!i){C.warn(`No TailorDB service found for namespace "${n}"`);continue}await i.loadTypes(),await i.processNamespacePlugins();let a=i.types;w.push({namespace:n,migrationsDir:r,currentSnapshot:createSnapshotFromLocalTypes(a,n),previousSnapshot:e.init?null:reconstructSnapshotFromMigrations(r)})}if(e.dataOnly&&_!==void 0)return{changed:!0,clearedNamespaces:[],skippedNamespaces:[],migrations:[await generateDataOnlyMigration(w,_,e,i,o)]};let T=matchFlagsToNamespaces(c,w,renameSpecApplies,`--rename does not match a removed + added field pair`),ee=matchFlagsToNamespaces(l,w,typeRenameSpecApplies,`--rename does not match a removed + added table pair`),D=matchFlagsToNamespaces(d,w,dropSpecApplies,`--drop does not match a removed field`),te=matchFlagsToNamespaces(f,w,typeDropSpecApplies,`--drop does not match a removed table`),ne=matchFlagsToNamespaces(u,w,nestedMemberRenameSpecApplies,`--rename does not match a removed + added nested member pair`),re=matchFlagsToNamespaces(p,w,nestedMemberDropSpecApplies,`--drop does not match a removed nested member`),O=/* @__PURE__ */ new Map,ie=/* @__PURE__ */ new Set,k=[];for(let{namespace:e,previousSnapshot:t,currentSnapshot:n}of w){if(!t)continue;let r=[];for(let i of m){let{spec:a}=i,o=t.tables[a.tableName]?.fields[a.fieldName],s=n.tables[a.tableName]?.fields[a.fieldName];if(!o||!s||!hasFieldShapeChange(o,s))continue;ie.add(i);let c=getExpandContractEligibility({previous:t,current:n,tableName:a.tableName,fieldName:a.fieldName});c.eligible?r.push(i):k.push(`--expand-contract cannot convert ${i.raw} (namespace: ${e}): ${c.reason}`)}O.set(e,new Set(r.map(({spec:e})=>fieldKey(e.tableName,e.fieldName))))}let ae=m.filter(e=>!ie.has(e));if(ae.length>0)throw E({code:`MIGRATION_EXPAND_CONTRACT_UNMATCHED`,message:`--expand-contract does not match a field whose type or array-ness changed: ${ae.map(e=>e.raw).join(`, `)}`,command:`tailordb migration generate`});if(k.length>0)throw E({code:`MIGRATION_EXPAND_CONTRACT_INELIGIBLE`,message:k.join(`
|
|
1030
|
+
`)});let oe=[];for(let t of w){let{namespace:n,previousSnapshot:r,currentSnapshot:i}=t;if(!r)continue;let a=compareSnapshots(r,i);if(!hasChanges(a)){t.diff=a;continue}let o=await resolveRenames(r,i,a,e,{fieldRenames:T.get(n)??[],typeRenames:ee.get(n)??[],fieldDrops:D.get(n)??[],typeDrops:te.get(n)??[],nestedMemberRenames:ne.get(n)??[],nestedMemberDrops:re.get(n)??[]});t.diff=o.diff,oe.push(...o.unresolved),t.expandPlans=await resolveExpandContractPlans({previousSnapshot:r,currentSnapshot:i,diff:o.diff,options:e,confirmedKeys:O.get(n)??/* @__PURE__ */ new Set})}if(oe.length>0){let e=oe.map(({namespace:e,label:t,targets:n})=>` - ${t} → ${n.join(`, `)}? (namespace: ${e})`).join(`
|
|
1025
1031
|
`);throw E({code:`MIGRATION_RENAME_UNRESOLVED`,message:`Possible rename(s) detected:\n${e}`,suggestion:`Re-run with --rename "Table.oldField:newField" (field), --rename "OldTable:NewTable" (table), or --rename "Table.field.oldMember:newMember" (nested member) to record a rename and scaffold a data copy script, or --drop "Table.field" / --drop "Table" / --drop "Table.field.member" to confirm the removal.`,command:`tailordb migration generate`})}assertMigrationNumbersAvailable(w.filter(({previousSnapshot:e,diff:t})=>e&&t&&hasChanges(t)),e.configPath);let se=e.init?await handleInitOption(v,e.yes):[],ce=[],le=[];for(let{namespace:t,migrationsDir:n,currentSnapshot:r,previousSnapshot:s,diff:c,expandPlans:l}of w)if(!s)le.push(await generateInitialSnapshot(t,r,n));else{let u=await generateDiffFromSnapshot(s,a(c,`Migration diff was not resolved during preflight`),n,e,r,l??[],i,o);u.declined&&ce.push(t),le.push(...u.migrations.map(e=>generatedMigration(t,e)))}return ce.length>0&&C.info(`Skipped: ${ce.join(`, `)}`),{changed:se.length>0||le.length>0,clearedNamespaces:se,skippedNamespaces:ce,migrations:le}}async function generateDataOnlyMigration(e,t,n,r,i){let a=e.find(e=>e.namespace===t);if(!a)throw E({code:`TAILORDB_NAMESPACE_NOT_FOUND`,message:`No TailorDB service found for namespace "${t}"`});let{migrationsDir:o,previousSnapshot:s,currentSnapshot:c}=a;if(!s)throw E({code:`MIGRATION_BASELINE_NOT_FOUND`,message:`Namespace "${t}" has no migration baseline.`,suggestion:`Create the initial schema snapshot first.`});let l=compareSnapshots(s,c);if(hasChanges(l))throw C.newline(),C.log(formatMigrationDiff(l)),C.newline(),E({code:`MIGRATION_SCHEMA_CHANGES_PENDING`,message:`Namespace "${t}" has schema changes that are not in migration files.`,suggestion:`Generate the schema migration first by running without --data-only.`});assertMigrationNumbersAvailable([a],n.configPath);let u=getNextMigrationNumber(o),d=await generateDataOnlyMigrationFiles({diff:{...l,requiresMigrationScript:!0},migrationsDir:o,migrationNumber:u,snapshot:s,description:n.name,temporal:r,dateDefault:i});return C.success(`Generated data-only migration ${h.bold(formatMigrationNumber(d.migrationNumber))}`),C.info(` Diff file: ${d.diffFilePath}`),C.info(` Migration script: ${d.migrateFilePath}`),C.info(` DB types: ${d.dbTypesFilePath}`),logPgliteSchemaResult(d),C.newline(),C.log(`This migration carries no schema changes.`),C.log(`Edit the script to implement the data transformation before running 'tailor deploy'.`),await openMigrationScriptInEditor(d.migrateFilePath),generatedMigration(t,d)}function logPgliteSchemaResult(e){e.pgliteSchemaFilePath&&C.info(` PGlite schema: ${e.pgliteSchemaFilePath}`),e.pgliteSchemaError&&C.warn(` PGlite schema skipped: ${e.pgliteSchemaError}`)}async function openMigrationScriptInEditor(e){let t=getConfiguredEditorCommand();if(t&&canPrompt()){try{await J.access(e)}catch{return}C.newline(),C.info(`Opening ${H.basename(e)} in ${t}...`);try{await openInConfiguredEditor(e)}catch{return}}}async function resolveExpandContractPlans(e){let{previousSnapshot:t,currentSnapshot:n,diff:r,options:i,confirmedKeys:a}=e,o=new Set(a);if(!i.yes&&canPrompt())for(let e of r.changes){if(!isExpandContractCandidate(e))continue;let r=fieldKey(e.tableName,e.fieldName);o.has(r)||canConvertField({previous:t,current:n,tableName:e.tableName,fieldName:e.fieldName})&&(C.newline(),C.info(`${e.tableName}.${e.fieldName} changes from ${formatFieldShape(e.before)} to ${formatFieldShape(e.after)}, which cannot be applied in one step.`),await X.confirm({message:`Generate two migrations to convert ${e.tableName}.${e.fieldName} through a temporary field?`,default:!0})&&o.add(r))}return planExpandContract({previous:t,current:n,diff:r,confirmed:o}).plans}async function generateInitialSnapshot(e,t,n){let r=await generateSchemaFile(t,n,0);return C.success(`Generated initial schema snapshot`),C.info(` File: ${r.filePath}`),C.info(` Tables: ${Object.keys(t.tables).length}`),C.log(`
|
|
1026
1032
|
This is the baseline schema. Future changes will be tracked as diffs.`),{namespace:e,migrationNumber:r.migrationNumber,schemaPath:r.filePath,diffPath:null,migratePath:null,dbTypesPath:null,pgliteSchemaPath:null,pgliteSchemaError:null}}function targetDepth(e){return(e.split(`:`)[0]??``).split(`.`).length-1}function nestedMemberKey(e){return`${e.tableName}.${e.fieldName}.${e.path.join(`.`)}`}function assertNoRenameDropConflict(e,t){let n=new Set(t),r=e.filter(e=>n.has(e));if(r.length>0)throw E({code:`MIGRATION_RENAME_DROP_CONFLICT`,message:`--rename and --drop conflict for: ${r.join(`, `)}`,command:`tailordb migration generate`})}function matchFlagsToNamespaces(e,t,n,r){let i=/* @__PURE__ */ new Map,a=/* @__PURE__ */ new Set;for(let{namespace:r,previousSnapshot:o,currentSnapshot:s}of t){if(!o)continue;let t=e.filter(({spec:e})=>n(e,o,s));for(let e of t)a.add(e);i.set(r,t.map(e=>e.spec))}let o=e.filter(e=>!a.has(e));if(o.length>0)throw E({code:`MIGRATION_FLAG_UNMATCHED`,message:`${r}: ${o.map(e=>e.raw).join(`, `)}`,command:`tailordb migration generate`});return i}function assertMigrationNumbersAvailable(e,t){let n=formatMigrationNumber(9999),r=e.flatMap(({namespace:e,migrationsDir:t,expandPlans:r})=>{let i=(r?.length??0)>0;return getNextMigrationNumber(t)+ +!!i<=9999?[]:[{namespace:e,reason:i?`Namespace "${e}" needs two migration numbers to convert a field type, and ${n} is the last one available.`:`Namespace "${e}" has reached migration ${n}, the last number available.`}]});if(r.length===0)return;let i=r.map(({namespace:e})=>formatRebaselineHint({namespace:e,configPath:t})).join(` and `);throw E({code:`MIGRATION_NUMBER_EXHAUSTED`,message:r.map(({reason:e})=>e).join(`
|
|
1027
1033
|
`),suggestion:`Re-baseline the migration history with ${i}, then generate again. Re-baselining requires the history to reproduce the local schema, so set aside schema changes not yet in a migration until it finishes.`,context:{namespaces:r.map(({namespace:e})=>e)}})}async function promptRename(e,t){let{label:n,oldName:r,kind:i}=e,a=i===`table`?`schema`:`type`,[o]=t;return t.length===1&&o?await X.confirm({message:`${n} was removed and ${o} was added with a compatible ${a}. Was it renamed to ${o}?`,default:!0})?o:void 0:await X.select({message:`${n} was removed. Was it renamed to one of these added ${i}s?`,choices:[...t.map(e=>({name:`Yes, renamed to ${e}`,value:e})),{name:`No, ${r} was removed`,value:null}]})??void 0}async function resolveRenames(e,t,n,r,i){let a=[...i.fieldRenames],o=[...i.typeRenames],s=[...i.nestedMemberRenames],c=new Set(o.flatMap(e=>[e.previousTableName,e.tableName])),l=new Set(i.typeDrops.map(e=>e.tableName)),u=new Set(a.flatMap(e=>[fieldKey(e.tableName,e.previousFieldName),fieldKey(e.tableName,e.fieldName)])),d=new Set(i.fieldDrops.map(e=>fieldKey(e.tableName,e.fieldName))),f=new Set(s.flatMap(e=>[nestedMemberKey({...e,path:e.previousPath}),nestedMemberKey(e)])),p=new Set(i.nestedMemberDrops.map(e=>nestedMemberKey(e))),m=[...findTypeRenameCandidates(n).map(e=>{let{removed:t,added:n}=e;return{label:t.tableName,oldName:t.tableName,added:n.map(e=>e.tableName),keyOf:e=>e,claimed:c,dropped:l,kind:`table`,record:e=>{o.push({previousTableName:t.tableName,tableName:e})}}}),...findRenameCandidates(n).map(e=>{let{tableName:t,removed:n,added:r}=e;return{label:fieldKey(t,n.fieldName),oldName:n.fieldName,added:r.map(e=>e.fieldName),keyOf:e=>fieldKey(t,e),claimed:u,dropped:d,kind:`field`,record:e=>{a.push({tableName:t,previousFieldName:n.fieldName,fieldName:e})}}}),...findNestedMemberRenameCandidates(n).map(e=>{let{tableName:t,fieldName:n,previousPath:r}=e,i=r.slice(0,-1);return{label:nestedMemberKey({tableName:t,fieldName:n,path:r}),oldName:r[r.length-1]??``,added:e.added,keyOf:e=>nestedMemberKey({tableName:t,fieldName:n,path:[...i,e]}),claimed:f,dropped:p,kind:`member`,record:e=>{s.push({tableName:t,fieldName:n,previousPath:r,path:[...i,e]})}}})],availableTargets=e=>e.added.filter(t=>!e.claimed.has(e.keyOf(t))),h=m.filter(e=>!e.dropped.has(e.label)&&!e.claimed.has(e.label)&&availableTargets(e).length>0),g=[];if(r.yes||!canPrompt())for(let e of h)g.push({namespace:n.namespace,label:e.label,targets:availableTargets(e)});else for(let e of h){let t=availableTargets(e);if(t.length===0)continue;let n=await promptRename(e,t);n&&(e.record(n),e.claimed.add(e.label),e.claimed.add(e.keyOf(n)))}return a.length===0&&o.length===0&&s.length===0?{diff:n,unresolved:g}:{diff:compareSnapshots(e,t,{fieldRenames:a,typeRenames:o,nestedMemberRenames:s}),unresolved:g}}async function generateDiffFromSnapshot(e,t,n,r,i,a=[],o=!1,s=`legacy`){if(!hasChanges(t))return C.info(`No schema differences detected.`),{declined:!1,migrations:[]};C.newline(),C.log(formatMigrationDiff(t)),C.newline(),C.info(`Summary: ${formatDiffSummary(t)}`);let c=new Set(a.map(e=>fieldKey(e.tableName,e.fieldName))),l=t.breakingChanges.filter(e=>e.unsupported&&!(e.fieldName&&c.has(fieldKey(e.tableName,e.fieldName))));if(l.length>0){for(let e of l)C.newline(),C.error(`Unsupported change: ${e.tableName}.${e.fieldName}`),C.error(` ${e.reason}`);let t=/* @__PURE__ */ new Set;for(let{tableName:n,fieldName:r}of l)r!==void 0&&canConvertField({previous:e,current:i,tableName:n,fieldName:r})&&t.add(fieldKey(n,r));if(t.size>0){C.newline(),C.info(`Convert these fields through a temporary field with:`);for(let e of t)C.info(` --expand-contract "${e}"`)}if(l.some(e=>e.showThreeStepHint)){C.newline();for(let e of getUnsupportedMigrationHintLines())C.info(e)}let n=l.map(e=>` - ${e.tableName}.${e.fieldName}: ${e.reason}`).join(`
|
|
1028
|
-
`);throw E({code:`MIGRATION_UNSUPPORTED_SCHEMA_CHANGE`,message:`Unsupported schema changes detected:\n${n}`})}if(t.hasBreakingChanges&&(C.newline(),C.warn(formatBreakingChanges(t.breakingChanges)),!r.yes)){if(!await X.confirm({message:`Continue generating migration?`,default:!0}))return C.info(`Skipped the migration for namespace "${t.namespace}".`),{declined:!0,migrations:[]};C.newline()}if(t.hasWarnings&&(C.newline(),C.warn(formatWarnings(t.warnings))),a.length>0)return{declined:!1,migrations:await generateExpandContractMigrations({previousSnapshot:e,currentSnapshot:i,resolvedDiff:t,plans:a,migrationsDir:n,description:r.name,temporal:o,dateDefault:s})};let u=await generateDiffFiles(t,n,getNextMigrationNumber(n),e,r.name,[],o,s);return C.success(`Generated migration ${h.bold(formatMigrationNumber(u.migrationNumber))}`),C.info(` Diff file: ${u.diffFilePath}`),u.migrateFilePath?(C.info(` Migration script: ${u.migrateFilePath}`),u.dbTypesFilePath&&(C.info(` DB types: ${u.dbTypesFilePath}`),logPgliteSchemaResult(u)),C.newline(),C.log(`A migration script was generated for breaking changes.`),C.log(`Please review and edit the script before running 'tailor deploy'.`),await openMigrationScriptInEditor(u.migrateFilePath)):t.hasWarnings&&await acknowledgeWarnings({namespace:t.namespace,migrationsDir:n,migrationNumber:u.migrationNumber,skipPrompt:r.yes,configPath:r.configPath}),{declined:!1,migrations:[u]}}async function generateExpandContractMigrations(e){let{previousSnapshot:t,currentSnapshot:n,resolvedDiff:r,plans:i,migrationsDir:a,description:o,temporal:s=!1,dateDefault:c=`legacy`}=e,l=buildIntermediateSnapshot(t,i),u=buildExpandDiff(t,l,i),d=r.changes.filter(e=>e.kind===`field_renamed`).map(({tableName:e,previousFieldName:t,fieldName:n})=>({tableName:e,previousFieldName:t,fieldName:n})),f=r.changes.filter(e=>e.kind===`table_renamed`).map(({previousTableName:e,tableName:t})=>({previousTableName:e,tableName:t})),p=compareSnapshots(l,n,{nestedMemberRenames:r.changes.flatMap(e=>e.kind===`field_modified`?(e.memberRenames??[]).map(t=>({tableName:e.tableName,fieldName:e.fieldName,...t})):[]),fieldRenames:[...d,...i.map(e=>({tableName:e.tableName,previousFieldName:e.tempFieldName,fieldName:e.fieldName}))],typeRenames:f}),m=getNextMigrationNumber(a),g=await generateDiffFiles(u,a,m,t,o,i,s,c),_=await generateDiffFiles(p,a,m+1,l,o,[],s,c,i),v=i.map(e=>`${e.tableName}.${e.fieldName}`).join(`, `);return C.success(`Generated migrations ${h.bold(formatMigrationNumber(g.migrationNumber))} and ${h.bold(formatMigrationNumber(_.migrationNumber))} to convert ${v}`),C.info(` Diff files: ${g.diffFilePath}, ${_.diffFilePath}`),g.migrateFilePath&&C.info(` Conversion script: ${g.migrateFilePath}`),_.migrateFilePath&&C.info(` Copy script: ${_.migrateFilePath}`),C.newline(),C.info(`Edit the conversion in ${formatMigrationNumber(g.migrationNumber)} before deploying. The copy script in ${formatMigrationNumber(_.migrationNumber)} is complete, though that migration also carries any other change in this run.`,{mode:`plain`}),C.info(`Both migrations are applied by 'tailor deploy'.`,{mode:`plain`}),[g,_]}async function acknowledgeWarnings(e){let{namespace:t,migrationsDir:n,migrationNumber:r,skipPrompt:i,configPath:a}=e,o=formatMigrationNumber(r);if(C.newline(),C.log(`Data loss is possible for this migration but no script was generated.`),!i&&canPrompt()&&await X.confirm({message:`Record a reason acknowledging that this migration intentionally has no script?`,default:!0})){let e=markMigrationScriptSkipped({migrationsDir:n,migrationNumber:r,reason:await X.text({message:`Reason:`,validate:e=>e.trim()!==``||`Reason must not be empty.`})});C.success(`Recorded that migration ${h.bold(o)} intentionally has no migration script`),C.info(` Reason: ${e.reason}`);return}let s={migrationNumber:r,namespace:t,configPath:a};C.log(`To add a custom migrate.ts, run:`),C.log(` ${h.bold(formatMigrationScriptHint(s))}`),C.log(`To record that this migration intentionally has no script, run:`),C.log(` ${h.bold(formatMigrationScriptHint({...s,noScript:!0}))}`)}const Il=Y({name:`generate`,description:`Generate migration files by detecting schema differences between current local tables and the previous migration snapshot.`,args:U.strictObject({...se,...oe,name:V(U.string().optional(),{alias:`n`,description:`Optional description for the migration`}),init:V(U.boolean().default(!1),{description:`Delete existing migrations and start fresh (all namespaces with migrations configured, or only the one given by --namespace)`}),"data-only":V(U.boolean().default(!1),{description:`Create a migration with no schema changes whose migration script runs a standalone data transformation`}),namespace:V(U.string().optional(),{description:`Target TailorDB namespace for --data-only (required if multiple namespaces exist), or the only namespace --init resets`}),rename:V(U.array(U.string()).optional(),{description:`Record a field, table, or nested member rename instead of remove + add (format: "Table.oldField:newField", "OldTable:NewTable", or "Table.field.oldMember:newMember"; repeatable). Renames require a migration script that copies the data.`}),drop:V(U.array(U.string()).optional(),{description:`Confirm that a removed field, table, or nested member is a genuine removal, not a rename (format: "Table.field", "Table", or "Table.field.member"; repeatable). Required in non-interactive runs for a removal with rename candidates.`}),"expand-contract":V(U.array(U.string()).optional(),{description:`Convert a field type, or a single value into an array, through a temporary field (format: "Table.field"; repeatable). Generates two migrations.`})}),run:async e=>{printMutationResult(await generateMigrations({configPath:e.config,name:e.name,yes:e.yes,init:e.init,dataOnly:e[`data-only`],namespace:e.namespace,renames:e.rename,drops:e.drop,expandContracts:e[`expand-contract`]}))}});async function resolveTableNamespaces(e){let t=/* @__PURE__ */ new Map;for(let n of e.tableNames){let e=n.toLowerCase(),r=t.get(e);r?r.push(n):t.set(e,[n])}let n=new Set(e.tableNames),r=/* @__PURE__ */ new Map;for(let i of e.namespaces){if(n.size===0)break;let a=``;do{let{tailordbTypes:o,nextPageToken:s}=await e.client.listTailorDBTypes({workspaceId:e.workspaceId,namespaceName:i,pageToken:a,pageSize:Ft});for(let e of o){let a=t.get(e.name.toLowerCase());if(a)for(let e of a)r.has(e)||(r.set(e,i),n.delete(e))}a=s}while(a&&n.size>0)}return r}async function truncateSingleType(e,t){await t.truncateTailorDBType({workspaceId:e.workspaceId,namespaceName:e.namespaceName,tailordbTypeName:e.tableName}),C.success(`Truncated table "${e.tableName}" in namespace "${e.namespaceName}"`)}async function truncateNamespace(e,t,n){await n.truncateTailorDBTypes({workspaceId:e,namespaceName:t}),C.success(`Truncated all tables in namespace "${t}"`)}async function truncate(e){await $truncate({...e,yes:!0})}async function $truncate(e={}){let{client:t,workspaceId:n}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId}),r=e.tables&&e.tables.length>0,i=!!e.namespace,o=!!e.all,s=[o,i,r].filter(Boolean).length;if(s===0)throw E({code:`TRUNCATE_TARGET_REQUIRED`,message:`Please specify one of: --all, --namespace <name>, or table names`,command:`tailordb truncate`});if(s>1)throw E({code:`TRUNCATE_OPTIONS_CONFLICT`,message:`Options --all, --namespace, and table names are mutually exclusive. Please specify only one.`,command:`tailordb truncate`});let{config:c}=await loadConfig(e.configPath),l=extractOwnedNamespaces(c);if(o){if(l.length===0)return C.warn(`No namespaces found in config file.`),{changed:!1,workspaceId:n,namespaces:[],tables:[]};if(!e.yes){let e=l.join(`, `);if(!await X.confirm({message:`This will truncate ALL tables in the following owned namespaces (external namespaces are excluded): ${e}. Continue?`,default:!1}))throw E({code:`TRUNCATE_CANCELLED`,message:`Truncate cancelled.`})}for(let e of l)await truncateNamespace(n,e,t);return C.success(`Truncated all tables in all owned namespaces`),{changed:!0,workspaceId:n,namespaces:l,tables:[]}}if(i){let r=a(e.namespace,`namespace option missing`);if(!l.includes(r)){let e=c.db?.[r];throw e&&`external`in e?E({code:`TAILORDB_NAMESPACE_EXTERNAL`,message:`Namespace "${r}" is declared as external in this app's config and cannot be truncated from here.`,suggestion:`Run truncate from the app that owns the namespace.`}):E({code:`TAILORDB_NAMESPACE_NOT_FOUND`,message:`Namespace "${r}" not found in config. Available owned namespaces (external namespaces are excluded): ${l.join(`, `)}`})}if(!e.yes&&!await X.confirm({message:`This will truncate ALL tables in namespace "${r}". Continue?`,default:!1}))throw E({code:`TRUNCATE_CANCELLED`,message:`Truncate cancelled.`});return await truncateNamespace(n,r,t),{changed:!0,workspaceId:n,namespaces:[r],tables:[]}}let u=[];if(r){let r=a(e.tables,`tables option missing`),i=await resolveTableNamespaces({workspaceId:n,namespaces:l,tableNames:r,client:t}),o=r.filter(e=>!i.has(e));if(o.length>0)throw E({code:`TAILORDB_TABLE_NOT_FOUND`,message:`The following tables were not found in any namespace: ${o.join(`, `)}`});if(!e.yes){let e=r.join(`, `);if(!await X.confirm({message:`This will truncate the following tables: ${e}. Continue?`,default:!1}))throw E({code:`TRUNCATE_CANCELLED`,message:`Truncate cancelled.`})}for(let e of r){let r=i.get(e);r&&(await truncateSingleType({workspaceId:n,namespaceName:r,tableName:e},t),u.push({namespace:r,name:e}))}}return{changed:u.length>0,workspaceId:n,namespaces:[],tables:u}}const Ll=Y({name:`truncate`,description:`Truncate (delete all records from) TailorDB tables.`,args:U.strictObject({...k,...se,tables:V(U.string().array().optional(),{positional:{named:!0},description:`Table names to truncate`}),all:V(U.boolean().default(!1),{alias:`a`,description:`Truncate all tables in all owned namespaces (excludes external namespaces)`}),namespace:V(U.string().optional(),{alias:`n`,description:`Truncate all tables in specified namespace`})}),run:async e=>{await assertWritable({profile:e.profile});let t=e.tables&&e.tables.length>0?e.tables:void 0;printMutationResult(await $truncate({workspaceId:e[`workspace-id`],profile:e.profile,configPath:e.config,all:e.all,namespace:e.namespace,tables:t,yes:e.yes}))}});async function listWorkflows(e){let{client:t,workspaceId:n}=await loadOperatorWorkspaceContext({profile:e?.profile,workspaceId:e?.workspaceId}),r=Ce(e?.order);return(await Mt(async(e,i)=>{let{workflows:a,nextPageToken:o}=await t.listWorkflows({workspaceId:n,pageToken:e,pageSize:i,pageDirection:r});return[a,o]},{limit:e?.limit})).map(toWorkflowListInfo)}const Rl=Y({name:`list`,description:`List all workflows in the workspace.`,args:U.strictObject({...j,...pe()}),run:async e=>{let t=C.jsonMode,n=await fetchWithinLimit(e.limit,t=>listWorkflows({workspaceId:e[`workspace-id`],profile:e.profile,order:e.order,limit:t})),r=n.items;r.length===0&&(C.info(`No workflows found.`),!t)||(C.out(r),await reportTruncation(n,e.limit))}});async function resumeWorkflow(e){let{client:t,workspaceId:n}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId});try{let{executionId:r}=await t.resumeWorkflowExecution({workspaceId:n,executionId:e.executionId});return{executionId:r,wait:i=>waitForWorkflowExecution({client:t,workspaceId:n,executionId:r,interval:e.interval??3e3,timeout:i?.timeout,until:i?.until,showProgress:i?.showProgress})}}catch(t){if(t instanceof q){if(t.code===K.NotFound)throw E({code:`WORKFLOW_EXECUTION_NOT_FOUND`,message:`Execution '${e.executionId}' not found.`,cause:t});if(t.code===K.FailedPrecondition)throw E({code:`WORKFLOW_EXECUTION_NOT_RESUMABLE`,message:`Execution '${e.executionId}' is not in a resumable state.`,cause:t})}throw t}}const zl=Y({name:`resume`,description:`Resume a failed or pending workflow execution.`,args:U.strictObject({...j,"execution-id":V(U.string(),{positional:!0,description:`Failed execution ID`}),...Wc}),run:async e=>{let t=C.jsonMode||e.json,{executionId:n,wait:r}=await resumeWorkflow({executionId:e.executionId,workspaceId:e[`workspace-id`],profile:e.profile,interval:he(e.interval)});if(t||C.info(`Execution ID: ${n}`,{mode:`stream`}),e.wait){let i=await r({showProgress:!t,timeout:he(e.timeout),until:e.until});if(e.logs&&!t){let{execution:t}=await getWorkflowExecution({executionId:n,workspaceId:e[`workspace-id`],profile:e.profile,logs:!0});printExecutionWithLogs(t)}else if(e.logs){let{execution:t}=await getWorkflowExecution({executionId:n,workspaceId:e[`workspace-id`],profile:e.profile,logs:!0});C.out({...i,jobDetails:t.jobDetails})}else C.out(i);let a=getWorkflowWaitFailure(i,e.until);if(a)throw a}else C.out({executionId:n})}});async function waitWorkflowExecution(e){return await waitForWorkflowExecutionById({...e,showProgress:e.showProgress??!C.jsonMode,trackJobs:e.trackJobs??!0})}async function addWorkflowLogsToWaitResult(e,t){let{execution:n}=await getWorkflowExecution({executionId:t.executionId,workspaceId:t.workspaceId,profile:t.profile,logs:!0});return{...e,jobDetails:n.jobDetails}}const Bl=Y({name:`wait`,description:`Wait for a workflow execution.`,examples:[{cmd:`execution-id --until success --timeout 10m --json`,desc:`Wait for workflow success`},{cmd:`execution-id --until suspended --timeout 6m --logs --json`,desc:`Wait for a workflow wait point`},{cmd:`execution-id --until terminal`,desc:`Wait for success, failure, or suspension`}],args:U.strictObject({...j,"execution-id":V(U.string(),{positional:!0,description:`Execution ID`}),...Uc}),run:async e=>{let t=C.jsonMode||e.json,n=await waitWorkflowExecution({executionId:e.executionId,workspaceId:e[`workspace-id`],profile:e.profile,interval:he(e.interval),timeout:he(e.timeout),until:e.until,showProgress:!t}),r=e.logs?await addWorkflowLogsToWaitResult(n,{executionId:e.executionId,workspaceId:e[`workspace-id`],profile:e.profile}):n;!t&&r.jobDetails?printExecutionWithLogs({id:r.id,workflowName:r.workflowName,status:r.status,jobExecutions:r.jobExecutions,startedAt:r.startedAt,finishedAt:r.finishedAt,jobDetails:r.jobDetails}):C.out(r);let i=getWorkflowWaitFailure(n,e.until);if(i)throw i}}),Vl={[kn.UNSPECIFIED]:`unknown`,[kn.OK]:`ok`,[kn.COMPOSITION_ERROR]:`composition_error`},Hl={[gn.UNSPECIFIED]:`unknown`,[gn.SUCCEEDED]:`success`,[gn.FAILED]:`failure`},statusToString=e=>protoEnumLookup(Vl,e,`unknown`),attemptStatusToString=e=>protoEnumLookup(Hl,e,`unknown`),appInfo=e=>({name:e.name,domain:e.domain,authNamespace:e.authNamespace,createdAt:formatTimestamp(e.createTime),updatedAt:formatTimestamp(e.updateTime)}),appHealthInfo=(e,t)=>{let n=t.lastSchemaUpdateAttempt;return{name:e,status:statusToString(t.status),currentServingSchemaUpdatedAt:formatTimestamp(t.currentServingSchemaUpdateTime),lastAttemptStatus:n?attemptStatusToString(n.status):`N/A`,lastAttemptAt:formatTimestamp(n?.attemptTime),lastAttemptError:n?.error??``}},Ul=U.object({workspaceId:U.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:U.string().optional(),name:U.string().min(1,{message:`name is required`})});async function loadOptions$9(e){let t=parseOptions(Ul,e),{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:t.profile,workspaceId:t.workspaceId});return{client:n,workspaceId:r,name:t.name}}async function getAppHealth(e){let{client:t,workspaceId:n,name:r}=await loadOptions$9(e),i=await t.getApplicationSchemaHealth({workspaceId:n,applicationName:r});return appHealthInfo(r,i)}const Wl=Y({name:`health`,description:`Check application schema health`,args:U.strictObject({...j,name:V(U.string(),{description:`Application name`,alias:`n`})}),run:async e=>{let t=await getAppHealth({workspaceId:e[`workspace-id`],profile:e.profile,name:e.name}),n=e.json?t:{...t,currentServingSchemaUpdatedAt:humanizeRelativeTime(t.currentServingSchemaUpdatedAt),lastAttemptAt:humanizeRelativeTime(t.lastAttemptAt)};C.out(n)}}),Gl=U.object({workspaceId:U.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:U.string().optional(),order:Te.optional(),limit:U.coerce.number().int().nonnegative().optional()});async function loadOptions$8(e){let t=parseOptions(Gl,e),{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:t.profile,workspaceId:t.workspaceId});return{client:n,workspaceId:r,order:t.order,limit:t.limit}}async function listApps(e){let{client:t,workspaceId:n,order:r,limit:i}=await loadOptions$8(e),a=Ce(r);return(await Mt(async(e,r)=>{let{applications:i,nextPageToken:o}=await t.listApplications({workspaceId:n,pageToken:e,pageSize:r,pageDirection:a});return[i,o]},{limit:i})).map(appInfo)}const Kl=Y({name:`list`,description:`List applications in a workspace`,args:U.strictObject({...j,...pe()}),run:async e=>{let t=C.jsonMode,n=await fetchWithinLimit(e.limit,t=>listApps({workspaceId:e[`workspace-id`],profile:e.profile,order:e.order,limit:t})),r=n.items,i=t?r:r.map(({updatedAt:e,createdAt:t,...n})=>({...n,createdAt:humanizeRelativeTime(t)}));C.out(i),await reportTruncation(n,e.limit)}});async function removeProfilesForWorkspaces(e){let t=await Oe(),n=Object.entries(t.profiles).filter(([,t])=>t?.workspace_id&&e.has(t.workspace_id)).map(([e])=>e);if(n.length===0)return n;for(let e of n)delete t.profiles[e];return ce(t),n}const ql=U.object({workspaceId:U.uuid({message:`workspace-id must be a valid UUID`})});async function loadOptions$7(e){let t=parseOptions(ql,e),n=await A();return{client:await N(n),workspaceId:t.workspaceId}}async function deleteWorkspace(e){let{client:t,workspaceId:n}=await loadOptions$7(e);await t.deleteWorkspace({workspaceId:n})}const Jl=Y({name:`delete`,description:`Delete a Tailor Platform workspace.`,args:U.strictObject({"workspace-id":V(U.string(),{alias:`w`,description:`Workspace ID`}),...se}),run:async e=>{await assertWritable();let{client:t,workspaceId:n}=await loadOptions$7({workspaceId:e[`workspace-id`]}),r;try{r=await t.getWorkspace({workspaceId:n})}catch(e){throw e instanceof q&&e.code===K.NotFound?E({code:`WORKSPACE_NOT_FOUND`,message:`Workspace "${n}" not found.`,cause:e}):e}let i=r.workspace,a=i?.name??n,o=workspaceDisplayName({name:a,folderName:i?await resolveWorkspaceFolderName(t,i):``});if(!e.yes){let e=await X.text({message:`Enter the workspace name to confirm deletion (${o}):`,suggestion:te});if(e!==a&&e!==o)throw E({code:`WORKSPACE_DELETION_CANCELLED`,message:`Workspace 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.deleteWorkspace({workspaceId:n})}catch(e){throw await removeProfilesForWorkspaces(/* @__PURE__ */ new Set([n])),e}let s=await removeProfilesForWorkspaces(/* @__PURE__ */ new Set([n]));s.length>0?C.success(`Workspace "${o}" and ${s.length} associated profile(s) deleted successfully.`):C.success(`Workspace "${o}" deleted successfully.`),printMutationResult({changed:!0,workspaceId:n,name:i?.name??null,removedProfiles:s})}}),Yl=U.object({workspaceId:U.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:U.string().optional()});async function loadOptions$6(e){let t=parseOptions(Yl,e),{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:t.profile,workspaceId:t.workspaceId});return{client:n,workspaceId:r}}async function getWorkspace(e){let{client:t,workspaceId:n}=await loadOptions$6(e),r=await t.getWorkspace({workspaceId:n});if(!r.workspace)throw E({code:`WORKSPACE_NOT_FOUND`,message:`Workspace "${n}" not found.`});let[i,a]=await Promise.all([workspaceDetailsWithFolderName(t,r.workspace),fetchWorkspaceExpiry(t,n,/* @__PURE__ */ new Date)]);return{...i,expiresAt:reportedExpiry(a)}}const Xl=Y({name:`get`,description:`Show detailed information about a workspace`,args:U.strictObject({...j}),run:async e=>{let t=await getWorkspace({workspaceId:e[`workspace-id`],profile:e.profile}),n=e.json?t:{...t,createdAt:humanizeRelativeTime(t.createdAt),updatedAt:humanizeRelativeTime(t.updatedAt)};C.out(n,{display:{name:Oc,folderName:null}})}}),Zl=U.object({workspaceId:U.uuid({message:`workspace-id must be a valid UUID`})});async function loadOptions$5(e){let t=parseOptions(Zl,e),n=await A();return{client:await N(n),workspaceId:t.workspaceId}}async function restoreWorkspace(e){let{client:t,workspaceId:n}=await loadOptions$5(e);await t.restoreWorkspace({workspaceId:n})}const Ql=Y({name:`restore`,description:`Restore a deleted workspace`,args:U.strictObject({"workspace-id":V(U.string(),{alias:`w`,description:`Workspace ID`}),...se}),run:async e=>{await assertWritable();let{client:t,workspaceId:n}=await loadOptions$5({workspaceId:e[`workspace-id`]});if(!e.yes&&await X.text({message:`Are you sure you want to restore workspace "${n}"? (yes/no):`,suggestion:`Pass --yes to skip the confirmation.`})!==`yes`)throw E({code:`WORKSPACE_RESTORATION_CANCELLED`,message:`Workspace restoration cancelled.`,suggestion:`Run the command again and type "yes" to confirm, or pass --yes to skip the confirmation.`});await t.restoreWorkspace({workspaceId:n}),C.success(`Workspace "${n}" restored successfully.`),printMutationResult({changed:!0,workspaceId:n})}}),$l=protoEnumNames(lr).filter(e=>e!==`UNSPECIFIED`).map(e=>e.toLowerCase()),roleToString=e=>{let t=protoEnumName(lr,e);return t===void 0||e===lr.UNSPECIFIED?`unknown`:t.toLowerCase()},stringToRole=e=>{let t=parseProtoEnumName(lr,e,[lr.UNSPECIFIED]);if(t===void 0)throw E({code:`WORKSPACE_ROLE_INVALID`,message:`Invalid role: ${e}. Valid roles: ${$l.join(`, `)}`});return t},userInfo=e=>({userId:e.platformUser?.userId??``,email:e.platformUser?.email??``,role:roleToString(e.role)}),eu=U.object({workspaceId:U.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:U.string().optional(),email:U.email({message:`email must be a valid email address`}),role:U.enum($l,{message:`role must be one of: ${$l.join(`, `)}`})});async function loadOptions$4(e){let t=parseOptions(eu,e),{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:t.profile,workspaceId:t.workspaceId});return{client:n,workspaceId:r,email:t.email,role:stringToRole(t.role)}}async function inviteUser(e){await inviteUserInWorkspace(e)}async function inviteUserInWorkspace(e){let{client:t,workspaceId:n,email:r,role:i}=await loadOptions$4(e);return await t.inviteWorkspacePlatformUser({workspaceId:n,email:r,role:i}),n}const tu=Y({name:`invite`,description:`Invite a user to a workspace`,args:U.strictObject({...j,email:V(U.email(),{description:`Email address of the user to invite`}),role:V(U.enum($l),{description:`Role to assign (${$l.join(`, `)})`,alias:`r`})}),run:async e=>{await assertWritable({profile:e.profile});let t=await inviteUserInWorkspace({workspaceId:e[`workspace-id`],profile:e.profile,email:e.email,role:e.role});C.success(`User "${e.email}" invited successfully with role "${e.role}".`),printMutationResult({changed:!0,workspaceId:t,email:e.email,role:e.role})}}),nu=U.object({workspaceId:U.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:U.string().optional(),order:Te.optional(),limit:U.coerce.number().int().nonnegative().optional()});async function loadOptions$3(e){let t=parseOptions(nu,e),{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:t.profile,workspaceId:t.workspaceId});return{client:n,workspaceId:r,order:t.order,limit:t.limit}}async function listUsers(e){let{client:t,workspaceId:n,order:r,limit:i}=await loadOptions$3(e),a=Ce(r);return(await Mt(async(e,r)=>{let{workspacePlatformUsers:i,nextPageToken:o}=await t.listWorkspacePlatformUsers({workspaceId:n,pageToken:e,pageSize:r,pageDirection:a});return[i,o]},{limit:i})).map(userInfo)}const ru=Y({name:`list`,description:`List users in a workspace`,args:U.strictObject({...j,...pe()}),run:async e=>{let t=await fetchWithinLimit(e.limit,t=>listUsers({workspaceId:e[`workspace-id`],profile:e.profile,order:e.order,limit:t})),n=t.items;C.out(n),await reportTruncation(t,e.limit)}}),iu=U.object({workspaceId:U.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:U.string().optional(),email:U.email({message:`email must be a valid email address`})});async function loadOptions$2(e){let t=parseOptions(iu,e),{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:t.profile,workspaceId:t.workspaceId});return{client:n,workspaceId:r,email:t.email}}async function removeUser(e){await removeUserFromWorkspace(e)}async function removeUserFromWorkspace(e){let{client:t,workspaceId:n,email:r}=await loadOptions$2(e);return await t.removeWorkspacePlatformUser({workspaceId:n,email:r}),n}const au=Y({name:`remove`,description:`Remove a user from a workspace`,args:U.strictObject({...j,email:V(U.email(),{description:`Email address of the user to remove`}),...se}),run:async e=>{if(await assertWritable({profile:e.profile}),!e.yes&&await X.text({message:`Are you sure you want to remove user "${e.email}" from the workspace? (yes/no):`,suggestion:`Pass --yes to skip the confirmation.`})!==`yes`)throw E({code:`WORKSPACE_USER_REMOVAL_CANCELLED`,message:`User removal cancelled.`,suggestion:`Run the command again and type "yes" to confirm, or pass --yes to skip the confirmation.`});let t=await removeUserFromWorkspace({workspaceId:e[`workspace-id`],profile:e.profile,email:e.email});C.success(`User "${e.email}" removed from workspace.`),printMutationResult({changed:!0,workspaceId:t,email:e.email})}}),ou=U.object({workspaceId:U.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:U.string().optional(),email:U.email({message:`email must be a valid email address`}),role:U.enum($l,{message:`role must be one of: ${$l.join(`, `)}`})});async function loadOptions$1(e){let t=parseOptions(ou,e),{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:t.profile,workspaceId:t.workspaceId});return{client:n,workspaceId:r,email:t.email,role:stringToRole(t.role)}}async function updateUser(e){await updateUserInWorkspace(e)}async function updateUserInWorkspace(e){let{client:t,workspaceId:n,email:r,role:i}=await loadOptions$1(e);return await t.updateWorkspacePlatformUser({workspaceId:n,email:r,role:i}),n}const su=Y({name:`update`,description:`Update a user's role in a workspace`,args:U.strictObject({...j,email:V(U.email(),{description:`Email address of the user to update`}),role:V(U.enum($l),{description:`New role to assign (${$l.join(`, `)})`,alias:`r`})}),run:async e=>{await assertWritable({profile:e.profile});let t=await updateUserInWorkspace({workspaceId:e[`workspace-id`],profile:e.profile,email:e.email,role:e.role});C.success(`User "${e.email}" updated to role "${e.role}".`),printMutationResult({changed:!0,workspaceId:t,email:e.email,role:e.role})}});function createSqlEntry(){return M`
|
|
1034
|
+
`);throw E({code:`MIGRATION_UNSUPPORTED_SCHEMA_CHANGE`,message:`Unsupported schema changes detected:\n${n}`})}if(t.hasBreakingChanges&&(C.newline(),C.warn(formatBreakingChanges(t.breakingChanges)),!r.yes)){if(!await X.confirm({message:`Continue generating migration?`,default:!0}))return C.info(`Skipped the migration for namespace "${t.namespace}".`),{declined:!0,migrations:[]};C.newline()}if(t.hasWarnings&&(C.newline(),C.warn(formatWarnings(t.warnings))),a.length>0)return{declined:!1,migrations:await generateExpandContractMigrations({previousSnapshot:e,currentSnapshot:i,resolvedDiff:t,plans:a,migrationsDir:n,description:r.name,temporal:o,dateDefault:s})};let u=await generateDiffFiles(t,n,getNextMigrationNumber(n),e,r.name,[],o,s);return C.success(`Generated migration ${h.bold(formatMigrationNumber(u.migrationNumber))}`),C.info(` Diff file: ${u.diffFilePath}`),u.migrateFilePath?(C.info(` Migration script: ${u.migrateFilePath}`),u.dbTypesFilePath&&(C.info(` DB types: ${u.dbTypesFilePath}`),logPgliteSchemaResult(u)),C.newline(),C.log(`A migration script was generated for breaking changes.`),C.log(`Please review and edit the script before running 'tailor deploy'.`),await openMigrationScriptInEditor(u.migrateFilePath)):t.hasWarnings&&await acknowledgeWarnings({namespace:t.namespace,migrationsDir:n,migrationNumber:u.migrationNumber,skipPrompt:r.yes,configPath:r.configPath}),{declined:!1,migrations:[u]}}async function generateExpandContractMigrations(e){let{previousSnapshot:t,currentSnapshot:n,resolvedDiff:r,plans:i,migrationsDir:a,description:o,temporal:s=!1,dateDefault:c=`legacy`}=e,l=buildIntermediateSnapshot(t,i),u=buildExpandDiff(t,l,i),d=r.changes.filter(e=>e.kind===`field_renamed`).map(({tableName:e,previousFieldName:t,fieldName:n})=>({tableName:e,previousFieldName:t,fieldName:n})),f=r.changes.filter(e=>e.kind===`table_renamed`).map(({previousTableName:e,tableName:t})=>({previousTableName:e,tableName:t})),p=compareSnapshots(l,n,{nestedMemberRenames:r.changes.flatMap(e=>e.kind===`field_modified`?(e.memberRenames??[]).map(t=>({tableName:e.tableName,fieldName:e.fieldName,...t})):[]),fieldRenames:[...d,...i.map(e=>({tableName:e.tableName,previousFieldName:e.tempFieldName,fieldName:e.fieldName}))],typeRenames:f}),m=getNextMigrationNumber(a),g=await generateDiffFiles(u,a,m,t,o,i,s,c),_=await generateDiffFiles(p,a,m+1,l,o,[],s,c,i),v=i.map(e=>`${e.tableName}.${e.fieldName}`).join(`, `);return C.success(`Generated migrations ${h.bold(formatMigrationNumber(g.migrationNumber))} and ${h.bold(formatMigrationNumber(_.migrationNumber))} to convert ${v}`),C.info(` Diff files: ${g.diffFilePath}, ${_.diffFilePath}`),g.migrateFilePath&&C.info(` Conversion script: ${g.migrateFilePath}`),_.migrateFilePath&&C.info(` Copy script: ${_.migrateFilePath}`),C.newline(),C.info(`Edit the conversion in ${formatMigrationNumber(g.migrationNumber)} before deploying. The copy script in ${formatMigrationNumber(_.migrationNumber)} is complete, though that migration also carries any other change in this run.`,{mode:`plain`}),C.info(`Both migrations are applied by 'tailor deploy'.`,{mode:`plain`}),[g,_]}async function acknowledgeWarnings(e){let{namespace:t,migrationsDir:n,migrationNumber:r,skipPrompt:i,configPath:a}=e,o=formatMigrationNumber(r);if(C.newline(),C.log(`Data loss is possible for this migration but no script was generated.`),!i&&canPrompt()&&await X.confirm({message:`Record a reason acknowledging that this migration intentionally has no script?`,default:!0})){let e=markMigrationScriptSkipped({migrationsDir:n,migrationNumber:r,reason:await X.text({message:`Reason:`,validate:e=>e.trim()!==``||`Reason must not be empty.`})});C.success(`Recorded that migration ${h.bold(o)} intentionally has no migration script`),C.info(` Reason: ${e.reason}`);return}let s={migrationNumber:r,namespace:t,configPath:a};C.log(`To add a custom migrate.ts, run:`),C.log(` ${h.bold(formatMigrationScriptHint(s))}`),C.log(`To record that this migration intentionally has no script, run:`),C.log(` ${h.bold(formatMigrationScriptHint({...s,noScript:!0}))}`)}const Hl=Y({name:`generate`,description:`Generate migration files by detecting schema differences between current local tables and the previous migration snapshot.`,args:U.strictObject({...se,...oe,name:V(U.string().optional(),{alias:`n`,description:`Optional description for the migration`}),init:V(U.boolean().default(!1),{description:`Delete existing migrations and start fresh (all namespaces with migrations configured, or only the one given by --namespace)`}),"data-only":V(U.boolean().default(!1),{description:`Create a migration with no schema changes whose migration script runs a standalone data transformation`}),namespace:V(U.string().optional(),{description:`Target TailorDB namespace for --data-only (required if multiple namespaces exist), or the only namespace --init resets`}),rename:V(U.array(U.string()).optional(),{description:`Record a field, table, or nested member rename instead of remove + add (format: "Table.oldField:newField", "OldTable:NewTable", or "Table.field.oldMember:newMember"; repeatable). Renames require a migration script that copies the data.`}),drop:V(U.array(U.string()).optional(),{description:`Confirm that a removed field, table, or nested member is a genuine removal, not a rename (format: "Table.field", "Table", or "Table.field.member"; repeatable). Required in non-interactive runs for a removal with rename candidates.`}),"expand-contract":V(U.array(U.string()).optional(),{description:`Convert a field type, or a single value into an array, through a temporary field (format: "Table.field"; repeatable). Generates two migrations.`})}),run:async e=>{printMutationResult(await generateMigrations({configPath:e.config,name:e.name,yes:e.yes,init:e.init,dataOnly:e[`data-only`],namespace:e.namespace,renames:e.rename,drops:e.drop,expandContracts:e[`expand-contract`]}))}});async function resolveTableNamespaces(e){let t=/* @__PURE__ */ new Map;for(let n of e.tableNames){let e=n.toLowerCase(),r=t.get(e);r?r.push(n):t.set(e,[n])}let n=new Set(e.tableNames),r=/* @__PURE__ */ new Map;for(let i of e.namespaces){if(n.size===0)break;let a=``;do{let{tailordbTypes:o,nextPageToken:s}=await e.client.listTailorDBTypes({workspaceId:e.workspaceId,namespaceName:i,pageToken:a,pageSize:Lt});for(let e of o){let a=t.get(e.name.toLowerCase());if(a)for(let e of a)r.has(e)||(r.set(e,i),n.delete(e))}a=s}while(a&&n.size>0)}return r}async function truncateSingleType(e,t){await t.truncateTailorDBType({workspaceId:e.workspaceId,namespaceName:e.namespaceName,tailordbTypeName:e.tableName}),C.success(`Truncated table "${e.tableName}" in namespace "${e.namespaceName}"`)}async function truncateNamespace(e,t,n){await n.truncateTailorDBTypes({workspaceId:e,namespaceName:t}),C.success(`Truncated all tables in namespace "${t}"`)}async function truncate(e){await $truncate({...e,yes:!0})}async function $truncate(e={}){let{client:t,workspaceId:n}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId}),r=e.tables&&e.tables.length>0,i=!!e.namespace,o=!!e.all,s=[o,i,r].filter(Boolean).length;if(s===0)throw E({code:`TRUNCATE_TARGET_REQUIRED`,message:`Please specify one of: --all, --namespace <name>, or table names`,command:`tailordb truncate`});if(s>1)throw E({code:`TRUNCATE_OPTIONS_CONFLICT`,message:`Options --all, --namespace, and table names are mutually exclusive. Please specify only one.`,command:`tailordb truncate`});let{config:c}=await loadConfig(e.configPath),l=extractOwnedNamespaces(c);if(o){if(l.length===0)return C.warn(`No namespaces found in config file.`),{changed:!1,workspaceId:n,namespaces:[],tables:[]};if(!e.yes){let e=l.join(`, `);if(!await X.confirm({message:`This will truncate ALL tables in the following owned namespaces (external namespaces are excluded): ${e}. Continue?`,default:!1}))throw E({code:`TRUNCATE_CANCELLED`,message:`Truncate cancelled.`})}for(let e of l)await truncateNamespace(n,e,t);return C.success(`Truncated all tables in all owned namespaces`),{changed:!0,workspaceId:n,namespaces:l,tables:[]}}if(i){let r=a(e.namespace,`namespace option missing`);if(!l.includes(r)){let e=c.db?.[r];throw e&&`external`in e?E({code:`TAILORDB_NAMESPACE_EXTERNAL`,message:`Namespace "${r}" is declared as external in this app's config and cannot be truncated from here.`,suggestion:`Run truncate from the app that owns the namespace.`}):E({code:`TAILORDB_NAMESPACE_NOT_FOUND`,message:`Namespace "${r}" not found in config. Available owned namespaces (external namespaces are excluded): ${l.join(`, `)}`})}if(!e.yes&&!await X.confirm({message:`This will truncate ALL tables in namespace "${r}". Continue?`,default:!1}))throw E({code:`TRUNCATE_CANCELLED`,message:`Truncate cancelled.`});return await truncateNamespace(n,r,t),{changed:!0,workspaceId:n,namespaces:[r],tables:[]}}let u=[];if(r){let r=a(e.tables,`tables option missing`),i=await resolveTableNamespaces({workspaceId:n,namespaces:l,tableNames:r,client:t}),o=r.filter(e=>!i.has(e));if(o.length>0)throw E({code:`TAILORDB_TABLE_NOT_FOUND`,message:`The following tables were not found in any namespace: ${o.join(`, `)}`});if(!e.yes){let e=r.join(`, `);if(!await X.confirm({message:`This will truncate the following tables: ${e}. Continue?`,default:!1}))throw E({code:`TRUNCATE_CANCELLED`,message:`Truncate cancelled.`})}for(let e of r){let r=i.get(e);r&&(await truncateSingleType({workspaceId:n,namespaceName:r,tableName:e},t),u.push({namespace:r,name:e}))}}return{changed:u.length>0,workspaceId:n,namespaces:[],tables:u}}const Ul=Y({name:`truncate`,description:`Truncate (delete all records from) TailorDB tables.`,args:U.strictObject({...O,...se,tables:V(U.string().array().optional(),{positional:{named:!0},description:`Table names to truncate`}),all:V(U.boolean().default(!1),{alias:`a`,description:`Truncate all tables in all owned namespaces (excludes external namespaces)`}),namespace:V(U.string().optional(),{alias:`n`,description:`Truncate all tables in specified namespace`})}),run:async e=>{await assertWritable({profile:e.profile});let t=e.tables&&e.tables.length>0?e.tables:void 0;printMutationResult(await $truncate({workspaceId:e[`workspace-id`],profile:e.profile,configPath:e.config,all:e.all,namespace:e.namespace,tables:t,yes:e.yes}))}});async function listWorkflows(e){let{client:t,workspaceId:n}=await loadOperatorWorkspaceContext({profile:e?.profile,workspaceId:e?.workspaceId}),r=Ce(e?.order);return(await Pt(async(e,i)=>{let{workflows:a,nextPageToken:o}=await t.listWorkflows({workspaceId:n,pageToken:e,pageSize:i,pageDirection:r});return[a,o]},{limit:e?.limit})).map(toWorkflowListInfo)}const Wl=Y({name:`list`,description:`List all workflows in the workspace.`,args:U.strictObject({...j,...pe()}),run:async e=>{let t=C.jsonMode,n=await fetchWithinLimit(e.limit,t=>listWorkflows({workspaceId:e[`workspace-id`],profile:e.profile,order:e.order,limit:t})),r=n.items;r.length===0&&(C.info(`No workflows found.`),!t)||(C.out(r),await reportTruncation(n,e.limit))}});async function resumeWorkflow(e){let{client:t,workspaceId:n}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId});try{let{executionId:r}=await t.resumeWorkflowExecution({workspaceId:n,executionId:e.executionId});return{executionId:r,wait:i=>waitForWorkflowExecution({client:t,workspaceId:n,executionId:r,interval:e.interval??3e3,timeout:i?.timeout,until:i?.until,showProgress:i?.showProgress})}}catch(t){if(t instanceof q){if(t.code===K.NotFound)throw E({code:`WORKFLOW_EXECUTION_NOT_FOUND`,message:`Execution '${e.executionId}' not found.`,cause:t});if(t.code===K.FailedPrecondition)throw E({code:`WORKFLOW_EXECUTION_NOT_RESUMABLE`,message:`Execution '${e.executionId}' is not in a resumable state.`,cause:t})}throw t}}const Gl=Y({name:`resume`,description:`Resume a failed or pending workflow execution.`,args:U.strictObject({...j,"execution-id":V(U.string(),{positional:!0,description:`Failed execution ID`}),...Xc}),run:async e=>{let t=C.jsonMode||e.json,{executionId:n,wait:r}=await resumeWorkflow({executionId:e.executionId,workspaceId:e[`workspace-id`],profile:e.profile,interval:he(e.interval)});if(t||C.info(`Execution ID: ${n}`,{mode:`stream`}),e.wait){let i=await r({showProgress:!t,timeout:he(e.timeout),until:e.until});if(e.logs&&!t){let{execution:t}=await getWorkflowExecution({executionId:n,workspaceId:e[`workspace-id`],profile:e.profile,logs:!0});printExecutionWithLogs(t)}else if(e.logs){let{execution:t}=await getWorkflowExecution({executionId:n,workspaceId:e[`workspace-id`],profile:e.profile,logs:!0});C.out({...i,jobDetails:t.jobDetails})}else C.out(i);let a=getWorkflowWaitFailure(i,e.until);if(a)throw a}else C.out({executionId:n})}});async function waitWorkflowExecution(e){return await waitForWorkflowExecutionById({...e,showProgress:e.showProgress??!C.jsonMode,trackJobs:e.trackJobs??!0})}async function addWorkflowLogsToWaitResult(e,t){let{execution:n}=await getWorkflowExecution({executionId:t.executionId,workspaceId:t.workspaceId,profile:t.profile,logs:!0});return{...e,jobDetails:n.jobDetails}}const Kl=Y({name:`wait`,description:`Wait for a workflow execution.`,examples:[{cmd:`execution-id --until success --timeout 10m --json`,desc:`Wait for workflow success`},{cmd:`execution-id --until suspended --timeout 6m --logs --json`,desc:`Wait for a workflow wait point`},{cmd:`execution-id --until terminal`,desc:`Wait for success, failure, or suspension`}],args:U.strictObject({...j,"execution-id":V(U.string(),{positional:!0,description:`Execution ID`}),...Yc}),run:async e=>{let t=C.jsonMode||e.json,n=await waitWorkflowExecution({executionId:e.executionId,workspaceId:e[`workspace-id`],profile:e.profile,interval:he(e.interval),timeout:he(e.timeout),until:e.until,showProgress:!t}),r=e.logs?await addWorkflowLogsToWaitResult(n,{executionId:e.executionId,workspaceId:e[`workspace-id`],profile:e.profile}):n;!t&&r.jobDetails?printExecutionWithLogs({id:r.id,workflowName:r.workflowName,status:r.status,jobExecutions:r.jobExecutions,startedAt:r.startedAt,finishedAt:r.finishedAt,jobDetails:r.jobDetails}):C.out(r);let i=getWorkflowWaitFailure(n,e.until);if(i)throw i}}),ql={[Mn.UNSPECIFIED]:`unknown`,[Mn.OK]:`ok`,[Mn.COMPOSITION_ERROR]:`composition_error`},Jl={[yn.UNSPECIFIED]:`unknown`,[yn.SUCCEEDED]:`success`,[yn.FAILED]:`failure`},statusToString=e=>protoEnumLookup(ql,e,`unknown`),attemptStatusToString=e=>protoEnumLookup(Jl,e,`unknown`),appInfo=e=>({name:e.name,domain:e.domain,authNamespace:e.authNamespace,createdAt:formatTimestamp(e.createTime),updatedAt:formatTimestamp(e.updateTime)}),appHealthInfo=(e,t)=>{let n=t.lastSchemaUpdateAttempt;return{name:e,status:statusToString(t.status),currentServingSchemaUpdatedAt:formatTimestamp(t.currentServingSchemaUpdateTime),lastAttemptStatus:n?attemptStatusToString(n.status):`N/A`,lastAttemptAt:formatTimestamp(n?.attemptTime),lastAttemptError:n?.error??``}},Yl=U.object({workspaceId:U.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:U.string().optional(),name:U.string().min(1,{message:`name is required`})});async function loadOptions$9(e){let t=parseOptions(Yl,e),{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:t.profile,workspaceId:t.workspaceId});return{client:n,workspaceId:r,name:t.name}}async function getAppHealth(e){let{client:t,workspaceId:n,name:r}=await loadOptions$9(e),i=await t.getApplicationSchemaHealth({workspaceId:n,applicationName:r});return appHealthInfo(r,i)}const Xl=Y({name:`health`,description:`Check application schema health`,args:U.strictObject({...j,name:V(U.string(),{description:`Application name`,alias:`n`})}),run:async e=>{let t=await getAppHealth({workspaceId:e[`workspace-id`],profile:e.profile,name:e.name}),n=e.json?t:{...t,currentServingSchemaUpdatedAt:humanizeRelativeTime(t.currentServingSchemaUpdatedAt),lastAttemptAt:humanizeRelativeTime(t.lastAttemptAt)};C.out(n)}}),Zl=U.object({workspaceId:U.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:U.string().optional(),order:Te.optional(),limit:U.coerce.number().int().nonnegative().optional()});async function loadOptions$8(e){let t=parseOptions(Zl,e),{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:t.profile,workspaceId:t.workspaceId});return{client:n,workspaceId:r,order:t.order,limit:t.limit}}async function listApps(e){let{client:t,workspaceId:n,order:r,limit:i}=await loadOptions$8(e),a=Ce(r);return(await Pt(async(e,r)=>{let{applications:i,nextPageToken:o}=await t.listApplications({workspaceId:n,pageToken:e,pageSize:r,pageDirection:a});return[i,o]},{limit:i})).map(appInfo)}const Ql=Y({name:`list`,description:`List applications in a workspace`,args:U.strictObject({...j,...pe()}),run:async e=>{let t=C.jsonMode,n=await fetchWithinLimit(e.limit,t=>listApps({workspaceId:e[`workspace-id`],profile:e.profile,order:e.order,limit:t})),r=n.items,i=t?r:r.map(({updatedAt:e,createdAt:t,...n})=>({...n,createdAt:humanizeRelativeTime(t)}));C.out(i),await reportTruncation(n,e.limit)}});async function removeProfilesForWorkspaces(e){let t=await Oe(),n=Object.entries(t.profiles).filter(([,t])=>t?.workspace_id&&e.has(t.workspace_id)).map(([e])=>e);if(n.length===0)return n;for(let e of n)delete t.profiles[e];return ce(t),n}const $l=U.object({workspaceId:U.uuid({message:`workspace-id must be a valid UUID`})});async function loadOptions$7(e){let t=parseOptions($l,e),n=await A();return{client:await N(n),workspaceId:t.workspaceId}}async function deleteWorkspace(e){let{client:t,workspaceId:n}=await loadOptions$7(e);await t.deleteWorkspace({workspaceId:n})}const eu=Y({name:`delete`,description:`Delete a Tailor Platform workspace.`,args:U.strictObject({"workspace-id":V(U.string(),{alias:`w`,description:`Workspace ID`}),...se}),run:async e=>{await assertWritable();let{client:t,workspaceId:n}=await loadOptions$7({workspaceId:e[`workspace-id`]}),r;try{r=await t.getWorkspace({workspaceId:n})}catch(e){throw e instanceof q&&e.code===K.NotFound?E({code:`WORKSPACE_NOT_FOUND`,message:`Workspace "${n}" not found.`,cause:e}):e}let i=r.workspace,a=i?.name??n,o=workspaceDisplayName({name:a,folderName:i?await resolveWorkspaceFolderName(t,i):``});if(!e.yes){let e=await X.text({message:`Enter the workspace name to confirm deletion (${o}):`,suggestion:ne});if(e!==a&&e!==o)throw E({code:`WORKSPACE_DELETION_CANCELLED`,message:`Workspace 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.deleteWorkspace({workspaceId:n})}catch(e){throw await removeProfilesForWorkspaces(/* @__PURE__ */ new Set([n])),e}let s=await removeProfilesForWorkspaces(/* @__PURE__ */ new Set([n]));s.length>0?C.success(`Workspace "${o}" and ${s.length} associated profile(s) deleted successfully.`):C.success(`Workspace "${o}" deleted successfully.`),printMutationResult({changed:!0,workspaceId:n,name:i?.name??null,removedProfiles:s})}}),tu=U.object({workspaceId:U.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:U.string().optional()});async function loadOptions$6(e){let t=parseOptions(tu,e),{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:t.profile,workspaceId:t.workspaceId});return{client:n,workspaceId:r}}async function getWorkspace(e){let{client:t,workspaceId:n}=await loadOptions$6(e),r=await t.getWorkspace({workspaceId:n});if(!r.workspace)throw E({code:`WORKSPACE_NOT_FOUND`,message:`Workspace "${n}" not found.`});let[i,a]=await Promise.all([workspaceDetailsWithFolderName(t,r.workspace),fetchWorkspaceExpiry(t,n,/* @__PURE__ */ new Date)]);return{...i,expiresAt:reportedExpiry(a)}}const nu=Y({name:`get`,description:`Show detailed information about a workspace`,args:U.strictObject({...j}),run:async e=>{let t=await getWorkspace({workspaceId:e[`workspace-id`],profile:e.profile}),n=e.json?t:{...t,createdAt:humanizeRelativeTime(t.createdAt),updatedAt:humanizeRelativeTime(t.updatedAt)};C.out(n,{display:{name:Nc,folderName:null}})}}),ru=U.object({workspaceId:U.uuid({message:`workspace-id must be a valid UUID`})});async function loadOptions$5(e){let t=parseOptions(ru,e),n=await A();return{client:await N(n),workspaceId:t.workspaceId}}async function restoreWorkspace(e){let{client:t,workspaceId:n}=await loadOptions$5(e);await t.restoreWorkspace({workspaceId:n})}const iu=Y({name:`restore`,description:`Restore a deleted workspace`,args:U.strictObject({"workspace-id":V(U.string(),{alias:`w`,description:`Workspace ID`}),...se}),run:async e=>{await assertWritable();let{client:t,workspaceId:n}=await loadOptions$5({workspaceId:e[`workspace-id`]});if(!e.yes&&await X.text({message:`Are you sure you want to restore workspace "${n}"? (yes/no):`,suggestion:`Pass --yes to skip the confirmation.`})!==`yes`)throw E({code:`WORKSPACE_RESTORATION_CANCELLED`,message:`Workspace restoration cancelled.`,suggestion:`Run the command again and type "yes" to confirm, or pass --yes to skip the confirmation.`});await t.restoreWorkspace({workspaceId:n}),C.success(`Workspace "${n}" restored successfully.`),printMutationResult({changed:!0,workspaceId:n})}}),au=protoEnumNames(fr).filter(e=>e!==`UNSPECIFIED`).map(e=>e.toLowerCase()),roleToString=e=>{let t=protoEnumName(fr,e);return t===void 0||e===fr.UNSPECIFIED?`unknown`:t.toLowerCase()},stringToRole=e=>{let t=parseProtoEnumName(fr,e,[fr.UNSPECIFIED]);if(t===void 0)throw E({code:`WORKSPACE_ROLE_INVALID`,message:`Invalid role: ${e}. Valid roles: ${au.join(`, `)}`});return t},userInfo=e=>({userId:e.platformUser?.userId??``,email:e.platformUser?.email??``,role:roleToString(e.role)}),ou=U.object({workspaceId:U.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:U.string().optional(),email:U.email({message:`email must be a valid email address`}),role:U.enum(au,{message:`role must be one of: ${au.join(`, `)}`})});async function loadOptions$4(e){let t=parseOptions(ou,e),{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:t.profile,workspaceId:t.workspaceId});return{client:n,workspaceId:r,email:t.email,role:stringToRole(t.role)}}async function inviteUser(e){await inviteUserInWorkspace(e)}async function inviteUserInWorkspace(e){let{client:t,workspaceId:n,email:r,role:i}=await loadOptions$4(e);return await t.inviteWorkspacePlatformUser({workspaceId:n,email:r,role:i}),n}const su=Y({name:`invite`,description:`Invite a user to a workspace`,args:U.strictObject({...j,email:V(U.email(),{description:`Email address of the user to invite`}),role:V(U.enum(au),{description:`Role to assign (${au.join(`, `)})`,alias:`r`})}),run:async e=>{await assertWritable({profile:e.profile});let t=await inviteUserInWorkspace({workspaceId:e[`workspace-id`],profile:e.profile,email:e.email,role:e.role});C.success(`User "${e.email}" invited successfully with role "${e.role}".`),printMutationResult({changed:!0,workspaceId:t,email:e.email,role:e.role})}}),cu=U.object({workspaceId:U.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:U.string().optional(),order:Te.optional(),limit:U.coerce.number().int().nonnegative().optional()});async function loadOptions$3(e){let t=parseOptions(cu,e),{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:t.profile,workspaceId:t.workspaceId});return{client:n,workspaceId:r,order:t.order,limit:t.limit}}async function listUsers(e){let{client:t,workspaceId:n,order:r,limit:i}=await loadOptions$3(e),a=Ce(r);return(await Pt(async(e,r)=>{let{workspacePlatformUsers:i,nextPageToken:o}=await t.listWorkspacePlatformUsers({workspaceId:n,pageToken:e,pageSize:r,pageDirection:a});return[i,o]},{limit:i})).map(userInfo)}const lu=Y({name:`list`,description:`List users in a workspace`,args:U.strictObject({...j,...pe()}),run:async e=>{let t=await fetchWithinLimit(e.limit,t=>listUsers({workspaceId:e[`workspace-id`],profile:e.profile,order:e.order,limit:t})),n=t.items;C.out(n),await reportTruncation(t,e.limit)}}),uu=U.object({workspaceId:U.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:U.string().optional(),email:U.email({message:`email must be a valid email address`})});async function loadOptions$2(e){let t=parseOptions(uu,e),{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:t.profile,workspaceId:t.workspaceId});return{client:n,workspaceId:r,email:t.email}}async function removeUser(e){await removeUserFromWorkspace(e)}async function removeUserFromWorkspace(e){let{client:t,workspaceId:n,email:r}=await loadOptions$2(e);return await t.removeWorkspacePlatformUser({workspaceId:n,email:r}),n}const du=Y({name:`remove`,description:`Remove a user from a workspace`,args:U.strictObject({...j,email:V(U.email(),{description:`Email address of the user to remove`}),...se}),run:async e=>{if(await assertWritable({profile:e.profile}),!e.yes&&await X.text({message:`Are you sure you want to remove user "${e.email}" from the workspace? (yes/no):`,suggestion:`Pass --yes to skip the confirmation.`})!==`yes`)throw E({code:`WORKSPACE_USER_REMOVAL_CANCELLED`,message:`User removal cancelled.`,suggestion:`Run the command again and type "yes" to confirm, or pass --yes to skip the confirmation.`});let t=await removeUserFromWorkspace({workspaceId:e[`workspace-id`],profile:e.profile,email:e.email});C.success(`User "${e.email}" removed from workspace.`),printMutationResult({changed:!0,workspaceId:t,email:e.email})}}),fu=U.object({workspaceId:U.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:U.string().optional(),email:U.email({message:`email must be a valid email address`}),role:U.enum(au,{message:`role must be one of: ${au.join(`, `)}`})});async function loadOptions$1(e){let t=parseOptions(fu,e),{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:t.profile,workspaceId:t.workspaceId});return{client:n,workspaceId:r,email:t.email,role:stringToRole(t.role)}}async function updateUser(e){await updateUserInWorkspace(e)}async function updateUserInWorkspace(e){let{client:t,workspaceId:n,email:r,role:i}=await loadOptions$1(e);return await t.updateWorkspacePlatformUser({workspaceId:n,email:r,role:i}),n}const pu=Y({name:`update`,description:`Update a user's role in a workspace`,args:U.strictObject({...j,email:V(U.email(),{description:`Email address of the user to update`}),role:V(U.enum(au),{description:`New role to assign (${au.join(`, `)})`,alias:`r`})}),run:async e=>{await assertWritable({profile:e.profile});let t=await updateUserInWorkspace({workspaceId:e[`workspace-id`],profile:e.profile,email:e.email,role:e.role});C.success(`User "${e.email}" updated to role "${e.role}".`),printMutationResult({changed:!0,workspaceId:t,email:e.email,role:e.role})}});function createSqlEntry(){return M`
|
|
1029
1035
|
import { Kysely, sql, TailordbDialect } from "@tailor-platform/sdk/kysely";
|
|
1030
1036
|
|
|
1031
1037
|
type QueryInput = {
|
|
@@ -1046,7 +1052,12 @@ This is the baseline schema. Future changes will be tracked as diffs.`),{namespa
|
|
|
1046
1052
|
for (const query of input.queries) {
|
|
1047
1053
|
const result = await sql.raw(query).execute(db);
|
|
1048
1054
|
const rows = result.rows ?? [];
|
|
1049
|
-
|
|
1055
|
+
if (result.numAffectedRows === undefined) {
|
|
1056
|
+
results.push({ rows, rowCount: rows.length });
|
|
1057
|
+
} else {
|
|
1058
|
+
const affectedRows = Number(result.numAffectedRows);
|
|
1059
|
+
results.push({ rows, rowCount: affectedRows, affectedRows });
|
|
1060
|
+
}
|
|
1050
1061
|
}
|
|
1051
1062
|
if (results.length === 1) {
|
|
1052
1063
|
return results[0];
|
|
@@ -1087,8 +1098,8 @@ This is the baseline schema. Future changes will be tracked as diffs.`),{namespa
|
|
|
1087
1098
|
const json = await response.json();
|
|
1088
1099
|
return json;
|
|
1089
1100
|
}
|
|
1090
|
-
`}async function bundleQueryScript(e,t){let n=H.resolve(
|
|
1091
|
-
`).at(0)?.trim();return E({code:`invalid_sql`,message:`SQL parse error.`,suggestion:e??`The SQL query contains unsupported syntax.`})}return e.error instanceof Error?e.error:Error(t)}function isGraphQLInputComplete(e){if(e.trim().length===0)return!1;try{return
|
|
1092
|
-
`&&(r=!1);else if(i>0){if(l===`/`&&u===`*`){i+=1,c+=1;continue}l===`*`&&u===`/`&&(--i,c+=1)}else if(o!=null)e.startsWith(o,c)&&(c+=o.length-1,o=null);else if(t){if(l===`'`&&u===`'`){c+=1;continue}l===`'`&&(t=!1)}else if(n){if(l===`"`&&u===`"`){c+=1;continue}l===`"`&&(n=!1)}else if(l===`-`&&u===`-`)r=!0,c+=1;else if(l===`/`&&u===`*`)i=1,c+=1;else if(l===`'`)s=!1,t=!0;else if(l===`"`)s=!1,n=!0;else{if(l===`$`){let t=e.slice(c),n=t.match(/^\$[A-Za-z_][A-Za-z0-9_]*\$/)??t.match(/^\$\$/);if(n!=null){s=!1,o=n[0],c+=n[0].length-1;continue}}l===`;`?s=!0:/\s/.test(l)||(s=!1)}}return s&&!t&&!n&&i===0&&o==null}function extractTableNamesFromSql(e){let t;try{t=Hi(e)}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`SQL parse error: ${t}\nIf your table name is a reserved keyword (e.g. User), wrap it in double quotes: SELECT * FROM "User"`,{cause:e})}let n=/* @__PURE__ */ new Set,r=Vi(e=>({tableRef:t=>(n.add(t.name),e.super().tableRef(t),t)}));for(let e of t)r.statement(e);return[...n]}function collectAliasMap(e){let t=/* @__PURE__ */ new Map;for(let n of e)if(n.type===`table`){let e=n.name.name,r=n.name.alias??e;t.set(r,e)}return t}function extractColumnTemplate(e){try{let t=Hi(e);for(let e of t){if(e.type!==`select`||!e.columns)continue;let t=collectAliasMap(e.from??[]),n=[],r=!1;for(let i of e.columns)if(i.expr.type===`ref`&&i.expr.name===`*`){if(r=!0,i.expr.table){let e=t.get(i.expr.table.name);n.push({type:`wildcard`,tableNames:e?[e]:[]})}else n.push({type:`wildcard`,tableNames:[...new Set(t.values())]})}else{let e=i.alias?.name??(i.expr.type===`ref`?i.expr.name:null);e&&n.push({type:`explicit`,name:e})}return r?n:null}return null}catch{return null}}async function loadTypeFieldOrder(e,t){let n=/* @__PURE__ */ new Map,r=e.db?.[t];if(!r||!(`files`in r)||r.files.length===0)return n;let i=H.dirname(e.path),a=gt(r,i);return await Promise.all(a.map(async e=>{try{let t=await import(ci(e).href);for(let e of Object.values(t)){let t=vt.safeParse(yt(e));t.success&&n.set(t.data.name,Object.keys(t.data.fields))}}catch{}})),n}const cu=U.enum([`sql`,`gql`]),lu=U.object({workspaceId:U.string().optional(),profile:U.string().optional(),configPath:U.string().optional(),engine:cu,machineUser:U.string().optional(),machineUserSource:U.enum([`option`,`env`]).optional()}),uu=lu.extend({query:U.string()});async function getNamespaceFromSqlQuery(e,t,n,r){if(r.length===0)throw Error(`No namespaces found in configuration.`);if(r.length===1)return a(r[0],`namespace missing`);let i=extractTableNamesFromSql(t);if(i.length===0)throw Error(`Could not infer namespace from query. Detected namespaces: ${r.join(`, `)}.`);let o=await resolveTableNamespaces({workspaceId:e,namespaces:r,tableNames:i,client:n}),s=i.filter(e=>!o.has(e));if(s.length>0)throw Error(`Could not find namespace for tables in query: ${s.join(`, `)}.`);let c=new Set(o.values());if(c.size===1)return a([...c][0],`namespace from types missing`);throw Error(`Query references tables from multiple namespaces: ${[...c].join(`, `)}.`)}async function loadOptions(e){let t=parseOptions(lu,e),n=await be({machineUser:t.machineUser,machineUserSource:t.machineUserSource,profile:t.profile});if(!n)throw Error(`Machine user is required. Specify --machine-user, set TAILOR_PLATFORM_MACHINE_USER_NAME, or set a profile default with 'tailor profile update <profile> --machine-user <name>'.`);let r=await A({profile:t.profile}),i=await N(r),a=await xe({workspaceId:t.workspaceId,profile:t.profile}),{config:o}=await loadConfig(e.configPath),s=extractAllNamespaces(o),{application:c}=await i.getApplication({workspaceId:a,applicationName:o.name});if(!c?.authNamespace)throw Error(`Application ${o.name} does not have an auth configuration.`);let{machineUser:l}=await i.getAuthMachineUser({workspaceId:a,authNamespace:c.authNamespace,name:n});if(!l)throw Error(`Machine user ${n} not found.`);return{engine:t.engine,client:i,workspaceId:a,config:o,application:c,machineUserResource:l,namespaces:s}}async function sqlQuery(e,t,n){let r=splitSqlStatements(n.query),i=await executeScript({client:e,workspaceId:n.workspaceId,name:`query-sql-${n.namespace}.js`,code:n.bundledCode,arg:{namespace:n.namespace,queries:r},invoker:t});if(!i.success)throw Error(i.error);return{engine:`sql`,namespace:n.namespace,query:n.query,result:parseExecutionResult(i.result)}}async function gqlQuery(e,t,n,r,i){let{access_token:a}=await Pt(n.url,r.clientId,r.clientSecret),o=await executeScript({client:e,workspaceId:i.workspaceId,name:`query-gql.js`,code:i.bundledCode,arg:{endpoint:`${n.url}/query`,accessToken:a,query:i.query},invoker:t});if(!o.success)throw Error(o.error);return{engine:`gql`,query:i.query,result:parseExecutionResult(o.result)}}function parseExecutionResult(e){if(!e)return null;try{return JSON.parse(e)}catch{return e}}async function resolveQueryCommandInput(e){return e.query==null?e.file==null?e.edit?await resolveEditedQueryInput(e.engine):{mode:`repl`}:{mode:`query`,query:await J.readFile(e.file,`utf-8`)}:{mode:`query`,query:e.query}}async function resolveEditedQueryInput(e){if(!process.stdin.isTTY||!process.stdout.isTTY)throw Error(`Non-interactive terminals are not supported. Pass -q/--query or -f/--file to run a query.`);let t=getEditorCommand(),n=await J.mkdtemp(H.join(hi(),`tailor-query-`)),r=e===`sql`?`sql`:`graphql`,i=H.join(n,`query.${r}`);try{await J.writeFile(i,``,`utf-8`);try{await openInEditor(i,t)}catch(e){throw Error(`Failed to open query editor "${t}": ${e instanceof Error?e.message:String(e)}`,{cause:e})}let e=await J.readFile(i,`utf-8`);return e.trim().length===0||e===``?{mode:`abort`}:{mode:`query`,query:e}}finally{await J.rm(n,{recursive:!0,force:!0})}}async function query(e){let t=parseOptions(uu,e);return await(await prepareQueryExecutor(t))(t.query)}async function prepareQueryExecutor(e){let{client:t,workspaceId:n,config:r,application:i,machineUserResource:a,engine:o,namespaces:s}=await loadOptions(e),c=await bundleQueryScript(o,H.dirname(r.path)),l=Kr(un,{namespace:i.authNamespace,machineUserName:a.name});return async e=>{let u;try{switch(o){case`sql`:return u=await getNamespaceFromSqlQuery(n,e,t,s),reorderSqlColumns(await sqlQuery(t,l,{workspaceId:n,namespace:u,bundledCode:c,query:e}),r,u,e);case`gql`:return await gqlQuery(t,l,i,a,{workspaceId:n,bundledCode:c,query:e});default:throw Error(`Unsupported query engine: ${o}`)}}catch(e){throw mapQueryExecutionError({error:e,engine:o,namespace:u,machineUser:a.name})}}}function resolveReplCommand(e){let t=e.trim();return t.startsWith(`\\`)?t===`\\q`||t===`\\quit`?`quit`:t===`\\help`||t===`\\h`||t===`\\?`?`help`:t===`\\clear`||t===`\\c`?`clear`:`unknown`:null}function clearReplScreen(){process.stdout.write(`\x1Bc`)}function sanitizeHistoryScope(e){return e.replace(/[^a-zA-Z0-9._-]/g,`_`)}function getReplHistoryPath(e,t,n){if(!ui)return;let r=[t,n].filter(e=>!!e).map(sanitizeHistoryScope).join(`-`),i=e===`sql`?`sql`:`gql`,a=r?`-${r}`:``;return H.join(ui,`tailor-platform`,`query-history-${i}${a}.json`)}function createReplValidator(e){return t=>{let n=t.trim();if(n!==``&&resolveReplCommand(n)===null)return e===`sql`?isSqlInputComplete(t)?void 0:`SQL statement is incomplete (missing ';').`:isGraphQLInputComplete(t)?void 0:`GraphQL document is incomplete.`}}async function runRepl(e){if(!process.stdin.isTTY||!process.stdout.isTTY)throw Error(`Non-interactive terminals are not supported. Pass -q/--query or -f/--file to run a query.`);let t=await prepareQueryExecutor(e),n=getReplHistoryPath(e.engine,e.profile,e.workspaceId),r=createReplValidator(e.engine),{highlightSqlLines:i,highlightGraphqlLines:a,replTransform:o}=await import(`./repl-editor-Bposemei.mjs`),s=e.engine===`sql`?i:a,c=Bi({prefix:``,preferNewlineOnEnter:e.newlineOnEnter,validate:r,highlightLines:s,transform:o,theme:{submitRender:`preserve`},history:n?{filePath:n,maxEntries:100}:[],helpFooter:{items:[`submit`,`newline`],maxLines:1}});for(C.info(`Entering ${e.engine.toUpperCase()} REPL mode.`),C.info(`Type \\help for usage, \\q to quit.`);;){let[n,r]=await c(`${e.engine}> `);if(r?.kind===`cancel`){if(n.length===0)return;continue}if(r?.kind===`eof`)return;let i=n.trim();if(i===``)continue;let a=resolveReplCommand(i);if(a===`quit`)return;if(a===`help`)printReplHelp(e.engine);else if(a===`clear`)clearReplScreen();else if(a===`unknown`)C.warn(`Unknown command: ${i}`);else try{let n=await t(i);n.engine===`sql`?printSqlResult(n,{json:e.json}):printGqlResult(n,{json:e.json})}catch(e){if(m(e)){C.log(e.format());continue}if(e instanceof Error){C.error(e.message);continue}C.error(String(e))}}}function printReplHelp(e){C.log(`REPL commands:`),C.log(` \\help, \\h, \\? Show this help`),C.log(` \\q, \\quit Exit REPL`),C.log(` \\clear, \\c Clear the screen`),C.log(``),C.log(`Key bindings (see footer for terminal-specific submit/newline keys):`),C.log(` Ctrl+J Insert newline (always available)`),C.log(` Ctrl+C Cancel current input`),C.log(` Ctrl+D Exit REPL (on empty input)`),C.log(` Ctrl+Z / Ctrl+Y Undo / Redo`),C.log(` Up/Down (first/last line) Navigate history`),C.log(``),C.log(`Editing aids:`),C.log(` Syntax highlighting Enabled for the current engine`),C.log(` ( [ { Auto-inserts the matching closing bracket`),C.log(` Enter after open bracket Adds one indent level and closes the block`),C.log(``),C.log(e===`sql`?`Input must end with ';' to submit.`:`Input must be a complete GraphQL document to submit.`)}async function querySql(e){let t=await query({...e,engine:`sql`});if(t.engine!==`sql`)throw Error(`Expected sql engine result but got: ${t.engine}`);return t}async function queryGql(e){let t=await query({...e,engine:`gql`});if(t.engine!==`gql`)throw Error(`Expected gql engine result but got: ${t.engine}`);return t}async function reorderSqlColumns(e,t,n,r){if(!isSQLExecutionResult(e.result)||e.result.rows.length===0)return e;let i=extractColumnTemplate(r);if(!i)return e;try{let r=buildExpectedColumnOrder(i,await loadTypeFieldOrder(t,n));if(r.length===0)return e;let a=e.result.rows.map(e=>reorderRowByTemplate(e,r));return{...e,result:{...e.result,rows:a}}}catch{return e}}const du=[`id`];function buildExpectedColumnOrder(e,t){let n=[];for(let r of e)if(r.type===`explicit`)n.push(r.name);else for(let e of r.tableNames)n.push(...du),n.push(...t.get(e)??[]);return n}function reorderRowByTemplate(e,t){let n={},r=new Set(Object.keys(e)),i=/* @__PURE__ */ new Map;for(let e of r)i.set(e.toLowerCase(),e);for(let a of t){let t=i.get(a.toLowerCase());t!=null&&r.has(t)&&(n[t]=e[t],r.delete(t),i.delete(a.toLowerCase()))}for(let t of r)n[t]=e[t];return n}const fu=Y({name:`query`,description:`Run SQL/GraphQL query.`,args:U.strictObject({...k,engine:V(cu,{description:`Query engine (sql or gql)`}),query:V(U.string().optional(),{alias:`q`,description:`Query string to execute directly; omit to start REPL mode`}),file:V(U.string().optional(),{alias:`f`,description:`Read query string from file; omit to start REPL mode`}),edit:V(U.boolean().default(!1),{description:`Open a temporary file in your editor; omit to start REPL mode`}),"machine-user":V(U.string().optional(),{alias:`m`,description:`Machine user name for query execution. Falls back to the active profile's default machine user.`,env:`TAILOR_PLATFORM_MACHINE_USER_NAME`}),"newline-on-enter":V(U.boolean().optional(),{description:`REPL: when true, Enter inserts a newline and Shift+Enter submits. Use --no-newline-on-enter to swap.`})}).superRefine((e,t)=>{e.query!=null&&e.file!=null&&t.addIssue({code:`custom`,path:[`file`],message:`Pass either -q/--query or -f/--file, not both.`}),e.edit&&e.query!=null&&t.addIssue({code:`custom`,path:[`edit`],message:`Pass only one of --edit, -q/--query, or -f/--file.`}),e.edit&&e.file!=null&&t.addIssue({code:`custom`,path:[`edit`],message:`Pass only one of --edit, -q/--query, or -f/--file.`})}),run:async e=>{let t=await resolveQueryCommandInput({query:e.query,file:e.file,edit:e.edit,engine:e.engine}),n={workspaceId:e[`workspace-id`],profile:e.profile,configPath:e.config,engine:e.engine,machineUser:e[`machine-user`],machineUserSource:_e(e[`machine-user`])};if(t.mode===`abort`){C.info(`Editor closed without a query. Nothing was executed.`);return}if(t.mode===`repl`){let t=e[`newline-on-enter`]??p(process.env.TAILOR_QUERY_NEWLINE_ON_ENTER)??!0;await runRepl({...n,json:e.json,newlineOnEnter:t});return}let r=t.query;e.engine===`sql`?printSqlResult(await querySql({...n,query:r}),{json:e.json}):printGqlResult(await queryGql({...n,query:r}),{json:e.json})}});function isSQLExecutionResult(e){if(!e||typeof e!=`object`)return!1;let t=e;return Array.isArray(t.rows)&&typeof t.rowCount==`number`}function printSingleSqlResult(e,t={}){if(e.rows.length===0){if(t.json){C.out({results:[],rowCount:0});return}C.info(`No rows returned.`)}else t.json?C.out({results:e.rows,rowCount:e.rowCount}):(C.out(e.rows,{showNull:!0}),C.out(`rows: ${e.rowCount}`))}function splitSqlStatements(e){let t=Hi(e,{locationTracking:!0});return t.map((n,r)=>{let i=a(n._location,`SQL statement location missing`).start,o=t[r+1],s=o===void 0?e.length:a(o._location,`SQL statement location missing`).start;return e.substring(i,s)})}function isSQLExecutionResultArray(e){return Array.isArray(e)&&e.length>0&&e.every(isSQLExecutionResult)}function printSqlResult(e,t={}){if(isSQLExecutionResultArray(e.result)){if(t.json){C.out(e.result.map(e=>({results:e.rows,rowCount:e.rowCount})));return}let n=splitSqlStatements(e.query);for(let r=0;r<e.result.length;r++)r>0&&C.log(``),C.info(n[r]??`Statement ${r+1}`),printSingleSqlResult(a(e.result[r],`SQL result at index ${r} missing`),t)}else isSQLExecutionResult(e.result)?printSingleSqlResult(e.result,t):C.out({engine:e.engine,query:e.query,result:e.result})}function printGqlResult(e,t={}){t.json?C.out({result:e.result}):C.out(JSON.stringify(e.result,null,2))}function escapeData(e){return e.replaceAll(`%`,`%25`).replaceAll(`\r`,`%0D`).replaceAll(`
|
|
1093
|
-
`,`%0A`)}function escapeProperty(e){return escapeData(e).replaceAll(`:`,`%3A`).replaceAll(`,`,`%2C`)}function annotationsEnabled(e){return e||de(process.argv.slice(2))||process.env.GITHUB_ACTIONS!==`true`?!1:p(process.env.TAILOR_GITHUB_ACTIONS_ANNOTATIONS)!==!1}function realPath(e){try{return
|
|
1094
|
-
//# sourceMappingURL=register-ts-hook-
|
|
1101
|
+
`}async function bundleQueryScript(e,t){let n=H.resolve(Qe(),`query`);W.mkdirSync(n,{recursive:!0});let r=H.join(n,`query_${e}.entry.ts`),i=e===`sql`?createSqlEntry():createGqlEntry();W.writeFileSync(r,i);let a=await Ie(t),o=Be({tsconfig:a}),s=await wi.build({plugins:[ze(r,t),Xe(),Je],input:r,write:!1,output:{format:`esm`,sourcemap:!1,minify:!0,comments:Re,codeSplitting:!1,globals:{tailordb:`tailordb`}},external:e===`sql`?[`tailordb`]:[],resolve:{conditionNames:[`node`,`import`]},tsconfig:a,treeshake:{moduleSideEffects:!1,annotations:!0,unknownGlobalSideEffects:!1},...o.options});return o.assertAllResolved(),s.output[0].code}function toErrorMessage(e){return e instanceof Error?e.message:String(e)}function mapQueryExecutionError(e){let t=toErrorMessage(e.error);if(t.includes(`machine user does not exist`))return E({code:`not_found`,message:`Machine user '${e.machineUser??`unknown`}' was not found.`,suggestion:"Run `tailor machineuser list` and use an existing name."});if(e.engine===`sql`&&t.includes(`sqlaccess error: failed to fetch schema: query returned an unexpected number of rows`))return E({code:`invalid_namespace`,message:`Failed to load TailorDB schema for namespace '${e.namespace}'.`,suggestion:`Ensure the query references TailorDB tables from a single namespace and re-apply if needed.`});if(e.engine===`sql`&&t.includes(`sqlaccess error: failed to parse:`)){let e=t.split(`sqlaccess error: failed to parse:`).at(1)?.split(`
|
|
1102
|
+
`).at(0)?.trim();return E({code:`invalid_sql`,message:`SQL parse error.`,suggestion:e??`The SQL query contains unsupported syntax.`})}return e.error instanceof Error?e.error:Error(t)}function isGraphQLInputComplete(e){if(e.trim().length===0)return!1;try{return Oi(e),!0}catch{return!1}}function isSqlInputComplete(e){let t=!1,n=!1,r=!1,i=0,o=null,s=!1;for(let c=0;c<e.length;c+=1){let l=a(e[c],`character at index ${c} missing`),u=e[c+1];if(r)l===`
|
|
1103
|
+
`&&(r=!1);else if(i>0){if(l===`/`&&u===`*`){i+=1,c+=1;continue}l===`*`&&u===`/`&&(--i,c+=1)}else if(o!=null)e.startsWith(o,c)&&(c+=o.length-1,o=null);else if(t){if(l===`'`&&u===`'`){c+=1;continue}l===`'`&&(t=!1)}else if(n){if(l===`"`&&u===`"`){c+=1;continue}l===`"`&&(n=!1)}else if(l===`-`&&u===`-`)r=!0,c+=1;else if(l===`/`&&u===`*`)i=1,c+=1;else if(l===`'`)s=!1,t=!0;else if(l===`"`)s=!1,n=!0;else{if(l===`$`){let t=e.slice(c),n=t.match(/^\$[A-Za-z_][A-Za-z0-9_]*\$/)??t.match(/^\$\$/);if(n!=null){s=!1,o=n[0],c+=n[0].length-1;continue}}l===`;`?s=!0:/\s/.test(l)||(s=!1)}}return s&&!t&&!n&&i===0&&o==null}function extractTableNamesFromSql(e){let t;try{t=Gi(e)}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`SQL parse error: ${t}\nIf your table name is a reserved keyword (e.g. User), wrap it in double quotes: SELECT * FROM "User"`,{cause:e})}let n=/* @__PURE__ */ new Set,r=Wi(e=>({tableRef:t=>(n.add(t.name),e.super().tableRef(t),t)}));for(let e of t)r.statement(e);return[...n]}function collectAliasMap(e){let t=/* @__PURE__ */ new Map;for(let n of e)if(n.type===`table`){let e=n.name.name,r=n.name.alias??e;t.set(r,e)}return t}function extractColumnTemplate(e){try{let t=Gi(e);for(let e of t){if(e.type!==`select`||!e.columns)continue;let t=collectAliasMap(e.from??[]),n=[],r=!1;for(let i of e.columns)if(i.expr.type===`ref`&&i.expr.name===`*`){if(r=!0,i.expr.table){let e=t.get(i.expr.table.name);n.push({type:`wildcard`,tableNames:e?[e]:[]})}else n.push({type:`wildcard`,tableNames:[...new Set(t.values())]})}else{let e=i.alias?.name??(i.expr.type===`ref`?i.expr.name:null);e&&n.push({type:`explicit`,name:e})}return r?n:null}return null}catch{return null}}async function loadTypeFieldOrder(e,t){let n=/* @__PURE__ */ new Map,r=e.db?.[t];if(!r||!(`files`in r)||r.files.length===0)return n;let i=H.dirname(e.path),a=vt(r,i);return await Promise.all(a.map(async e=>{try{let t=await import(di(e).href);for(let e of Object.values(t)){let t=bt.safeParse(xt(e));t.success&&n.set(t.data.name,Object.keys(t.data.fields))}}catch{}})),n}const mu=U.enum([`sql`,`gql`]),hu=U.object({workspaceId:U.string().optional(),profile:U.string().optional(),configPath:U.string().optional(),engine:mu,machineUser:U.string().optional(),machineUserSource:U.enum([`option`,`env`]).optional()}),gu=hu.extend({query:U.string()});async function getNamespaceFromSqlQuery(e,t,n,r){if(r.length===0)throw Error(`No namespaces found in configuration.`);if(r.length===1)return a(r[0],`namespace missing`);let i=extractTableNamesFromSql(t);if(i.length===0)throw Error(`Could not infer namespace from query. Detected namespaces: ${r.join(`, `)}.`);let o=await resolveTableNamespaces({workspaceId:e,namespaces:r,tableNames:i,client:n}),s=i.filter(e=>!o.has(e));if(s.length>0)throw Error(`Could not find namespace for tables in query: ${s.join(`, `)}.`);let c=new Set(o.values());if(c.size===1)return a([...c][0],`namespace from types missing`);throw Error(`Query references tables from multiple namespaces: ${[...c].join(`, `)}.`)}async function loadOptions(e){let t=parseOptions(hu,e),n=await be({machineUser:t.machineUser,machineUserSource:t.machineUserSource,profile:t.profile});if(!n)throw Error(`Machine user is required. Specify --machine-user, set TAILOR_PLATFORM_MACHINE_USER_NAME, or set a profile default with 'tailor profile update <profile> --machine-user <name>'.`);let r=await A({profile:t.profile}),i=await N(r),a=await xe({workspaceId:t.workspaceId,profile:t.profile}),{config:o}=await loadConfig(e.configPath),s=extractAllNamespaces(o),{application:c}=await i.getApplication({workspaceId:a,applicationName:o.name});if(!c?.authNamespace)throw Error(`Application ${o.name} does not have an auth configuration.`);let{machineUser:l}=await i.getAuthMachineUser({workspaceId:a,authNamespace:c.authNamespace,name:n});if(!l)throw Error(`Machine user ${n} not found.`);return{engine:t.engine,client:i,workspaceId:a,config:o,application:c,machineUserResource:l,namespaces:s}}async function sqlQuery(e,t,n){let r=splitSqlStatements(n.query),i=await executeScript({client:e,workspaceId:n.workspaceId,name:`query-sql-${n.namespace}.js`,code:n.bundledCode,arg:{namespace:n.namespace,queries:r},invoker:t});if(!i.success)throw Error(i.error);return{engine:`sql`,namespace:n.namespace,query:n.query,result:parseExecutionResult(i.result)}}async function gqlQuery(e,t,n,r,i){let{access_token:a}=await It(n.url,r.clientId,r.clientSecret),o=await executeScript({client:e,workspaceId:i.workspaceId,name:`query-gql.js`,code:i.bundledCode,arg:{endpoint:`${n.url}/query`,accessToken:a,query:i.query},invoker:t});if(!o.success)throw Error(o.error);return{engine:`gql`,query:i.query,result:parseExecutionResult(o.result)}}function parseExecutionResult(e){if(!e)return null;try{return JSON.parse(e)}catch{return e}}async function resolveQueryCommandInput(e){return e.query==null?e.file==null?e.edit?await resolveEditedQueryInput(e.engine):{mode:`repl`}:{mode:`query`,query:await J.readFile(e.file,`utf-8`)}:{mode:`query`,query:e.query}}async function resolveEditedQueryInput(e){if(!process.stdin.isTTY||!process.stdout.isTTY)throw Error(`Non-interactive terminals are not supported. Pass -q/--query or -f/--file to run a query.`);let t=getEditorCommand(),n=await J.mkdtemp(H.join(vi(),`tailor-query-`)),r=e===`sql`?`sql`:`graphql`,i=H.join(n,`query.${r}`);try{await J.writeFile(i,``,`utf-8`);try{await openInEditor(i,t)}catch(e){throw Error(`Failed to open query editor "${t}": ${e instanceof Error?e.message:String(e)}`,{cause:e})}let e=await J.readFile(i,`utf-8`);return e.trim().length===0||e===``?{mode:`abort`}:{mode:`query`,query:e}}finally{await J.rm(n,{recursive:!0,force:!0})}}async function query(e){let t=parseOptions(gu,e);return await(await prepareQueryExecutor(t))(t.query)}async function prepareQueryExecutor(e){let{client:t,workspaceId:n,config:r,application:i,machineUserResource:a,engine:o,namespaces:s}=await loadOptions(e),c=await bundleQueryScript(o,H.dirname(r.path)),l=Yr(pn,{namespace:i.authNamespace,machineUserName:a.name});return async e=>{let u;try{switch(o){case`sql`:return u=await getNamespaceFromSqlQuery(n,e,t,s),reorderSqlColumns(await sqlQuery(t,l,{workspaceId:n,namespace:u,bundledCode:c,query:e}),r,u,e);case`gql`:return await gqlQuery(t,l,i,a,{workspaceId:n,bundledCode:c,query:e});default:throw Error(`Unsupported query engine: ${o}`)}}catch(e){throw mapQueryExecutionError({error:e,engine:o,namespace:u,machineUser:a.name})}}}function resolveReplCommand(e){let t=e.trim();return t.startsWith(`\\`)?t===`\\q`||t===`\\quit`?`quit`:t===`\\help`||t===`\\h`||t===`\\?`?`help`:t===`\\clear`||t===`\\c`?`clear`:`unknown`:null}function clearReplScreen(){process.stdout.write(`\x1Bc`)}function sanitizeHistoryScope(e){return e.replace(/[^a-zA-Z0-9._-]/g,`_`)}function getReplHistoryPath(e,t,n){if(!pi)return;let r=[t,n].filter(e=>!!e).map(sanitizeHistoryScope).join(`-`),i=e===`sql`?`sql`:`gql`,a=r?`-${r}`:``;return H.join(pi,`tailor-platform`,`query-history-${i}${a}.json`)}function createReplValidator(e){return t=>{let n=t.trim();if(n!==``&&resolveReplCommand(n)===null)return e===`sql`?isSqlInputComplete(t)?void 0:`SQL statement is incomplete (missing ';').`:isGraphQLInputComplete(t)?void 0:`GraphQL document is incomplete.`}}async function runRepl(e){if(!process.stdin.isTTY||!process.stdout.isTTY)throw Error(`Non-interactive terminals are not supported. Pass -q/--query or -f/--file to run a query.`);let t=await prepareQueryExecutor(e),n=getReplHistoryPath(e.engine,e.profile,e.workspaceId),r=createReplValidator(e.engine),{highlightSqlLines:i,highlightGraphqlLines:a,replTransform:o}=await import(`./repl-editor-Bposemei.mjs`),s=e.engine===`sql`?i:a,c=Ui({prefix:``,preferNewlineOnEnter:e.newlineOnEnter,validate:r,highlightLines:s,transform:o,theme:{submitRender:`preserve`},history:n?{filePath:n,maxEntries:100}:[],helpFooter:{items:[`submit`,`newline`],maxLines:1}});for(C.info(`Entering ${e.engine.toUpperCase()} REPL mode.`),C.info(`Type \\help for usage, \\q to quit.`);;){let[n,r]=await c(`${e.engine}> `);if(r?.kind===`cancel`){if(n.length===0)return;continue}if(r?.kind===`eof`)return;let i=n.trim();if(i===``)continue;let a=resolveReplCommand(i);if(a===`quit`)return;if(a===`help`)printReplHelp(e.engine);else if(a===`clear`)clearReplScreen();else if(a===`unknown`)C.warn(`Unknown command: ${i}`);else try{let n=await t(i);n.engine===`sql`?printSqlResult(n,{json:e.json}):printGqlResult(n,{json:e.json})}catch(e){if(m(e)){C.log(e.format());continue}if(e instanceof Error){C.error(e.message);continue}C.error(String(e))}}}function printReplHelp(e){C.log(`REPL commands:`),C.log(` \\help, \\h, \\? Show this help`),C.log(` \\q, \\quit Exit REPL`),C.log(` \\clear, \\c Clear the screen`),C.log(``),C.log(`Key bindings (see footer for terminal-specific submit/newline keys):`),C.log(` Ctrl+J Insert newline (always available)`),C.log(` Ctrl+C Cancel current input`),C.log(` Ctrl+D Exit REPL (on empty input)`),C.log(` Ctrl+Z / Ctrl+Y Undo / Redo`),C.log(` Up/Down (first/last line) Navigate history`),C.log(``),C.log(`Editing aids:`),C.log(` Syntax highlighting Enabled for the current engine`),C.log(` ( [ { Auto-inserts the matching closing bracket`),C.log(` Enter after open bracket Adds one indent level and closes the block`),C.log(``),C.log(e===`sql`?`Input must end with ';' to submit.`:`Input must be a complete GraphQL document to submit.`)}async function querySql(e){let t=await query({...e,engine:`sql`});if(t.engine!==`sql`)throw Error(`Expected sql engine result but got: ${t.engine}`);return t}async function queryGql(e){let t=await query({...e,engine:`gql`});if(t.engine!==`gql`)throw Error(`Expected gql engine result but got: ${t.engine}`);return t}async function reorderSqlColumns(e,t,n,r){if(!isSQLExecutionResult(e.result)||e.result.rows.length===0)return e;let i=extractColumnTemplate(r);if(!i)return e;try{let r=buildExpectedColumnOrder(i,await loadTypeFieldOrder(t,n));if(r.length===0)return e;let a=e.result.rows.map(e=>reorderRowByTemplate(e,r));return{...e,result:{...e.result,rows:a}}}catch{return e}}const _u=[`id`];function buildExpectedColumnOrder(e,t){let n=[];for(let r of e)if(r.type===`explicit`)n.push(r.name);else for(let e of r.tableNames)n.push(..._u),n.push(...t.get(e)??[]);return n}function reorderRowByTemplate(e,t){let n={},r=new Set(Object.keys(e)),i=/* @__PURE__ */ new Map;for(let e of r)i.set(e.toLowerCase(),e);for(let a of t){let t=i.get(a.toLowerCase());t!=null&&r.has(t)&&(n[t]=e[t],r.delete(t),i.delete(a.toLowerCase()))}for(let t of r)n[t]=e[t];return n}const vu=Y({name:`query`,description:`Run SQL/GraphQL query.`,args:U.strictObject({...O,engine:V(mu,{description:`Query engine (sql or gql)`}),query:V(U.string().optional(),{alias:`q`,description:`Query string to execute directly; omit to start REPL mode`}),file:V(U.string().optional(),{alias:`f`,description:`Read query string from file; omit to start REPL mode`}),edit:V(U.boolean().default(!1),{description:`Open a temporary file in your editor; omit to start REPL mode`}),"machine-user":V(U.string().optional(),{alias:`m`,description:`Machine user name for query execution. Falls back to the active profile's default machine user.`,env:`TAILOR_PLATFORM_MACHINE_USER_NAME`}),"newline-on-enter":V(U.boolean().optional(),{description:`REPL: when true, Enter inserts a newline and Shift+Enter submits. Use --no-newline-on-enter to swap.`})}).superRefine((e,t)=>{e.query!=null&&e.file!=null&&t.addIssue({code:`custom`,path:[`file`],message:`Pass either -q/--query or -f/--file, not both.`}),e.edit&&e.query!=null&&t.addIssue({code:`custom`,path:[`edit`],message:`Pass only one of --edit, -q/--query, or -f/--file.`}),e.edit&&e.file!=null&&t.addIssue({code:`custom`,path:[`edit`],message:`Pass only one of --edit, -q/--query, or -f/--file.`})}),run:async e=>{let t=await resolveQueryCommandInput({query:e.query,file:e.file,edit:e.edit,engine:e.engine}),n={workspaceId:e[`workspace-id`],profile:e.profile,configPath:e.config,engine:e.engine,machineUser:e[`machine-user`],machineUserSource:_e(e[`machine-user`])};if(t.mode===`abort`){C.info(`Editor closed without a query. Nothing was executed.`);return}if(t.mode===`repl`){let t=e[`newline-on-enter`]??p(process.env.TAILOR_QUERY_NEWLINE_ON_ENTER)??!0;await runRepl({...n,json:e.json,newlineOnEnter:t});return}let r=t.query;e.engine===`sql`?printSqlResult(await querySql({...n,query:r}),{json:e.json}):printGqlResult(await queryGql({...n,query:r}),{json:e.json})}});function isSQLExecutionResult(e){if(!e||typeof e!=`object`)return!1;let t=e;return Array.isArray(t.rows)&&typeof t.rowCount==`number`&&(t.affectedRows===void 0||typeof t.affectedRows==`number`)}function toSqlJsonResult(e){let{rows:t,rowCount:n,affectedRows:r}=e;return{results:t,rowCount:n,affectedRows:r}}function printSingleSqlResult(e,t={}){if(t.json)C.out(toSqlJsonResult(e));else if(e.rows.length===0){let{affectedRows:t}=e;C.info(t===void 0?`No rows returned.`:`${t} ${t===1?`row`:`rows`} affected.`)}else C.out(e.rows,{showNull:!0}),C.out(`rows: ${e.rowCount}`)}function splitSqlStatements(e){let t=Gi(e,{locationTracking:!0});return t.map((n,r)=>{let i=a(n._location,`SQL statement location missing`).start,o=t[r+1],s=o===void 0?e.length:a(o._location,`SQL statement location missing`).start;return e.substring(i,s)})}function isSQLExecutionResultArray(e){return Array.isArray(e)&&e.length>0&&e.every(isSQLExecutionResult)}function printSqlResult(e,t={}){if(isSQLExecutionResultArray(e.result)){if(t.json){C.out(e.result.map(toSqlJsonResult));return}let n=splitSqlStatements(e.query);for(let r=0;r<e.result.length;r++)r>0&&C.log(``),C.info(n[r]??`Statement ${r+1}`),printSingleSqlResult(a(e.result[r],`SQL result at index ${r} missing`),t)}else isSQLExecutionResult(e.result)?printSingleSqlResult(e.result,t):C.out({engine:e.engine,query:e.query,result:e.result})}function printGqlResult(e,t={}){t.json?C.out({result:e.result}):C.out(JSON.stringify(e.result,null,2))}function escapeData(e){return e.replaceAll(`%`,`%25`).replaceAll(`\r`,`%0D`).replaceAll(`
|
|
1104
|
+
`,`%0A`)}function escapeProperty(e){return escapeData(e).replaceAll(`:`,`%3A`).replaceAll(`,`,`%2C`)}function annotationsEnabled(e){return e||de(process.argv.slice(2))||process.env.GITHUB_ACTIONS!==`true`?!1:p(process.env.TAILOR_GITHUB_ACTIONS_ANNOTATIONS)!==!1}function realPath(e){try{return ti(Kr(e))}catch{return Kr(e)}}function workspaceRelativePath(e){let t=process.env.GITHUB_WORKSPACE;if(!t||!Ur(e))return;let n=Gr(realPath(t),realPath(e));if(n===``||Ur(n))return;let r=n.split(qr);if(r[0]!==`..`)return r.join(`/`)}function formatAnnotation(e,t,n={}){let r=[];return n.title!==void 0&&r.push(`title=${escapeProperty(S(n.title))}`),n.file!==void 0&&r.push(`file=${escapeProperty(n.file)}`),n.line!==void 0&&r.push(`line=${n.line}`),`::${e}${r.length>0?` ${r.join(`,`)}`:``}::${escapeData(S(t))}\n`}function formattedMessage(e){let t=e.format;if(typeof t!=`function`)return;let n=t.call(e);return typeof n==`string`?n:void 0}function describeTerminalError(e,t){if(m(e))return{message:e.format(),title:e.code||`CLI_ERROR`};if(e instanceof Error){let n=s(e).code??(e.name||`Error`),r=formattedMessage(e);if(r!==void 0)return{message:r,title:n};let i=t?`\nSuggestion: ${t}`:``;return{message:`${e.message}${i}`,title:n}}return{message:`Unknown error: ${String(e)}`,title:`UNKNOWN_ERROR`}}function withSourceLocation(e,t){return l(e,{location:t})}function annotateTerminalError(e,t){if(!annotationsEnabled(t.jsonMode))return;let{message:n,title:r}=describeTerminalError(e,t.suggestion);process.stderr.write(formatAnnotation(`error`,n,{title:r,...sourceLocation(e)}))}function sourceLocation(e){if(!(e instanceof Error))return{};let t=s(e).location;if(!t)return{};let n=workspaceRelativePath(t.file);return n===void 0?{}:t.line===void 0?{file:n}:{file:n,line:t.line}}function isNativeTypeScriptRuntime(){return isBun()||isDeno()}function isBun(){return`Bun`in globalThis}function isDeno(){return`Deno`in globalThis}async function registerTsHook(e){if(isNativeTypeScriptRuntime())return;let{resolveSync:t,loadSync:n}=await import(e.href);Rr.registerHooks({resolve:t,load:n})}export{listFolders as $,settlingResolution as $n,createSnapshotType as $r,deployFromCLI as $t,listWorkflows as A,collectForeignKeyTargets as Ai,planAppIds as An,missingCheckpointRecoveryHints as Ar,getExecutorWaitFailureMessage as At,remove as B,ma as Bi,clearMaintenanceModeRecord as Bn,matchesLocalMigrationHistory as Br,listWorkflowExecutions as Bt,getAppHealth as C,loadDiff as Ci,xc as Cn,ws as Cr,listWebhookExecutors as Ct,Gl as D,handleOptionalToRequiredError as Di,appIdLockKey as Dn,locateRemoteCheckpoint as Dr,tl as Dt,waitWorkflowExecution as E,createMigrationHistoryId as Ei,_c as En,formatRemoteVerificationResults as Er,triggerExecutor as Et,Vl as F,formatDiffSummary as Fi,uc as Fn,assertNoMigrationInProgress as Fr,startWorkflow as Ft,kl as G,reportTruncation as Gi,updateMigrationLabel as Gn,getNamespacesWithMigrations as Gr,loadTailorDBNamespaces as Gt,jl as H,pa as Hi,isScriptBundleFailure as Hn,compareSnapshotWithRemote as Hr,getExecutor as Ht,generateSchemaFile as I,formatMigrationDiff as Ii,deployStaticWebsite as In,fetchRemoteMigrationState as Ir,Qc as It,Dl as J,printMutationResult as Ji,selectSkipStepsOfNamespaces as Jn,captureFileState as Jr,executeScript as Jt,Ol as K,X as Ki,noStepsToSkipError as Kn,migrationConfigNotFoundError as Kr,resolvePluginConfig as Kt,logBetaWarning as L,hasChanges as Li,checkMigrationInProgress as Ln,formatInProgressMigrationAction as Lr,getWorkflow as Lt,Ul as M,normalizeSchemaSnapshot as Mi,resolveAppId as Mn,unsetCheckpointDriftHints as Mr,listExecutorJobs as Mt,generate as N,formatMigrationNumber as Ni,ensureConfigId as Nn,verifyRemoteSchema as Nr,watchExecutorJob as Nt,resumeWorkflow as O,compareLocalTypesWithSnapshot as Oi,findAppIdLock as On,logRebaselinePendingGuidance as Or,listExecutors as Ot,Hl as P,parseMigrationNumberArg as Pi,generateUserTypes as Pn,assertLocalMigrationHistory as Pr,$c as Pt,Cl as Q,Y as Qi,retryCommandActiveError as Qn,createSnapshotFromLocalTypes as Qr,deploy as Qt,show as R,subscribesToEvents as Ri,checkpointRepairInProgressError as Rn,inProgressMigrationActions as Rr,Zc as Rt,Ql as S,getNextMigrationNumber as Si,Cc as Sn,ignoredStepsWarning as Sr,getFunctionRegistry as St,Kl as T,Ja as Ti,Q as Tn,fetchRemoteSchemaSnapshot as Tr,il as Tt,updateOrganization as U,writeMetadataLabels as Ui,pendingMigrationsAfter as Un,generateAllTypeManifestsFromSnapshot as Ur,loadSeedContext as Ut,Ml as V,fa as Vi,getMigrationMachineUser as Vn,migrationHistoryMismatchError as Vr,Kc as Vt,organizationTree as W,fetchWithinLimit as Wi,removeRunResources as Wn,protoGqlPermission as Wr,loadApplicationNamespaces as Wt,Tl as X,assertWritable as Xi,formatMigrationExecutionsHint as Xn,createRemoteComparableSnapshot as Xr,bundleSeedDumpScript as Xt,getOrganization as Y,apiCall as Yi,assertNoActiveMigrationExecution as Yn,captureMigrationFileState as Yr,waitForExecution as Yt,updateFolder as Z,loadConfig as Zi,readMigrationRunStatus as Zn,formatSchemaDrifts as Zr,bundleSeedScript as Zt,getWorkspace as _,assertMigrationNumberExists as _i,Ec as _n,protoEnumName as _r,extractAllNamespaces as _t,vu as a,migrationCommandContext as ai,createValidatedWorkspaceWithClient as an,teardownTemporaryWorkflow as ar,createFolder as at,removeProfilesForWorkspaces as b,getMigrationFilePath as bi,Oc as bn,analyzeMigrationScript as br,listFunctionRegistries as bt,du as c,as as ci,workspaceInfosWithFolderNames as cn,isRetryableWaitError as cr,ml as ct,listUsers as d,rs as di,formatTimestamp as dn,formatFunctionLogLines as dr,fl as dt,assertValidMigrationFiles as ei,deployMigrationTestBaseline as en,createTemporaryWorkflow as er,xl as et,su as f,ss as fi,humanizeRelativeTime as fn,functionExecutionStatusToString as fr,dl as ft,nu as g,ts as gi,writeWorkspaceExpiry as gn,protoEnumLookup as gr,serializeError as gt,restoreWorkspace as h,cs as hi,recordedExpiresAt as hn,toFunctionLogEntryInfo as hr,errorToJson as ht,query as i,migrationCommandArgs as ii,Fc as in,reclaimTemporaryWorkflow as ir,_l as it,truncate as j,Na as ji,removeAdoptedConfigIds as jn,toTailorDBDeployInput as jr,el as jt,Wl as k,compareSnapshots as ki,parseAppIds as kn,logRemoteDriftGuidance as kr,getExecutorJob as kt,removeUser as l,ns as li,Nc as ln,colorizeFunctionExecutionStatus as lr,getOAuth2Client as lt,iu as m,ls as mi,fetchWorkspaceExpiry as mn,joinFunctionLogMessages as mr,generate$1 as mt,annotateTerminalError as n,formatMigrationScriptHint as ni,Ic as nn,listTemporaryWorkflowExecutions as nr,yl as nt,pu as o,migrationContextArgs as oi,createWorkspace$1 as on,uploadTemporaryFunction as or,hl as ot,inviteUser as p,is as pi,clearWorkspaceExpiry as pn,isFunctionExecutionTerminalStatus as pr,listMachineUsers as pt,listOrganizations as q,loadOperatorWorkspaceContext as qi,parseMigrationSkipSteps as qn,selectTargetNamespace as qr,chunkSeedData as qt,withSourceLocation as r,formatNamespaceMigrationHint as ri,listWorkspaces as rn,pollUntilTerminal$1 as rr,deleteFolder as rt,updateUser as s,os as si,workspaceDisplayName as sn,formatWaitError as sr,listOAuth2Clients as st,registerTsHook as t,reconstructSnapshotFromMigrations as ti,deployMigrationTestTarget as tn,isExecutionActive as tr,getFolder as tt,lu as u,es as ui,formatKeyValueTable as un,formatFunctionLogEntry as ur,getMachineUserToken as ut,eu as v,getLatestMigrationNumber as vi,parseAge as vn,bundleMigrationScript as vr,extractOwnedNamespaces as vt,Xl as w,loadSnapshot as wi,parseOptions as wn,checkMigrationDiffs as wr,ol as wt,listApps as x,getMigrationFiles as xi,Sc as xn,countUnresolvedTodosInFile as xr,cl as xt,deleteWorkspace as y,getMigrationDirPath as yi,kc as yn,Ds as yr,ul as yt,Pl as z,resourceTrn as zi,assertPendingMigrationsRunnable as zn,isStaleMigrationInProgress as zr,getWorkflowExecution as zt};
|
|
1105
|
+
//# sourceMappingURL=register-ts-hook-CORbtrSN.mjs.map
|