@tailor-platform/sdk 2.17.0 → 2.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -0
- package/dist/{application-ChuNPwnl.mjs → application-BYlhYQyh.mjs} +14 -14
- package/dist/application-BYlhYQyh.mjs.map +1 -0
- package/dist/application-KZRJHv2j.mjs +1 -0
- package/dist/cli/commands/deploy/event-subscriptions.d.mts +1 -0
- package/dist/cli/commands/generate/service.d.mts +1 -0
- package/dist/cli/lib.d.mts +3 -2
- package/dist/cli/lib.mjs +1 -1
- package/dist/cli/lib.mjs.map +1 -1
- package/dist/cli/main.mjs +28 -28
- package/dist/cli/main.mjs.map +1 -1
- package/dist/cli/services/executor/service.d.mts +1 -0
- package/dist/cli/shared/error-diagnostics.d.mts +10 -0
- package/dist/cli/shared/github-actions.d.mts +11 -0
- package/dist/completion/zsh-worker.zsh +1 -1
- package/dist/configure/index.d.mts +7 -7
- package/dist/configure/index.mjs +1 -1
- package/dist/configure/index.mjs.map +1 -1
- package/dist/configure/types/field.types.d.mts +24 -4
- package/dist/configure/types/type.d.mts +1 -0
- package/dist/date-B7-oyTGE.mjs +2 -0
- package/dist/date-B7-oyTGE.mjs.map +1 -0
- package/dist/field-parse-BbNyotv5.mjs +2 -0
- package/dist/field-parse-BbNyotv5.mjs.map +1 -0
- package/dist/{manager-C26Gi1bX.mjs → manager-qfbUL7ru.mjs} +2 -2
- package/dist/{manager-C26Gi1bX.mjs.map → manager-qfbUL7ru.mjs.map} +1 -1
- package/dist/parser/service/auth/schema.d.mts +1 -0
- package/dist/plugin/index.mjs +1 -1
- package/dist/{register-ts-hook-Dn-XlVSD.mjs → register-ts-hook-Djjnj5R8.mjs} +52 -52
- package/dist/register-ts-hook-Djjnj5R8.mjs.map +1 -0
- package/dist/runtime/date.d.mts +3 -3
- package/dist/runtime/field-parse.d.mts +1 -0
- package/dist/runtime/index.d.mts +2 -1
- package/dist/runtime/index.mjs +1 -1
- package/dist/runtime/temporal.d.mts +31 -0
- package/dist/{schema-DRyQEabV.mjs → schema-BKvcWdVf.mjs} +2 -2
- package/dist/{schema-DRyQEabV.mjs.map → schema-BKvcWdVf.mjs.map} +1 -1
- package/dist/seed/index.d.mts +5 -0
- package/dist/seed/index.mjs +3 -2
- package/dist/seed/index.mjs.map +1 -1
- package/dist/service-BgrEteZ2.mjs +1 -0
- package/dist/service-CuqkHP1r.mjs +7 -0
- package/dist/service-CuqkHP1r.mjs.map +1 -0
- package/dist/types/field.generated.d.mts +1 -1
- package/dist/types/helpers.d.mts +8 -6
- package/dist/utils/test/index.mjs +1 -1
- package/dist/vitest/environment.mjs +1 -1
- package/dist/vitest/environment.mjs.map +1 -1
- package/docs/cli-reference.md +11 -2
- package/docs/github-actions.md +22 -15
- package/docs/migration/v3.md +0 -33
- package/docs/services/resolver.md +53 -1
- package/docs/services/tailordb-migration.md +4 -0
- package/docs/testing.md +17 -0
- package/package.json +12 -10
- package/dist/application-ChuNPwnl.mjs.map +0 -1
- package/dist/application-Oh5dMmb5.mjs +0 -1
- package/dist/date-CGBZbMW5.mjs +0 -2
- package/dist/date-CGBZbMW5.mjs.map +0 -1
- package/dist/field-parse-CzlKC4b7.mjs +0 -2
- package/dist/field-parse-CzlKC4b7.mjs.map +0 -1
- package/dist/register-ts-hook-Dn-XlVSD.mjs.map +0 -1
- package/dist/service-B3OiWCYg.mjs +0 -1
- package/dist/service-eM7Fd8zS.mjs +0 -7
- package/dist/service-eM7Fd8zS.mjs.map +0 -1
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import{t as e}from"./wait-point-registry-B-ESkTZX.mjs";import{$ as t,At as n,B as r,Bt as i,C as a,D as o,Dt as s,Et as c,Ft as l,G as u,Gt as d,I as f,J as p,Jt as m,K as h,Kt as g,L as _,Lt as v,M as y,Mt as b,N as x,Nt as S,O as C,Ot as w,P as ee,Pt as te,R as ne,Rt as re,S as ie,St as ae,Tt as oe,U as se,V as ce,W as le,Wt as ue,X as de,Xt as fe,Yt as pe,Z as me,Zt as he,_ as ge,_t as _e,a as ve,at as ye,b as be,bt as xe,ct as Se,d as Ce,dt as we,et as T,f as Te,ft as Ee,g as De,gt as Oe,h as E,ht as ke,i as Ae,in as je,it as Me,j as Ne,jt as Pe,k as Fe,kt as Ie,l as D,lt as Le,mt as Re,nn as ze,nt as Be,o as Ve,ot as He,p as Ue,pt as We,r as Ge,rn as Ke,rt as qe,s as Je,st as Ye,t as Xe,tn as Ze,tt as O,u as Qe,ut as $e,v as et,vt as tt,w as nt,wt as rt,x as it,xt as at,y as ot,yt as st,zt as ct}from"./workspace_resource_pb-BOoRts_z.mjs";import{t as k}from"./assert-WeXvmG4j.mjs";import{a as A,c as lt,i as j,n as M,o as ut,r as dt,s as ft,t as pt}from"./logger-72hM4JWZ.mjs";import{$ as mt,A as ht,B as gt,C as _t,D as vt,E as yt,F as bt,H as N,I as xt,J as St,K as Ct,L as wt,O as Tt,Q as P,R as Et,S as Dt,T as Ot,U as kt,V as At,W as jt,X as Mt,Y as F,Z as Nt,a as Pt,at as Ft,c as It,ct as Lt,et as Rt,f as zt,g as Bt,i as Vt,it as Ht,j as Ut,k as Wt,l as Gt,n as Kt,nt as qt,ot as Jt,p as Yt,q as Xt,r as Zt,rt as Qt,s as $t,st as en,t as tn,tt as nn,u as rn,v as an,w as on,x as sn,y as cn}from"./application-ChuNPwnl.mjs";import{_ as ln,d as un,g as dn,l as fn,t as pn,v as mn,x as hn,y as gn}from"./service-eM7Fd8zS.mjs";import{a as _n}from"./guards-ForsrxnH.mjs";import{t as I}from"./multiline-EyzjEwn9.mjs";import{t as vn}from"./package-json-C690ceex.mjs";import{t as yn}from"./user-agent-vdHYF3QL.mjs";import{a as L,c as bn,o as xn,r as Sn,s as Cn,t as R}from"./errors-BjJnpXkK.mjs";import{n as wn,r as Tn}from"./secret-file-C9wp_FCX.mjs";import{r as z}from"./telemetry-Bklv9kQY.mjs";import{t as En}from"./manager-C26Gi1bX.mjs";import{n as Dn,r as On,t as kn}from"./tailordb-ddl-Fgm2cNvT.mjs";import{a as An,i as jn,o as Mn,r as Nn,s as Pn,t as Fn}from"./seed-C3P_T_Eh.mjs";import*as In from"node:module";import{arg as B,createDefineCommand as Ln,defineCommand as Rn,runCommand as zn}from"@politty/zod";import*as V from"pathe";import{basename as Bn,dirname as Vn,join as Hn,resolve as Un}from"pathe";import{resolveTSConfig as Wn}from"pkg-types";import{z as H}from"zod";import{create as Gn,createRegistry as Kn,fromJson as qn,toJson as Jn}from"@bufbuild/protobuf";import*as U from"node:fs";import{mkdirSync as Yn,readFileSync as Xn,renameSync as Zn,rmSync as Qn,statSync as $n,utimesSync as er,writeFileSync as tr}from"node:fs";import{parseEnv as nr,stripVTControlCharacters as rr}from"node:util";import{ValueSchema as ir,timestampDate as W}from"@bufbuild/protobuf/wkt";import{formatDistanceToNowStrict as ar}from"date-fns";import{pathToFileURL as or}from"node:url";import{parseYAML as sr,stringifyYAML as cr}from"confbox";import{findUpSync as lr}from"find-up-simple";import{lt as ur}from"semver";import{xdgConfig as dr}from"xdg-basedir";import{Code as G,ConnectError as K}from"@connectrpc/connect";import fr from"p-limit";import*as pr from"node:crypto";import{createHash as mr,randomUUID as hr}from"node:crypto";import{ExitPromptError as gr}from"@inquirer/core";import{confirm as _r,input as vr,password as yr,select as br}from"@inquirer/prompts";import{isCI as xr}from"std-env";import*as Sr from"rolldown";import{parseSync as Cr}from"oxc-parser";import*as wr from"inflection";import{tmpdir as Tr}from"node:os";import{pathToString as Er,usedTypes as Dr}from"@bufbuild/protobuf/reflect";import{createValidator as Or}from"@bufbuild/protovalidate";import*as q from"node:fs/promises";import{mkdir as kr,readFile as Ar,rename as jr,rm as Mr,writeFile as Nr}from"node:fs/promises";import{setTimeout as Pr}from"timers/promises";import{setTimeout as Fr}from"node:timers/promises";import{spawn as Ir}from"node:child_process";import*as Lr from"fs";import{lookup as Rr}from"mime-types";import{createPrompt as zr}from"@toiroakr/read-multiline";import{astVisitor as Br,parse as Vr}from"pgsql-ast-parser";import{parse as Hr}from"@0no-co/graphql.web";const Ur={ms:1,s:1e3,m:6e4},Wr=/^(\d+)(ms|s|m)$/,Gr=H.string().refine(e=>Wr.test(e),{message:`Invalid duration format. Expected format: '3s', '500ms', '1m'`}).refine(e=>{let t=e.match(Wr);if(!t)return!1;let n=t[1];return n!==void 0&&parseInt(n,10)>0},{message:`Duration must be greater than 0`});function parseDuration(e){let t=k(e.match(Wr),`invalid duration format: ${e}`),n=parseInt(k(t[1],`duration digits group missing`),10),r=k(t[2],`duration unit group missing`);return n*Ur[r]}const Kr=H.coerce.number().int().positive(),qr=H.coerce.number().int().nonnegative(),Jr=H.enum([`asc`,`desc`]);function toPageDirection(e){if(e!==void 0)return e===`asc`?je.ASC:je.DESC}function hasMachineUserFlag(e){return e.slice(0,e.indexOf(`--`)===-1?e.length:e.indexOf(`--`)).some(e=>e===`-m`||e.startsWith(`-m=`)||e===`--machine-user`||e.startsWith(`--machine-user=`)||e===`--machineUser`||e.startsWith(`--machineUser=`)||e===`--machineuser`||e.startsWith(`--machineuser=`))}function resolveMachineUserInputSource(e,t=process.argv.slice(2),n={}){if(e!==void 0)return n.valueIsExplicit||hasMachineUserFlag(t)?`option`:process.env.TAILOR_PLATFORM_MACHINE_USER_NAME===e?`env`:`option`}function loadEnvFiles(e,t){let n=new Set(Object.keys(process.env)),load=(e,t)=>{for(let r of[e??[]].flat()){let e=V.resolve(process.cwd(),r);if(!U.existsSync(e)){if(t)throw Error(`Environment file not found: ${e}`);continue}let i=U.readFileSync(e,`utf-8`),a=nr(i);for(let[e,t]of Object.entries(a))n.has(e)||(process.env[e]=t)}};load(e,!0),load(t,!1)}function createCommonArgs(e={}){return{"env-file":B(H.string().optional(),{alias:`e`,description:`Path to the environment file (error if not found)`,completion:{type:`file`,matcher:[`.env.*`,`.env`]}}),"env-file-if-exists":B(H.string().optional(),{description:`Path to the environment file (ignored if not found)`,completion:{type:`file`,matcher:[`.env.*`,`.env`]},effect:(e,{args:t})=>{loadEnvFiles(t[`env-file`],t[`env-file-if-exists`])}}),verbose:B(H.boolean().default(!1),{...e.verboseAlias===void 0?{}:{alias:e.verboseAlias},description:`Enable verbose logging`,effect:e=>{M.verbose=e}}),json:B(H.boolean().default(!1),{alias:`j`,description:`Output as JSON`,effect:e=>{M.jsonMode=e}})}}const Yr=createCommonArgs(),J={"workspace-id":B(H.string().optional(),{alias:`w`,description:`Workspace ID`,env:`TAILOR_PLATFORM_WORKSPACE_ID`,completion:{type:`none`}}),profile:B(H.string().optional(),{alias:`p`,description:`Workspace profile`,env:`TAILOR_PLATFORM_PROFILE`,completion:{type:`none`}})},Xr=`tailor.config.ts`;function formatConfigArg(e){if(!e)return;let t=V.relative(process.cwd(),e);if(t!==`tailor.config.ts`)return`--config=${t}`}function recoveryContextArgs(e){return[...e.workspaceId?[`--workspace-id=${e.workspaceId}`]:[],...e.profile?[`--profile=${e.profile}`]:[]]}const Zr={config:B(H.string().default(Xr),{alias:`c`,description:`Path to Tailor config file`,env:`TAILOR_CONFIG_PATH`,completion:{type:`file`,extensions:[`ts`]}})},Qr={config:B(H.string().default(Xr),{alias:`c`,description:`Path to SDK config file. Use comma-separated paths to deploy multiple apps together.`,env:`TAILOR_PLATFORM_SDK_CONFIG_PATH`,completion:{type:`file`,extensions:[`ts`]}})},$r={...J,...Zr},ei={yes:B(H.boolean().default(!1),{alias:`y`,description:`Skip confirmation prompts`})},ti={"organization-id":B(H.string(),{alias:`o`,description:`Organization ID`,env:`TAILOR_PLATFORM_ORGANIZATION_ID`,completion:{type:`none`}})},paginationArgs=(e=`desc`)=>({order:B(Jr.default(e),{description:`Sort order (asc or desc)`}),limit:B(qr.optional(),{alias:`l`,description:`Maximum number of items to return (0 or omit: unlimited)`})}),ni={order:B(Jr.default(`desc`),{description:`Sort order (asc or desc)`}),limit:B(qr.default(50),{alias:`l`,description:`Maximum number of items to return (0: unlimited)`})},ri={"folder-id":B(H.string(),{alias:`f`,description:`Folder ID`,env:`TAILOR_PLATFORM_FOLDER_ID`,completion:{type:`none`}})},Y=Ln();async function runDefaultSubCommand(e,t=[]){let n=await zn(e,t);if(!n.success)throw n.error}const ii=H.union([H.string(),H.number(),H.boolean()]),ai=H.union([H.string(),H.number()]),oi=H.union([ii,H.strictObject({value:ai,allowSecretReason:H.string().min(1,{message:`'allowSecretReason' must state why the value is safe to keep in 'env'.`})})]),si=H.enum(Lt),ci=/^[a-z][a-z0-9_-]{0,62}$/,li=/^$|^[a-z][a-z0-9_-]{0,62}$/,ui=`sdk-`,di=H.string().regex(li,{message:`'metadata' values must match ${li.source}.`}),fi=H.record(H.string(),di).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)ci.test(e)?e.startsWith(ui)&&t.addIssue({code:`custom`,path:[e],message:`'metadata' keys starting with '${ui}' are reserved for the SDK.`}):t.addIssue({code:`custom`,path:[e],message:`'metadata' keys must match ${ci.source}.`})}),pi=H.string().refine(e=>si.safeParse(e.trim().toUpperCase()).success,{message:`'logLevel' must be one of: ${Lt.join(`, `)}.`}),mi=H.strictObject({id:H.uuid({message:`'id' must be a UUID.`}).optional(),name:H.string().min(1,{message:`'name' must be a non-empty string.`}),env:H.record(H.string(),oi).optional(),cors:H.array(H.string()).optional(),allowedIpAddresses:H.array(H.string()).optional(),disableIntrospection:H.boolean().optional(),inlineSourcemap:H.boolean().optional(),logLevel:pi.optional(),metadata:fi.optional(),db:H.unknown().optional(),resolver:H.unknown().optional(),idp:H.unknown().optional(),auth:H.unknown().optional(),executor:H.unknown().optional(),workflow:H.unknown().optional(),httpAdapter:H.unknown().optional(),staticWebsites:H.unknown().optional(),aiGateways:H.unknown().optional(),secrets:H.unknown().optional()}),hi=H.looseObject({id:H.string(),description:H.string(),importPath:H.string().optional(),pluginConfig:H.unknown().optional(),tableConfigRequired:H.union([H.boolean(),hn]).optional(),onTableLoaded:hn.optional(),onNamespaceLoaded:hn.optional(),onTailorDBReady:hn.optional(),onResolverReady:hn.optional(),onExecutorReady:hn.optional()}).refine(e=>!(e.onTableLoaded||e.onNamespaceLoaded)||!!e.importPath,{message:`importPath is required when plugin has definition-time hooks (onTableLoaded/onNamespaceLoaded)`}).transform(e=>e),gi=`tailor-platform-cli`;let _i;async function getEntryClass(){if(_i!==void 0)return _i;try{_i=(await import(`@napi-rs/keyring`)).Entry}catch{M.warn(`System keyring is not available. Tokens will be stored in the config file. Set TAILOR_PLATFORM_TOKEN environment variable for CI environments.`),_i=!1}return _i}async function isKeyringAvailable(){return await getEntryClass()!==!1}async function loadKeyringTokens(e){let t=await getEntryClass();if(!t)throw Error(`System keyring is not available.`);let n=new t(gi,e).getPassword();if(n!==null)try{return JSON.parse(n)}catch{return}}async function saveKeyringTokens(e,t){let n=await getEntryClass();if(!n)throw Error(`System keyring is not available.`);new n(gi,e).setPassword(JSON.stringify(t))}async function deleteKeyringTokens(e){let t=await getEntryClass();if(t)try{new t(gi,e).deletePassword()}catch{}}const vi=H.object({user:H.string(),workspace_id:H.string(),readonly:H.boolean().optional(),machine_user:H.string().optional(),machine_user_override:H.enum([`allow`,`deny`]).optional(),platform_url:H.url().optional(),oauth2_client_id:H.string().optional(),console_url:H.url().optional()}),yi=H.object({access_token:H.string(),refresh_token:H.string().optional(),token_expires_at:H.string()}),bi=H.object({storage:H.literal(`keyring`),token_expires_at:H.string()}),xi=H.object({storage:H.literal(`file`),token_expires_at:H.string(),access_token:H.string(),refresh_token:H.string().optional()}),Si=H.discriminatedUnion(`storage`,[bi,xi]),Ci=bi.extend({email:H.string().optional()}),wi=xi.extend({email:H.string().optional()}),Ti=H.discriminatedUnion(`storage`,[Ci,wi]),Ei=H.object({version:H.literal(1),users:H.partialRecord(H.string(),yi),profiles:H.partialRecord(H.string(),vi),current_user:H.string().nullable()}),Di=`2.0.0`,Oi=H.templateLiteral([H.number().int(),`.`,H.number().int(),`.`,H.number().int()]),ki=H.object({version:H.literal(2),min_sdk_version:Oi,latest_version:H.number().int().optional(),latest_min_sdk_version:Oi.optional(),users:H.partialRecord(H.string(),Si),profiles:H.partialRecord(H.string(),vi),current_user:H.string().nullable()}),Ai=H.object({version:H.literal(3),min_sdk_version:Oi,latest_version:H.number().int().optional(),latest_min_sdk_version:Oi.optional(),users:H.partialRecord(H.string(),Ti),profiles:H.partialRecord(H.string(),vi),current_user:H.string().nullable()});function platformConfigPath(){if(!dr)throw Error(`User home directory not found`);return V.join(dr,`tailor-platform`,`config.yaml`)}function platformConfigFromProfile(e){let t={...e?.platform_url?{platformUrl:e.platform_url}:{},...e?.oauth2_client_id?{oauth2ClientId:e.oauth2_client_id}:{},...e?.console_url?{consoleUrl:e.console_url}:{}};return Object.keys(t).length>0?t:void 0}function platformUserKey(e,t){let n=Mt(t);return n===nn(`https://api.tailor.tech`)?e:`${n}|${e}`}function userFromPlatformUserKey(e,t){let n=`${Mt(t)}|`;return e.startsWith(n)?e.slice(n.length):e}function canUseLegacyUserKey(e){try{return Mt()===e}catch{return!1}}function findUserByEmail(e,t,n){let r=Mt(n),i=`${r}|`,a=r===nn(gt);return Object.entries(e).find(([e,n])=>n?.email===t?a?!e.includes(`|`):e.startsWith(i):!1)}function findUserEntry(e,t,n,r={}){let i=platformUserKey(t,n),a=e.users[i];if(a)return{userKey:i,userEntry:a};let o=findUserByEmail(e.users,t,n);if(o?.[1])return{userKey:o[0],userEntry:o[1]};let s=Mt(n);if(i!==t&&(r.allowLegacyUserKey===!1||!canUseLegacyUserKey(s)))return{userKey:i,userEntry:a};let c=e.users[t];return c?{userKey:t,userEntry:c}:{userKey:i,userEntry:a}}function resolveUserTokenKey(e,t,n,r){return findUserEntry(e,t,n,r).userKey}function resolveConfigUser(e,t,n,r){let{userKey:i,userEntry:a}=findUserEntry(e,t,n,r);return a?userFromPlatformUserKey(i,n):void 0}function hasUserTokenEntry(e,t,n,r){return findUserEntry(e,t,n,r).userEntry!==void 0}function hasUserKeyForName(e,t){return e[t]!==void 0||Object.keys(e).some(e=>e.endsWith(`|${t}`))}function hasUserEmailEntry(e,t){return Object.values(e).some(e=>e?.email===t)}function hasAnyUserTokenEntry(e,t){return hasUserKeyForName(e.users,t)||hasUserEmailEntry(e.users,t)}function hasCurrentUserEntry(e,t){return hasUserKeyForName(e,t)}function migrateV1ToV2(e){let t={};for(let[n,r]of Object.entries(e.users))r&&(t[n]={access_token:r.access_token,refresh_token:r.refresh_token,token_expires_at:r.token_expires_at,storage:`file`});return{version:2,min_sdk_version:`1.29.0`,users:t,profiles:e.profiles,current_user:e.current_user}}function inferEmailFromUserId(e){return H.email().safeParse(e).success?e:void 0}function migrateV2ToV3(e){let t={};for(let[n,r]of Object.entries(e.users)){if(!r)continue;let e=inferEmailFromUserId(n);t[n]={...r,...e?{email:e}:{}}}return{version:3,min_sdk_version:Di,users:t,profiles:e.profiles,current_user:e.current_user}}function migrateV1ToV3(e){return migrateV2ToV3(migrateV1ToV2(e))}function formatUnknownError(e){return e instanceof Error?e.message:String(e)}async function trySaveTokensInKeyring(e,t){if(!await isKeyringAvailable())return!1;try{return await saveKeyringTokens(e,t),!0}catch(e){return M.warn(`System keyring failed to store credentials. Tokens will be stored in the config file. ${formatUnknownError(e)}`),!1}}async function warnIfNewerConfigAvailable(e){if(!e.latest_min_sdk_version)return;let t=(await vn()).version??`0.0.0`;ur(t,e.latest_min_sdk_version)&&M.warn(I`
|
|
1
|
+
import{t as e}from"./wait-point-registry-B-ESkTZX.mjs";import{$ as t,At as n,B as r,Bt as i,C as a,D as o,Dt as s,Et as c,Ft as l,G as u,Gt as d,I as f,J as p,Jt as m,K as h,Kt as g,L as _,Lt as v,M as y,Mt as b,N as x,Nt as S,O as C,Ot as w,P as ee,Pt as te,R as ne,Rt as re,S as ie,St as ae,Tt as oe,U as se,V as ce,W as le,Wt as ue,X as de,Xt as fe,Yt as pe,Z as me,Zt as he,_ as ge,_t as _e,a as ve,at as ye,b as be,bt as xe,ct as Se,d as Ce,dt as we,et as T,f as Te,ft as Ee,g as De,gt as Oe,h as E,ht as ke,i as Ae,in as je,it as Me,j as Ne,jt as Pe,k as Fe,kt as Ie,l as D,lt as Le,mt as Re,nn as ze,nt as Be,o as Ve,ot as He,p as Ue,pt as We,r as Ge,rn as Ke,rt as qe,s as Je,st as Ye,t as Xe,tn as Ze,tt as O,u as Qe,ut as $e,v as et,vt as tt,w as nt,wt as rt,x as it,xt as at,y as ot,yt as st,zt as ct}from"./workspace_resource_pb-BOoRts_z.mjs";import{t as k}from"./assert-WeXvmG4j.mjs";import{a as A,c as lt,i as j,n as M,o as ut,r as dt,s as ft,t as pt}from"./logger-72hM4JWZ.mjs";import{$ as mt,A as ht,B as gt,C as _t,D as vt,E as yt,G as bt,H as xt,J as St,K as Ct,L as wt,M as Tt,N as Et,O as Dt,Q as Ot,R as kt,S as At,T as jt,U as Mt,W as N,X as Nt,Y as Pt,Z as P,a as Ft,at as It,c as Lt,ct as Rt,et as F,f as zt,g as Bt,i as Vt,it as Ht,j as Ut,k as Wt,l as Gt,lt as Kt,n as qt,nt as Jt,ot as Yt,p as Xt,r as Zt,rt as Qt,s as $t,st as en,t as tn,tt as nn,u as rn,ut as an,v as on,w as sn,x as cn,y as ln,z as un}from"./application-BYlhYQyh.mjs";import{_ as dn,d as fn,g as pn,l as mn,t as hn,v as gn,x as _n,y as vn}from"./service-CuqkHP1r.mjs";import{a as yn}from"./guards-ForsrxnH.mjs";import{t as I}from"./multiline-EyzjEwn9.mjs";import{t as bn}from"./package-json-C690ceex.mjs";import{t as xn}from"./user-agent-vdHYF3QL.mjs";import{a as L,c as Sn,o as Cn,r as wn,s as Tn,t as R}from"./errors-BjJnpXkK.mjs";import{n as En,r as Dn}from"./secret-file-C9wp_FCX.mjs";import{r as z}from"./telemetry-Bklv9kQY.mjs";import{t as On}from"./manager-qfbUL7ru.mjs";import{n as kn,r as An,t as jn}from"./tailordb-ddl-Fgm2cNvT.mjs";import{a as Mn,i as Nn,o as Pn,r as Fn,s as In,t as Ln}from"./seed-C3P_T_Eh.mjs";import*as Rn from"node:module";import{arg as B,createDefineCommand as zn,defineCommand as Bn,runCommand as Vn}from"@politty/zod";import*as V from"pathe";import{basename as Hn,dirname as Un,isAbsolute as Wn,join as Gn,relative as Kn,resolve as qn,sep as Jn}from"pathe";import{resolveTSConfig as Yn}from"pkg-types";import{z as H}from"zod";import{create as Xn,createRegistry as Zn,fromJson as Qn,toJson as $n}from"@bufbuild/protobuf";import*as U from"node:fs";import{mkdirSync as er,readFileSync as tr,realpathSync as nr,renameSync as rr,rmSync as ir,statSync as ar,utimesSync as or,writeFileSync as sr}from"node:fs";import{parseEnv as cr,stripVTControlCharacters as lr}from"node:util";import{ValueSchema as ur,timestampDate as W}from"@bufbuild/protobuf/wkt";import{formatDistanceToNowStrict as dr}from"date-fns";import{pathToFileURL as fr}from"node:url";import{parseYAML as pr,stringifyYAML as mr}from"confbox";import{findUpSync as hr}from"find-up-simple";import{lt as gr}from"semver";import{xdgConfig as _r}from"xdg-basedir";import{Code as G,ConnectError as K}from"@connectrpc/connect";import vr from"p-limit";import*as yr from"node:crypto";import{createHash as br,randomUUID as xr}from"node:crypto";import{ExitPromptError as Sr}from"@inquirer/core";import{confirm as Cr,input as wr,password as Tr,select as Er}from"@inquirer/prompts";import{isCI as Dr}from"std-env";import*as Or from"rolldown";import{parseSync as kr}from"oxc-parser";import*as Ar from"inflection";import{tmpdir as jr}from"node:os";import{pathToString as Mr,usedTypes as Nr}from"@bufbuild/protobuf/reflect";import{createValidator as Pr}from"@bufbuild/protovalidate";import*as q from"node:fs/promises";import{mkdir as Fr,readFile as Ir,rename as Lr,rm as Rr,writeFile as zr}from"node:fs/promises";import{setTimeout as Br}from"timers/promises";import{setTimeout as Vr}from"node:timers/promises";import{spawn as Hr}from"node:child_process";import*as Ur from"fs";import{lookup as Wr}from"mime-types";import{createPrompt as Gr}from"@toiroakr/read-multiline";import{astVisitor as Kr,parse as qr}from"pgsql-ast-parser";import{parse as Jr}from"@0no-co/graphql.web";const Yr={ms:1,s:1e3,m:6e4},Xr=/^(\d+)(ms|s|m)$/,Zr=H.string().refine(e=>Xr.test(e),{message:`Invalid duration format. Expected format: '3s', '500ms', '1m'`}).refine(e=>{let t=e.match(Xr);if(!t)return!1;let n=t[1];return n!==void 0&&parseInt(n,10)>0},{message:`Duration must be greater than 0`});function parseDuration(e){let t=k(e.match(Xr),`invalid duration format: ${e}`),n=parseInt(k(t[1],`duration digits group missing`),10),r=k(t[2],`duration unit group missing`);return n*Yr[r]}const Qr=H.coerce.number().int().positive(),$r=H.coerce.number().int().nonnegative(),ei=H.enum([`asc`,`desc`]);function toPageDirection(e){if(e!==void 0)return e===`asc`?je.ASC:je.DESC}function hasMachineUserFlag(e){return e.slice(0,e.indexOf(`--`)===-1?e.length:e.indexOf(`--`)).some(e=>e===`-m`||e.startsWith(`-m=`)||e===`--machine-user`||e.startsWith(`--machine-user=`)||e===`--machineUser`||e.startsWith(`--machineUser=`)||e===`--machineuser`||e.startsWith(`--machineuser=`))}function resolveMachineUserInputSource(e,t=process.argv.slice(2),n={}){if(e!==void 0)return n.valueIsExplicit||hasMachineUserFlag(t)?`option`:process.env.TAILOR_PLATFORM_MACHINE_USER_NAME===e?`env`:`option`}function loadEnvFiles(e,t){let n=new Set(Object.keys(process.env)),load=(e,t)=>{for(let r of[e??[]].flat()){let e=V.resolve(process.cwd(),r);if(!U.existsSync(e)){if(t)throw Error(`Environment file not found: ${e}`);continue}let i=U.readFileSync(e,`utf-8`),a=cr(i);for(let[e,t]of Object.entries(a))n.has(e)||(process.env[e]=t)}};load(e,!0),load(t,!1)}function createCommonArgs(e={}){return{"env-file":B(H.string().optional(),{alias:`e`,description:`Path to the environment file (error if not found)`,completion:{type:`file`,matcher:[`.env.*`,`.env`]}}),"env-file-if-exists":B(H.string().optional(),{description:`Path to the environment file (ignored if not found)`,completion:{type:`file`,matcher:[`.env.*`,`.env`]},effect:(e,{args:t})=>{loadEnvFiles(t[`env-file`],t[`env-file-if-exists`])}}),verbose:B(H.boolean().default(!1),{...e.verboseAlias===void 0?{}:{alias:e.verboseAlias},description:`Enable verbose logging`,effect:e=>{M.verbose=e}}),json:B(H.boolean().default(!1),{alias:`j`,description:`Output as JSON`,effect:e=>{M.jsonMode=e}})}}const ti=createCommonArgs(),J={"workspace-id":B(H.string().optional(),{alias:`w`,description:`Workspace ID`,env:`TAILOR_PLATFORM_WORKSPACE_ID`,completion:{type:`none`}}),profile:B(H.string().optional(),{alias:`p`,description:`Workspace profile`,env:`TAILOR_PLATFORM_PROFILE`,completion:{type:`none`}})},ni=`tailor.config.ts`;function formatConfigArg(e){if(!e)return;let t=V.relative(process.cwd(),e);if(t!==`tailor.config.ts`)return`--config=${t}`}function recoveryContextArgs(e){return[...e.workspaceId?[`--workspace-id=${e.workspaceId}`]:[],...e.profile?[`--profile=${e.profile}`]:[]]}const ri={config:B(H.string().default(ni),{alias:`c`,description:`Path to Tailor config file`,env:`TAILOR_CONFIG_PATH`,completion:{type:`file`,extensions:[`ts`]}})},ii={config:B(H.string().default(ni),{alias:`c`,description:`Path to SDK config file. Use comma-separated paths to deploy multiple apps together.`,env:`TAILOR_PLATFORM_SDK_CONFIG_PATH`,completion:{type:`file`,extensions:[`ts`]}})},ai={...J,...ri},oi={yes:B(H.boolean().default(!1),{alias:`y`,description:`Skip confirmation prompts`})},si={"organization-id":B(H.string(),{alias:`o`,description:`Organization ID`,env:`TAILOR_PLATFORM_ORGANIZATION_ID`,completion:{type:`none`}})},paginationArgs=(e=`desc`)=>({order:B(ei.default(e),{description:`Sort order (asc or desc)`}),limit:B($r.optional(),{alias:`l`,description:`Maximum number of items to return (0 or omit: unlimited)`})}),ci={order:B(ei.default(`desc`),{description:`Sort order (asc or desc)`}),limit:B($r.default(50),{alias:`l`,description:`Maximum number of items to return (0: unlimited)`})},li={"folder-id":B(H.string(),{alias:`f`,description:`Folder ID`,env:`TAILOR_PLATFORM_FOLDER_ID`,completion:{type:`none`}})},Y=zn();async function runDefaultSubCommand(e,t=[]){let n=await Vn(e,t);if(!n.success)throw n.error}const ui=H.union([H.string(),H.number(),H.boolean()]),di=H.union([H.string(),H.number()]),fi=H.union([ui,H.strictObject({value:di,allowSecretReason:H.string().min(1,{message:`'allowSecretReason' must state why the value is safe to keep in 'env'.`})})]),pi=H.enum(an),mi=/^[a-z][a-z0-9_-]{0,62}$/,hi=/^$|^[a-z][a-z0-9_-]{0,62}$/,gi=`sdk-`,_i=H.string().regex(hi,{message:`'metadata' values must match ${hi.source}.`}),vi=H.record(H.string(),_i).superRefine((e,t)=>{let n=Object.keys(e);n.length>17&&t.addIssue({code:`custom`,message:`'metadata' can hold at most 17 entries.`});for(let e of n)mi.test(e)?e.startsWith(gi)&&t.addIssue({code:`custom`,path:[e],message:`'metadata' keys starting with '${gi}' are reserved for the SDK.`}):t.addIssue({code:`custom`,path:[e],message:`'metadata' keys must match ${mi.source}.`})}),yi=H.string().refine(e=>pi.safeParse(e.trim().toUpperCase()).success,{message:`'logLevel' must be one of: ${an.join(`, `)}.`}),bi=H.strictObject({id:H.uuid({message:`'id' must be a UUID.`}).optional(),name:H.string().min(1,{message:`'name' must be a non-empty string.`}),env:H.record(H.string(),fi).optional(),cors:H.array(H.string()).optional(),allowedIpAddresses:H.array(H.string()).optional(),disableIntrospection:H.boolean().optional(),inlineSourcemap:H.boolean().optional(),logLevel:yi.optional(),metadata:vi.optional(),db:H.unknown().optional(),resolver:H.unknown().optional(),idp:H.unknown().optional(),auth:H.unknown().optional(),executor:H.unknown().optional(),workflow:H.unknown().optional(),httpAdapter:H.unknown().optional(),staticWebsites:H.unknown().optional(),aiGateways:H.unknown().optional(),secrets:H.unknown().optional()}),xi=H.looseObject({id:H.string(),description:H.string(),importPath:H.string().optional(),pluginConfig:H.unknown().optional(),tableConfigRequired:H.union([H.boolean(),_n]).optional(),onTableLoaded:_n.optional(),onNamespaceLoaded:_n.optional(),onTailorDBReady:_n.optional(),onResolverReady:_n.optional(),onExecutorReady:_n.optional()}).refine(e=>!(e.onTableLoaded||e.onNamespaceLoaded)||!!e.importPath,{message:`importPath is required when plugin has definition-time hooks (onTableLoaded/onNamespaceLoaded)`}).transform(e=>e),Si=`tailor-platform-cli`;let Ci;async function getEntryClass(){if(Ci!==void 0)return Ci;try{Ci=(await import(`@napi-rs/keyring`)).Entry}catch{M.warn(`System keyring is not available. Tokens will be stored in the config file. Set TAILOR_PLATFORM_TOKEN environment variable for CI environments.`),Ci=!1}return Ci}async function isKeyringAvailable(){return await getEntryClass()!==!1}async function loadKeyringTokens(e){let t=await getEntryClass();if(!t)throw Error(`System keyring is not available.`);let n=new t(Si,e).getPassword();if(n!==null)try{return JSON.parse(n)}catch{return}}async function saveKeyringTokens(e,t){let n=await getEntryClass();if(!n)throw Error(`System keyring is not available.`);new n(Si,e).setPassword(JSON.stringify(t))}async function deleteKeyringTokens(e){let t=await getEntryClass();if(t)try{new t(Si,e).deletePassword()}catch{}}const wi=H.object({user:H.string(),workspace_id:H.string(),readonly:H.boolean().optional(),machine_user:H.string().optional(),machine_user_override:H.enum([`allow`,`deny`]).optional(),platform_url:H.url().optional(),oauth2_client_id:H.string().optional(),console_url:H.url().optional()}),Ti=H.object({access_token:H.string(),refresh_token:H.string().optional(),token_expires_at:H.string()}),Ei=H.object({storage:H.literal(`keyring`),token_expires_at:H.string()}),Di=H.object({storage:H.literal(`file`),token_expires_at:H.string(),access_token:H.string(),refresh_token:H.string().optional()}),Oi=H.discriminatedUnion(`storage`,[Ei,Di]),ki=Ei.extend({email:H.string().optional()}),Ai=Di.extend({email:H.string().optional()}),ji=H.discriminatedUnion(`storage`,[ki,Ai]),Mi=H.object({version:H.literal(1),users:H.partialRecord(H.string(),Ti),profiles:H.partialRecord(H.string(),wi),current_user:H.string().nullable()}),Ni=`2.0.0`,Pi=H.templateLiteral([H.number().int(),`.`,H.number().int(),`.`,H.number().int()]),Fi=H.object({version:H.literal(2),min_sdk_version:Pi,latest_version:H.number().int().optional(),latest_min_sdk_version:Pi.optional(),users:H.partialRecord(H.string(),Oi),profiles:H.partialRecord(H.string(),wi),current_user:H.string().nullable()}),Ii=H.object({version:H.literal(3),min_sdk_version:Pi,latest_version:H.number().int().optional(),latest_min_sdk_version:Pi.optional(),users:H.partialRecord(H.string(),ji),profiles:H.partialRecord(H.string(),wi),current_user:H.string().nullable()});function platformConfigPath(){if(!_r)throw Error(`User home directory not found`);return V.join(_r,`tailor-platform`,`config.yaml`)}function platformConfigFromProfile(e){let t={...e?.platform_url?{platformUrl:e.platform_url}:{},...e?.oauth2_client_id?{oauth2ClientId:e.oauth2_client_id}:{},...e?.console_url?{consoleUrl:e.console_url}:{}};return Object.keys(t).length>0?t:void 0}function platformUserKey(e,t){let n=Ot(t);return n===Qt(`https://api.tailor.tech`)?e:`${n}|${e}`}function userFromPlatformUserKey(e,t){let n=`${Ot(t)}|`;return e.startsWith(n)?e.slice(n.length):e}function canUseLegacyUserKey(e){try{return Ot()===e}catch{return!1}}function findUserByEmail(e,t,n){let r=Ot(n),i=`${r}|`,a=r===Qt(xt);return Object.entries(e).find(([e,n])=>n?.email===t?a?!e.includes(`|`):e.startsWith(i):!1)}function findUserEntry(e,t,n,r={}){let i=platformUserKey(t,n),a=e.users[i];if(a)return{userKey:i,userEntry:a};let o=findUserByEmail(e.users,t,n);if(o?.[1])return{userKey:o[0],userEntry:o[1]};let s=Ot(n);if(i!==t&&(r.allowLegacyUserKey===!1||!canUseLegacyUserKey(s)))return{userKey:i,userEntry:a};let c=e.users[t];return c?{userKey:t,userEntry:c}:{userKey:i,userEntry:a}}function resolveUserTokenKey(e,t,n,r){return findUserEntry(e,t,n,r).userKey}function resolveConfigUser(e,t,n,r){let{userKey:i,userEntry:a}=findUserEntry(e,t,n,r);return a?userFromPlatformUserKey(i,n):void 0}function hasUserTokenEntry(e,t,n,r){return findUserEntry(e,t,n,r).userEntry!==void 0}function hasUserKeyForName(e,t){return e[t]!==void 0||Object.keys(e).some(e=>e.endsWith(`|${t}`))}function hasUserEmailEntry(e,t){return Object.values(e).some(e=>e?.email===t)}function hasAnyUserTokenEntry(e,t){return hasUserKeyForName(e.users,t)||hasUserEmailEntry(e.users,t)}function hasCurrentUserEntry(e,t){return hasUserKeyForName(e,t)}function migrateV1ToV2(e){let t={};for(let[n,r]of Object.entries(e.users))r&&(t[n]={access_token:r.access_token,refresh_token:r.refresh_token,token_expires_at:r.token_expires_at,storage:`file`});return{version:2,min_sdk_version:`1.29.0`,users:t,profiles:e.profiles,current_user:e.current_user}}function inferEmailFromUserId(e){return H.email().safeParse(e).success?e:void 0}function migrateV2ToV3(e){let t={};for(let[n,r]of Object.entries(e.users)){if(!r)continue;let e=inferEmailFromUserId(n);t[n]={...r,...e?{email:e}:{}}}return{version:3,min_sdk_version:Ni,users:t,profiles:e.profiles,current_user:e.current_user}}function migrateV1ToV3(e){return migrateV2ToV3(migrateV1ToV2(e))}function formatUnknownError(e){return e instanceof Error?e.message:String(e)}async function trySaveTokensInKeyring(e,t){if(!await isKeyringAvailable())return!1;try{return await saveKeyringTokens(e,t),!0}catch(e){return M.warn(`System keyring failed to store credentials. Tokens will be stored in the config file. ${formatUnknownError(e)}`),!1}}async function warnIfNewerConfigAvailable(e){if(!e.latest_min_sdk_version)return;let t=(await bn()).version??`0.0.0`;gr(t,e.latest_min_sdk_version)&&M.warn(I`
|
|
2
2
|
A newer config version (${String(e.latest_version)}) is available.
|
|
3
3
|
Please update your SDK to >= ${e.latest_min_sdk_version}: pnpm update @tailor-platform/sdk
|
|
4
|
-
`)}async function readPlatformConfig(){let e=platformConfigPath();if(!U.existsSync(e)){let e={version:3,min_sdk_version:
|
|
4
|
+
`)}async function readPlatformConfig(){let e=platformConfigPath();if(!U.existsSync(e)){let e={version:3,min_sdk_version:Ni,users:{},profiles:{},current_user:null};return writePlatformConfig(e),e}let t=pr(U.readFileSync(e,`utf-8`));En(e);let n=typeof t==`object`&&t&&`version`in t?t.version:void 0;if(typeof n==`number`&&n>3){let e=`min_sdk_version`in t?String(t.min_sdk_version):void 0,r=e?`Please update your SDK to >= ${e}: pnpm update @tailor-platform/sdk`:`Please update your SDK: pnpm update @tailor-platform/sdk`;throw Error(I`
|
|
5
5
|
Config file uses version ${String(n)}, but this SDK only supports up to version ${`3`}.
|
|
6
6
|
${r}
|
|
7
|
-
`)}let r=
|
|
7
|
+
`)}let r=Ii.safeParse(t);if(r.success)return await warnIfNewerConfigAvailable(r.data),r.data;let i=Fi.safeParse(t);if(i.success)return await warnIfNewerConfigAvailable(i.data),migrateV2ToV3(i.data);let a=Mi.safeParse(t);if(a.success)return migrateV1ToV3(a.data);throw Error(I`
|
|
8
8
|
Failed to parse config file at ${e}.
|
|
9
9
|
The file may be corrupted or created by an incompatible SDK version.
|
|
10
|
-
`)}function toV1ForDisk(e){let t={};for(let[n,r]of Object.entries(e.users))r&&r.storage!==`keyring`&&(t[n]={access_token:r.access_token,refresh_token:r.refresh_token,token_expires_at:r.token_expires_at});let n=e.current_user&&hasCurrentUserEntry(t,e.current_user)?e.current_user:null;return{version:1,users:t,profiles:e.profiles,current_user:n}}function hasProfilePlatformSettings(e){return Object.values(e.profiles).some(e=>e?.platform_url!==void 0||e?.oauth2_client_id!==void 0||e?.console_url!==void 0)}function hasScopedUserKeys(e){return Object.keys(e.users).some(e=>e.includes(`|`))}function hasUserEmailMetadata(e){return Object.values(e.users).some(e=>e!=null&&`email`in e&&e.email!==void 0)}function toLatestForDisk(e){return{...e.version===1?migrateV1ToV2(e):e,version:3,min_sdk_version:
|
|
10
|
+
`)}function toV1ForDisk(e){let t={};for(let[n,r]of Object.entries(e.users))r&&r.storage!==`keyring`&&(t[n]={access_token:r.access_token,refresh_token:r.refresh_token,token_expires_at:r.token_expires_at});let n=e.current_user&&hasCurrentUserEntry(t,e.current_user)?e.current_user:null;return{version:1,users:t,profiles:e.profiles,current_user:n}}function hasProfilePlatformSettings(e){return Object.values(e.profiles).some(e=>e?.platform_url!==void 0||e?.oauth2_client_id!==void 0||e?.console_url!==void 0)}function hasScopedUserKeys(e){return Object.keys(e.users).some(e=>e.includes(`|`))}function hasUserEmailMetadata(e){return Object.values(e.users).some(e=>e!=null&&`email`in e&&e.email!==void 0)}function toLatestForDisk(e){return{...e.version===1?migrateV1ToV2(e):e,version:3,min_sdk_version:Ni}}function writePlatformConfig(e){let t=platformConfigPath(),n=e.version!==1&&Object.values(e.users).some(e=>e?.storage===`keyring`),r=e.version===3||hasProfilePlatformSettings(e)||hasScopedUserKeys(e)||hasUserEmailMetadata(e)?toLatestForDisk(e):e.version===2&&!n?toV1ForDisk(e):e;Dn(t,mr(r))}function validateUUID(e,t){let n=H.uuid().safeParse(e);if(!n.success)throw Error(`Invalid value from ${t}: must be a valid UUID`);return n.data}async function loadWorkspaceId(e){let t=await tryLoadWorkspaceId(e);if(t)return t;throw Error(I`
|
|
11
11
|
Workspace ID not found.
|
|
12
12
|
Please specify workspace ID via --workspace-id option or TAILOR_PLATFORM_WORKSPACE_ID environment variable.
|
|
13
|
-
`)}async function tryLoadWorkspaceId(e){let t=e?.profile||process.env.TAILOR_PLATFORM_PROFILE;if(e?.workspaceId!==void 0)return validateUUID(e.workspaceId,`--workspace-id option`);if(process.env.TAILOR_PLATFORM_WORKSPACE_ID)return validateUUID(process.env.TAILOR_PLATFORM_WORKSPACE_ID,`TAILOR_PLATFORM_WORKSPACE_ID environment variable`);if(t){let e=(await readPlatformConfig()).profiles[t]?.workspace_id;if(!e)throw Error(`Profile "${t}" not found`);return validateUUID(e,`profile "${t}"`)}}async function loadMachineUserName(e){if(e?.machineUser===``)throw R({code:`MACHINE_USER_NAME_EMPTY`,message:`Machine user name cannot be empty.`,suggestion:`Pass a non-empty machine user name, or omit the option to use the environment variable or profile default.`});let t=process.env.TAILOR_PLATFORM_MACHINE_USER_NAME||void 0,n=e?.machineUser?{source:e.machineUserSource??`option`,value:e.machineUser}:t?{source:`env`,value:t}:void 0,r=n?.value,i=e?.profile||process.env.TAILOR_PLATFORM_PROFILE;if(!i)return r;let a=(await readPlatformConfig()).profiles[i];if(!a){if(r)return r;throw Error(`Profile "${i}" not found`)}if(a.machine_user&&a.machine_user_override===`deny`){if(r&&r!==a.machine_user){let e=n.source===`env`?`The machine user is being set to "${r}" via the TAILOR_PLATFORM_MACHINE_USER_NAME environment variable, which conflicts with this profile's pinned machine user "${a.machine_user}".`:`This profile fixes the machine user to "${a.machine_user}" for application-data commands.`;throw R({code:`PROFILE_MACHINE_USER_OVERRIDE_DENIED`,message:`Profile "${i}" denies overriding the machine user.`,details:e,suggestion:`Omit the machine user option, unset TAILOR_PLATFORM_MACHINE_USER_NAME, or run 'tailor profile update ${i} --machine-user-override allow'.`})}return a.machine_user}return r||a.machine_user}async function loadAccessToken(e){let t=e?.profile||process.env.TAILOR_PLATFORM_PROFILE,n=process.env.TAILOR_PLATFORM_TOKEN??process.env.TAILOR_TOKEN;if(n&&!process.env.TAILOR_PLATFORM_TOKEN&&M.warn(`TAILOR_TOKEN is deprecated. Please use TAILOR_PLATFORM_TOKEN instead.`),n){M.registerSecret(n);let e=await loadPlatformClientConfig({profile:t,allowMissingProfile:!0});return
|
|
13
|
+
`)}async function tryLoadWorkspaceId(e){let t=e?.profile||process.env.TAILOR_PLATFORM_PROFILE;if(e?.workspaceId!==void 0)return validateUUID(e.workspaceId,`--workspace-id option`);if(process.env.TAILOR_PLATFORM_WORKSPACE_ID)return validateUUID(process.env.TAILOR_PLATFORM_WORKSPACE_ID,`TAILOR_PLATFORM_WORKSPACE_ID environment variable`);if(t){let e=(await readPlatformConfig()).profiles[t]?.workspace_id;if(!e)throw Error(`Profile "${t}" not found`);return validateUUID(e,`profile "${t}"`)}}async function loadMachineUserName(e){if(e?.machineUser===``)throw R({code:`MACHINE_USER_NAME_EMPTY`,message:`Machine user name cannot be empty.`,suggestion:`Pass a non-empty machine user name, or omit the option to use the environment variable or profile default.`});let t=process.env.TAILOR_PLATFORM_MACHINE_USER_NAME||void 0,n=e?.machineUser?{source:e.machineUserSource??`option`,value:e.machineUser}:t?{source:`env`,value:t}:void 0,r=n?.value,i=e?.profile||process.env.TAILOR_PLATFORM_PROFILE;if(!i)return r;let a=(await readPlatformConfig()).profiles[i];if(!a){if(r)return r;throw Error(`Profile "${i}" not found`)}if(a.machine_user&&a.machine_user_override===`deny`){if(r&&r!==a.machine_user){let e=n.source===`env`?`The machine user is being set to "${r}" via the TAILOR_PLATFORM_MACHINE_USER_NAME environment variable, which conflicts with this profile's pinned machine user "${a.machine_user}".`:`This profile fixes the machine user to "${a.machine_user}" for application-data commands.`;throw R({code:`PROFILE_MACHINE_USER_OVERRIDE_DENIED`,message:`Profile "${i}" denies overriding the machine user.`,details:e,suggestion:`Omit the machine user option, unset TAILOR_PLATFORM_MACHINE_USER_NAME, or run 'tailor profile update ${i} --machine-user-override allow'.`})}return a.machine_user}return r||a.machine_user}async function loadAccessToken(e){let t=e?.profile||process.env.TAILOR_PLATFORM_PROFILE,n=process.env.TAILOR_PLATFORM_TOKEN??process.env.TAILOR_TOKEN;if(n&&!process.env.TAILOR_PLATFORM_TOKEN&&M.warn(`TAILOR_TOKEN is deprecated. Please use TAILOR_PLATFORM_TOKEN instead.`),n){M.registerSecret(n);let e=await loadPlatformClientConfig({profile:t,allowMissingProfile:!0});return Ht(n,e),n}let r=await readPlatformConfig(),i=t?r.profiles[t]:void 0;if(t&&!i)throw Error(`Profile "${t}" not found`);let a=i?.user??r.current_user;if(!a)throw R({code:`AUTH_TOKEN_NOT_FOUND`,message:`Tailor Platform token not found.`,suggestion:`Set TAILOR_PLATFORM_TOKEN or log in using the selected profile.`,next:{command:`tailor`,args:[`login`,...recoveryContextArgs({profile:t})]},context:{profile:t??null}});return(await fetchLatestToken(r,a,i?platformConfigFromProfile(i):void 0,t)).accessToken}async function loadAuthStatus(e){let t=e?.profile||process.env.TAILOR_PLATFORM_PROFILE,n=process.env.TAILOR_PLATFORM_TOKEN??process.env.TAILOR_TOKEN;if(n&&!process.env.TAILOR_PLATFORM_TOKEN&&M.warn(`TAILOR_TOKEN is deprecated. Please use TAILOR_PLATFORM_TOKEN instead.`),n){M.registerSecret(n);let e=await readPlatformConfig().catch(()=>void 0),r=t?e?.profiles[t]:void 0,i=r?platformConfigFromProfile(r):void 0;return{authenticated:!0,identity:null,identitySource:`environment`,profile:t??null,workspaceId:process.env.TAILOR_PLATFORM_WORKSPACE_ID??r?.workspace_id??null,permission:r?.readonly===!0?`read`:`write`,platformUrl:Ot(i),tokenStatus:`environment`}}let r=await readPlatformConfig(),i=t?r.profiles[t]:void 0;if(t&&!i)throw Error(`Profile "${t}" not found`);let a=i?platformConfigFromProfile(i):void 0,o=Ot(a),s=process.env.TAILOR_PLATFORM_WORKSPACE_ID??i?.workspace_id??null,c=i?.user??r.current_user,l=i?.user?`profile`:c?`default`:`none`,u=`missing`;if(c){let{userKey:e,userEntry:t}=findUserEntry(r,c,a);if(t){let n=await resolveTokens(t,e,c).catch(()=>void 0);n&&(u=new Date(t.token_expires_at)<=new Date?n.refreshToken?`refreshable`:`expired`:`valid`)}}return{authenticated:u===`valid`||u===`refreshable`,identity:c??null,identitySource:l,profile:t??null,workspaceId:s,permission:i?.readonly===!0?`read`:`write`,platformUrl:o,tokenStatus:u}}async function loadPlatformClientConfig(e){let t=e?.profile||process.env.TAILOR_PLATFORM_PROFILE;if(!t)return;let n;try{n=await readPlatformConfig()}catch(t){if(e?.allowMissingProfile)return;throw t}let r=n.profiles[t];if(!r){if(e?.allowMissingProfile)return;throw Error(`Profile "${t}" not found`)}return platformConfigFromProfile(r)}async function loadConsoleBaseUrl(e){let t=await loadPlatformClientConfig(e);return Pt(t)}function registerTokenSecrets(e){M.registerSecret(e.accessToken),e.refreshToken&&M.registerSecret(e.refreshToken)}async function resolveTokens(e,t,n=t){if(e.storage===`keyring`){let e;try{e=await loadKeyringTokens(t)}catch(e){throw Error(I`
|
|
14
14
|
Failed to read credentials from OS keyring for "${n}". ${formatUnknownError(e)}
|
|
15
15
|
Restore access to the OS keyring and try again, or run 'tailor login' in this environment to authenticate again.
|
|
16
16
|
For non-interactive environments, set TAILOR_PLATFORM_TOKEN.
|
|
@@ -19,20 +19,20 @@ import{t as e}from"./wait-point-registry-B-ESkTZX.mjs";import{$ as t,At as n,B a
|
|
|
19
19
|
Credentials may be missing or inaccessible from this environment (for example, due to sandbox restrictions).
|
|
20
20
|
Restore access to the OS keyring and try again, or run 'tailor login' in this environment to authenticate again.
|
|
21
21
|
For non-interactive environments, set TAILOR_PLATFORM_TOKEN.
|
|
22
|
-
`);return registerTokenSecrets(e),e}let r={accessToken:e.access_token,refreshToken:e.refresh_token};return registerTokenSecrets(r),r}async function saveUserTokens(e,t,n,r,i={}){registerTokenSecrets(n);let a=platformUserKey(t,i.platformConfig),o=i.email??e.users[a]?.email;await trySaveTokensInKeyring(a,n)?e.users[a]={token_expires_at:r,storage:`keyring`,...o?{email:o}:{}}:(e.users[a]?.storage===`keyring`&&await deleteKeyringTokens(a),e.users[a]={access_token:n.accessToken,refresh_token:n.refreshToken,token_expires_at:r,storage:`file`,...o?{email:o}:{}})}async function deleteUserTokens(e,t,n,r){let{userKey:i,userEntry:a}=findUserEntry(e,t,n,r);a?.storage===`keyring`&&await deleteKeyringTokens(i),delete e.users[i]}async function loadStoredUserTokens(e,t,n,r){let{userKey:i,userEntry:a}=findUserEntry(e,t,n,r);if(a)return{userEntry:a,...await resolveTokens(a,i,t)}}function updateUserReferences(e,t,n){if(t!==n){e.current_user===t&&(e.current_user=n);for(let r of Object.values(e.profiles))r?.user===t&&(r.user=n)}}async function removeLegacyUserAlias(e,t,n,r){if(t===n)return;updateUserReferences(e,t,n);let i=platformUserKey(n,r),a=new Set([t,platformUserKey(t,r)]);for(let t of a)t!==i&&(e.users[t]?.storage===`keyring`&&await deleteKeyringTokens(t),delete e.users[t])}function shouldResolveSubjectOnRefresh(e,t){return!!(t.email||inferEmailFromUserId(e))}async function fetchLatestToken(e,t,n,r){let i=r?[`--profile`,r]:[],loginFailure=(e,t,n)=>R({code:e,message:t,suggestion:n,next:{command:`tailor`,args:[`login`,...i,`--help`]},context:{profile:r??null}}),{userKey:a,userEntry:o}=findUserEntry(e,t,n);if(!o)throw loginFailure(`AUTH_USER_NOT_FOUND`,`User "${t}" not found.`,`Verify the selected user and use the original login method (browser or --machine-user) on the same platform.`);let s=userFromPlatformUserKey(a,n),c=await resolveTokens(o,a,t);if(new Date(o.token_expires_at)>new Date)return
|
|
22
|
+
`);return registerTokenSecrets(e),e}let r={accessToken:e.access_token,refreshToken:e.refresh_token};return registerTokenSecrets(r),r}async function saveUserTokens(e,t,n,r,i={}){registerTokenSecrets(n);let a=platformUserKey(t,i.platformConfig),o=i.email??e.users[a]?.email;await trySaveTokensInKeyring(a,n)?e.users[a]={token_expires_at:r,storage:`keyring`,...o?{email:o}:{}}:(e.users[a]?.storage===`keyring`&&await deleteKeyringTokens(a),e.users[a]={access_token:n.accessToken,refresh_token:n.refreshToken,token_expires_at:r,storage:`file`,...o?{email:o}:{}})}async function deleteUserTokens(e,t,n,r){let{userKey:i,userEntry:a}=findUserEntry(e,t,n,r);a?.storage===`keyring`&&await deleteKeyringTokens(i),delete e.users[i]}async function loadStoredUserTokens(e,t,n,r){let{userKey:i,userEntry:a}=findUserEntry(e,t,n,r);if(a)return{userEntry:a,...await resolveTokens(a,i,t)}}function updateUserReferences(e,t,n){if(t!==n){e.current_user===t&&(e.current_user=n);for(let r of Object.values(e.profiles))r?.user===t&&(r.user=n)}}async function removeLegacyUserAlias(e,t,n,r){if(t===n)return;updateUserReferences(e,t,n);let i=platformUserKey(n,r),a=new Set([t,platformUserKey(t,r)]);for(let t of a)t!==i&&(e.users[t]?.storage===`keyring`&&await deleteKeyringTokens(t),delete e.users[t])}function shouldResolveSubjectOnRefresh(e,t){return!!(t.email||inferEmailFromUserId(e))}async function fetchLatestToken(e,t,n,r){let i=r?[`--profile`,r]:[],loginFailure=(e,t,n)=>R({code:e,message:t,suggestion:n,next:{command:`tailor`,args:[`login`,...i,`--help`]},context:{profile:r??null}}),{userKey:a,userEntry:o}=findUserEntry(e,t,n);if(!o)throw loginFailure(`AUTH_USER_NOT_FOUND`,`User "${t}" not found.`,`Verify the selected user and use the original login method (browser or --machine-user) on the same platform.`);let s=userFromPlatformUserKey(a,n),c=await resolveTokens(o,a,t);if(new Date(o.token_expires_at)>new Date)return Ht(c.accessToken,n),{accessToken:c.accessToken,user:s};if(!c.refreshToken)throw loginFailure(`AUTH_TOKEN_EXPIRED`,`Token expired.`,`Use the original login method (browser or --machine-user) to authenticate again on the same platform.`);let l=mt(n),u;try{u=await l.refreshToken({accessToken:c.accessToken,refreshToken:c.refreshToken,expiresAt:Date.parse(o.token_expires_at)})}catch{throw loginFailure(`AUTH_TOKEN_REFRESH_FAILED`,`Failed to refresh token. Your session may have expired.`,`Check network connectivity and platform availability, then use the original login method (browser or --machine-user) on the same platform if needed.`)}registerTokenSecrets({accessToken:u.accessToken,refreshToken:u.refreshToken??void 0});let d=new Date(k(u.expiresAt,`token refresh response missing expiresAt`)).toISOString(),f=s,p=o.email??inferEmailFromUserId(t)??inferEmailFromUserId(s),m=p;if(shouldResolveSubjectOnRefresh(t,o)||shouldResolveSubjectOnRefresh(s,o))try{let e=await St(u.accessToken,n);f=e.sub,m=e.email}catch(e){M.debug(`Failed to resolve refreshed token user info: ${String(e)}`)}return await saveUserTokens(e,f,{accessToken:u.accessToken,refreshToken:u.refreshToken??c.refreshToken},d,{platformConfig:n,email:m}),await removeLegacyUserAlias(e,t,f,n),a!==platformUserKey(f,n)&&(e.users[a]?.storage===`keyring`&&await deleteKeyringTokens(a),delete e.users[a]),p&&m&&p!==m&&M.info(`Updated local user email from "${p}" to "${m}".`),writePlatformConfig(e),Ht(u.accessToken,n),{accessToken:u.accessToken,user:f}}function loadConfigPath(e){return e||(process.env.TAILOR_CONFIG_PATH?process.env.TAILOR_CONFIG_PATH:hr(`tailor.config.ts`))}const Li=/^[A-Za-z0-9+/=_.-]+$/,Ri=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=br(`sha256`).update(JSON.stringify([e.configPath??``,e.env??{}])).digest(`hex`),n=Ri.get(t);if(n)return n;let r=reportEnvSecrets(e);return Ri.set(t,r),r}async function reportEnvSecrets(e){let t=await scanEnvForSecrets(e);for(let e of t)e.severity===`warning`&&M.warn(`env.${e.key} looks like a randomly generated credential. If it is one, move it to Secret Manager; otherwise allow it with ${j.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(`
|
|
23
23
|
`),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.
|
|
24
|
-
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=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||!
|
|
25
|
-
`);throw Error(`Invalid Tailor config in ${r}:\n${e}`)}let c=o.default;await assertEnvHasNoSecrets({env:c.env,configPath:r});let l=c.env?Object.fromEntries(Object.entries(c.env).map(([e,t])=>[e,resolveEnvValue(t)])):void 0,u=[];for(let e of _n(o)){let t=e.map(e=>hi.safeParse(e));t.every(e=>e.success)&&u.push(...t.map(e=>e.data))}return{config:{...c,...l?{env:l}:{},path:r},plugins:u}}async function assertWritable(e){let t=e?.profile||process.env.TAILOR_PLATFORM_PROFILE;if(!t)return;let n=(await readPlatformConfig()).profiles[t];if(n&&n.readonly===!0)throw R({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 'tailor profile update ${t} --permission write'.`})}function hasEnvAccessToken(){return!!(process.env.TAILOR_PLATFORM_TOKEN??process.env.TAILOR_TOKEN)}async function apiCall(e){let t=await loadAccessToken({profile:e.profile}),n;try{n=await loadPlatformClientConfig({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,Mt(n)),a=await fetch(i.toString(),{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${t}`,"User-Agent":await yn()},body:e.body??`{}`}),o=await a.json();if(!a.ok)throw R({code:`API_REQUEST_FAILED`,message:`API call failed (${a.status}): ${JSON.stringify(o)}`,context:{status:a.status}});return{status:a.status,data:o}}async function loadOperatorWorkspaceContext(e){let t=await loadAccessToken({profile:e.profile});return{client:await P(t),workspaceId:await loadWorkspaceId({profile:e.profile,workspaceId:e.workspaceId})}}function canPrompt(){return!xr&&process.stdin.isTTY===!0&&process.stdout.isTTY===!0&&!M.jsonMode}function withGuard(e,t){return async n=>{if(!canPrompt())throw new pt(t);try{return await e(n)}catch(e){throw e instanceof gr&&process.exit(130),e}}}const X={confirm:withGuard(_r,`Interactive confirmations are not available in this environment. Use --yes to skip confirmation prompts, or provide the required options explicitly.`),text:withGuard(vr),password:withGuard(yr),select:e=>withGuard(br)(e)};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}`,...(t.details??[]).map(e=>` ${e}`)];return[j.bold(`${e}:`),...t.flatMap(itemLines(A.create)),...r.flatMap(itemLines(A.delete)),...n.flatMap(itemLines(A.update)),...i.flatMap(itemLines(A.replace))]}}}function summarizeChangeSets(e){let t={create:0,update:0,delete:0,replace: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;return t}function formatPlanSummary(e){let t=[`${e.create} to create`,`${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 Jn(e,Gn(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 Ni=`sdk-name`,Pi=`sdk-version`,Fi=`sdk-app-id`;function sdkAppIdLabelValue(e){return`app-${e}`}function hasMatchingSdkVersion(e,t){return e?.[Pi]===t?.[Pi]}function isOwnedByApp(e,t,n){if(!e)return!1;let r=e[Fi];return r?n!==void 0&&r===sdkAppIdLabelValue(n):e[Ni]===t}function prefixFor(e){return e===`jobs`?`sdk-job-depended-by-app-`:`sdk-depended-by-app-`}const Ii=/^[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 Ii.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 Ii.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??new Map,s=r??new Set,c={};for(let[e,t]of o){let n=dependedByAppLabelKey(e,a);if(!n)throw R({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 vn(),o=a.version?`v${a.version.replace(/\./g,`-`)}`:`unknown`;return{trn:t,labels:{...i,[Ni]:n,[Pi]:o,...r?{[Fi]:sdkAppIdLabelValue(r)}:{}},remove:r?void 0:[Fi]}}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 Li=Symbol(`metadataWriteBatch`);var MetadataWriteBatch=class{#e;#t=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 F(()=>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=>xn(e)?rr(e.format()):Cn(e).message;return Ft(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===Li?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[Li];if(n){await n.enqueue(t);return}await writeMetadataLabelsDirect(e,t)}async function writeMetadataLabelsDirect(e,t){if(!hasMetadataLabelChange(t))return;let{trn:n}=t,r=(await F(()=>e.getMetadata({trn:n})))?.metadata?.labels??{},i=applyMetadataLabelWrite(r,t);areSameLabels(r,i)||await e.setMetadata({trn:n,labels:i})}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 N(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,label:a?.labels[Ni],allLabels:a?.labels}})),o}function trackDesiredResourceOwnership(e){let{labels:t,ownerLabel:n,appName:r,appId:i,resourceType:a,resourceName:o,conflicts:s,unmanaged:c}=e,l=isOwnedByApp(t,r,i);return l||(n?s.push({resourceType:a,resourceName:o,currentOwner:n}):c.push({resourceType:a,resourceName:o})),l}function trackRemainingResourceOwner(e){let{labels:t,ownerLabel:n,appName:r,appId:i,resourceOwners:a}=e,o=isOwnedByApp(t,r,i);return n&&!o&&a.add(n),o}async function applyStaticWebsite(e,t,n=`create-update`){let{changeSet:r,customDomainChangeSet:i}=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=>{await e.addCustomDomain(t.request),await writeMetadataLabels(e,t.metaRequest)}),...i.deletes.map(t=>e.removeCustomDomain(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}`}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=[],c=[],l=new Set,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=new Set,f=i?[]:r.staticWebsiteServices;for(let e of f){let t=e,i=e.name,o=u[i],l=await buildMetaRequest({trn:resourceTrn(n,`staticwebsite`,i),appName:r.name,appId:r.id}),f=normalizeComparableStaticWebsite(t),p={workspaceId:n,staticwebsite:{name:i,description:t.description||``,allowedIpAddresses:t.allowedIpAddresses||[]}};if(o){let e=trackDesiredResourceOwnership({labels:o.allLabels,ownerLabel:o.label,appName:r.name,appId:r.id,resourceType:`StaticWebsite`,resourceName:i,conflicts:s,unmanaged:c});e&&hasMatchingSdkVersion(o.allLabels,l.labels)&&areStaticWebsitesEqual(o.resource,f)?a.unchanged.push({name:i}):a.updates.push({name:i,request:p,metaRequest:l}),e&&d.add(i),delete u[i]}else a.creates.push({name:i,request:p,metaRequest:l}),d.add(i)}Object.entries(u).forEach(([e])=>{let t=u[e],i=t?.label;trackRemainingResourceOwner({labels:t?.allLabels,ownerLabel:i,appName:r.name,appId:r.id,resourceOwners:l})&&a.deletes.push({name:e,request:{workspaceId:n,name:e}})});let p=new Map;for(let e of f)e.customDomains!==void 0&&d.has(e.name)&&p.set(e.name,e.customDomains);let m=new Map,h=[...d].filter(e=>!a.creates.some(t=>t.name===e));await Promise.all(h.map(async e=>{let r=await F(async()=>{let{customDomains:r}=await t.listCustomDomains({workspaceId:n,staticWebsiteName:e});return await Promise.all(r.map(async r=>{let{metadata:i}=await t.getMetadata({trn:customDomainTrn(n,e,r.domain)});return{domain:r.domain,allLabels:i?.labels}}))});r&&m.set(e,r)}));for(let e of d){let t=new Set(p.get(e)??[]),i=m.get(e)??[],a=new Set(i.map(e=>e.domain)),s=new Set(i.filter(e=>isOwnedByApp(e.allLabels,r.name,r.id)).map(e=>e.domain));for(let i of t)if(a.has(i))o.unchanged.push({name:i});else{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 s)t.has(e)||o.deletes.push({name:e,request:{workspaceId:n,domain:e}})}return{changeSet:a,customDomainChangeSet:o,conflicts:s,unmanaged:c,resourceOwners:l}}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 Qt(e,k(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 Qt(e,k(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=[],s=[],c=new Set,l=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)}),u=i?[]:r.aiGatewayServices,d=expectedLocalStaticWebsiteNames(e);for(let e of u){let i=e,c=e.name,u=l[c],f=await buildMetaRequest({trn:resourceTrn(n,`aigateway`,c),appName:r.name,appId:r.id}),p=await Qt(t,n,i.cors?[...i.cors]:[],`AIGateway CORS`,{expectedLocalNames:d}),m=normalizeComparableAIGateway({...i,cors:p}),h={workspaceId:n,aigatewayName:c,authNamespace:i.authNamespace,cors:i.cors?[...i.cors]:[]};u?(trackDesiredResourceOwnership({labels:u.allLabels,ownerLabel:u.label,appName:r.name,appId:r.id,resourceType:`AIGateway`,resourceName:c,conflicts:o,unmanaged:s})&&hasMatchingSdkVersion(u.allLabels,f.labels)&&areAIGatewaysEqual(u.resource,m)?a.unchanged.push({name:c}):a.updates.push({name:c,request:h,metaRequest:f}),delete l[c]):a.creates.push({name:c,request:h,metaRequest:f})}return Object.entries(l).forEach(([e,t])=>{let i=t?.label;trackRemainingResourceOwner({labels:t?.allLabels,ownerLabel:i,appName:r.name,appId:r.id,resourceOwners:c})&&a.deletes.push({name:e,request:{workspaceId:n,aigatewayName:e}})}),{changeSet:a,conflicts:o,unmanaged:s,resourceOwners:c}}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 Qt(e,k(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 Qt(e,k(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)}))}function sortStrings(e){return(e??[]).toSorted()}function normalizeSubgraphs(e){return[...e??[]].map(e=>({serviceType:k(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){let{client:n,workspaceId:r,application:i,forRemoval:a}=e,o=[],s=[],c=new Set,l=createChangeSet(`Applications`),u=await N(async(e,t)=>{let{applications:i,nextPageToken:a}=await n.listApplications({workspaceId:r,pageToken:e,pageSize:t});return[i,a]});if(a){let e=i.id?u:u.filter(e=>e.name===i.name),t=await Promise.all(e.map(async e=>{let t=await fetchAppLabels(n,r,e.name);return trackRemainingResourceOwner({labels:t,ownerLabel:t?.[`sdk-name`],appName:i.name,appId:i.id,resourceOwners:c})?e.name:null}));for(let e of t)e&&l.deletes.push({name:e,request:{workspaceId:r,applicationName:e}});return withOwnership(l,o,s,c)}if(i.subgraphs.length===0)return withOwnership(l,o,s,c);let d,f;if(i.authService){d=i.authService.config.name;let e=i.authService.config.idProvider;e&&(f=e.name)}else if(i.config.auth){if(d=i.config.auth.name,e.externalAuthIdpConfigNames?.has(d))f=e.externalAuthIdpConfigNames.get(d);else{let e=await N(async(e,t)=>{let{idpConfigs:i,nextPageToken:a}=await n.listAuthIDPConfigs({workspaceId:r,namespaceName:k(d,`authNamespace must be set before listing IDP configs`),pageToken:e,pageSize:t});return[i,a]});if(e.length>0){let[t]=e;t&&(f=t.name)}}}let p=await buildMetaRequest({trn:resourceTrn(r,`application`,i.name),appName:i.name,appId:i.id,metadata:i.config.metadata}),m=await fetchAppLabels(n,r,i.name);assertLabelBudget(i.name,m,p);let h=diffMetadataDisplay(m,i.config.metadata),g=expectedLocalStaticWebsiteNames(e),_=await Qt(n,r,i.config.cors,`CORS`,{expectedLocalNames:g}),v=buildHttpAdapters(i,t),y=normalizeComparableApplication(i,d,f,_,v),b={workspaceId:r,applicationName:i.name,authNamespace:d,authIdpConfigName:f,cors:i.config.cors,subgraphs:i.subgraphs.map(e=>protoSubgraph(e)),allowedIpAddresses:i.config.allowedIpAddresses,disableIntrospection:i.config.disableIntrospection,httpAdapters:v},x=u.find(e=>e.name===i.name);if(i.id){let e=u.filter(e=>e.name!==i.name),t=await Promise.all(e.map(async e=>isOwnedByApp(await fetchAppLabels(n,r,e.name),i.name,i.id)?e.name:null));for(let e of t)e&&l.deletes.push({name:e,request:{workspaceId:r,applicationName:e}})}if(x){let e=trackDesiredResourceOwnership({labels:m,ownerLabel:m?.[Ni],appName:i.name,appId:i.id,resourceType:`Application`,resourceName:i.name,conflicts:o,unmanaged:s}),t={name:i.name,request:b,metaRequest:p};if(e&&hasMatchingSdkVersion(m,p.labels)&&areApplicationsEqual(x,y)&&h.length===0)l.unchanged.push(t);else{let e=[...diffHttpAdapterDisplay(x.httpAdapters,v),...h];e.length>0&&(t.details=e),l.updates.push(t)}}else{let e=[...diffHttpAdapterDisplay(void 0,v),...h];l.creates.push({name:i.name,request:b,metaRequest:p,details:e.length>0?e:void 0})}return withOwnership(l,o,s,c)}function withOwnership(e,t,n,r){return Object.assign(e,{conflicts:t,unmanaged:n,resourceOwners:r})}async function fetchAppLabels(e,t,n){return(await F(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:A.update}):i.push({name:e,symbol:A.create})}for(let e of n.keys())r.has(e)||i.push({name:e,symbol:A.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=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 R({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)?A.update:A.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 L(`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 L(`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=>Bt[e]),inputScript:n,outputScript:r,enabled:e.adapter.enabled,priority:e.adapter.priority}})}function protoSubgraph(e){let t;switch(e.Type){case`tailordb`:t=pe.TAILORDB;break;case`pipeline`:t=pe.PIPELINE;break;case`idp`:t=pe.IDP;break;case`auth`:t=pe.AUTH;break;default:throw L(`Unknown subgraph type: ${e.Type}`)}return{serviceType:t,serviceNamespace:e.Name}}const Ri=H.object({hash:H.string(),updateTime:H.string().optional()}),zi=H.object({vaults:H.record(H.string(),H.record(H.string(),Ri)),connections:H.record(H.string(),H.string()).optional()}),Bi=H.object({version:H.literal(2),workspaceId:H.string(),applicationKey:H.string(),state:zi});function getSecretsStatePath(e){let t=hashValue(JSON.stringify([e.workspaceId,applicationStateKey(e)]));return V.join($t(),`secrets-state`,`${t}.json`)}function loadPersistedSecretsState(e){try{let t=Xn(getSecretsStatePath(e),`utf-8`),n=Bi.parse(JSON.parse(t));return n.workspaceId!==e.workspaceId||n.applicationKey!==applicationStateKey(e)?void 0:n}catch{return}}function applicationStateKey(e){if(!e.applicationId)throw L(`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=V.dirname(n);Yn(r,{recursive:!0});let i=`${n}.tmp-${hr()}`;tr(i,JSON.stringify({version:2,workspaceId:e.workspaceId,applicationKey:applicationStateKey(e),state:t},null,2),`utf-8`),Zn(i,n)}function hashValue(e){return mr(`sha256`).update(e).digest(`hex`)}function serializeUpdateTime(e){return e===void 0?void 0:`${e.seconds}.${e.nanos}`}const Vi=new Map;async function withSecretsStateLock(e,t){if(!e.applicationId)return t();let n=`${getSecretsStatePath(e)}.lock`,r=Vi.get(n);return r||(r=fr(1),Vi.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){Yn(V.dirname(e),{recursive:!0});let t=hr(),n=Date.now()+3e5;for(;;){let r=!0;try{Yn(e)}catch(e){if(e.code!==`EEXIST`)throw e;r=!1}if(r){try{tr(V.join(e,`owner.json`),JSON.stringify({pid:process.pid,token:t}))}catch(t){throw Qn(e,{recursive:!0,force:!0}),t}return t}if(!(isLockExpired(e)&&stealLock(e))){if(Date.now()>=n)throw R({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.`});await new Promise(e=>setTimeout(e,100))}}}function isLockExpired(e){try{return Date.now()-$n(e).mtimeMs>6e4}catch{return!1}}function readLockToken(e){try{return JSON.parse(Xn(V.join(e,`owner.json`),`utf-8`)).token}catch{return}}function refreshLock(e,t){if(readLockToken(e)!==t)return;let n=new Date;try{er(e,n,n)}catch{}}function releaseFileLock(e,t){readLockToken(e)===t&&Qn(e,{recursive:!0,force:!0})}function stealLock(e){let t=`${e}.stale-${process.pid}-${Date.now()}`;try{Zn(e,t)}catch{return!1}if(isLockExpired(t))return Qn(t,{recursive:!0,force:!0}),!0;try{Zn(t,e)}catch{Qn(t,{recursive:!0,force:!0})}return!1}function buildConnectionRequest(e,t,n){return{workspaceId:e,connection:{name:t,type:oe.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=[],c=[],l=new Set,u={};for(let e of i)for(let[t,n]of Object.entries(e.connections))u[t]=n,M.registerSecret(n.clientSecret);let d=await N(async(n,r)=>{let{connections:i,nextPageToken:a}=await e.listAuthConnections({workspaceId:t,pageToken:n,pageSize:r});return[i,a]}),f={};await Promise.all(d.map(async n=>{let{metadata:r}=await e.getMetadata({trn:resourceTrn(t,`auth_connection`,n.name)});f[n.name]={resource:n,label:r?.labels[Ni],allLabels:r?.labels}}));let p=loadSecretsState(a);for(let[e,i]of Object.entries(u)){let a=f[e],l=await buildMetaRequest({trn:resourceTrn(t,`auth_connection`,e),appName:n,appId:r});if(a){let u=trackDesiredResourceOwnership({labels:a.allLabels,ownerLabel:a.label,appName:n,appId:r,resourceType:`Auth connection`,resourceName:e,conflicts:s,unmanaged:c}),d=hashValue(i.clientSecret)!==p.connections?.[e],m=buildUpdateMask(a.resource,i,d);m.paths.length>0?o.replaces.push({name:e,updateRequest:{...buildConnectionRequest(t,e,i),updateMask:m},metaRequest:l}):u?o.unchanged.push({name:e}):o.updates.push({name:e,metaRequest:l}),delete f[e]}else o.creates.push({name:e,request:buildConnectionRequest(t,e,i),metaRequest:l})}for(let[e,i]of Object.entries(f))i&&trackRemainingResourceOwner({labels:i.allLabels,ownerLabel:i.label,appName:n,appId:r,resourceOwners:l})&&o.deletes.push({name:e,request:{workspaceId:t,connectionName:e}});return{changeSet:o,conflicts:s,unmanaged:c,resourceOwners:l,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),M.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===rt.UNAUTHORIZED&&M.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 Hi=65536;function computeContentHash(e){return pr.createHash(`sha256`).update(e,`utf-8`).digest(`hex`)}const Ui=`workflow--`;function resolverFunctionName(e,t){return`resolver--${e}--${t}`}function executorFunctionName(e){return`executor--${e}`}function workflowJobFunctionName(e){return`${Ui}${e}`}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(Pt(e.namespace,t.name));if(!i){M.warn(`Bundled code not found for resolver: ${e.namespace}/${t.name}`);continue}r.push({name:resolverFunctionName(e.namespace,t.name),scriptContent:i,contentHash:computeContentHash(i),description:`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){M.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);if(!t){M.warn(`Bundled code not found for workflow job: ${e.name}`);continue}r.push({name:workflowJobFunctionName(e.name),scriptContent:t,contentHash:computeContentHash(t),description:`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){M.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){let a=createChangeSet(`Function registry`),o=[],s=[],c=new Set,l=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)});for(let e of i){let i=l[e.name],c=await buildMetaRequest({trn:resourceTrn(t,`function_registry`,e.name),appName:n,appId:r});if(i){let t=trackDesiredResourceOwnership({labels:i.allLabels,ownerLabel:i.label,appName:n,appId:r,resourceType:`Function registry`,resourceName:e.name,conflicts:o,unmanaged:s});i.resource.contentHash===e.contentHash&&t&&hasMatchingSdkVersion(i.allLabels,c.labels)?a.unchanged.push({name:e.name}):a.updates.push({name:e.name,entry:e,metaRequest:c}),delete l[e.name]}else a.creates.push({name:e.name,entry:e,metaRequest:c})}for(let[e,i]of Object.entries(l))i&&trackRemainingResourceOwner({labels:i.allLabels,ownerLabel:i.label,appName:n,appId:r,resourceOwners:c})&&a.deletes.push({name:e,workspaceId:t});let{workflowJobChanges:u,resolverFunctionChanges:d,executorFunctionChanges:f,authHookFunctionChanges:p}=splitFunctionRegistryChanges(a);return{changeSet:a,workflowJobChanges:u,resolverFunctionChanges:d,executorFunctionChanges:f,authHookFunctionChanges:p,conflicts:o,unmanaged:s,resourceOwners: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+=Hi)yield{payload:{case:`chunk`,value:i.subarray(e,Math.min(e+Hi,i.length))}}}await e.createFunctionRegistry(createStream())}else{async function*updateStream(){yield{payload:{case:`info`,value:a}};for(let e=0;e<i.length;e+=Hi)yield{payload:{case:`chunk`,value:i.subarray(e,Math.min(e+Hi,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=en();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(t=>e.deleteFunctionRegistry({workspaceId:t.workspaceId,name:t.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 Wi={create:A.create,update:A.update,delete:A.delete,replace:A.replace};function formatChangeSetEntries(e,t=[],n){function toEntry(e,r){return{action:e,symbol:Wi[e],name:r.name,labels:[...t],namespace:n?.(r)}}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}`}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=createRelatedFunctionRegistryNameSets()){return[[`create`,e.creates,t.creates],[`delete`,e.deletes,t.deletes],[`update`,e.updates,t.updates],[`replace`,e.replaces,t.replaces]].flatMap(([e,t,n])=>[...t].filter(e=>!n.has(e)).map(t=>{let{displayName:n,namespace:r}=parseFunctionRegistryName(t);return{action:e,symbol:Wi[e],name:n,labels:[`function`],namespace:r}}))}function formatChangeEntriesWithFunctionRegistry(e,t,n,r,i){let{getNamespace:a,getDisplayName:o}=i??{},s=createRelatedFunctionRegistryNameSets(n),c=createRelatedFunctionRegistryNameSets();function processItems(t,n,i,s){return t.map(t=>{let c=r(t,n),l=c.some(e=>i.has(e));if(l)for(let e of c)i.has(e)&&s.add(e);return{action:n,symbol:Wi[n],name:o?.(t)??t.name,labels:l?[e,`function`]:[e],namespace:a?.(t)}})}return[...processItems(t.creates,`create`,s.creates,c.creates),...processItems(t.deletes,`delete`,s.deletes,c.deletes),...processItems(t.updates,`update`,s.updates,c.updates),...t.replaces.map(t=>({action:`replace`,symbol:Wi.replace,name:o?.(t)??t.name,labels:[e],namespace:a?.(t)})),...buildRemainingFunctionRegistryEntries(s,c)]}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.replaces.map(e=>({name:e.name,action:`replace`}))]}function buildGroupedDisplayLines(e,t,n){let r=new Map;if(n)for(let e of n)r.set(e.name,e.action);if(t.length===0&&r.size===0)return[];let i=[j.bold(`${e}:`)],a=[],o=new Map;for(let e of t){let t=e.namespace;o.has(t)||(a.push(t),o.set(t,[])),k(o.get(t),`namespace group missing`).push(e)}let s=new Set;for(let e of a){let t=k(o.get(e),`namespace group missing`);if(e){let n=r.get(e),a=n?`${Wi[n]} `:``;i.push(` ${a}${j.bold(`${e}:`)}`),s.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)s.has(e)||i.push(` ${Wi[t]} ${e}`);return i}const Gi={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}"`},Ki={tailorDBType:e=>({resource:Gi.tailorDBType(e),trigger:`record`}),resolver:e=>({resource:Gi.resolver(e),trigger:`resolverExecuted`}),idpService:e=>({resource:Gi.idpService(e),trigger:`idpUser`}),workflow:e=>({resource:Gi.workflow(e),trigger:`workflowExecution`}),workflowJob:e=>({resource:Gi.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:qi}=_t({"=":`eq`,"!=":`ne`,in:`in`,"not in":`nin`});function normalizeIdPActionPermission(e){return qi(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)=>{on(e)&&t.push(`${String(n)}[${r}]`)});return t}async function resolveServiceReturnOrigins(e,t){let n=t.userAuthPolicy,r=n?.allowedReturnOrigins;if(!n||!r?.length)return;let i=await Qt(e,k(t.workspaceId,`request missing workspaceId`),r,`IdP service "${t.namespaceName??``}" allowedReturnOrigins`);if(i.length!==r.length)throw R({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&&M.registerSecret(n.client.clientSecret);let r=idpClientVaultName(k(t.request.namespaceName,`request missing namespaceName`),t.request.client?.name||``),i=idpClientSecretName(k(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);await F(async()=>await e.getSecretManagerVault({workspaceId:t.workspaceId,secretmanagerVaultName:n}))||(await e.createSecretManagerVault({workspaceId:t.workspaceId,secretmanagerVaultName:n}),await e.createSecretManagerSecret({workspaceId:t.workspaceId,secretmanagerVaultName:n,secretmanagerSecretName:r,secretmanagerSecretValue:t.clientSecret}))})])):n===`delete-resources`?await Promise.all(r.client.deletes.map(async t=>{await e.deleteIdPClient(t.request);let n=`idp-${t.request.namespaceName}-${t.request.name}`;await e.deleteSecretManagerVault({workspaceId:t.request.workspaceId,secretmanagerVaultName:n})})):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??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===se.UNSPECIFIED?se.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=[],u=[],d=new Set,f=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,p=f[i],m=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}),h;switch(d.authorization){case`insecure`:h=`true==true`;break;case`loggedIn`:h=`user != null && size(user.id) > 0`;break;case void 0:h=void 0;break;default:h=d.authorization.cel}let g=convertLang(d.lang),_=d.userAuthPolicy,v=resolvePublishEvents({explicit:d.publishEvents,subscribed:a.has(i),conflict:Ki.idpService(i)}),y=d.emailConfig;d.permission||M.warn(`IdP service "${i}" has no permission configured.`);let b=findOmittedPermitRules(d.permission);b.length>0&&M.warn(`IdP service "${i}" has permission rule(s) ${b.join(`, `)} in object form without an explicit "permit"; they default to "deny". Set permit: true (allow) or permit: false (deny) to silence this warning.`),Vt(_)&&M.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,C=await Qt(e,t,_?.allowedReturnOrigins?[..._.allowedReturnOrigins]:[],`IdP service "${i}" allowedReturnOrigins`,{expectedLocalNames:o}),w=_&&{..._,allowedReturnOrigins:C},ee=normalizeComparableIdPService({authorization:h,lang:g,userAuthPolicy:normalizeComparableUserAuthPolicy(w),publishEvents:v,disableGqlOperations:normalizeComparableDisableGqlOperations(convertGqlOperationsToDisable(d.gqlOperations)),emailConfig:normalizeComparableEmailConfig(y),permission:S}),te={workspaceId:t,namespaceName:i,authorization:h,lang:g,userAuthPolicy:_,publishUserEvents:v,disableGqlOperations:convertGqlOperationsToDisable(d.gqlOperations),emailConfig:y,permission:S};p?(trackDesiredResourceOwnership({labels:p.allLabels,ownerLabel:p.label,appName:n,appId:r,resourceType:`IdP service`,resourceName:d.name,conflicts:l,unmanaged:u})&&hasMatchingSdkVersion(p.allLabels,m.labels)&&areIdPServicesEqual(p.resource,ee)?c.unchanged.push({name:i,metaRequest:m}):c.updates.push({name:i,request:te,metaRequest:m}),delete f[i]):c.creates.push({name:i,request:te,metaRequest:m})}return Object.entries(f).forEach(([e])=>{let i=f[e];trackRemainingResourceOwner({labels:i?.allLabels,ownerLabel:i?.label,appName:n,appId:r,resourceOwners:d})&&c.deletes.push({name:e,request:{workspaceId:t,namespaceName:e}})}),{changeSet:c,conflicts:l,unmanaged:u,resourceOwners:d}}async function planClients(e,t,n,r,i=!1){let a=createChangeSet(`IdP clients`),fetchClients=n=>N(async(r,i)=>{let{clients:a,nextPageToken:o}=await e.listIdPClients({workspaceId:t,namespaceName:n,pageToken:r,pageSize:i});return[a,o]}),o=await Promise.all(n.map(e=>fetchClients(e.name)));for(let[e,r]of n.entries()){let n=r.name,s=k(o[e],`clientsByIdp missing entry for idp index`),c=new Map;s.forEach(e=>{c.set(e.name,e.clientSecret),M.registerSecret(e.clientSecret)});for(let e of r.clients)c.has(e)?(i?a.updates.push({name:e,workspaceId:t,namespaceName:n,clientSecret:c.get(e)??``}):a.unchanged.push({name:e}),c.delete(e)):a.creates.push({name:e,request:{workspaceId:t,namespaceName:n,client:{name:e}}});c.forEach((e,r)=>{a.deletes.push({name:r,request:{workspaceId:t,namespaceName:n,name:r}})})}let s=await Promise.all(r.map(e=>fetchClients(e)));for(let[e,n]of r.entries())k(s[e],`deletedClientsByService missing entry for service index`).forEach(e=>{M.registerSecret(e.clientSecret),a.deletes.push({name:e.name,request:{workspaceId:t,namespaceName:n,name:e.name}})});return a}function convertLang(e){switch(e){case`en`:return se.EN;case`ja`:return se.JA;default:return se.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=u.ALLOW;break;case`deny`:t=u.DENY;break;default:throw L(`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=le.EQ;break;case`ne`:o=le.NE;break;case`in`:o=le.IN;break;case`nin`:o=le.NIN;break;default:throw L(`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 L(`Unknown operand: ${JSON.stringify(e)}`)}return{kind:{case:`value`,value:qn(ir,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&&M.registerSecret(n.machineUser.clientSecret),n}),...r.machineUser.updates.map(async t=>{let n=await e.updateAuthMachineUser(t.request);return n.machineUser?.clientSecret&&M.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`&&(k(t.request.idpConfig,`request missing idpConfig`).config=await protoBuiltinIdPConfig(e,k(t.request.workspaceId,`request missing workspaceId`),t.idpConfig)),e.createAuthIDPConfig(t.request))),...r.idpConfig.updates.map(async t=>(t.idpConfig.kind===`BuiltInIdP`&&(k(t.request.idpConfig,`request missing idpConfig`).config=await protoBuiltinIdPConfig(e,k(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=k(t.request.oauth2Client,`request missing oauth2Client`);n.redirectUris=await Qt(e,k(t.request.workspaceId,`request missing workspaceId`),n.redirectUris,`OAuth2 redirect URIs`);let r=await e.createAuthOAuth2Client(t.request);return r.oauth2Client?.clientSecret&&M.registerSecret(r.oauth2Client.clientSecret),r}),...r.oauth2Client.updates.map(async t=>{let n=k(t.request.oauth2Client,`request missing oauth2Client`);n.redirectUris=await Qt(e,k(t.request.workspaceId,`request missing workspaceId`),n.redirectUris,`OAuth2 redirect URIs`);let r=await e.updateAuthOAuth2Client(t.request);return r.oauth2Client?.clientSecret&&M.registerSecret(r.oauth2Client.clientSecret),r})]);for(let t of r.oauth2Client.replaces){await e.deleteAuthOAuth2Client(t.deleteRequest);let n=k(t.createRequest.oauth2Client,`createRequest missing oauth2Client`);n.redirectUris=await Qt(e,k(t.createRequest.workspaceId,`createRequest missing workspaceId`),n.redirectUris,`OAuth2 redirect URIs`);let r=await e.createAuthOAuth2Client(t.createRequest);r.oauth2Client?.clientSecret&&M.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: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=[],c=[],l=new Set,u=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=u[i.name],d=await buildMetaRequest({trn:resourceTrn(t,`auth`,i.name),appName:n,appId:r}),f={workspaceId:t,namespaceName:i.name,publishSessionEvents:i.publishSessionEvents};if(l){let e=trackDesiredResourceOwnership({labels:l.allLabels,ownerLabel:l.label,appName:n,appId:r,resourceType:`Auth service`,resourceName:i.name,conflicts:s,unmanaged:c});!a&&l.resource.publishSessionEvents===(i.publishSessionEvents??!1)&&e?o.unchanged.push({name:i.name}):o.updates.push({name:i.name,request:f,metaRequest:d}),delete u[i.name]}else o.creates.push({name:i.name,request:f,metaRequest:d})}return Object.entries(u).forEach(([e])=>{let i=u[e];trackRemainingResourceOwner({labels:i?.allLabels,ownerLabel:i?.label,appName:n,appId:r,resourceOwners:l})&&o.deletes.push({name:e,request:{workspaceId:t,namespaceName:e}})}),{changeSet:o,conflicts:s,unmanaged:c,resourceOwners:l}}async function planIdPConfigs(e,t,n,r,i=!1){let a=createChangeSet(`Auth idpConfigs`),fetchIdPConfigs=n=>N(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=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}!i&&areAuthIdPConfigsEqual(o,l)?a.unchanged.push({name:c.name}):a.updates.push({name:c.name,idpConfig:c,request:{workspaceId:t,namespaceName:n.name,idpConfig:r}}),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(s,e)}function areAuthIdPConfigsEqual(e,t){return areNormalizedEqual(normalizeComparableAuthIdPConfig(e),normalizeComparableAuthIdPConfig(t))}function protoIdPConfig(e){switch(e.kind){case`IDToken`:return{name:e.name,authType:w.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:w.SAML,config:{config:{case:`saml`,value:{...e.metadataURL===void 0?{rawMetadata:k(e.rawMetadata,`SAML config missing rawMetadata`)}:{metadataUrl:e.metadataURL},enableSignRequest:e.enableSignRequest,defaultRedirectUrl:e.defaultRedirectURL}}}};case`OIDC`:return{name:e.name,authType:w.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:w.OIDC,config:{}};default:throw L(`Unexpected idp kind: ${e}`)}}async function protoBuiltinIdPConfig(e,t,n){let r=await tryProtoBuiltinIdPConfig(e,t,n);if(!r)throw R({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 F(async()=>await e.getIdPService({workspaceId:t,namespaceName:n.namespace}));if(!r)return;let i=await F(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 F(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);!i&&areUserProfileConfigsEqual(s.userProfileProviderConfig??{},e)?a.unchanged.push({name:o}):a.updates.push({name:o,request:{workspaceId:t,namespaceName:n.name,userProfileProviderConfig:e}})}else a.deletes.push({name:o,request:{workspaceId:t,namespaceName:n.name}})}for(let n of r)await F(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:i.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 F(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)}});continue}if(n.tenantProvider){let e=protoTenantConfig(n.tenantProvider);!i&&areTenantProviderConfigsEqual(s.tenantProviderConfig,e)?a.unchanged.push({name:o}):a.updates.push({name:o,request:{workspaceId:t,namespaceName:n.name,tenantProviderConfig:e}})}else a.deletes.push({name:o,request:{workspaceId:t,namespaceName:n.name}})}for(let n of r)await F(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:re.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=>N(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=new Map;r.forEach(e=>{o.set(e.name,e),M.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);c?(!i&&areMachineUsersEqual(c,s)?a.unchanged.push({name:e}):a.updates.push({name:e,request:{workspaceId:t,authNamespace:n.name,name:e,attributes:r.attributeList,attributeMap:s.attributeMap}}),o.delete(e)):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=>{M.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]=qn(ir,r??null);return t}function normalizeComparableUserProfileConfig(e){let t=e.config?.config,n=t?.case===`tailordb`?t.value:void 0;return toComparableProtoJson(ct,{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(v,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,a=!1){let o=createChangeSet(`Auth oauth2Clients`),fetchOAuth2Clients=n=>N(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,s=await fetchOAuth2Clients(n.name),c=new Map;s.forEach(e=>{c.set(e.name,e),M.registerSecret(e.clientSecret)});for(let r of Object.keys(n.oauth2Clients??{})){let s=n.oauth2Clients?.[r];if(!s)continue;let l=protoOAuth2Client(r,s),u=await Qt(e,t,l.redirectUris??[],`OAuth2 redirect URIs`,{expectedLocalNames:i});if(c.has(r)){let e=k(c.get(r),`existingClientsMap missing entry for oauth2ClientName`);if(e.clientType!==l.clientType)o.replaces.push({name:r,deleteRequest:{workspaceId:t,namespaceName:n.name,name:r},createRequest:{workspaceId:t,namespaceName:n.name,oauth2Client:l}});else{let i={...l,redirectUris:u,accessTokenLifetime:oauth2LifetimeToSeconds(l.accessTokenLifetime),refreshTokenLifetime:oauth2LifetimeToSeconds(l.refreshTokenLifetime)},s={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};!a&&areOAuth2ClientsEqual(s,i)?o.unchanged.push({name:r}):o.updates.push({name:r,request:{workspaceId:t,namespaceName:n.name,oauth2Client:l}})}c.delete(r)}else o.creates.push({name:r,request:{workspaceId:t,namespaceName:n.name,oauth2Client:l}})}c.forEach((e,r)=>{o.deletes.push({name:r,request:{workspaceId:t,namespaceName:n.name,name:r}})})}for(let e of r)(await fetchOAuth2Clients(e)).forEach(n=>{M.registerSecret(n.clientSecret),o.deletes.push({name:n.name,request:{workspaceId:t,namespaceName:e,name:n.name}})});return o}function protoOAuth2Client(e,t){return{name:e,description:t.description,grantTypes:t.grantTypes.map(e=>{switch(e){case`authorization_code`:return Pe.AUTHORIZATION_CODE;case`refresh_token`:return Pe.REFRESH_TOKEN;default:throw L(`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 F(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 F(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=l.BEARER;break;case`oauth2`:t=l.OAUTH2;break;default:throw L(`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 F(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=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=S.STRING;break;case`number`:t=S.NUMBER;break;case`boolean`:t=S.BOOLEAN;break;case`datetime`:t=S.DATETIME;break;case`complex`:t=S.COMPLEX;break;default:throw L(`Unknown SCIM attribute type: ${e.type}`)}let n;if(e.mutability)switch(e.mutability){case`readOnly`:n=b.READ_ONLY;break;case`readWrite`:n=b.READ_WRITE;break;case`writeOnly`:n=b.WRITE_ONLY;break;default:throw L(`Unknown SCIM attribute mutability: ${e.mutability}`)}let r;if(e.uniqueness)switch(e.uniqueness){case`none`:r=te.NONE;break;case`server`:r=te.SERVER;break;case`global`:r=te.GLOBAL;break;default:throw L(`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 F(async()=>{let{hook:r}=await e.getAuthHook({workspaceId:t,namespaceName:n.name,hookPoint:c.BEFORE_LOGIN});return r});if(o){let e={workspaceId:t,namespaceName:n.name,hook:{hookPoint:c.BEFORE_LOGIN,scriptRef:authHookFunctionName(n.name,`before-login`),invoker:{namespace:n.name,machineUserName:o.invoker}}};s?!i&&areAuthHooksEqual(s,e.hook)?a.unchanged.push({name:`${n.name}/before-login`}):a.updates.push({name:`${n.name}/before-login`,request:e}):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:c.BEFORE_LOGIN}})}for(let n of r)await F(async()=>await e.getAuthHook({workspaceId:t,namespaceName:n,hookPoint:c.BEFORE_LOGIN}))&&a.deletes.push({name:`${n}/before-login`,request:{workspaceId:t,namespaceName:n,hookPoint:c.BEFORE_LOGIN}});return a}function normalizeInvoker(e,t,n){if(e!==void 0){if(typeof e==`string`){if(!t)throw R({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){let{client:t,workspaceId:n,application:r,forRemoval:i}=e,a=createChangeSet(`Executors`),o=[],s=[],c=new Set,l=await fetchExistingResourcesWithLabels({client:t,fetchPage:async(e,r)=>{let{executors:i,nextPageToken:a}=await t.listExecutorExecutors({workspaceId:n,pageToken:e,pageSize:r});return[i,a]},getName:e=>e.name,getTrn:e=>resourceTrn(n,`executor`,e)}),u=i?{}:await r.executorService?.loadExecutors()??{};for(let t of Object.values(u)){let i=l[t.name],c=await buildMetaRequest({trn:resourceTrn(n,`executor`,t.name),appName:r.name,appId:r.id}),u=protoExecutor(e,t);i?(trackDesiredResourceOwnership({labels:i.allLabels,ownerLabel:i.label,appName:r.name,appId:r.id,resourceType:`Executor`,resourceName:t.name,conflicts:o,unmanaged:s})&&hasMatchingSdkVersion(i.allLabels,c.labels)&&areExecutorsEqual(i.resource,u)?a.unchanged.push({name:t.name}):a.updates.push({name:t.name,request:{workspaceId:n,executor:u},metaRequest:c}),delete l[t.name]):a.creates.push({name:t.name,request:{workspaceId:n,executor:u},metaRequest:c})}return Object.entries(l).forEach(([e])=>{let t=l[e],i=t?.label;trackRemainingResourceOwner({labels:t?.allLabels,ownerLabel:i,appName:r.name,appId:r.id,resourceOwners:c})&&a.deletes.push({name:e,request:{workspaceId:n,name:e}})}),{changeSet:a,conflicts:o,unmanaged:s,resourceOwners:c}}function isFunctionBackedExecutor(e){return e?.targetType===O.FUNCTION||e?.targetType===O.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 n=normalizeProtoConfig(e),r=n.targetConfig?.config?.case===`webhook`?(n.targetConfig.config.value.headers??[]).toSorted((e,t)=>(e.key??``).localeCompare(t.key??``)):void 0,i=n.triggerConfig?.config?.case===`incomingWebhook`?{...n.triggerConfig,config:{...n.triggerConfig.config,value:{...n.triggerConfig.config.value,secret:void 0}}}:n.triggerConfig?.config?.case===`event`?{...n.triggerConfig,config:{...n.triggerConfig.config,value:{...n.triggerConfig.config.value,eventType:void 0}}}:n.triggerConfig,a=normalizeProtoConfig({name:n.name,description:n.description??``,disabled:n.disabled??!1,triggerType:n.triggerType,triggerConfig:i,targetType:n.targetType,targetConfig:n.targetConfig?.config?.case===`webhook`?{...n.targetConfig,config:{...n.targetConfig.config,value:{...n.targetConfig.config.value,headers:r}}}:n.targetConfig?.config?.case===`function`?{...n.targetConfig,config:{...n.targetConfig.config,value:{...n.targetConfig.config.value,script:void 0}}}:n.targetConfig});return toComparableProtoJson(t,a)}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 R({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 R({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 R({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 R({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 R({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 k([...i][0],`idp service missing`)}function protoExecutor(e,t){let{application:n}=e,r=n.name,i=n.env,a=t.trigger,o,s,c=an(a.kind,i);function typedEventTrigger(e){return{config:{case:`event`,value:{typedConfig:e}}}}switch(a.kind){case`schedule`:o=Be.SCHEDULE,s={config:{case:`schedule`,value:{timezone:a.timezone,frequency:a.cron}}};break;case`tailordb`:o=Be.EVENT,s=typedEventTrigger({case:`tailordb`,value:{eventTypes:a.events,namespaceName:resolveTailorDBNamespace(n,a.tableName,e.tailorDBTypeNamespaces),typeName:a.tableName,...a.condition?{condition:{expr:`(${Ot(a.condition)})(${c})`}}:{}}});break;case`resolverExecuted`:o=Be.EVENT,s=typedEventTrigger({case:`pipeline`,value:{eventTypes:[`pipeline.resolver.executed`],namespaceName:resolveResolverNamespace(n,a.resolverName,e.resolverNamespaces),resolverName:a.resolverName,...a.condition?{condition:{expr:`(${Ot(a.condition)})(${c})`}}:{}}});break;case`incomingWebhook`:o=Be.INCOMING_WEBHOOK,s={config:{case:`incomingWebhook`,value:a.response?{response:{...a.response.body?{body:{expr:`(${Ot(a.response.body)})(${c})`}}:{},...a.response.statusCode==null?{}:{statusCode:a.response.statusCode}}}:{}}};break;case`idpUser`:o=Be.EVENT,s=typedEventTrigger({case:`idp`,value:{eventTypes:a.events,namespaceName:resolveIdpNamespace(n,t.name,a.idp,e.idpNames)}});break;case`authAccessToken`:o=Be.EVENT,s=typedEventTrigger({case:`auth`,value:{eventTypes:a.events,namespaceName:Gt(n)}});break;case`workflowExecution`:case`workflowJobExecution`:o=Be.EVENT,s=typedEventTrigger({case:`workflow`,value:{eventTypes:a.events,workflowName:a.workflowName,...a.condition?{condition:{expr:`(${Ot(a.condition)})(${c})`}}:{}}});break;default:throw L(`Unknown trigger: ${a}`)}let l=t.operation,u,d,f=It(n),p=`Executor "${t.name}"`;switch(l.kind){case`webhook`:u=O.WEBHOOK,d={config:{case:`webhook`,value:{url:{expr:`(${Ot(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:`(${Ot(l.requestBody)})(${c})`}:void 0}}};break;case`graphql`:u=O.TAILOR_GRAPHQL,d={config:{case:`tailorGraphql`,value:{appName:l.appName??r,query:l.query,variables:l.variables?{expr:`(${Ot(l.variables)})(${c})`}:void 0,invoker:normalizeInvoker(l.invoker,f,p)}}};break;case`function`:case`jobFunction`:u=l.kind===`function`?O.FUNCTION:O.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=O.WORKFLOW,d={config:{case:`workflow`,value:{workflowName:l.workflowName,variables:l.args===void 0?void 0:typeof l.args==`function`?{expr:`(${Ot(l.args)})(${c})`}:{expr:JSON.stringify(l.args)},invoker:normalizeInvoker(l.invoker,f,p)}}};break;default:throw L(`Unknown target: ${l}`)}return{name:t.name,description:t.description,disabled:t.disabled,triggerType:o,triggerConfig:s,targetType:u,targetConfig:d}}const Ji={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){let{client:t,workspaceId:n,application:r,forRemoval:i,forceApplyAll:a=!1}=e,o=[];if(!i)for(let e of r.resolverServices)await e.loadResolvers(),o.push(e);let s=i?[]:Object.values(await r.executorService?.loadExecutors()??{}),{changeSet:c,conflicts:l,unmanaged:u,resourceOwners:d}=await planServices$1(t,n,r.name,r.id,o),f=c.deletes.map(e=>e.name),{changeSet:p}=await planResolvers(t,n,o,s,e.executorUsedResolvers??new Set,f,r.env,It(r),a,{appName:r.name,appId:r.id,dependentApps:e.dependentApps,runAppIds:e.runAppIds});return{changeSet:{service:c,resolver:p},conflicts:l,unmanaged:u,resourceOwners:d}}async function planServices$1(e,t,n,r,i){let a=createChangeSet(`Pipeline services`),o=[],s=[],c=new Set,l=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)});for(let e of i){let i=l[e.namespace],c=await buildMetaRequest({trn:resourceTrn(t,`pipeline`,e.namespace),appName:n,appId:r});i?(trackDesiredResourceOwnership({labels:i.allLabels,ownerLabel:i.label,appName:n,appId:r,resourceType:`Pipeline service`,resourceName:e.namespace,conflicts:o,unmanaged:s})&&hasMatchingSdkVersion(i.allLabels,c.labels)?a.unchanged.push({name:e.namespace}):a.updates.push({name:e.namespace,request:{workspaceId:t,namespaceName:e.namespace},metaRequest:c}),delete l[e.namespace]):a.creates.push({name:e.namespace,request:{workspaceId:t,namespaceName:e.namespace},metaRequest:c})}return Object.entries(l).forEach(([e])=>{let i=l[e];trackRemainingResourceOwner({labels:i?.allLabels,ownerLabel:i?.label,appName:n,appId:r,resourceOwners:c})&&a.deletes.push({name:e,request:{workspaceId:t,namespaceName:e}})}),{changeSet:a,conflicts:o,unmanaged:s,resourceOwners:c}}async function planResolvers(e,t,n,r,i,a,o,s,c=!1,l={}){let u=createChangeSet(`Pipeline resolvers`),{appName:d,appId:f,dependentApps:p,runAppIds:m}=l,resolverMetaRequest=async(e,n)=>addDependencyRecords(await buildMetaRequest({trn:resolverTrn(t,e,n.name),appName:d??``,appId:f}),{key:Z.resolver(e,n.name),dependentApps:p,runAppIds:m,pinned:n.publishEvents!==void 0}),fetchResolvers=n=>N(async(r,i)=>{let{pipelineResolvers:a,nextPageToken:o}=await e.listPipelineResolvers({workspaceId:t,namespaceName:n,pageToken:r,pageSize:i});return[a,o]}),h=new Set(i);for(let e of r)subscribesToEvents(e)&&e.trigger.kind===`resolverExecuted`&&h.add(e.trigger.resolverName);for(let e of n)for(let t of Object.values(e.resolvers))assertNoPublishEventsConflict({explicit:t.publishEvents,subscribed:h.has(t.name),conflict:Ki.resolver(t.name)});for(let r of n){let n=await fetchResolvers(r.namespace),i=new Map(n.map(e=>[e.name,e]));for(let n of Object.values(r.resolvers)){let a=processResolver(r.namespace,n,h,o,s),l=i.get(n.name),d=await resolverMetaRequest(r.namespace,n);if(l){let{pipelineResolver:o}=await e.getPipelineResolver({workspaceId:t,namespaceName:r.namespace,resolverName:n.name});!c&&o&&areResolversEqual(o,a)?u.unchanged.push({name:n.name,metaRequest:d}):u.updates.push({name:n.name,request:{workspaceId:t,namespaceName:r.namespace,pipelineResolver:a},metaRequest:d}),i.delete(n.name)}else u.creates.push({name:n.name,request:{workspaceId:t,namespaceName:r.namespace,pipelineResolver:a},metaRequest:d})}i.forEach((e,n)=>{u.deletes.push({name:n,request:{workspaceId:t,namespaceName:r.namespace,resolverName:n}})})}for(let e of a)(await fetchResolvers(e)).forEach(n=>{u.deletes.push({name:n.name,request:{workspaceId:t,namespaceName:e,resolverName:n.name}})});return{changeSet:u}}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(f,e)}function areResolversEqual(e,t){return areNormalizedEqual(normalizeComparableResolver(e),normalizeComparableResolver(t))}function processResolver(e,t,n,r,i){let a=[{name:`body`,operationName:`body`,description:`${t.name} function body`,operationType:_.FUNCTION,operationSourceRef:resolverFunctionName(e,t.name),operationHook:{expr:cn(r)},postScript:`args.body`,invoker:normalizeInvoker(t.invoker,i,`Resolver "${t.name}"`)}],o=wr.camelize(t.name),s=t.input?protoFields(t.input,`${o}Input`,!0):[],c=k(protoFields({"":t.output},`${o}Output`,!1)[0],`resolver output field missing`),l=t.description||`${t.name} resolver`,u=t.output.metadata.description,d=u?`${l}\n\nReturns:\n${u}`:l,f=resolvePublishEvents({explicit:t.publishEvents,subscribed:n.has(t.name),conflict:Ki.resolver(t.name)});return{authorization:`true==true`,description:d,inputs:s,name:t.name,operationType:t.operation,response:c,pipelines:a,publishExecutionEvents:f}}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}${wr.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}${wr.camelize(e)}`,required:a,allowedValues:r.metadata.allowedValues}:{...Ji[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}}async function planSecretManager(e){let{client:t,workspaceId:n,application:r,forRemoval:i,forceApplyAll:a=!1}=e,o=i?[]:r.secrets,s=createChangeSet(`Secret Manager vaults`),c=createChangeSet(`Secret Manager secrets`),l=[],u=[],d=new Set,f=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)}),p={workspaceId:n,applicationId:r.id,applicationName:r.name},m=loadSecretsState(p),h=[];await Promise.all(o.map(async e=>{let i=e.vaultName,o=f[i];if(o){let e=await buildMetaRequest({trn:resourceTrn(n,`vault`,i),appName:r.name,appId:r.id});trackDesiredResourceOwnership({labels:o.allLabels,ownerLabel:o.label,appName:r.name,appId:r.id,resourceType:`Secret Manager vault`,resourceName:i,conflicts:l,unmanaged:u})&&hasMatchingSdkVersion(o.allLabels,e.labels)?s.unchanged.push({name:i}):s.updates.push({name:i,workspaceId:n}),delete f[i]}else s.creates.push({name:i,workspaceId:n});let d=new Map;if(o){let e=await N(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 p=new Set(d.keys());for(let t of e.secrets){if(t.value==null){p.delete(t.name),h.push(`${i}/${t.name}`);continue}if(M.registerSecret(t.value),p.has(t.name)){let e=m.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}),p.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 p)c.deletes.push({name:`${i}/${e}`,secretName:e,workspaceId:n,vaultName:i})}));for(let[e,i]of Object.entries(f))if(i&&trackRemainingResourceOwner({labels:i.allLabels,ownerLabel:i.label,appName:r.name,appId:r.id,resourceOwners:d})){let r=await N(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:h,conflicts:l,unmanaged:u,resourceOwners:d,stateScope:p}}async function applySecretManager(e,t,n=`create-update`,r){let{vaultChangeSet:i,secretChangeSet:a,stateScope:o}=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=[...a.creates,...a.updates];t.length>0&&await withSecretsStateLock(o,async()=>{let n=new Map;if(await Promise.all(a.creates.map(async t=>{let r=await e.createSecretManagerSecret(secretCreateRequest(t));n.set(t.name,serializeUpdateTime(r.secret?.updateTime))})),await Promise.all(a.updates.map(async t=>{let r=await e.updateSecretManagerSecret(secretUpdateRequest(t));n.set(t.name,serializeUpdateTime(r.secret?.updateTime))})),r){let e=loadSecretsState(o);for(let r of t){Object.hasOwn(e.vaults,r.vaultName)||(e.vaults[r.vaultName]={});let t=n.get(r.name);k(e.vaults[r.vaultName],`vault state entry missing`)[r.secretName]={hash:hashValue(r.value),...t===void 0?{}:{updateTime:t}}}saveSecretsState(o,e)}})}else(a.deletes.length>0||i.deletes.length>0)&&await withSecretsStateLock(o,async()=>{await Promise.all(a.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(o);for(let e of a.deletes)Object.hasOwn(t.vaults,e.vaultName)&&(delete k(t.vaults[e.vaultName],`vault state entry missing`)[e.secretName],Object.keys(k(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(o,t)})}const Yi=[`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;if(!s){r.push({kind:`removed`,path:e,before:o});continue}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})}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 Yi)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 a=e.hooks,o=t.hooks;if(!!a!=!!o||a&&o&&((a.create?.expr??``)!==(o.create?.expr??``)||(a.update?.expr??``)!==(o.update?.expr??``)))return!0;let s=e.validate??[],c=t.validate??[];if(s.length!==c.length)return!0;for(let e=0;e<s.length;e++){let t=k(s[e],`oldValidate missing index ${e}`),n=k(c[e],`newValidate missing index ${e}`);if((t.script?.expr??``)!==(n.script?.expr??``)||t.errorMessage!==n.errorMessage)return!0}let l=e.serial,u=t.serial;return!!(!!l!=!!u||l&&u&&(l.start!==u.start||l.maxValue!==u.maxValue||(l.format??``)!==(u.format??``))||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=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(`
|
|
26
|
-
`)}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=>`${
|
|
24
|
+
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=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||!Li.test(e)?!1:shannonEntropyPerChar(e)>=4.2}function shannonEntropyPerChar(e){let t=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(){globalThis.tailordb={Client:class{constructor(e){}async connect(){}async end(){}async queryObject(){return{}}}}}async function loadConfig(e,t={}){installCliTailordbStub();let n=loadConfigPath(e);if(!n)throw Error(`Configuration file not found: tailor.config.ts not found in current or parent directories`);let r=V.resolve(process.cwd(),n);if(!U.existsSync(r))throw Error(`Configuration file not found: ${e}`);let i=fr(r),a=t.importNonce??vn();a&&i.searchParams.set(dn,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(Error(`Invalid Tailor config module: default export not found`),r);let s=bi.safeParse(o.default);if(!s.success){let e=s.error.issues.map(e=>` - ${e.path.join(`.`)||`(root)`}: ${e.message}`).join(`
|
|
25
|
+
`);throw atConfigFile(Error(`Invalid Tailor config in ${r}:\n${e}`),r)}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=[];for(let e of yn(o)){let t=e.map(e=>xi.safeParse(e));t.every(e=>e.success)&&u.push(...t.map(e=>e.data))}return{config:{...c,...l?{env:l}:{},path:r},plugins:u}}function atConfigFile(e,t){return en(e,{location:{file:t}})}function isSyntaxDiagnostic(e){if(typeof e!=`object`||!e||e instanceof Error)return!1;let{code:t,message:n,filename:r,startLine:i}=e;return t===`InvalidSyntax`&&typeof n==`string`&&typeof r==`string`&&(i===void 0||typeof i==`number`)}function atConfigSource(e,t){return isSyntaxDiagnostic(e)?en(SyntaxError(e.message,{cause:e}),{location:{file:e.filename,...e.startLine===void 0?{}:{line:e.startLine}}}):e instanceof Error?Yt(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 readPlatformConfig()).profiles[t];if(n&&n.readonly===!0)throw R({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 'tailor profile update ${t} --permission write'.`})}function hasEnvAccessToken(){return!!(process.env.TAILOR_PLATFORM_TOKEN??process.env.TAILOR_TOKEN)}async function apiCall(e){let t=await loadAccessToken({profile:e.profile}),n;try{n=await loadPlatformClientConfig({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,Ot(n)),a=await fetch(i.toString(),{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${t}`,"User-Agent":await xn()},body:e.body??`{}`}),o=await a.json();if(!a.ok)throw R({code:`API_REQUEST_FAILED`,message:`API call failed (${a.status}): ${JSON.stringify(o)}`,context:{status:a.status}});return{status:a.status,data:o}}async function loadOperatorWorkspaceContext(e){let t=await loadAccessToken({profile:e.profile});return{client:await F(t),workspaceId:await loadWorkspaceId({profile:e.profile,workspaceId:e.workspaceId})}}function canPrompt(){return!Dr&&process.stdin.isTTY===!0&&process.stdout.isTTY===!0&&!M.jsonMode}function withGuard(e,t){return async n=>{if(!canPrompt())throw new pt(t);try{return await e(n)}catch(e){throw e instanceof Sr&&process.exit(130),e}}}const X={confirm:withGuard(Cr,`Interactive confirmations are not available in this environment. Use --yes to skip confirmation prompts, or provide the required options explicitly.`),text:withGuard(wr),password:withGuard(Tr),select:e=>withGuard(Er)(e)};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}`,...(t.details??[]).map(e=>` ${e}`)];return[j.bold(`${e}:`),...t.flatMap(itemLines(A.create)),...r.flatMap(itemLines(A.delete)),...n.flatMap(itemLines(A.update)),...i.flatMap(itemLines(A.replace))]}}}function summarizeChangeSets(e){let t={create:0,update:0,delete:0,replace: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;return t}function formatPlanSummary(e){let t=[`${e.create} to create`,`${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 $n(e,Xn(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 zi=`sdk-name`,Bi=`sdk-version`,Vi=`sdk-app-id`;function sdkAppIdLabelValue(e){return`app-${e}`}function hasMatchingSdkVersion(e,t){return e?.[Bi]===t?.[Bi]}function isOwnedByApp(e,t,n){if(!e)return!1;let r=e[Vi];return r?n!==void 0&&r===sdkAppIdLabelValue(n):e[zi]===t}function prefixFor(e){return e===`jobs`?`sdk-job-depended-by-app-`:`sdk-depended-by-app-`}const Hi=/^[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 Hi.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 Hi.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??new Map,s=r??new Set,c={};for(let[e,t]of o){let n=dependedByAppLabelKey(e,a);if(!n)throw R({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 bn(),o=a.version?`v${a.version.replace(/\./g,`-`)}`:`unknown`;return{trn:t,labels:{...i,[zi]:n,[Bi]:o,...r?{[Vi]:sdkAppIdLabelValue(r)}:{}},remove:r?void 0:[Vi]}}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 Ui=Symbol(`metadataWriteBatch`);var MetadataWriteBatch=class{#e;#t=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=>Cn(e)?lr(e.format()):Tn(e).message;return en(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===Ui?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[Ui];if(n){await n.enqueue(t);return}await writeMetadataLabelsDirect(e,t)}async function writeMetadataLabelsDirect(e,t){if(!hasMetadataLabelChange(t))return;let{trn:n}=t,r=(await P(()=>e.getMetadata({trn:n})))?.metadata?.labels??{},i=applyMetadataLabelWrite(r,t);areSameLabels(r,i)||await e.setMetadata({trn:n,labels:i})}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 N(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,label:a?.labels[zi],allLabels:a?.labels}})),o}function trackDesiredResourceOwnership(e){let{labels:t,ownerLabel:n,appName:r,appId:i,resourceType:a,resourceName:o,conflicts:s,unmanaged:c}=e,l=isOwnedByApp(t,r,i);return l||(n?s.push({resourceType:a,resourceName:o,currentOwner:n}):c.push({resourceType:a,resourceName:o})),l}function trackRemainingResourceOwner(e){let{labels:t,ownerLabel:n,appName:r,appId:i,resourceOwners:a}=e,o=isOwnedByApp(t,r,i);return n&&!o&&a.add(n),o}async function applyStaticWebsite(e,t,n=`create-update`){let{changeSet:r,customDomainChangeSet:i}=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=>{await e.addCustomDomain(t.request),await writeMetadataLabels(e,t.metaRequest)}),...i.deletes.map(t=>e.removeCustomDomain(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}`}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=[],c=[],l=new Set,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=new Set,f=i?[]:r.staticWebsiteServices;for(let e of f){let t=e,i=e.name,o=u[i],l=await buildMetaRequest({trn:resourceTrn(n,`staticwebsite`,i),appName:r.name,appId:r.id}),f=normalizeComparableStaticWebsite(t),p={workspaceId:n,staticwebsite:{name:i,description:t.description||``,allowedIpAddresses:t.allowedIpAddresses||[]}};if(o){let e=trackDesiredResourceOwnership({labels:o.allLabels,ownerLabel:o.label,appName:r.name,appId:r.id,resourceType:`StaticWebsite`,resourceName:i,conflicts:s,unmanaged:c});e&&hasMatchingSdkVersion(o.allLabels,l.labels)&&areStaticWebsitesEqual(o.resource,f)?a.unchanged.push({name:i}):a.updates.push({name:i,request:p,metaRequest:l}),e&&d.add(i),delete u[i]}else a.creates.push({name:i,request:p,metaRequest:l}),d.add(i)}Object.entries(u).forEach(([e])=>{let t=u[e],i=t?.label;trackRemainingResourceOwner({labels:t?.allLabels,ownerLabel:i,appName:r.name,appId:r.id,resourceOwners:l})&&a.deletes.push({name:e,request:{workspaceId:n,name:e}})});let p=new Map;for(let e of f)e.customDomains!==void 0&&d.has(e.name)&&p.set(e.name,e.customDomains);let m=new Map,h=[...d].filter(e=>!a.creates.some(t=>t.name===e));await Promise.all(h.map(async e=>{let r=await P(async()=>{let{customDomains:r}=await t.listCustomDomains({workspaceId:n,staticWebsiteName:e});return await Promise.all(r.map(async r=>{let{metadata:i}=await t.getMetadata({trn:customDomainTrn(n,e,r.domain)});return{domain:r.domain,allLabels:i?.labels}}))});r&&m.set(e,r)}));for(let e of d){let t=new Set(p.get(e)??[]),i=m.get(e)??[],a=new Set(i.map(e=>e.domain)),s=new Set(i.filter(e=>isOwnedByApp(e.allLabels,r.name,r.id)).map(e=>e.domain));for(let i of t)if(a.has(i))o.unchanged.push({name:i});else{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 s)t.has(e)||o.deletes.push({name:e,request:{workspaceId:n,domain:e}})}return{changeSet:a,customDomainChangeSet:o,conflicts:s,unmanaged:c,resourceOwners:l}}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 It(e,k(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 It(e,k(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=[],s=[],c=new Set,l=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)}),u=i?[]:r.aiGatewayServices,d=expectedLocalStaticWebsiteNames(e);for(let e of u){let i=e,c=e.name,u=l[c],f=await buildMetaRequest({trn:resourceTrn(n,`aigateway`,c),appName:r.name,appId:r.id}),p=await It(t,n,i.cors?[...i.cors]:[],`AIGateway CORS`,{expectedLocalNames:d}),m=normalizeComparableAIGateway({...i,cors:p}),h={workspaceId:n,aigatewayName:c,authNamespace:i.authNamespace,cors:i.cors?[...i.cors]:[]};u?(trackDesiredResourceOwnership({labels:u.allLabels,ownerLabel:u.label,appName:r.name,appId:r.id,resourceType:`AIGateway`,resourceName:c,conflicts:o,unmanaged:s})&&hasMatchingSdkVersion(u.allLabels,f.labels)&&areAIGatewaysEqual(u.resource,m)?a.unchanged.push({name:c}):a.updates.push({name:c,request:h,metaRequest:f}),delete l[c]):a.creates.push({name:c,request:h,metaRequest:f})}return Object.entries(l).forEach(([e,t])=>{let i=t?.label;trackRemainingResourceOwner({labels:t?.allLabels,ownerLabel:i,appName:r.name,appId:r.id,resourceOwners:c})&&a.deletes.push({name:e,request:{workspaceId:n,aigatewayName:e}})}),{changeSet:a,conflicts:o,unmanaged:s,resourceOwners:c}}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 It(e,k(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 It(e,k(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)}))}function sortStrings(e){return(e??[]).toSorted()}function normalizeSubgraphs(e){return[...e??[]].map(e=>({serviceType:k(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){let{client:n,workspaceId:r,application:i,forRemoval:a}=e,o=[],s=[],c=new Set,l=createChangeSet(`Applications`),u=await N(async(e,t)=>{let{applications:i,nextPageToken:a}=await n.listApplications({workspaceId:r,pageToken:e,pageSize:t});return[i,a]});if(a){let e=i.id?u:u.filter(e=>e.name===i.name),t=await Promise.all(e.map(async e=>{let t=await fetchAppLabels(n,r,e.name);return trackRemainingResourceOwner({labels:t,ownerLabel:t?.[`sdk-name`],appName:i.name,appId:i.id,resourceOwners:c})?e.name:null}));for(let e of t)e&&l.deletes.push({name:e,request:{workspaceId:r,applicationName:e}});return withOwnership(l,o,s,c)}if(i.subgraphs.length===0)return withOwnership(l,o,s,c);let d,f;if(i.authService){d=i.authService.config.name;let e=i.authService.config.idProvider;e&&(f=e.name)}else if(i.config.auth){if(d=i.config.auth.name,e.externalAuthIdpConfigNames?.has(d))f=e.externalAuthIdpConfigNames.get(d);else{let e=await N(async(e,t)=>{let{idpConfigs:i,nextPageToken:a}=await n.listAuthIDPConfigs({workspaceId:r,namespaceName:k(d,`authNamespace must be set before listing IDP configs`),pageToken:e,pageSize:t});return[i,a]});if(e.length>0){let[t]=e;t&&(f=t.name)}}}let p=await buildMetaRequest({trn:resourceTrn(r,`application`,i.name),appName:i.name,appId:i.id,metadata:i.config.metadata}),m=await fetchAppLabels(n,r,i.name);assertLabelBudget(i.name,m,p);let h=diffMetadataDisplay(m,i.config.metadata),g=expectedLocalStaticWebsiteNames(e),_=await It(n,r,i.config.cors,`CORS`,{expectedLocalNames:g}),v=buildHttpAdapters(i,t),y=normalizeComparableApplication(i,d,f,_,v),b={workspaceId:r,applicationName:i.name,authNamespace:d,authIdpConfigName:f,cors:i.config.cors,subgraphs:i.subgraphs.map(e=>protoSubgraph(e)),allowedIpAddresses:i.config.allowedIpAddresses,disableIntrospection:i.config.disableIntrospection,httpAdapters:v},x=u.find(e=>e.name===i.name);if(i.id){let e=u.filter(e=>e.name!==i.name),t=await Promise.all(e.map(async e=>isOwnedByApp(await fetchAppLabels(n,r,e.name),i.name,i.id)?e.name:null));for(let e of t)e&&l.deletes.push({name:e,request:{workspaceId:r,applicationName:e}})}if(x){let e=trackDesiredResourceOwnership({labels:m,ownerLabel:m?.[zi],appName:i.name,appId:i.id,resourceType:`Application`,resourceName:i.name,conflicts:o,unmanaged:s}),t={name:i.name,request:b,metaRequest:p};if(e&&hasMatchingSdkVersion(m,p.labels)&&areApplicationsEqual(x,y)&&h.length===0)l.unchanged.push(t);else{let e=[...diffHttpAdapterDisplay(x.httpAdapters,v),...h];e.length>0&&(t.details=e),l.updates.push(t)}}else{let e=[...diffHttpAdapterDisplay(void 0,v),...h];l.creates.push({name:i.name,request:b,metaRequest:p,details:e.length>0?e:void 0})}return withOwnership(l,o,s,c)}function withOwnership(e,t,n,r){return Object.assign(e,{conflicts:t,unmanaged:n,resourceOwners:r})}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:A.update}):i.push({name:e,symbol:A.create})}for(let e of n.keys())r.has(e)||i.push({name:e,symbol:A.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=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 R({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)?A.update:A.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 L(`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 L(`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=>Bt[e]),inputScript:n,outputScript:r,enabled:e.adapter.enabled,priority:e.adapter.priority}})}function protoSubgraph(e){let t;switch(e.Type){case`tailordb`:t=pe.TAILORDB;break;case`pipeline`:t=pe.PIPELINE;break;case`idp`:t=pe.IDP;break;case`auth`:t=pe.AUTH;break;default:throw L(`Unknown subgraph type: ${e.Type}`)}return{serviceType:t,serviceNamespace:e.Name}}const Wi=H.object({hash:H.string(),updateTime:H.string().optional()}),Gi=H.object({vaults:H.record(H.string(),H.record(H.string(),Wi)),connections:H.record(H.string(),H.string()).optional()}),Ki=H.object({version:H.literal(2),workspaceId:H.string(),applicationKey:H.string(),state:Gi});function getSecretsStatePath(e){let t=hashValue(JSON.stringify([e.workspaceId,applicationStateKey(e)]));return V.join($t(),`secrets-state`,`${t}.json`)}function loadPersistedSecretsState(e){try{let t=tr(getSecretsStatePath(e),`utf-8`),n=Ki.parse(JSON.parse(t));return n.workspaceId!==e.workspaceId||n.applicationKey!==applicationStateKey(e)?void 0:n}catch{return}}function applicationStateKey(e){if(!e.applicationId)throw L(`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=V.dirname(n);er(r,{recursive:!0});let i=`${n}.tmp-${xr()}`;sr(i,JSON.stringify({version:2,workspaceId:e.workspaceId,applicationKey:applicationStateKey(e),state:t},null,2),`utf-8`),rr(i,n)}function hashValue(e){return br(`sha256`).update(e).digest(`hex`)}function serializeUpdateTime(e){return e===void 0?void 0:`${e.seconds}.${e.nanos}`}const qi=new Map;async function withSecretsStateLock(e,t){if(!e.applicationId)return t();let n=`${getSecretsStatePath(e)}.lock`,r=qi.get(n);return r||(r=vr(1),qi.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){er(V.dirname(e),{recursive:!0});let t=xr(),n=Date.now()+3e5;for(;;){let r=!0;try{er(e)}catch(e){if(e.code!==`EEXIST`)throw e;r=!1}if(r){try{sr(V.join(e,`owner.json`),JSON.stringify({pid:process.pid,token:t}))}catch(t){throw ir(e,{recursive:!0,force:!0}),t}return t}if(!(isLockExpired(e)&&stealLock(e))){if(Date.now()>=n)throw R({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.`});await new Promise(e=>setTimeout(e,100))}}}function isLockExpired(e){try{return Date.now()-ar(e).mtimeMs>6e4}catch{return!1}}function readLockToken(e){try{return JSON.parse(tr(V.join(e,`owner.json`),`utf-8`)).token}catch{return}}function refreshLock(e,t){if(readLockToken(e)!==t)return;let n=new Date;try{or(e,n,n)}catch{}}function releaseFileLock(e,t){readLockToken(e)===t&&ir(e,{recursive:!0,force:!0})}function stealLock(e){let t=`${e}.stale-${process.pid}-${Date.now()}`;try{rr(e,t)}catch{return!1}if(isLockExpired(t))return ir(t,{recursive:!0,force:!0}),!0;try{rr(t,e)}catch{ir(t,{recursive:!0,force:!0})}return!1}function buildConnectionRequest(e,t,n){return{workspaceId:e,connection:{name:t,type:oe.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=[],c=[],l=new Set,u={};for(let e of i)for(let[t,n]of Object.entries(e.connections))u[t]=n,M.registerSecret(n.clientSecret);let d=await N(async(n,r)=>{let{connections:i,nextPageToken:a}=await e.listAuthConnections({workspaceId:t,pageToken:n,pageSize:r});return[i,a]}),f={};await Promise.all(d.map(async n=>{let{metadata:r}=await e.getMetadata({trn:resourceTrn(t,`auth_connection`,n.name)});f[n.name]={resource:n,label:r?.labels[zi],allLabels:r?.labels}}));let p=loadSecretsState(a);for(let[e,i]of Object.entries(u)){let a=f[e],l=await buildMetaRequest({trn:resourceTrn(t,`auth_connection`,e),appName:n,appId:r});if(a){let u=trackDesiredResourceOwnership({labels:a.allLabels,ownerLabel:a.label,appName:n,appId:r,resourceType:`Auth connection`,resourceName:e,conflicts:s,unmanaged:c}),d=hashValue(i.clientSecret)!==p.connections?.[e],m=buildUpdateMask(a.resource,i,d);m.paths.length>0?o.replaces.push({name:e,updateRequest:{...buildConnectionRequest(t,e,i),updateMask:m},metaRequest:l}):u?o.unchanged.push({name:e}):o.updates.push({name:e,metaRequest:l}),delete f[e]}else o.creates.push({name:e,request:buildConnectionRequest(t,e,i),metaRequest:l})}for(let[e,i]of Object.entries(f))i&&trackRemainingResourceOwner({labels:i.allLabels,ownerLabel:i.label,appName:n,appId:r,resourceOwners:l})&&o.deletes.push({name:e,request:{workspaceId:t,connectionName:e}});return{changeSet:o,conflicts:s,unmanaged:c,resourceOwners:l,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),M.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===rt.UNAUTHORIZED&&M.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 Ji=65536;function computeContentHash(e){return yr.createHash(`sha256`).update(e,`utf-8`).digest(`hex`)}const Yi=`workflow--`;function resolverFunctionName(e,t){return`resolver--${e}--${t}`}function executorFunctionName(e){return`executor--${e}`}function workflowJobFunctionName(e){return`${Yi}${e}`}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(Ft(e.namespace,t.name));if(!i){M.warn(`Bundled code not found for resolver: ${e.namespace}/${t.name}`);continue}r.push({name:resolverFunctionName(e.namespace,t.name),scriptContent:i,contentHash:computeContentHash(i),description:`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){M.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);if(!t){M.warn(`Bundled code not found for workflow job: ${e.name}`);continue}r.push({name:workflowJobFunctionName(e.name),scriptContent:t,contentHash:computeContentHash(t),description:`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){M.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){let a=createChangeSet(`Function registry`),o=[],s=[],c=new Set,l=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)});for(let e of i){let i=l[e.name],c=await buildMetaRequest({trn:resourceTrn(t,`function_registry`,e.name),appName:n,appId:r});if(i){let t=trackDesiredResourceOwnership({labels:i.allLabels,ownerLabel:i.label,appName:n,appId:r,resourceType:`Function registry`,resourceName:e.name,conflicts:o,unmanaged:s});i.resource.contentHash===e.contentHash&&t&&hasMatchingSdkVersion(i.allLabels,c.labels)?a.unchanged.push({name:e.name}):a.updates.push({name:e.name,entry:e,metaRequest:c}),delete l[e.name]}else a.creates.push({name:e.name,entry:e,metaRequest:c})}for(let[e,i]of Object.entries(l))i&&trackRemainingResourceOwner({labels:i.allLabels,ownerLabel:i.label,appName:n,appId:r,resourceOwners:c})&&a.deletes.push({name:e,workspaceId:t});let{workflowJobChanges:u,resolverFunctionChanges:d,executorFunctionChanges:f,authHookFunctionChanges:p}=splitFunctionRegistryChanges(a);return{changeSet:a,workflowJobChanges:u,resolverFunctionChanges:d,executorFunctionChanges:f,authHookFunctionChanges:p,conflicts:o,unmanaged:s,resourceOwners: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+=Ji)yield{payload:{case:`chunk`,value:i.subarray(e,Math.min(e+Ji,i.length))}}}await e.createFunctionRegistry(createStream())}else{async function*updateStream(){yield{payload:{case:`info`,value:a}};for(let e=0;e<i.length;e+=Ji)yield{payload:{case:`chunk`,value:i.subarray(e,Math.min(e+Ji,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=Kt();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(t=>e.deleteFunctionRegistry({workspaceId:t.workspaceId,name:t.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 Xi={create:A.create,update:A.update,delete:A.delete,replace:A.replace};function formatChangeSetEntries(e,t=[],n){function toEntry(e,r){return{action:e,symbol:Xi[e],name:r.name,labels:[...t],namespace:n?.(r)}}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}`}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=createRelatedFunctionRegistryNameSets()){return[[`create`,e.creates,t.creates],[`delete`,e.deletes,t.deletes],[`update`,e.updates,t.updates],[`replace`,e.replaces,t.replaces]].flatMap(([e,t,n])=>[...t].filter(e=>!n.has(e)).map(t=>{let{displayName:n,namespace:r}=parseFunctionRegistryName(t);return{action:e,symbol:Xi[e],name:n,labels:[`function`],namespace:r}}))}function formatChangeEntriesWithFunctionRegistry(e,t,n,r,i){let{getNamespace:a,getDisplayName:o}=i??{},s=createRelatedFunctionRegistryNameSets(n),c=createRelatedFunctionRegistryNameSets();function processItems(t,n,i,s){return t.map(t=>{let c=r(t,n),l=c.some(e=>i.has(e));if(l)for(let e of c)i.has(e)&&s.add(e);return{action:n,symbol:Xi[n],name:o?.(t)??t.name,labels:l?[e,`function`]:[e],namespace:a?.(t)}})}return[...processItems(t.creates,`create`,s.creates,c.creates),...processItems(t.deletes,`delete`,s.deletes,c.deletes),...processItems(t.updates,`update`,s.updates,c.updates),...t.replaces.map(t=>({action:`replace`,symbol:Xi.replace,name:o?.(t)??t.name,labels:[e],namespace:a?.(t)})),...buildRemainingFunctionRegistryEntries(s,c)]}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.replaces.map(e=>({name:e.name,action:`replace`}))]}function buildGroupedDisplayLines(e,t,n){let r=new Map;if(n)for(let e of n)r.set(e.name,e.action);if(t.length===0&&r.size===0)return[];let i=[j.bold(`${e}:`)],a=[],o=new Map;for(let e of t){let t=e.namespace;o.has(t)||(a.push(t),o.set(t,[])),k(o.get(t),`namespace group missing`).push(e)}let s=new Set;for(let e of a){let t=k(o.get(e),`namespace group missing`);if(e){let n=r.get(e),a=n?`${Xi[n]} `:``;i.push(` ${a}${j.bold(`${e}:`)}`),s.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)s.has(e)||i.push(` ${Xi[t]} ${e}`);return i}const Zi={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}"`},Qi={tailorDBType:e=>({resource:Zi.tailorDBType(e),trigger:`record`}),resolver:e=>({resource:Zi.resolver(e),trigger:`resolverExecuted`}),idpService:e=>({resource:Zi.idpService(e),trigger:`idpUser`}),workflow:e=>({resource:Zi.workflow(e),trigger:`workflowExecution`}),workflowJob:e=>({resource:Zi.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:$i}=sn({"=":`eq`,"!=":`ne`,in:`in`,"not in":`nin`});function normalizeIdPActionPermission(e){return $i(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)=>{jt(e)&&t.push(`${String(n)}[${r}]`)});return t}async function resolveServiceReturnOrigins(e,t){let n=t.userAuthPolicy,r=n?.allowedReturnOrigins;if(!n||!r?.length)return;let i=await It(e,k(t.workspaceId,`request missing workspaceId`),r,`IdP service "${t.namespaceName??``}" allowedReturnOrigins`);if(i.length!==r.length)throw R({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&&M.registerSecret(n.client.clientSecret);let r=idpClientVaultName(k(t.request.namespaceName,`request missing namespaceName`),t.request.client?.name||``),i=idpClientSecretName(k(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);await P(async()=>await e.getSecretManagerVault({workspaceId:t.workspaceId,secretmanagerVaultName:n}))||(await e.createSecretManagerVault({workspaceId:t.workspaceId,secretmanagerVaultName:n}),await e.createSecretManagerSecret({workspaceId:t.workspaceId,secretmanagerVaultName:n,secretmanagerSecretName:r,secretmanagerSecretValue:t.clientSecret}))})])):n===`delete-resources`?await Promise.all(r.client.deletes.map(async t=>{await e.deleteIdPClient(t.request);let n=`idp-${t.request.namespaceName}-${t.request.name}`;await e.deleteSecretManagerVault({workspaceId:t.request.workspaceId,secretmanagerVaultName:n})})):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??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===se.UNSPECIFIED?se.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=[],u=[],d=new Set,f=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,p=f[i],m=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}),h;switch(d.authorization){case`insecure`:h=`true==true`;break;case`loggedIn`:h=`user != null && size(user.id) > 0`;break;case void 0:h=void 0;break;default:h=d.authorization.cel}let g=convertLang(d.lang),_=d.userAuthPolicy,v=resolvePublishEvents({explicit:d.publishEvents,subscribed:a.has(i),conflict:Qi.idpService(i)}),y=d.emailConfig;d.permission||M.warn(`IdP service "${i}" has no permission configured.`);let b=findOmittedPermitRules(d.permission);b.length>0&&M.warn(`IdP service "${i}" has permission rule(s) ${b.join(`, `)} in object form without an explicit "permit"; they default to "deny". Set permit: true (allow) or permit: false (deny) to silence this warning.`),Vt(_)&&M.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,C=await It(e,t,_?.allowedReturnOrigins?[..._.allowedReturnOrigins]:[],`IdP service "${i}" allowedReturnOrigins`,{expectedLocalNames:o}),w=_&&{..._,allowedReturnOrigins:C},ee=normalizeComparableIdPService({authorization:h,lang:g,userAuthPolicy:normalizeComparableUserAuthPolicy(w),publishEvents:v,disableGqlOperations:normalizeComparableDisableGqlOperations(convertGqlOperationsToDisable(d.gqlOperations)),emailConfig:normalizeComparableEmailConfig(y),permission:S}),te={workspaceId:t,namespaceName:i,authorization:h,lang:g,userAuthPolicy:_,publishUserEvents:v,disableGqlOperations:convertGqlOperationsToDisable(d.gqlOperations),emailConfig:y,permission:S};p?(trackDesiredResourceOwnership({labels:p.allLabels,ownerLabel:p.label,appName:n,appId:r,resourceType:`IdP service`,resourceName:d.name,conflicts:l,unmanaged:u})&&hasMatchingSdkVersion(p.allLabels,m.labels)&&areIdPServicesEqual(p.resource,ee)?c.unchanged.push({name:i,metaRequest:m}):c.updates.push({name:i,request:te,metaRequest:m}),delete f[i]):c.creates.push({name:i,request:te,metaRequest:m})}return Object.entries(f).forEach(([e])=>{let i=f[e];trackRemainingResourceOwner({labels:i?.allLabels,ownerLabel:i?.label,appName:n,appId:r,resourceOwners:d})&&c.deletes.push({name:e,request:{workspaceId:t,namespaceName:e}})}),{changeSet:c,conflicts:l,unmanaged:u,resourceOwners:d}}async function planClients(e,t,n,r,i=!1){let a=createChangeSet(`IdP clients`),fetchClients=n=>N(async(r,i)=>{let{clients:a,nextPageToken:o}=await e.listIdPClients({workspaceId:t,namespaceName:n,pageToken:r,pageSize:i});return[a,o]}),o=await Promise.all(n.map(e=>fetchClients(e.name)));for(let[e,r]of n.entries()){let n=r.name,s=k(o[e],`clientsByIdp missing entry for idp index`),c=new Map;s.forEach(e=>{c.set(e.name,e.clientSecret),M.registerSecret(e.clientSecret)});for(let e of r.clients)c.has(e)?(i?a.updates.push({name:e,workspaceId:t,namespaceName:n,clientSecret:c.get(e)??``}):a.unchanged.push({name:e}),c.delete(e)):a.creates.push({name:e,request:{workspaceId:t,namespaceName:n,client:{name:e}}});c.forEach((e,r)=>{a.deletes.push({name:r,request:{workspaceId:t,namespaceName:n,name:r}})})}let s=await Promise.all(r.map(e=>fetchClients(e)));for(let[e,n]of r.entries())k(s[e],`deletedClientsByService missing entry for service index`).forEach(e=>{M.registerSecret(e.clientSecret),a.deletes.push({name:e.name,request:{workspaceId:t,namespaceName:n,name:e.name}})});return a}function convertLang(e){switch(e){case`en`:return se.EN;case`ja`:return se.JA;default:return se.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=u.ALLOW;break;case`deny`:t=u.DENY;break;default:throw L(`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=le.EQ;break;case`ne`:o=le.NE;break;case`in`:o=le.IN;break;case`nin`:o=le.NIN;break;default:throw L(`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 L(`Unknown operand: ${JSON.stringify(e)}`)}return{kind:{case:`value`,value:Qn(ur,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&&M.registerSecret(n.machineUser.clientSecret),n}),...r.machineUser.updates.map(async t=>{let n=await e.updateAuthMachineUser(t.request);return n.machineUser?.clientSecret&&M.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`&&(k(t.request.idpConfig,`request missing idpConfig`).config=await protoBuiltinIdPConfig(e,k(t.request.workspaceId,`request missing workspaceId`),t.idpConfig)),e.createAuthIDPConfig(t.request))),...r.idpConfig.updates.map(async t=>(t.idpConfig.kind===`BuiltInIdP`&&(k(t.request.idpConfig,`request missing idpConfig`).config=await protoBuiltinIdPConfig(e,k(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=k(t.request.oauth2Client,`request missing oauth2Client`);n.redirectUris=await It(e,k(t.request.workspaceId,`request missing workspaceId`),n.redirectUris,`OAuth2 redirect URIs`);let r=await e.createAuthOAuth2Client(t.request);return r.oauth2Client?.clientSecret&&M.registerSecret(r.oauth2Client.clientSecret),r}),...r.oauth2Client.updates.map(async t=>{let n=k(t.request.oauth2Client,`request missing oauth2Client`);n.redirectUris=await It(e,k(t.request.workspaceId,`request missing workspaceId`),n.redirectUris,`OAuth2 redirect URIs`);let r=await e.updateAuthOAuth2Client(t.request);return r.oauth2Client?.clientSecret&&M.registerSecret(r.oauth2Client.clientSecret),r})]);for(let t of r.oauth2Client.replaces){await e.deleteAuthOAuth2Client(t.deleteRequest);let n=k(t.createRequest.oauth2Client,`createRequest missing oauth2Client`);n.redirectUris=await It(e,k(t.createRequest.workspaceId,`createRequest missing workspaceId`),n.redirectUris,`OAuth2 redirect URIs`);let r=await e.createAuthOAuth2Client(t.createRequest);r.oauth2Client?.clientSecret&&M.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: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=[],c=[],l=new Set,u=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=u[i.name],d=await buildMetaRequest({trn:resourceTrn(t,`auth`,i.name),appName:n,appId:r}),f={workspaceId:t,namespaceName:i.name,publishSessionEvents:i.publishSessionEvents};if(l){let e=trackDesiredResourceOwnership({labels:l.allLabels,ownerLabel:l.label,appName:n,appId:r,resourceType:`Auth service`,resourceName:i.name,conflicts:s,unmanaged:c});!a&&l.resource.publishSessionEvents===(i.publishSessionEvents??!1)&&e?o.unchanged.push({name:i.name}):o.updates.push({name:i.name,request:f,metaRequest:d}),delete u[i.name]}else o.creates.push({name:i.name,request:f,metaRequest:d})}return Object.entries(u).forEach(([e])=>{let i=u[e];trackRemainingResourceOwner({labels:i?.allLabels,ownerLabel:i?.label,appName:n,appId:r,resourceOwners:l})&&o.deletes.push({name:e,request:{workspaceId:t,namespaceName:e}})}),{changeSet:o,conflicts:s,unmanaged:c,resourceOwners:l}}async function planIdPConfigs(e,t,n,r,i=!1){let a=createChangeSet(`Auth idpConfigs`),fetchIdPConfigs=n=>N(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=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}!i&&areAuthIdPConfigsEqual(o,l)?a.unchanged.push({name:c.name}):a.updates.push({name:c.name,idpConfig:c,request:{workspaceId:t,namespaceName:n.name,idpConfig:r}}),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(s,e)}function areAuthIdPConfigsEqual(e,t){return areNormalizedEqual(normalizeComparableAuthIdPConfig(e),normalizeComparableAuthIdPConfig(t))}function protoIdPConfig(e){switch(e.kind){case`IDToken`:return{name:e.name,authType:w.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:w.SAML,config:{config:{case:`saml`,value:{...e.metadataURL===void 0?{rawMetadata:k(e.rawMetadata,`SAML config missing rawMetadata`)}:{metadataUrl:e.metadataURL},enableSignRequest:e.enableSignRequest,defaultRedirectUrl:e.defaultRedirectURL}}}};case`OIDC`:return{name:e.name,authType:w.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:w.OIDC,config:{}};default:throw L(`Unexpected idp kind: ${e}`)}}async function protoBuiltinIdPConfig(e,t,n){let r=await tryProtoBuiltinIdPConfig(e,t,n);if(!r)throw R({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);!i&&areUserProfileConfigsEqual(s.userProfileProviderConfig??{},e)?a.unchanged.push({name:o}):a.updates.push({name:o,request:{workspaceId:t,namespaceName:n.name,userProfileProviderConfig:e}})}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:i.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)}});continue}if(n.tenantProvider){let e=protoTenantConfig(n.tenantProvider);!i&&areTenantProviderConfigsEqual(s.tenantProviderConfig,e)?a.unchanged.push({name:o}):a.updates.push({name:o,request:{workspaceId:t,namespaceName:n.name,tenantProviderConfig:e}})}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:re.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=>N(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=new Map;r.forEach(e=>{o.set(e.name,e),M.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);c?(!i&&areMachineUsersEqual(c,s)?a.unchanged.push({name:e}):a.updates.push({name:e,request:{workspaceId:t,authNamespace:n.name,name:e,attributes:r.attributeList,attributeMap:s.attributeMap}}),o.delete(e)):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=>{M.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]=Qn(ur,r??null);return t}function normalizeComparableUserProfileConfig(e){let t=e.config?.config,n=t?.case===`tailordb`?t.value:void 0;return toComparableProtoJson(ct,{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(v,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,a=!1){let o=createChangeSet(`Auth oauth2Clients`),fetchOAuth2Clients=n=>N(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,s=await fetchOAuth2Clients(n.name),c=new Map;s.forEach(e=>{c.set(e.name,e),M.registerSecret(e.clientSecret)});for(let r of Object.keys(n.oauth2Clients??{})){let s=n.oauth2Clients?.[r];if(!s)continue;let l=protoOAuth2Client(r,s),u=await It(e,t,l.redirectUris??[],`OAuth2 redirect URIs`,{expectedLocalNames:i});if(c.has(r)){let e=k(c.get(r),`existingClientsMap missing entry for oauth2ClientName`);if(e.clientType!==l.clientType)o.replaces.push({name:r,deleteRequest:{workspaceId:t,namespaceName:n.name,name:r},createRequest:{workspaceId:t,namespaceName:n.name,oauth2Client:l}});else{let i={...l,redirectUris:u,accessTokenLifetime:oauth2LifetimeToSeconds(l.accessTokenLifetime),refreshTokenLifetime:oauth2LifetimeToSeconds(l.refreshTokenLifetime)},s={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};!a&&areOAuth2ClientsEqual(s,i)?o.unchanged.push({name:r}):o.updates.push({name:r,request:{workspaceId:t,namespaceName:n.name,oauth2Client:l}})}c.delete(r)}else o.creates.push({name:r,request:{workspaceId:t,namespaceName:n.name,oauth2Client:l}})}c.forEach((e,r)=>{o.deletes.push({name:r,request:{workspaceId:t,namespaceName:n.name,name:r}})})}for(let e of r)(await fetchOAuth2Clients(e)).forEach(n=>{M.registerSecret(n.clientSecret),o.deletes.push({name:n.name,request:{workspaceId:t,namespaceName:e,name:n.name}})});return o}function protoOAuth2Client(e,t){return{name:e,description:t.description,grantTypes:t.grantTypes.map(e=>{switch(e){case`authorization_code`:return Pe.AUTHORIZATION_CODE;case`refresh_token`:return Pe.REFRESH_TOKEN;default:throw L(`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=l.BEARER;break;case`oauth2`:t=l.OAUTH2;break;default:throw L(`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=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=S.STRING;break;case`number`:t=S.NUMBER;break;case`boolean`:t=S.BOOLEAN;break;case`datetime`:t=S.DATETIME;break;case`complex`:t=S.COMPLEX;break;default:throw L(`Unknown SCIM attribute type: ${e.type}`)}let n;if(e.mutability)switch(e.mutability){case`readOnly`:n=b.READ_ONLY;break;case`readWrite`:n=b.READ_WRITE;break;case`writeOnly`:n=b.WRITE_ONLY;break;default:throw L(`Unknown SCIM attribute mutability: ${e.mutability}`)}let r;if(e.uniqueness)switch(e.uniqueness){case`none`:r=te.NONE;break;case`server`:r=te.SERVER;break;case`global`:r=te.GLOBAL;break;default:throw L(`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:c.BEFORE_LOGIN});return r});if(o){let e={workspaceId:t,namespaceName:n.name,hook:{hookPoint:c.BEFORE_LOGIN,scriptRef:authHookFunctionName(n.name,`before-login`),invoker:{namespace:n.name,machineUserName:o.invoker}}};s?!i&&areAuthHooksEqual(s,e.hook)?a.unchanged.push({name:`${n.name}/before-login`}):a.updates.push({name:`${n.name}/before-login`,request:e}):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:c.BEFORE_LOGIN}})}for(let n of r)await P(async()=>await e.getAuthHook({workspaceId:t,namespaceName:n,hookPoint:c.BEFORE_LOGIN}))&&a.deletes.push({name:`${n}/before-login`,request:{workspaceId:t,namespaceName:n,hookPoint:c.BEFORE_LOGIN}});return a}function normalizeInvoker(e,t,n){if(e!==void 0){if(typeof e==`string`){if(!t)throw R({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){let{client:t,workspaceId:n,application:r,forRemoval:i}=e,a=createChangeSet(`Executors`),o=[],s=[],c=new Set,l=await fetchExistingResourcesWithLabels({client:t,fetchPage:async(e,r)=>{let{executors:i,nextPageToken:a}=await t.listExecutorExecutors({workspaceId:n,pageToken:e,pageSize:r});return[i,a]},getName:e=>e.name,getTrn:e=>resourceTrn(n,`executor`,e)}),u=i?{}:await r.executorService?.loadExecutors()??{};for(let t of Object.values(u)){let i=l[t.name],c=await buildMetaRequest({trn:resourceTrn(n,`executor`,t.name),appName:r.name,appId:r.id}),u=protoExecutor(e,t);i?(trackDesiredResourceOwnership({labels:i.allLabels,ownerLabel:i.label,appName:r.name,appId:r.id,resourceType:`Executor`,resourceName:t.name,conflicts:o,unmanaged:s})&&hasMatchingSdkVersion(i.allLabels,c.labels)&&areExecutorsEqual(i.resource,u)?a.unchanged.push({name:t.name}):a.updates.push({name:t.name,request:{workspaceId:n,executor:u},metaRequest:c}),delete l[t.name]):a.creates.push({name:t.name,request:{workspaceId:n,executor:u},metaRequest:c})}return Object.entries(l).forEach(([e])=>{let t=l[e],i=t?.label;trackRemainingResourceOwner({labels:t?.allLabels,ownerLabel:i,appName:r.name,appId:r.id,resourceOwners:c})&&a.deletes.push({name:e,request:{workspaceId:n,name:e}})}),{changeSet:a,conflicts:o,unmanaged:s,resourceOwners:c}}function isFunctionBackedExecutor(e){return e?.targetType===O.FUNCTION||e?.targetType===O.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 n=normalizeProtoConfig(e),r=n.targetConfig?.config?.case===`webhook`?(n.targetConfig.config.value.headers??[]).toSorted((e,t)=>(e.key??``).localeCompare(t.key??``)):void 0,i=n.triggerConfig?.config?.case===`incomingWebhook`?{...n.triggerConfig,config:{...n.triggerConfig.config,value:{...n.triggerConfig.config.value,secret:void 0}}}:n.triggerConfig?.config?.case===`event`?{...n.triggerConfig,config:{...n.triggerConfig.config,value:{...n.triggerConfig.config.value,eventType:void 0}}}:n.triggerConfig,a=normalizeProtoConfig({name:n.name,description:n.description??``,disabled:n.disabled??!1,triggerType:n.triggerType,triggerConfig:i,targetType:n.targetType,targetConfig:n.targetConfig?.config?.case===`webhook`?{...n.targetConfig,config:{...n.targetConfig.config,value:{...n.targetConfig.config.value,headers:r}}}:n.targetConfig?.config?.case===`function`?{...n.targetConfig,config:{...n.targetConfig.config,value:{...n.targetConfig.config.value,script:void 0}}}:n.targetConfig});return toComparableProtoJson(t,a)}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 R({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 R({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 R({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 R({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 R({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 k([...i][0],`idp service missing`)}function protoExecutor(e,t){let{application:n}=e,r=n.name,i=n.env,a=t.trigger,o,s,c=on(a.kind,i);function typedEventTrigger(e){return{config:{case:`event`,value:{typedConfig:e}}}}switch(a.kind){case`schedule`:o=Be.SCHEDULE,s={config:{case:`schedule`,value:{timezone:a.timezone,frequency:a.cron}}};break;case`tailordb`:o=Be.EVENT,s=typedEventTrigger({case:`tailordb`,value:{eventTypes:a.events,namespaceName:resolveTailorDBNamespace(n,a.tableName,e.tailorDBTypeNamespaces),typeName:a.tableName,...a.condition?{condition:{expr:`(${yt(a.condition)})(${c})`}}:{}}});break;case`resolverExecuted`:o=Be.EVENT,s=typedEventTrigger({case:`pipeline`,value:{eventTypes:[`pipeline.resolver.executed`],namespaceName:resolveResolverNamespace(n,a.resolverName,e.resolverNamespaces),resolverName:a.resolverName,...a.condition?{condition:{expr:`(${yt(a.condition)})(${c})`}}:{}}});break;case`incomingWebhook`:o=Be.INCOMING_WEBHOOK,s={config:{case:`incomingWebhook`,value:a.response?{response:{...a.response.body?{body:{expr:`(${yt(a.response.body)})(${c})`}}:{},...a.response.statusCode==null?{}:{statusCode:a.response.statusCode}}}:{}}};break;case`idpUser`:o=Be.EVENT,s=typedEventTrigger({case:`idp`,value:{eventTypes:a.events,namespaceName:resolveIdpNamespace(n,t.name,a.idp,e.idpNames)}});break;case`authAccessToken`:o=Be.EVENT,s=typedEventTrigger({case:`auth`,value:{eventTypes:a.events,namespaceName:Gt(n)}});break;case`workflowExecution`:case`workflowJobExecution`:o=Be.EVENT,s=typedEventTrigger({case:`workflow`,value:{eventTypes:a.events,workflowName:a.workflowName,...a.condition?{condition:{expr:`(${yt(a.condition)})(${c})`}}:{}}});break;default:throw L(`Unknown trigger: ${a}`)}let l=t.operation,u,d,f=Lt(n),p=`Executor "${t.name}"`;switch(l.kind){case`webhook`:u=O.WEBHOOK,d={config:{case:`webhook`,value:{url:{expr:`(${yt(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:`(${yt(l.requestBody)})(${c})`}:void 0}}};break;case`graphql`:u=O.TAILOR_GRAPHQL,d={config:{case:`tailorGraphql`,value:{appName:l.appName??r,query:l.query,variables:l.variables?{expr:`(${yt(l.variables)})(${c})`}:void 0,invoker:normalizeInvoker(l.invoker,f,p)}}};break;case`function`:case`jobFunction`:u=l.kind===`function`?O.FUNCTION:O.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=O.WORKFLOW,d={config:{case:`workflow`,value:{workflowName:l.workflowName,variables:l.args===void 0?void 0:typeof l.args==`function`?{expr:`(${yt(l.args)})(${c})`}:{expr:JSON.stringify(l.args)},invoker:normalizeInvoker(l.invoker,f,p)}}};break;default:throw L(`Unknown target: ${l}`)}return{name:t.name,description:t.description,disabled:t.disabled,triggerType:o,triggerConfig:s,targetType:u,targetConfig:d}}const ea={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){let{client:t,workspaceId:n,application:r,forRemoval:i,forceApplyAll:a=!1}=e,o=[];if(!i)for(let e of r.resolverServices)await e.loadResolvers(),o.push(e);let s=i?[]:Object.values(await r.executorService?.loadExecutors()??{}),{changeSet:c,conflicts:l,unmanaged:u,resourceOwners:d}=await planServices$1(t,n,r.name,r.id,o),f=c.deletes.map(e=>e.name),{changeSet:p}=await planResolvers(t,n,o,s,e.executorUsedResolvers??new Set,f,r.env,Lt(r),a,{appName:r.name,appId:r.id,dependentApps:e.dependentApps,runAppIds:e.runAppIds});return{changeSet:{service:c,resolver:p},conflicts:l,unmanaged:u,resourceOwners:d}}async function planServices$1(e,t,n,r,i){let a=createChangeSet(`Pipeline services`),o=[],s=[],c=new Set,l=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)});for(let e of i){let i=l[e.namespace],c=await buildMetaRequest({trn:resourceTrn(t,`pipeline`,e.namespace),appName:n,appId:r});i?(trackDesiredResourceOwnership({labels:i.allLabels,ownerLabel:i.label,appName:n,appId:r,resourceType:`Pipeline service`,resourceName:e.namespace,conflicts:o,unmanaged:s})&&hasMatchingSdkVersion(i.allLabels,c.labels)?a.unchanged.push({name:e.namespace}):a.updates.push({name:e.namespace,request:{workspaceId:t,namespaceName:e.namespace},metaRequest:c}),delete l[e.namespace]):a.creates.push({name:e.namespace,request:{workspaceId:t,namespaceName:e.namespace},metaRequest:c})}return Object.entries(l).forEach(([e])=>{let i=l[e];trackRemainingResourceOwner({labels:i?.allLabels,ownerLabel:i?.label,appName:n,appId:r,resourceOwners:c})&&a.deletes.push({name:e,request:{workspaceId:t,namespaceName:e}})}),{changeSet:a,conflicts:o,unmanaged:s,resourceOwners:c}}async function planResolvers(e,t,n,r,i,a,o,s,c=!1,l={}){let u=createChangeSet(`Pipeline resolvers`),{appName:d,appId:f,dependentApps:p,runAppIds:m}=l,resolverMetaRequest=async(e,n)=>addDependencyRecords(await buildMetaRequest({trn:resolverTrn(t,e,n.name),appName:d??``,appId:f}),{key:Z.resolver(e,n.name),dependentApps:p,runAppIds:m,pinned:n.publishEvents!==void 0}),fetchResolvers=n=>N(async(r,i)=>{let{pipelineResolvers:a,nextPageToken:o}=await e.listPipelineResolvers({workspaceId:t,namespaceName:n,pageToken:r,pageSize:i});return[a,o]}),h=new Set(i);for(let e of r)subscribesToEvents(e)&&e.trigger.kind===`resolverExecuted`&&h.add(e.trigger.resolverName);for(let e of n)for(let t of Object.values(e.resolvers))assertNoPublishEventsConflict({explicit:t.publishEvents,subscribed:h.has(t.name),conflict:Qi.resolver(t.name)});for(let r of n){let n=await fetchResolvers(r.namespace),i=new Map(n.map(e=>[e.name,e]));for(let n of Object.values(r.resolvers)){let a=processResolver(r.namespace,n,h,o,s),l=i.get(n.name),d=await resolverMetaRequest(r.namespace,n);if(l){let{pipelineResolver:o}=await e.getPipelineResolver({workspaceId:t,namespaceName:r.namespace,resolverName:n.name});!c&&o&&areResolversEqual(o,a)?u.unchanged.push({name:n.name,metaRequest:d}):u.updates.push({name:n.name,request:{workspaceId:t,namespaceName:r.namespace,pipelineResolver:a},metaRequest:d}),i.delete(n.name)}else u.creates.push({name:n.name,request:{workspaceId:t,namespaceName:r.namespace,pipelineResolver:a},metaRequest:d})}i.forEach((e,n)=>{u.deletes.push({name:n,request:{workspaceId:t,namespaceName:r.namespace,resolverName:n}})})}for(let e of a)(await fetchResolvers(e)).forEach(n=>{u.deletes.push({name:n.name,request:{workspaceId:t,namespaceName:e,resolverName:n.name}})});return{changeSet:u}}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(f,e)}function areResolversEqual(e,t){return areNormalizedEqual(normalizeComparableResolver(e),normalizeComparableResolver(t))}function processResolver(e,t,n,r,i){let a=[{name:`body`,operationName:`body`,description:`${t.name} function body`,operationType:_.FUNCTION,operationSourceRef:resolverFunctionName(e,t.name),operationHook:{expr:ln(r)},postScript:`args.body`,invoker:normalizeInvoker(t.invoker,i,`Resolver "${t.name}"`)}],o=Ar.camelize(t.name),s=t.input?protoFields(t.input,`${o}Input`,!0):[],c=k(protoFields({"":t.output},`${o}Output`,!1)[0],`resolver output field missing`),l=t.description||`${t.name} resolver`,u=t.output.metadata.description,d=u?`${l}\n\nReturns:\n${u}`:l,f=resolvePublishEvents({explicit:t.publishEvents,subscribed:n.has(t.name),conflict:Qi.resolver(t.name)});return{authorization:`true==true`,description:d,inputs:s,name:t.name,operationType:t.operation,response:c,pipelines:a,publishExecutionEvents:f}}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}${Ar.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}${Ar.camelize(e)}`,required:a,allowedValues:r.metadata.allowedValues}:{...ea[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}}async function planSecretManager(e){let{client:t,workspaceId:n,application:r,forRemoval:i,forceApplyAll:a=!1}=e,o=i?[]:r.secrets,s=createChangeSet(`Secret Manager vaults`),c=createChangeSet(`Secret Manager secrets`),l=[],u=[],d=new Set,f=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)}),p={workspaceId:n,applicationId:r.id,applicationName:r.name},m=loadSecretsState(p),h=[];await Promise.all(o.map(async e=>{let i=e.vaultName,o=f[i];if(o){let e=await buildMetaRequest({trn:resourceTrn(n,`vault`,i),appName:r.name,appId:r.id});trackDesiredResourceOwnership({labels:o.allLabels,ownerLabel:o.label,appName:r.name,appId:r.id,resourceType:`Secret Manager vault`,resourceName:i,conflicts:l,unmanaged:u})&&hasMatchingSdkVersion(o.allLabels,e.labels)?s.unchanged.push({name:i}):s.updates.push({name:i,workspaceId:n}),delete f[i]}else s.creates.push({name:i,workspaceId:n});let d=new Map;if(o){let e=await N(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 p=new Set(d.keys());for(let t of e.secrets){if(t.value==null){p.delete(t.name),h.push(`${i}/${t.name}`);continue}if(M.registerSecret(t.value),p.has(t.name)){let e=m.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}),p.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 p)c.deletes.push({name:`${i}/${e}`,secretName:e,workspaceId:n,vaultName:i})}));for(let[e,i]of Object.entries(f))if(i&&trackRemainingResourceOwner({labels:i.allLabels,ownerLabel:i.label,appName:r.name,appId:r.id,resourceOwners:d})){let r=await N(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:h,conflicts:l,unmanaged:u,resourceOwners:d,stateScope:p}}async function applySecretManager(e,t,n=`create-update`,r){let{vaultChangeSet:i,secretChangeSet:a,stateScope:o}=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=[...a.creates,...a.updates];t.length>0&&await withSecretsStateLock(o,async()=>{let n=new Map;if(await Promise.all(a.creates.map(async t=>{let r=await e.createSecretManagerSecret(secretCreateRequest(t));n.set(t.name,serializeUpdateTime(r.secret?.updateTime))})),await Promise.all(a.updates.map(async t=>{let r=await e.updateSecretManagerSecret(secretUpdateRequest(t));n.set(t.name,serializeUpdateTime(r.secret?.updateTime))})),r){let e=loadSecretsState(o);for(let r of t){Object.hasOwn(e.vaults,r.vaultName)||(e.vaults[r.vaultName]={});let t=n.get(r.name);k(e.vaults[r.vaultName],`vault state entry missing`)[r.secretName]={hash:hashValue(r.value),...t===void 0?{}:{updateTime:t}}}saveSecretsState(o,e)}})}else(a.deletes.length>0||i.deletes.length>0)&&await withSecretsStateLock(o,async()=>{await Promise.all(a.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(o);for(let e of a.deletes)Object.hasOwn(t.vaults,e.vaultName)&&(delete k(t.vaults[e.vaultName],`vault state entry missing`)[e.secretName],Object.keys(k(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(o,t)})}const ta=[`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;if(!s){r.push({kind:`removed`,path:e,before:o});continue}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})}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 ta)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 a=e.hooks,o=t.hooks;if(!!a!=!!o||a&&o&&((a.create?.expr??``)!==(o.create?.expr??``)||(a.update?.expr??``)!==(o.update?.expr??``)))return!0;let s=e.validate??[],c=t.validate??[];if(s.length!==c.length)return!0;for(let e=0;e<s.length;e++){let t=k(s[e],`oldValidate missing index ${e}`),n=k(c[e],`newValidate missing index ${e}`);if((t.script?.expr??``)!==(n.script?.expr??``)||t.errorMessage!==n.errorMessage)return!0}let l=e.serial,u=t.serial;return!!(!!l!=!!u||l&&u&&(l.start!==u.start||l.maxValue!==u.maxValue||(l.format??``)!==(u.format??``))||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=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(`
|
|
26
|
+
`)}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=>`${na[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 na={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(`
|
|
27
27
|
`)}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(`
|
|
28
|
-
`)}const Zi={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]} ${Zi[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 R({code:`MIGRATION_NUMBER_INVALID`,message:`Migration number ${e} is out of range. Expected 0-9999.`});return t}throw R({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 Qi=`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<=6)return;let r;throw r=n>6?`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.`,R({code:Qi,message:`Unsupported migration file format version ${n} at ${e}.`,details:`This SDK supports migration file format versions 1-6.`,suggestion:r})}const $i=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=$i.get(t);return n===void 0?e:{...e,kind:n}});return{...e,changes:n}}const ea=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=ea.get(e);a!==void 0&&!(a in t)?(n[a]=i,r=!0):n[e]=i}return r?n:e}const ta=[`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 ta){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||wr.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 na=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||!na.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`}}const ra=new Set([`index`,`unique`,`vector`]);function isRenameCompatible(e,t){if(e.type!==t.type)return!1;for(let n of Yi)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=new Map,n=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=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 R({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 R({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 R({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${s}: field "${a}" does not exist in the previous schema.`});if(l.fields[a])throw R({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${s}: field "${a}" still exists in the current schema.`});let d=l.fields[o];if(!d)throw R({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${s}: field "${o}" does not exist in the current schema.`});if(c.fields[o])throw R({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${s}: field "${o}" already exists in the previous schema.`});if(!isRenameCompatible(u,d))throw R({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 R({code:`MIGRATION_RENAME_FLAG_INVALID`,message:`Invalid --rename value "${e}". Expected format: "Table.oldField:newField".`,command:`tailordb migration generate`});if(n===r)throw R({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 aa=/^([^.:\s]+)\.([^.:\s]+)$/;function parseDropOption(e){let[,t,n]=e.match(aa)??[];if(!t||!n)throw R({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(aa)??[];if(!t||!n)throw R({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 Yi)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=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 R({code:`MIGRATION_RENAME_INVALID`,message:`Member "${e}" appears in more than one rename.`});r.add(e)}if(o.length===0||!haveSameParent(o,s))throw R({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 R({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${l}: "${n}.${a}" must be a nested field in both the previous and the current schema.`});let f=getNestedMember(u,o);if(!f)throw R({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${l}: member "${o.join(`.`)}" does not exist in the previous schema.`});if(getNestedMember(d,o))throw R({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 R({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${l}: member "${s.join(`.`)}" does not exist in the current schema.`});if(getNestedMember(u,s))throw R({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${l}: member "${s.join(`.`)}" already exists in the previous schema.`});if(!isNestedMemberRenameCompatible(f,p))throw R({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 oa=/^([^.:\s]+)\.([^.:\s]+)((?:\.[^.:\s]+)+):([^.:\s]+)$/;function parseNestedMemberRenameOption(e){let[,t,n,r,i]=e.match(oa)??[];if(!t||!n||!r||!i)throw R({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 R({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 sa=/^([^.:\s]+)\.([^.:\s]+)((?:\.[^.:\s]+)+)$/;function parseNestedMemberDropOption(e){let[,t,n,r]=e.match(sa)??[];if(!t||!n||!r)throw R({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 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)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||n.foreignKeyType===e.name&&n.required||!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=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 R({code:`MIGRATION_RENAME_INVALID`,message:`Table "${e}" appears in more than one rename.`});r.add(e)}let s=e.tables[n];if(!s)throw R({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${o}: table "${n}" does not exist in the previous schema.`});if(t.tables[n])throw R({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${o}: table "${n}" still exists in the current schema.`});let c=t.tables[a];if(!c)throw R({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${o}: table "${a}" does not exist in the current schema.`});if(e.tables[a])throw R({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${o}: table "${a}" already exists in the previous schema.`});if(!isTypeRenameCompatible(s,c))throw R({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 ca=/^([^.:\s]+):([^.:\s]+)$/;function parseTypeRenameOption(e){let[,t,n]=e.match(ca)??[];if(!t||!n)throw R({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 R({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 la=/^([^.:\s]+)$/;function parseTypeDropOption(e){let[,t]=e.match(la)??[];if(!t)throw R({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 ua=`Field removed (existing data will no longer be accessible through the schema)`,da=`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:ua}):n.kind===`table_removed`?t.push({tableName:n.tableName,reason:da}):n.kind===`field_modified`&&t.push(...collectNestedMemberRemovalWarnings(n));return t}function areFieldsDifferent(e,t){return areOwnFieldConfigsDifferent(e,t)||collectNestedMemberChanges(e,t).length>0}function getBreakingFieldChanges(e,t,n,r,i){let a=[];if(!n&&r&&r.required&&a.push({tableName:e,fieldName:t,reason:`Required field added`}),n&&r&&n.type!==r.type){let i=supportsInPlaceFieldTypeChange(n,r);a.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&&a.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`];a.push({tableName:e,fieldName:t,reason:`Field changed from ${r} to ${i}`,unsupported:!0,showThreeStepHint:!0})}if(n&&r&&isBreakingForeignKeyRetarget(n,r,i)&&a.push({tableName:e,fieldName:t,reason:`Foreign key target type changed from ${n.foreignKeyType} to ${r.foreignKeyType}`}),n&&r&&!(n.unique??!1)&&(r.unique??!1)&&a.push({tableName:e,fieldName:t,reason:`Unique constraint added to field`}),n?.type===`decimal`&&r?.type===`decimal`&&n.scale!==r.scale&&a.push({tableName:e,fieldName:t,reason:`Decimal scale changed from ${n.scale} to ${r.scale}`}),n&&r&&n.type===`enum`&&r.type===`enum`){let i=n.allowedValues??[],o=r.allowedValues??[],s=i.map(e=>e.value),c=new Set(o.map(e=>e.value)),l=s.filter(e=>!c.has(e));l.length>0&&a.push({tableName:e,fieldName:t,reason:`Enum values removed: ${l.join(`, `)}`})}return a}function addChange(e,t,n,r){if(e.changes.push(t),!t.fieldName)return;t.kind===`field_modified`&&e.warnings.push(...collectNestedMemberRemovalWarnings(t));let i=getBreakingFieldChanges(t.tableName,t.fieldName,n,r,e.typeRenameTargets);if(i.length>0){e.breakingChanges.push(...i);return}t.kind===`field_removed`&&e.warnings.push({tableName:t.tableName,fieldName:t.fieldName,reason:ua})}function compareTypeFields(e,t,n,r,i=[],a=[]){let o=new Set(Object.keys(n.fields)),s=new Set(Object.keys(r.fields)),c=new Set(i.map(e=>e.previousFieldName)),l=new Set(i.map(e=>e.fieldName));for(let a of i){let i=k(n.fields[a.previousFieldName],`renamed field "${a.previousFieldName}" missing from prevType`),o=k(r.fields[a.fieldName],`renamed field "${a.fieldName}" missing from currType`);e.changes.push({kind:`field_renamed`,tableName:t,fieldName:a.fieldName,previousFieldName:a.previousFieldName,before:i,after:o}),e.breakingChanges.push({tableName:t,fieldName:a.fieldName,reason:`Field renamed from ${a.previousFieldName} to ${a.fieldName} (existing values must be copied by the migration script)`})}for(let n of s)if(!l.has(n)&&!o.has(n)){let i=k(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 o)if(!c.has(r)&&!s.has(r)){let i=k(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 s){if(!o.has(i))continue;let s=k(n.fields[i],`field "${i}" missing from prevType`),c=k(r.fields[i],`field "${i}" missing from currType`);if(!areFieldsDifferent(s,c))continue;if(s.type!==c.type){addChange(e,{kind:`field_type_modified`,tableName:t,fieldName:i,before:s,after:c},s,c);continue}let l=a.filter(e=>e.fieldName===i).map(({previousPath:e,path:t})=>({previousPath:e,path:t}));addChange(e,{kind:`field_modified`,tableName:t,fieldName:i,before:s,after:c,...l.length>0&&{memberRenames:l}},s,c);for(let n of l)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||{})),a=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??{}))a.has(r)||e.changes.push({kind:`index_removed`,tableName:t,indexName:r,before:i});for(let[a,o]of Object.entries(r??{}))if(i.has(a)){let r=k(k(n,`oldIndexes is undefined when oldKeys has entry`)[a],`index "${a}" missing from oldIndexes`),i=JSON.stringify(r.fields.toSorted()),s=JSON.stringify(o.fields.toSorted());if(i!==s||(r.unique??!1)!==(o.unique??!1)){let n=[];i!==s&&n.push(`fields changed`),(r.unique??!1)!==(o.unique??!1)&&n.push(`unique constraint changed`),e.changes.push({kind:`index_modified`,tableName:t,indexName:a,reason:n.join(`, `),before:r,after:o});let c=isBreakingIndexChange(t,a,r,o);c&&e.breakingChanges.push(c)}}}function compareFiles(e,t,n,r){let i=new Set(Object.keys(n||{})),a=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??{}))a.has(r)||e.changes.push({kind:`file_removed`,tableName:t,fieldName:r,before:i});for(let[a,o]of Object.entries(r??{}))if(i.has(a)){let r=k(k(n,`oldFiles is undefined when oldKeys has entry`)[a],`file "${a}" missing from oldFiles`);r!==o&&e.changes.push({kind:`file_modified`,tableName:t,fieldName:a,reason:`description changed`,before:r,after:o})}}function compareRelationships(e,t,n,r,i){let a=new Set(Object.keys(r||{})),o=new Set(Object.keys(i||{}));for(let[r,o]of Object.entries(i??{}))a.has(r)||e.changes.push({kind:`relationship_added`,tableName:t,relationshipName:r,relationshipType:n,after:o});for(let[i,a]of Object.entries(r??{}))o.has(i)||e.changes.push({kind:`relationship_removed`,tableName:t,relationshipName:i,relationshipType:n,before:a});for(let[o,s]of Object.entries(i??{}))if(a.has(o)){let i=k(k(r,`oldRelationships is undefined when oldKeys has entry`)[o],`relationship "${o}" missing from oldRelationships`),a=[];i.targetType!==s.targetType&&a.push(`targetType changed`),i.targetField!==s.targetField&&a.push(`targetField changed`),i.sourceField!==s.sourceField&&a.push(`sourceField changed`),i.isArray!==s.isArray&&a.push(`isArray changed`),i.description!==s.description&&a.push(`description changed`),a.length>0&&e.changes.push({kind:`relationship_modified`,tableName:t,relationshipName:o,relationshipType:n,reason:a.join(`, `),before:i,after:s})}}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 fa={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)=>fa[e]-fa[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,wr.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=new Map;for(let e of r){let t=i.get(e.tableName)??[];t.push(e),i.set(e.tableName,t)}let a=n?.nestedMemberRenames??[];assertValidNestedMemberRenames(e,t,a);let o=new Map;for(let e of a){let t=o.get(e.tableName)??[];t.push(e),o.set(e.tableName,t)}let s=n?.typeRenames??[];assertValidTypeRenames(e,t,s);let c=new Map(s.map(e=>[e.previousTableName,e.tableName])),l=new Set(s.map(e=>e.tableName)),u={changes:[],breakingChanges:[],warnings:[],typeRenameTargets:c},d=new Set(Object.keys(e.tables)),f=new Set(Object.keys(t.tables));for(let n of s){let r=k(e.tables[n.previousTableName],`renamed table "${n.previousTableName}" missing from previous snapshot`),i=k(t.tables[n.tableName],`renamed table "${n.tableName}" missing from current snapshot`);u.changes.push({kind:`table_renamed`,tableName:n.tableName,previousTableName:n.previousTableName,before:r,after:i}),u.breakingChanges.push({tableName:n.tableName,reason:`Table renamed from ${n.previousTableName} to ${n.tableName} (existing records must be copied by the migration script)`}),u.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))l.has(e)||d.has(e)||u.changes.push({kind:`table_added`,tableName:e,after:n});for(let[t,n]of Object.entries(e.tables))c.has(t)||f.has(t)||(u.changes.push({kind:`table_removed`,tableName:t,before:n}),u.warnings.push({tableName:t,reason:da}));for(let n of f){if(!d.has(n))continue;let r=k(e.tables[n],`table "${n}" missing from previous snapshot`),a=k(t.tables[n],`table "${n}" missing from current snapshot`);compareTypeSettings(u,n,r,a),compareTypeScripts(u,n,r,a),compareTypeFields(u,n,r,a,i.get(n),o.get(n)),compareIndexes(u,n,r.indexes,a.indexes),compareFiles(u,n,r.files,a.files),compareRelationships(u,n,`forward`,r.forwardRelationships,a.forwardRelationships),compareRelationships(u,n,`backward`,r.backwardRelationships,a.backwardRelationships),comparePermissions(u,n,r.permissions?.record,a.permissions?.record,r.permissions?.gql,a.permissions?.gql)}return{version:6,namespace:t.namespace,createdAt:new Date().toISOString(),changes:u.changes,hasBreakingChanges:u.breakingChanges.length>0,breakingChanges:u.breakingChanges,hasWarnings:u.warnings.length>0,warnings:u.warnings,requiresMigrationScript:u.breakingChanges.length>0}}function compareLocalTypesWithSnapshot(e,t,n){let r={version:6,namespace:n,createdAt:new Date().toISOString(),tables:t};return compareSnapshots(normalizeSchemaSnapshot(e),normalizeSchemaSnapshot(r))}const pa=`sdk-migration`,ma=`sdk-migration-history`,ha=/^[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 parseMigrationHistoryId(e){return ha.test(e)?e:null}function createMigrationHistoryId(){return`h${hr().replaceAll(`-`,``)}`}function handleOptionalToRequiredError(e,t){if(e instanceof K&&e.code===G.FailedPrecondition&&e.message.includes(`cannot be updated from non-required to required when records exist`)){M.error(`Schema change failed: Cannot change field from optional to required when records exist.`),M.newline();for(let e of t)M.info(e)}throw e}function snapshotRecordSchema(e){return H.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){for(let e of a.error.issues)n.addIssue({...e,path:[i,...e.path]});continue}r[i]=a.data}return r})}const ga=H.looseObject({expr:H.string()}),_a=H.looseObject({script:H.looseObject({expr:H.string()}).optional(),errorMessage:H.string()}),va=H.looseObject({start:H.number(),maxValue:H.number().optional(),format:H.string().optional()}),ya=H.looseObject({value:H.string(),description:H.string().optional()}),ba=H.looseObject({type:H.string(),required:H.boolean().default(!0),array:H.boolean().optional(),index:H.boolean().optional(),unique:H.boolean().optional(),allowedValues:H.array(ya).optional(),foreignKey:H.boolean().optional(),foreignKeyType:H.string().optional(),foreignKeyField:H.string().optional(),description:H.string().optional(),vector:H.boolean().optional(),hooks:H.looseObject({create:ga.optional(),update:ga.optional()}).optional(),validate:H.array(_a).optional(),serial:va.optional(),scale:H.number().optional(),default:H.unknown().optional(),fields:H.lazy(()=>snapshotRecordSchema(ba)).optional()}),xa=H.looseObject({fields:H.array(H.string()),unique:H.boolean().optional()}),Sa=H.looseObject({targetType:H.string(),targetField:H.string(),sourceField:H.string(),isArray:H.boolean(),description:H.string()}),Ca=[`user`,`record`,`newRecord`,`oldRecord`],wa=H.unknown().refine(e=>{if(typeof e!=`object`||!e||Array.isArray(e))return!0;let t=Object.keys(e);return Ca.filter(e=>t.includes(e)).length<2},`Ambiguous field-ref operand: contains more than one of user/record/newRecord/oldRecord`),Ta=H.unknown().refine(e=>{if(typeof e!=`object`||!e||Array.isArray(e))return!0;let t=Object.keys(e);return Ca.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`),Ea=H.string(),Da=H.tuple([wa,Ea,wa]).rest(H.unknown()),Oa=H.tuple([Ta,Ea,Ta]).rest(H.unknown()),ka=H.looseObject({conditions:H.array(Da),description:H.string().optional(),permit:H.enum([`allow`,`deny`])}),Aa=H.looseObject({create:H.array(ka).default([]),read:H.array(ka).default([]),update:H.array(ka).default([]),delete:H.array(ka).default([])}),ja=H.string(),Ma=H.looseObject({conditions:H.array(Oa),actions:H.array(ja),permit:H.enum([`allow`,`deny`]),description:H.string().optional()}),Na=H.array(Ma),Pa=H.looseObject({name:H.string(),pluralForm:H.string().optional(),description:H.string().optional(),fields:snapshotRecordSchema(ba),settings:H.looseObject({aggregation:H.boolean().optional(),bulkUpsert:H.boolean().optional(),gqlOperations:H.looseObject({create:H.boolean().optional(),update:H.boolean().optional(),delete:H.boolean().optional(),read:H.boolean().optional()}).optional(),publishEvents:H.boolean().optional()}).optional(),indexes:snapshotRecordSchema(xa).optional(),files:snapshotRecordSchema(H.string()).optional(),forwardRelationships:snapshotRecordSchema(Sa).optional(),backwardRelationships:snapshotRecordSchema(Sa).optional(),permissions:H.looseObject({record:Aa.optional(),gql:Na.optional()}).optional()}),Fa=H.looseObject({historyId:H.string().regex(ha),replacedHistoryId:H.string().regex(ha).nullable(),replacedLatestMigration:H.number().int().min(0).max(9999)}),Ia=H.looseObject({version:H.number(),namespace:H.string(),createdAt:H.string(),tables:snapshotRecordSchema(Pa),rebaseline:Fa.optional()}),La=H.looseObject({indexes:snapshotRecordSchema(xa).optional(),files:snapshotRecordSchema(H.string()).optional()}),Ra=H.looseObject({description:H.string().optional(),pluralForm:H.string(),settings:H.looseObject({aggregation:H.boolean().optional(),bulkUpsert:H.boolean().optional(),gqlOperations:H.looseObject({create:H.boolean().optional(),update:H.boolean().optional(),delete:H.boolean().optional(),read:H.boolean().optional()}).optional(),publishEvents:H.boolean().optional()}).optional()}),za=H.looseObject({recordPermission:Aa.optional(),gqlPermission:Na.optional()}),Ba=H.looseObject({kind:H.literal(`table_added`),tableName:H.string(),reason:H.string().optional(),after:Pa}),Va=H.looseObject({kind:H.literal(`table_removed`),tableName:H.string(),reason:H.string().optional(),before:Pa}),Ha=H.looseObject({kind:H.literal(`table_renamed`),tableName:H.string(),reason:H.string().optional(),previousTableName:H.string(),before:Pa,after:Pa}),Ua=H.looseObject({kind:H.literal(`table_modified`),tableName:H.string(),reason:H.string().optional(),before:La.optional(),after:La.optional()}),Wa=H.looseObject({kind:H.literal(`table_settings_modified`),tableName:H.string(),reason:H.string().optional(),before:Ra,after:Ra}),Ga=H.looseObject({kind:H.literal(`field_added`),tableName:H.string(),reason:H.string().optional(),fieldName:H.string(),after:ba}),Ka=H.looseObject({kind:H.literal(`field_removed`),tableName:H.string(),reason:H.string().optional(),fieldName:H.string(),before:ba}),qa=H.looseObject({kind:H.literal(`field_modified`),tableName:H.string(),reason:H.string().optional(),fieldName:H.string(),before:ba,after:ba,memberRenames:H.array(H.looseObject({previousPath:H.array(H.string()).min(1),path:H.array(H.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()}),Ja=H.looseObject({kind:H.literal(`field_renamed`),tableName:H.string(),reason:H.string().optional(),fieldName:H.string(),previousFieldName:H.string(),before:ba,after:ba}),Ya=H.looseObject({kind:H.literal(`field_type_modified`),tableName:H.string(),reason:H.string().optional(),fieldName:H.string(),before:ba,after:ba}),Xa=H.looseObject({kind:H.literal(`index_added`),tableName:H.string(),reason:H.string().optional(),indexName:H.string(),after:xa}),Za=H.looseObject({kind:H.literal(`index_removed`),tableName:H.string(),reason:H.string().optional(),indexName:H.string(),before:xa}),Qa=H.looseObject({kind:H.literal(`index_modified`),tableName:H.string(),reason:H.string().optional(),indexName:H.string(),before:xa,after:xa}),$a=H.looseObject({kind:H.literal(`file_added`),tableName:H.string(),reason:H.string().optional(),fieldName:H.string(),after:H.string()}),eo=H.looseObject({kind:H.literal(`file_removed`),tableName:H.string(),reason:H.string().optional(),fieldName:H.string(),before:H.string()}),to=H.looseObject({kind:H.literal(`file_modified`),tableName:H.string(),reason:H.string().optional(),fieldName:H.string(),before:H.string(),after:H.string()}),no=H.looseObject({kind:H.literal(`relationship_added`),tableName:H.string(),reason:H.string().optional(),relationshipName:H.string(),relationshipType:H.enum([`forward`,`backward`]).optional(),after:Sa}),ro=H.looseObject({kind:H.literal(`relationship_removed`),tableName:H.string(),reason:H.string().optional(),relationshipName:H.string(),relationshipType:H.enum([`forward`,`backward`]).optional(),before:Sa}),io=H.looseObject({kind:H.literal(`relationship_modified`),tableName:H.string(),reason:H.string().optional(),relationshipName:H.string(),relationshipType:H.enum([`forward`,`backward`]).optional(),before:Sa,after:Sa}),ao=H.looseObject({kind:H.literal(`permission_modified`),tableName:H.string(),reason:H.string().optional(),before:za.optional(),after:za.optional()}),oo=H.looseObject({typeHookExpr:H.looseObject({create:H.string().optional(),update:H.string().optional()}).optional(),typeValidateExpr:H.string().optional()}),so=H.looseObject({kind:H.literal(`table_scripts_modified`),tableName:H.string(),reason:H.string().optional(),before:oo,after:oo}),co=H.discriminatedUnion(`kind`,[Ba,Va,Ha,Ua,Wa,Ga,Ka,qa,Ja,Ya,Xa,Za,Qa,$a,eo,to,no,ro,io,ao,so]),lo=H.looseObject({tableName:H.string(),fieldName:H.string().optional(),reason:H.string(),unsupported:H.boolean().optional(),showThreeStepHint:H.boolean().optional()}),uo=H.looseObject({tableName:H.string(),fieldName:H.string().optional(),reason:H.string()}),fo=H.looseObject({reason:H.string().trim().min(1),acknowledgedAt:H.string()}),po=H.looseObject({version:H.number(),namespace:H.string(),createdAt:H.string(),description:H.string().optional(),changes:H.array(co),hasBreakingChanges:H.boolean(),breakingChanges:H.array(lo),hasWarnings:H.boolean().optional(),warnings:H.array(uo).optional(),requiresMigrationScript:H.boolean(),scriptSkipped:fo.optional()}),mo=0,ho=`schema.json`,go=`diff.json`,_o=`migrate.ts`,vo=`migrate.test.ts`,yo=`db.ts`,bo=`db.pglite.ts`,xo=`migrate.pglite.test.ts`,So=/^\d{4}$/;function isValidMigrationNumber(e){return So.test(e)}const Co={schema:ho,diff:go,migrate:_o,test:vo,db:yo,pgliteSchema:bo,pgliteTest:xo};function getMigrationDirPath(e,t){let n=formatMigrationNumber(t);return V.join(e,n)}function getMigrationFilePath(e,t,n){let r=getMigrationDirPath(e,t);return V.join(r,Co[n])}function loadSnapshot(e){let t=U.readFileSync(e,`utf-8`),n;try{n=JSON.parse(t)}catch(t){throw R({code:`MIGRATION_FILE_INVALID`,message:`Invalid schema snapshot at ${e}: ${String(t)}`,cause:t})}assertSupportedMigrationFileVersion(e,n);let r=Ia.safeParse(normalizeLegacyTablesKey(n));if(!r.success)throw R({code:`MIGRATION_FILE_INVALID`,message:`Invalid schema snapshot at ${e}: ${H.prettifyError(r.error)}`,cause:r.error});let i=r.data;return normalizeSchemaSnapshot(i)}function loadDiff(e){let t=U.readFileSync(e,`utf-8`),n;try{n=JSON.parse(t)}catch(t){throw R({code:`MIGRATION_FILE_INVALID`,message:`Invalid migration diff at ${e}: ${String(t)}`,cause:t})}assertSupportedMigrationFileVersion(e,n);let r=po.safeParse(normalizeLegacyFieldNames(normalizeLegacyChangeKinds(n)));if(!r.success)throw R({code:`MIGRATION_FILE_INVALID`,message:`Invalid migration diff at ${e}: ${H.prettifyError(r.error)}`,cause:r.error});let i=r.data,a=i.warnings??deriveWarningsFromChanges(i);return{...i,warnings:a,hasWarnings:a.length>0}}function getMigrationFiles(e){if(!U.existsSync(e))return[];let t=U.readdirSync(e,{withFileTypes:!0}),n=[];for(let r of t){if(!r.isDirectory()||!isValidMigrationNumber(r.name))continue;let t=parseInt(r.name,10),i=V.join(e,r.name),a=V.join(i,ho);U.existsSync(a)&&n.push({number:t,type:`schema`,path:a});let o=V.join(i,go);U.existsSync(o)&&n.push({number:t,type:`diff`,path:o})}return n.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 R({code:`MIGRATION_NOT_FOUND`,message:`Migration ${formatMigrationNumber(t)} does not exist in working tree (latest is ${formatMigrationNumber(latestMigrationNumber(n))}).`});return latestMigrationNumber(n)}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 R({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(!U.existsSync(e))return t;let n=getMigrationFiles(e);if(n.length===0)return t;let r=[],i=[];for(let e of n)e.type===`schema`?r.push(e.number):i.push(e.number);r.includes(0)||t.push({type:`missing_schema`,message:`Initial schema snapshot (${formatMigrationNumber(0)}/schema.json) is missing`,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});let a=[...new Set([...r,...i])].toSorted((e,t)=>e-t);if(a.length===0)return t;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 o=Math.max(...a);for(let e=0;e<=o;e++)a.includes(e)||t.push({type:`gap`,message:`Migration ${formatMigrationNumber(e)} is missing (gap in sequence)`,migrationNumber:e});for(let e of a)e>0&&!i.includes(e)&&t.push({type:`missing_diff`,message:`Migration ${formatMigrationNumber(e)} is missing diff file`,migrationNumber:e});return t}function assertValidMigrationFiles(e,t){let n=validateMigrationFiles(e);if(n.length>0){let e=n.map(e=>` - ${e.message}`).join(`
|
|
29
|
-
`);throw R({code:`MIGRATION_FILES_INVALID`,message:`Migration file validation failed for namespace "${t}":\n${e}`})}}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.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||
|
|
30
|
-
`);
|
|
31
|
-
`)
|
|
32
|
-
`)}\n})
|
|
33
|
-
`)}\n}`)}}}return r}function principalDeclIfReferenced(...e){return e.some(e=>e?.includes(`_principal`))?` const ${vt} = (${yt});`:``}function wrapHook(e){return`((_invoker) => { const ${To} = 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(`
|
|
34
|
-
`)}${i}\nreturn __errs; })(typeof _invoker !== "undefined" ? _invoker : undefined)`}function buildTypeScripts(e,t){let n={},r=t?.typeHookExpr,i=t?.typeValidateExpr,a=computeSourceScriptHash(e,t),o=a?` // @sdk-source-hash:${a}`:``,s={};for(let t of[`create`,`update`]){let n=buildHookObject(e,wo,`_oldRecord`,t),i=r?.[t],a;if(n!==null&&i){let e=principalDeclIfReferenced(n,i);a=`((_invoker) => { const ${To} = new Date();${e} const __fl = ${n}; return Object.assign({}, __fl, ((${wo}) => ${i})(Object.assign({}, ${wo}, __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.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===it.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 Do=new Map([[be.ALLOW,`allow`],[be.DENY,`deny`]]),Oo=new Map([[ot.EQ,`eq`],[ot.NE,`ne`],[ot.IN,`in`],[ot.NIN,`nin`],[ot.HAS_ANY,`hasAny`],[ot.NHAS_ANY,`nhasAny`]]);function convertRemotePermit(e,t){let n=Do.get(e);if(n)return n;throw L(`Unsupported ${t} permission permit: ${e}`)}function convertRemoteOperator(e,t){let n=Oo.get(e);if(n)return n;throw L(`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 Jn(ir,e.kind.value);default:throw L(`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 E.ALL:return`all`;case E.CREATE:return`create`;case E.READ:return`read`;case E.UPDATE:return`update`;case E.DELETE:return`delete`;case E.AGGREGATE:return`aggregate`;case E.BULK_UPSERT:return`bulkUpsert`;default:throw L(`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||wr.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:6,namespace:t,createdAt: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??[],a=r.validate??[];i.length!==a.length&&e.push(`${fieldDifferenceKey(t,`validate`)} count: remote=${i.length}, expected=${a.length}`);let o=Math.min(i.length,a.length);for(let n=0;n<o;n++){let r=k(i[n],`remoteValidate missing index ${n}`),o=k(a[n],`snapshotValidate missing index ${n}`);addFieldDifference(e,t,`validate[${n}].script`,r.script?.expr??``,o.script?.expr??``),addFieldDifference(e,t,`validate[${n}].errorMessage`,r.errorMessage,o.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??``)}function addNestedFieldDifferences(e,t,n,r){let i=n.fields??{},a=r.fields??{},o=Object.keys(i),s=Object.keys(a);o.length!==s.length&&e.push(`${fieldDifferenceKey(t,`fields`)} count: remote=${o.length}, expected=${s.length}`);for(let n of o){let r=i[n],o=a[n],s=fieldDifferenceKey(t,`fields.${n}`);if(!o){e.push(`${s}: exists in remote but not snapshot`);continue}addFieldDifferences(e,s,k(r,`remote field "${n}" missing`),o)}for(let n of s)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 Yi)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 ko=new Set([`id`]);function compareRemoteWithSnapshot(e,t,n=[]){let r=compareNormalizedRemoteWithSnapshot(createRemoteComparableSnapshot(createSnapshotFromRemoteTypes(e,t.namespace,n,t)),createRemoteComparableSnapshot(t)),i=compareScriptHashes(e,t);return[...r,...i]}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 Ao=`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}' ${Ao}`:`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))ko.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 L(`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=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(`
|
|
35
|
-
`)}const jo=Object.keys(Co);function getMigrationArtifactNumbers(e){return U.existsSync(e)?U.readdirSync(e,{withFileTypes:!0}).filter(e=>e.isDirectory()&&So.test(e.name)).map(e=>Number.parseInt(e.name,10)).filter(t=>jo.some(n=>U.existsSync(getMigrationFilePath(e,t,n)))).toSorted((e,t)=>e-t):[]}function updateHashWithDirectory(e,t,n=``,r=new Set){let i=U.realpathSync(t);if(r.has(i)){e.update(`directory-cycle\0${n}\0${i}\0`);return}r.add(i);let a=U.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=V.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(U.readFileSync(o)),e.update(`\0`);else if(i.isSymbolicLink()){e.update(`symlink\0${a}\0${U.readlinkSync(o)}\0`);try{let t=U.statSync(o);t.isDirectory()?(e.update(`target-directory\0`),updateHashWithDirectory(e,o,`${a}@target`,r)):t.isFile()?(e.update(`target-file\0`),e.update(U.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=mr(`sha256`);for(let n of[...new Set(e)].toSorted())t.update(n),t.update(`\0`),U.existsSync(n)?t.update(U.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=mr(`sha256`),i=getMigrationArtifactNumbers(r);for(let t of i){let n=formatMigrationNumber(t);e.update(`migration\0${n}\0`),updateHashWithDirectory(e,V.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=V.resolve(t,i.migration.directory);n.push({namespace:r,migrationsDir:a})}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 R({code:`TAILORDB_NAMESPACE_NOT_FOUND`,message:`Namespace "${t}" not found or does not have migrations configured`});return n}if(e.length>1)throw R({code:`MIGRATION_NAMESPACE_REQUIRED`,message:`Multiple TailorDB services found. Please specify namespace with --namespace flag: ${e.map(e=>e.namespace).join(`, `)}`});return k(e[0],`namespace with migrations missing`)}function migrationConfigNotFoundError(){return R({code:`MIGRATION_CONFIG_NOT_FOUND`,message:`No TailorDB services with migrations configuration found`,suggestion:"Configure `migration` on the TailorDB service in tailor.config.ts."})}async function fetchRemoteMigrationState(e,t){let n=await F(async()=>{let{metadata:n}=await e.getMetadata({trn:t});return n});if(!n)return{metadataExists:!1,number:null,historyId:null,historyIdInvalid:!1};let r=n.labels[pa],i=n.labels[ma],a=i?parseMigrationHistoryId(i):null;return{metadataExists:!0,number:r?parseMigrationLabelNumber(r):null,historyId:a,historyIdInvalid:i!==void 0&&a===null}}async function fetchRemoteMigrationNumber(e,t){return(await fetchRemoteMigrationState(e,t)).number}function publishesRecordEvents(e,t){return resolvePublishEvents({explicit:e.settings?.publishEvents,subscribed:t,conflict:Ki.tailorDBType(e.name)})}function generateTailorDBTypeManifestFromSnapshot(e,t={}){let n=wr.camelize(e.pluralForm,!0),r={aggregation:e.settings?.aggregation??!1,bulkUpsert:t.suppressGqlOperations===!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.suppressGqlOperations===!0)&&(r.disableGqlOperations={create:t.suppressGqlOperations===!0||i?.create===!1,update:t.suppressGqlOperations===!0||i?.update===!1,delete:t.suppressGqlOperations===!0||i?.delete===!1,read:t.suppressGqlOperations===!0||i?.read===!1});let a=Object.fromEntries(Object.entries(e.fields).filter(([e])=>e!==`id`).map(([e,t])=>[e,convertFieldConfigToProto(t)])),o=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=new Map;if(e.indexes)for(let[t,n]of Object.entries(e.indexes))s.set(t,convertIndexToProto(n));let c=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(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.scale!==void 0&&{scale:e.scale}};return e.type===`nested`&&e.fields&&(t.fields=processNestedFieldsFromSnapshot(e.fields)),t}function processNestedFieldsFromSnapshot(e){let t=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:!1,unique:!1,foreignKey:!1,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=be.ALLOW;break;case`deny`:t=be.DENY;break;default:throw L(`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=ot.EQ;break;case`ne`:o=ot.NE;break;case`in`:o=ot.IN;break;case`nin`:o=ot.NIN;break;case`hasAny`:o=ot.HAS_ANY;break;case`nhasAny`:o=ot.NHAS_ANY;break;default:throw L(`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 L(`Unknown field-ref operand shape: ${JSON.stringify(e)}`)}return{kind:{case:`value`,value:qn(ir,e)}}}function generateAllTypeManifestsFromSnapshot(e,t={}){let n=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(E.ALL);break;case`create`:t.push(E.CREATE);break;case`read`:t.push(E.READ);break;case`update`:t.push(E.UPDATE);break;case`delete`:t.push(E.DELETE);break;case`aggregate`:t.push(E.AGGREGATE);break;case`bulkUpsert`:t.push(E.BULK_UPSERT);break;default:throw L(`Unknown action: ${n}`)}let n;switch(e.permit){case`allow`:n=ge.ALLOW;break;case`deny`:n=ge.DENY;break;default:throw L(`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=De.EQ;break;case`ne`:o=De.NE;break;case`in`:o=De.IN;break;case`nin`:o=De.NIN;break;case`hasAny`:o=De.HAS_ANY;break;case`nhasAny`:o=De.NHAS_ANY;break;default:throw L(`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 R({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:qn(ir,e)}}}async function bundleMigrationScript(e,t,n,r={},i){let a=V.resolve($t(),`migrations`);U.mkdirSync(a,{recursive:!0});let o=V.join(a,`migration_${t}_${n}.entry.js`),s=V.resolve(e).replace(/\\/g,`/`),c=I`
|
|
28
|
+
`)}const ra={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]} ${ra[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 R({code:`MIGRATION_NUMBER_INVALID`,message:`Migration number ${e} is out of range. Expected 0-9999.`});return t}throw R({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 ia=`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<=6)return;let r;throw r=n>6?`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.`,R({code:ia,message:`Unsupported migration file format version ${n} at ${e}.`,details:`This SDK supports migration file format versions 1-6.`,suggestion:r})}const aa=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=aa.get(t);return n===void 0?e:{...e,kind:n}});return{...e,changes:n}}const oa=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=oa.get(e);a!==void 0&&!(a in t)?(n[a]=i,r=!0):n[e]=i}return r?n:e}const sa=[`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 sa){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||Ar.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 ca=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||!ca.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`}}const la=new Set([`index`,`unique`,`vector`]);function isRenameCompatible(e,t){if(e.type!==t.type)return!1;for(let n of ta)if(!la.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=new Map,n=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=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 R({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 R({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 R({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${s}: field "${a}" does not exist in the previous schema.`});if(l.fields[a])throw R({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${s}: field "${a}" still exists in the current schema.`});let d=l.fields[o];if(!d)throw R({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${s}: field "${o}" does not exist in the current schema.`});if(c.fields[o])throw R({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${s}: field "${o}" already exists in the previous schema.`});if(!isRenameCompatible(u,d))throw R({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 ua=/^([^.:\s]+)\.([^.:\s]+):([^.:\s]+)$/;function parseRenameOption(e){let[,t,n,r]=e.match(ua)??[];if(!t||!n||!r)throw R({code:`MIGRATION_RENAME_FLAG_INVALID`,message:`Invalid --rename value "${e}". Expected format: "Table.oldField:newField".`,command:`tailordb migration generate`});if(n===r)throw R({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 da=/^([^.:\s]+)\.([^.:\s]+)$/;function parseDropOption(e){let[,t,n]=e.match(da)??[];if(!t||!n)throw R({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(da)??[];if(!t||!n)throw R({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 ta)if(!la.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=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 R({code:`MIGRATION_RENAME_INVALID`,message:`Member "${e}" appears in more than one rename.`});r.add(e)}if(o.length===0||!haveSameParent(o,s))throw R({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 R({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${l}: "${n}.${a}" must be a nested field in both the previous and the current schema.`});let f=getNestedMember(u,o);if(!f)throw R({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${l}: member "${o.join(`.`)}" does not exist in the previous schema.`});if(getNestedMember(d,o))throw R({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 R({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${l}: member "${s.join(`.`)}" does not exist in the current schema.`});if(getNestedMember(u,s))throw R({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${l}: member "${s.join(`.`)}" already exists in the previous schema.`});if(!isNestedMemberRenameCompatible(f,p))throw R({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 fa=/^([^.:\s]+)\.([^.:\s]+)((?:\.[^.:\s]+)+):([^.:\s]+)$/;function parseNestedMemberRenameOption(e){let[,t,n,r,i]=e.match(fa)??[];if(!t||!n||!r||!i)throw R({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 R({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 pa=/^([^.:\s]+)\.([^.:\s]+)((?:\.[^.:\s]+)+)$/;function parseNestedMemberDropOption(e){let[,t,n,r]=e.match(pa)??[];if(!t||!n||!r)throw R({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 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)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||n.foreignKeyType===e.name&&n.required||!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=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 R({code:`MIGRATION_RENAME_INVALID`,message:`Table "${e}" appears in more than one rename.`});r.add(e)}let s=e.tables[n];if(!s)throw R({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${o}: table "${n}" does not exist in the previous schema.`});if(t.tables[n])throw R({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${o}: table "${n}" still exists in the current schema.`});let c=t.tables[a];if(!c)throw R({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${o}: table "${a}" does not exist in the current schema.`});if(e.tables[a])throw R({code:`MIGRATION_RENAME_INVALID`,message:`Cannot rename ${o}: table "${a}" already exists in the previous schema.`});if(!isTypeRenameCompatible(s,c))throw R({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 ma=/^([^.:\s]+):([^.:\s]+)$/;function parseTypeRenameOption(e){let[,t,n]=e.match(ma)??[];if(!t||!n)throw R({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 R({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 ha=/^([^.:\s]+)$/;function parseTypeDropOption(e){let[,t]=e.match(ha)??[];if(!t)throw R({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)`,_a=`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:_a}):n.kind===`field_modified`&&t.push(...collectNestedMemberRemovalWarnings(n));return t}function areFieldsDifferent(e,t){return areOwnFieldConfigsDifferent(e,t)||collectNestedMemberChanges(e,t).length>0}function getBreakingFieldChanges(e,t,n,r,i){let a=[];if(!n&&r&&r.required&&a.push({tableName:e,fieldName:t,reason:`Required field added`}),n&&r&&n.type!==r.type){let i=supportsInPlaceFieldTypeChange(n,r);a.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&&a.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`];a.push({tableName:e,fieldName:t,reason:`Field changed from ${r} to ${i}`,unsupported:!0,showThreeStepHint:!0})}if(n&&r&&isBreakingForeignKeyRetarget(n,r,i)&&a.push({tableName:e,fieldName:t,reason:`Foreign key target type changed from ${n.foreignKeyType} to ${r.foreignKeyType}`}),n&&r&&!(n.unique??!1)&&(r.unique??!1)&&a.push({tableName:e,fieldName:t,reason:`Unique constraint added to field`}),n?.type===`decimal`&&r?.type===`decimal`&&n.scale!==r.scale&&a.push({tableName:e,fieldName:t,reason:`Decimal scale changed from ${n.scale} to ${r.scale}`}),n&&r&&n.type===`enum`&&r.type===`enum`){let i=n.allowedValues??[],o=r.allowedValues??[],s=i.map(e=>e.value),c=new Set(o.map(e=>e.value)),l=s.filter(e=>!c.has(e));l.length>0&&a.push({tableName:e,fieldName:t,reason:`Enum values removed: ${l.join(`, `)}`})}return a}function addChange(e,t,n,r){if(e.changes.push(t),!t.fieldName)return;t.kind===`field_modified`&&e.warnings.push(...collectNestedMemberRemovalWarnings(t));let i=getBreakingFieldChanges(t.tableName,t.fieldName,n,r,e.typeRenameTargets);if(i.length>0){e.breakingChanges.push(...i);return}t.kind===`field_removed`&&e.warnings.push({tableName:t.tableName,fieldName:t.fieldName,reason:ga})}function compareTypeFields(e,t,n,r,i=[],a=[]){let o=new Set(Object.keys(n.fields)),s=new Set(Object.keys(r.fields)),c=new Set(i.map(e=>e.previousFieldName)),l=new Set(i.map(e=>e.fieldName));for(let a of i){let i=k(n.fields[a.previousFieldName],`renamed field "${a.previousFieldName}" missing from prevType`),o=k(r.fields[a.fieldName],`renamed field "${a.fieldName}" missing from currType`);e.changes.push({kind:`field_renamed`,tableName:t,fieldName:a.fieldName,previousFieldName:a.previousFieldName,before:i,after:o}),e.breakingChanges.push({tableName:t,fieldName:a.fieldName,reason:`Field renamed from ${a.previousFieldName} to ${a.fieldName} (existing values must be copied by the migration script)`})}for(let n of s)if(!l.has(n)&&!o.has(n)){let i=k(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 o)if(!c.has(r)&&!s.has(r)){let i=k(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 s){if(!o.has(i))continue;let s=k(n.fields[i],`field "${i}" missing from prevType`),c=k(r.fields[i],`field "${i}" missing from currType`);if(!areFieldsDifferent(s,c))continue;if(s.type!==c.type){addChange(e,{kind:`field_type_modified`,tableName:t,fieldName:i,before:s,after:c},s,c);continue}let l=a.filter(e=>e.fieldName===i).map(({previousPath:e,path:t})=>({previousPath:e,path:t}));addChange(e,{kind:`field_modified`,tableName:t,fieldName:i,before:s,after:c,...l.length>0&&{memberRenames:l}},s,c);for(let n of l)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||{})),a=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??{}))a.has(r)||e.changes.push({kind:`index_removed`,tableName:t,indexName:r,before:i});for(let[a,o]of Object.entries(r??{}))if(i.has(a)){let r=k(k(n,`oldIndexes is undefined when oldKeys has entry`)[a],`index "${a}" missing from oldIndexes`),i=JSON.stringify(r.fields.toSorted()),s=JSON.stringify(o.fields.toSorted());if(i!==s||(r.unique??!1)!==(o.unique??!1)){let n=[];i!==s&&n.push(`fields changed`),(r.unique??!1)!==(o.unique??!1)&&n.push(`unique constraint changed`),e.changes.push({kind:`index_modified`,tableName:t,indexName:a,reason:n.join(`, `),before:r,after:o});let c=isBreakingIndexChange(t,a,r,o);c&&e.breakingChanges.push(c)}}}function compareFiles(e,t,n,r){let i=new Set(Object.keys(n||{})),a=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??{}))a.has(r)||e.changes.push({kind:`file_removed`,tableName:t,fieldName:r,before:i});for(let[a,o]of Object.entries(r??{}))if(i.has(a)){let r=k(k(n,`oldFiles is undefined when oldKeys has entry`)[a],`file "${a}" missing from oldFiles`);r!==o&&e.changes.push({kind:`file_modified`,tableName:t,fieldName:a,reason:`description changed`,before:r,after:o})}}function compareRelationships(e,t,n,r,i){let a=new Set(Object.keys(r||{})),o=new Set(Object.keys(i||{}));for(let[r,o]of Object.entries(i??{}))a.has(r)||e.changes.push({kind:`relationship_added`,tableName:t,relationshipName:r,relationshipType:n,after:o});for(let[i,a]of Object.entries(r??{}))o.has(i)||e.changes.push({kind:`relationship_removed`,tableName:t,relationshipName:i,relationshipType:n,before:a});for(let[o,s]of Object.entries(i??{}))if(a.has(o)){let i=k(k(r,`oldRelationships is undefined when oldKeys has entry`)[o],`relationship "${o}" missing from oldRelationships`),a=[];i.targetType!==s.targetType&&a.push(`targetType changed`),i.targetField!==s.targetField&&a.push(`targetField changed`),i.sourceField!==s.sourceField&&a.push(`sourceField changed`),i.isArray!==s.isArray&&a.push(`isArray changed`),i.description!==s.description&&a.push(`description changed`),a.length>0&&e.changes.push({kind:`relationship_modified`,tableName:t,relationshipName:o,relationshipType:n,reason:a.join(`, `),before:i,after:s})}}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 va={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)=>va[e]-va[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,Ar.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=new Map;for(let e of r){let t=i.get(e.tableName)??[];t.push(e),i.set(e.tableName,t)}let a=n?.nestedMemberRenames??[];assertValidNestedMemberRenames(e,t,a);let o=new Map;for(let e of a){let t=o.get(e.tableName)??[];t.push(e),o.set(e.tableName,t)}let s=n?.typeRenames??[];assertValidTypeRenames(e,t,s);let c=new Map(s.map(e=>[e.previousTableName,e.tableName])),l=new Set(s.map(e=>e.tableName)),u={changes:[],breakingChanges:[],warnings:[],typeRenameTargets:c},d=new Set(Object.keys(e.tables)),f=new Set(Object.keys(t.tables));for(let n of s){let r=k(e.tables[n.previousTableName],`renamed table "${n.previousTableName}" missing from previous snapshot`),i=k(t.tables[n.tableName],`renamed table "${n.tableName}" missing from current snapshot`);u.changes.push({kind:`table_renamed`,tableName:n.tableName,previousTableName:n.previousTableName,before:r,after:i}),u.breakingChanges.push({tableName:n.tableName,reason:`Table renamed from ${n.previousTableName} to ${n.tableName} (existing records must be copied by the migration script)`}),u.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))l.has(e)||d.has(e)||u.changes.push({kind:`table_added`,tableName:e,after:n});for(let[t,n]of Object.entries(e.tables))c.has(t)||f.has(t)||(u.changes.push({kind:`table_removed`,tableName:t,before:n}),u.warnings.push({tableName:t,reason:_a}));for(let n of f){if(!d.has(n))continue;let r=k(e.tables[n],`table "${n}" missing from previous snapshot`),a=k(t.tables[n],`table "${n}" missing from current snapshot`);compareTypeSettings(u,n,r,a),compareTypeScripts(u,n,r,a),compareTypeFields(u,n,r,a,i.get(n),o.get(n)),compareIndexes(u,n,r.indexes,a.indexes),compareFiles(u,n,r.files,a.files),compareRelationships(u,n,`forward`,r.forwardRelationships,a.forwardRelationships),compareRelationships(u,n,`backward`,r.backwardRelationships,a.backwardRelationships),comparePermissions(u,n,r.permissions?.record,a.permissions?.record,r.permissions?.gql,a.permissions?.gql)}return{version:6,namespace:t.namespace,createdAt:new Date().toISOString(),changes:u.changes,hasBreakingChanges:u.breakingChanges.length>0,breakingChanges:u.breakingChanges,hasWarnings:u.warnings.length>0,warnings:u.warnings,requiresMigrationScript:u.breakingChanges.length>0}}function compareLocalTypesWithSnapshot(e,t,n){let r={version:6,namespace:n,createdAt:new Date().toISOString(),tables:t};return compareSnapshots(normalizeSchemaSnapshot(e),normalizeSchemaSnapshot(r))}const ya=`sdk-migration`,ba=`sdk-migration-history`,xa=/^[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 parseMigrationHistoryId(e){return xa.test(e)?e:null}function createMigrationHistoryId(){return`h${xr().replaceAll(`-`,``)}`}function handleOptionalToRequiredError(e,t){if(e instanceof K&&e.code===G.FailedPrecondition&&e.message.includes(`cannot be updated from non-required to required when records exist`)){M.error(`Schema change failed: Cannot change field from optional to required when records exist.`),M.newline();for(let e of t)M.info(e)}throw e}function snapshotRecordSchema(e){return H.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){for(let e of a.error.issues)n.addIssue({...e,path:[i,...e.path]});continue}r[i]=a.data}return r})}const Sa=H.looseObject({expr:H.string()}),Ca=H.looseObject({script:H.looseObject({expr:H.string()}).optional(),errorMessage:H.string()}),wa=H.looseObject({start:H.number(),maxValue:H.number().optional(),format:H.string().optional()}),Ta=H.looseObject({value:H.string(),description:H.string().optional()}),Ea=H.looseObject({type:H.string(),required:H.boolean().default(!0),array:H.boolean().optional(),index:H.boolean().optional(),unique:H.boolean().optional(),allowedValues:H.array(Ta).optional(),foreignKey:H.boolean().optional(),foreignKeyType:H.string().optional(),foreignKeyField:H.string().optional(),description:H.string().optional(),vector:H.boolean().optional(),hooks:H.looseObject({create:Sa.optional(),update:Sa.optional()}).optional(),validate:H.array(Ca).optional(),serial:wa.optional(),scale:H.number().optional(),default:H.unknown().optional(),fields:H.lazy(()=>snapshotRecordSchema(Ea)).optional()}),Da=H.looseObject({fields:H.array(H.string()),unique:H.boolean().optional()}),Oa=H.looseObject({targetType:H.string(),targetField:H.string(),sourceField:H.string(),isArray:H.boolean(),description:H.string()}),ka=[`user`,`record`,`newRecord`,`oldRecord`],Aa=H.unknown().refine(e=>{if(typeof e!=`object`||!e||Array.isArray(e))return!0;let t=Object.keys(e);return ka.filter(e=>t.includes(e)).length<2},`Ambiguous field-ref operand: contains more than one of user/record/newRecord/oldRecord`),ja=H.unknown().refine(e=>{if(typeof e!=`object`||!e||Array.isArray(e))return!0;let t=Object.keys(e);return ka.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`),Ma=H.string(),Na=H.tuple([Aa,Ma,Aa]).rest(H.unknown()),Pa=H.tuple([ja,Ma,ja]).rest(H.unknown()),Fa=H.looseObject({conditions:H.array(Na),description:H.string().optional(),permit:H.enum([`allow`,`deny`])}),Ia=H.looseObject({create:H.array(Fa).default([]),read:H.array(Fa).default([]),update:H.array(Fa).default([]),delete:H.array(Fa).default([])}),La=H.string(),Ra=H.looseObject({conditions:H.array(Pa),actions:H.array(La),permit:H.enum([`allow`,`deny`]),description:H.string().optional()}),za=H.array(Ra),Ba=H.looseObject({name:H.string(),pluralForm:H.string().optional(),description:H.string().optional(),fields:snapshotRecordSchema(Ea),settings:H.looseObject({aggregation:H.boolean().optional(),bulkUpsert:H.boolean().optional(),gqlOperations:H.looseObject({create:H.boolean().optional(),update:H.boolean().optional(),delete:H.boolean().optional(),read:H.boolean().optional()}).optional(),publishEvents:H.boolean().optional()}).optional(),indexes:snapshotRecordSchema(Da).optional(),files:snapshotRecordSchema(H.string()).optional(),forwardRelationships:snapshotRecordSchema(Oa).optional(),backwardRelationships:snapshotRecordSchema(Oa).optional(),permissions:H.looseObject({record:Ia.optional(),gql:za.optional()}).optional()}),Va=H.looseObject({historyId:H.string().regex(xa),replacedHistoryId:H.string().regex(xa).nullable(),replacedLatestMigration:H.number().int().min(0).max(9999)}),Ha=H.looseObject({version:H.number(),namespace:H.string(),createdAt:H.string(),tables:snapshotRecordSchema(Ba),rebaseline:Va.optional()}),Ua=H.looseObject({indexes:snapshotRecordSchema(Da).optional(),files:snapshotRecordSchema(H.string()).optional()}),Wa=H.looseObject({description:H.string().optional(),pluralForm:H.string(),settings:H.looseObject({aggregation:H.boolean().optional(),bulkUpsert:H.boolean().optional(),gqlOperations:H.looseObject({create:H.boolean().optional(),update:H.boolean().optional(),delete:H.boolean().optional(),read:H.boolean().optional()}).optional(),publishEvents:H.boolean().optional()}).optional()}),Ga=H.looseObject({recordPermission:Ia.optional(),gqlPermission:za.optional()}),Ka=H.looseObject({kind:H.literal(`table_added`),tableName:H.string(),reason:H.string().optional(),after:Ba}),qa=H.looseObject({kind:H.literal(`table_removed`),tableName:H.string(),reason:H.string().optional(),before:Ba}),Ja=H.looseObject({kind:H.literal(`table_renamed`),tableName:H.string(),reason:H.string().optional(),previousTableName:H.string(),before:Ba,after:Ba}),Ya=H.looseObject({kind:H.literal(`table_modified`),tableName:H.string(),reason:H.string().optional(),before:Ua.optional(),after:Ua.optional()}),Xa=H.looseObject({kind:H.literal(`table_settings_modified`),tableName:H.string(),reason:H.string().optional(),before:Wa,after:Wa}),Za=H.looseObject({kind:H.literal(`field_added`),tableName:H.string(),reason:H.string().optional(),fieldName:H.string(),after:Ea}),Qa=H.looseObject({kind:H.literal(`field_removed`),tableName:H.string(),reason:H.string().optional(),fieldName:H.string(),before:Ea}),$a=H.looseObject({kind:H.literal(`field_modified`),tableName:H.string(),reason:H.string().optional(),fieldName:H.string(),before:Ea,after:Ea,memberRenames:H.array(H.looseObject({previousPath:H.array(H.string()).min(1),path:H.array(H.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()}),eo=H.looseObject({kind:H.literal(`field_renamed`),tableName:H.string(),reason:H.string().optional(),fieldName:H.string(),previousFieldName:H.string(),before:Ea,after:Ea}),to=H.looseObject({kind:H.literal(`field_type_modified`),tableName:H.string(),reason:H.string().optional(),fieldName:H.string(),before:Ea,after:Ea}),no=H.looseObject({kind:H.literal(`index_added`),tableName:H.string(),reason:H.string().optional(),indexName:H.string(),after:Da}),ro=H.looseObject({kind:H.literal(`index_removed`),tableName:H.string(),reason:H.string().optional(),indexName:H.string(),before:Da}),io=H.looseObject({kind:H.literal(`index_modified`),tableName:H.string(),reason:H.string().optional(),indexName:H.string(),before:Da,after:Da}),ao=H.looseObject({kind:H.literal(`file_added`),tableName:H.string(),reason:H.string().optional(),fieldName:H.string(),after:H.string()}),oo=H.looseObject({kind:H.literal(`file_removed`),tableName:H.string(),reason:H.string().optional(),fieldName:H.string(),before:H.string()}),so=H.looseObject({kind:H.literal(`file_modified`),tableName:H.string(),reason:H.string().optional(),fieldName:H.string(),before:H.string(),after:H.string()}),co=H.looseObject({kind:H.literal(`relationship_added`),tableName:H.string(),reason:H.string().optional(),relationshipName:H.string(),relationshipType:H.enum([`forward`,`backward`]).optional(),after:Oa}),lo=H.looseObject({kind:H.literal(`relationship_removed`),tableName:H.string(),reason:H.string().optional(),relationshipName:H.string(),relationshipType:H.enum([`forward`,`backward`]).optional(),before:Oa}),uo=H.looseObject({kind:H.literal(`relationship_modified`),tableName:H.string(),reason:H.string().optional(),relationshipName:H.string(),relationshipType:H.enum([`forward`,`backward`]).optional(),before:Oa,after:Oa}),fo=H.looseObject({kind:H.literal(`permission_modified`),tableName:H.string(),reason:H.string().optional(),before:Ga.optional(),after:Ga.optional()}),po=H.looseObject({typeHookExpr:H.looseObject({create:H.string().optional(),update:H.string().optional()}).optional(),typeValidateExpr:H.string().optional()}),mo=H.looseObject({kind:H.literal(`table_scripts_modified`),tableName:H.string(),reason:H.string().optional(),before:po,after:po}),ho=H.discriminatedUnion(`kind`,[Ka,qa,Ja,Ya,Xa,Za,Qa,$a,eo,to,no,ro,io,ao,oo,so,co,lo,uo,fo,mo]),go=H.looseObject({tableName:H.string(),fieldName:H.string().optional(),reason:H.string(),unsupported:H.boolean().optional(),showThreeStepHint:H.boolean().optional()}),_o=H.looseObject({tableName:H.string(),fieldName:H.string().optional(),reason:H.string()}),vo=H.looseObject({reason:H.string().trim().min(1),acknowledgedAt:H.string()}),yo=H.looseObject({version:H.number(),namespace:H.string(),createdAt:H.string(),description:H.string().optional(),changes:H.array(ho),hasBreakingChanges:H.boolean(),breakingChanges:H.array(go),hasWarnings:H.boolean().optional(),warnings:H.array(_o).optional(),requiresMigrationScript:H.boolean(),scriptSkipped:vo.optional()}),bo=0,xo=`schema.json`,So=`diff.json`,Co=`migrate.ts`,wo=`migrate.test.ts`,To=`db.ts`,Eo=`db.pglite.ts`,Do=`migrate.pglite.test.ts`,Oo=/^\d{4}$/;function isValidMigrationNumber(e){return Oo.test(e)}const ko={schema:xo,diff:So,migrate:Co,test:wo,db:To,pgliteSchema:Eo,pgliteTest:Do};function getMigrationDirPath(e,t){let n=formatMigrationNumber(t);return V.join(e,n)}function getMigrationFilePath(e,t,n){let r=getMigrationDirPath(e,t);return V.join(r,ko[n])}function loadSnapshot(e){let t=U.readFileSync(e,`utf-8`),n;try{n=JSON.parse(t)}catch(t){throw R({code:`MIGRATION_FILE_INVALID`,message:`Invalid schema snapshot at ${e}: ${String(t)}`,cause:t})}assertSupportedMigrationFileVersion(e,n);let r=Ha.safeParse(normalizeLegacyTablesKey(n));if(!r.success)throw R({code:`MIGRATION_FILE_INVALID`,message:`Invalid schema snapshot at ${e}: ${H.prettifyError(r.error)}`,cause:r.error});let i=r.data;return normalizeSchemaSnapshot(i)}function loadDiff(e){let t=U.readFileSync(e,`utf-8`),n;try{n=JSON.parse(t)}catch(t){throw R({code:`MIGRATION_FILE_INVALID`,message:`Invalid migration diff at ${e}: ${String(t)}`,cause:t})}assertSupportedMigrationFileVersion(e,n);let r=yo.safeParse(normalizeLegacyFieldNames(normalizeLegacyChangeKinds(n)));if(!r.success)throw R({code:`MIGRATION_FILE_INVALID`,message:`Invalid migration diff at ${e}: ${H.prettifyError(r.error)}`,cause:r.error});let i=r.data,a=i.warnings??deriveWarningsFromChanges(i);return{...i,warnings:a,hasWarnings:a.length>0}}function getMigrationFiles(e){if(!U.existsSync(e))return[];let t=U.readdirSync(e,{withFileTypes:!0}),n=[];for(let r of t){if(!r.isDirectory()||!isValidMigrationNumber(r.name))continue;let t=parseInt(r.name,10),i=V.join(e,r.name),a=V.join(i,xo);U.existsSync(a)&&n.push({number:t,type:`schema`,path:a});let o=V.join(i,So);U.existsSync(o)&&n.push({number:t,type:`diff`,path:o})}return n.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 R({code:`MIGRATION_NOT_FOUND`,message:`Migration ${formatMigrationNumber(t)} does not exist in working tree (latest is ${formatMigrationNumber(latestMigrationNumber(n))}).`});return latestMigrationNumber(n)}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 R({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(!U.existsSync(e))return t;let n=getMigrationFiles(e);if(n.length===0)return t;let r=[],i=[];for(let e of n)e.type===`schema`?r.push(e.number):i.push(e.number);r.includes(0)||t.push({type:`missing_schema`,message:`Initial schema snapshot (${formatMigrationNumber(0)}/schema.json) is missing`,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});let a=[...new Set([...r,...i])].toSorted((e,t)=>e-t);if(a.length===0)return t;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 o=Math.max(...a);for(let e=0;e<=o;e++)a.includes(e)||t.push({type:`gap`,message:`Migration ${formatMigrationNumber(e)} is missing (gap in sequence)`,migrationNumber:e});for(let e of a)e>0&&!i.includes(e)&&t.push({type:`missing_diff`,message:`Migration ${formatMigrationNumber(e)} is missing diff file`,migrationNumber:e});return t}function assertValidMigrationFiles(e,t){let n=validateMigrationFiles(e);if(n.length>0){let e=n.map(e=>` - ${e.message}`).join(`
|
|
29
|
+
`);throw R({code:`MIGRATION_FILES_INVALID`,message:`Migration file validation failed for namespace "${t}":\n${e}`})}}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.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||Ar.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:6,namespace:t,createdAt:new Date().toISOString(),tables:n})}const Ao=`_input`,jo=`_oldRecord`,Mo=`_now`,No=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))){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]),br(`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`&&No.has(t)?Mo: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(`
|
|
30
|
+
`);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(`
|
|
31
|
+
`)}\n});`)}else{let t=buildValidateStatements(o.fields,e,s,r);t.length>0&&i.push(`if (${e} != null) {\n${t.join(`
|
|
32
|
+
`)}\n}`)}}}return i}function principalDeclIfReferenced(...e){return e.some(e=>e?.includes(`_principal`))?` const ${Dt} = (${vt});`:``}function wrapHook(e){return`((_invoker) => { const ${Mo} = 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(`
|
|
33
|
+
`)}${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,Ao,jo,t,!1,t===`update`?`Object.assign({}, ${jo}, ${Ao})`:Ao),i=r?.[t],a;if(n!==null&&i){let e=principalDeclIfReferenced(n,i);a=`((_invoker) => { const ${Mo} = new Date();${e} const __fl = ${n}; return Object.assign({}, __fl, ((${Ao}) => ${i})(Object.assign({}, ${Ao}, __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.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===it.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 Po=new Map([[be.ALLOW,`allow`],[be.DENY,`deny`]]),Fo=new Map([[ot.EQ,`eq`],[ot.NE,`ne`],[ot.IN,`in`],[ot.NIN,`nin`],[ot.HAS_ANY,`hasAny`],[ot.NHAS_ANY,`nhasAny`]]);function convertRemotePermit(e,t){let n=Po.get(e);if(n)return n;throw L(`Unsupported ${t} permission permit: ${e}`)}function convertRemoteOperator(e,t){let n=Fo.get(e);if(n)return n;throw L(`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 $n(ur,e.kind.value);default:throw L(`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 E.ALL:return`all`;case E.CREATE:return`create`;case E.READ:return`read`;case E.UPDATE:return`update`;case E.DELETE:return`delete`;case E.AGGREGATE:return`aggregate`;case E.BULK_UPSERT:return`bulkUpsert`;default:throw L(`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||Ar.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:6,namespace:t,createdAt: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??[],a=r.validate??[];i.length!==a.length&&e.push(`${fieldDifferenceKey(t,`validate`)} count: remote=${i.length}, expected=${a.length}`);let o=Math.min(i.length,a.length);for(let n=0;n<o;n++){let r=k(i[n],`remoteValidate missing index ${n}`),o=k(a[n],`snapshotValidate missing index ${n}`);addFieldDifference(e,t,`validate[${n}].script`,r.script?.expr??``,o.script?.expr??``),addFieldDifference(e,t,`validate[${n}].errorMessage`,r.errorMessage,o.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??``)}function addNestedFieldDifferences(e,t,n,r){let i=n.fields??{},a=r.fields??{},o=Object.keys(i),s=Object.keys(a);o.length!==s.length&&e.push(`${fieldDifferenceKey(t,`fields`)} count: remote=${o.length}, expected=${s.length}`);for(let n of o){let r=i[n],o=a[n],s=fieldDifferenceKey(t,`fields.${n}`);if(!o){e.push(`${s}: exists in remote but not snapshot`);continue}addFieldDifferences(e,s,k(r,`remote field "${n}" missing`),o)}for(let n of s)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 ta)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 Io=new Set([`id`]);function compareRemoteWithSnapshot(e,t,n=[]){let r=compareNormalizedRemoteWithSnapshot(createRemoteComparableSnapshot(createSnapshotFromRemoteTypes(e,t.namespace,n,t)),createRemoteComparableSnapshot(t)),i=compareScriptHashes(e,t);return[...r,...i]}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 Lo=`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}' ${Lo}`:`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))Io.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 L(`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=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(`
|
|
34
|
+
`)}const Ro=Object.keys(ko);function getMigrationArtifactNumbers(e){return U.existsSync(e)?U.readdirSync(e,{withFileTypes:!0}).filter(e=>e.isDirectory()&&Oo.test(e.name)).map(e=>Number.parseInt(e.name,10)).filter(t=>Ro.some(n=>U.existsSync(getMigrationFilePath(e,t,n)))).toSorted((e,t)=>e-t):[]}function updateHashWithDirectory(e,t,n=``,r=new Set){let i=U.realpathSync(t);if(r.has(i)){e.update(`directory-cycle\0${n}\0${i}\0`);return}r.add(i);let a=U.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=V.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(U.readFileSync(o)),e.update(`\0`);else if(i.isSymbolicLink()){e.update(`symlink\0${a}\0${U.readlinkSync(o)}\0`);try{let t=U.statSync(o);t.isDirectory()?(e.update(`target-directory\0`),updateHashWithDirectory(e,o,`${a}@target`,r)):t.isFile()?(e.update(`target-file\0`),e.update(U.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=br(`sha256`);for(let n of[...new Set(e)].toSorted())t.update(n),t.update(`\0`),U.existsSync(n)?t.update(U.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=br(`sha256`),i=getMigrationArtifactNumbers(r);for(let t of i){let n=formatMigrationNumber(t);e.update(`migration\0${n}\0`),updateHashWithDirectory(e,V.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=V.resolve(t,i.migration.directory);n.push({namespace:r,migrationsDir:a})}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 R({code:`TAILORDB_NAMESPACE_NOT_FOUND`,message:`Namespace "${t}" not found or does not have migrations configured`});return n}if(e.length>1)throw R({code:`MIGRATION_NAMESPACE_REQUIRED`,message:`Multiple TailorDB services found. Please specify namespace with --namespace flag: ${e.map(e=>e.namespace).join(`, `)}`});return k(e[0],`namespace with migrations missing`)}function migrationConfigNotFoundError(){return R({code:`MIGRATION_CONFIG_NOT_FOUND`,message:`No TailorDB services with migrations configuration found`,suggestion:"Configure `migration` on the TailorDB service in tailor.config.ts."})}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};let r=n.labels[ya],i=n.labels[ba],a=i?parseMigrationHistoryId(i):null;return{metadataExists:!0,number:r?parseMigrationLabelNumber(r):null,historyId:a,historyIdInvalid:i!==void 0&&a===null}}async function fetchRemoteMigrationNumber(e,t){return(await fetchRemoteMigrationState(e,t)).number}function usesLegacyData(e){return e.includes(`_data`)&&_t(`(${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:Wt(`((_data) => { ${i.join(`
|
|
35
|
+
`)} })(${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:Wt(`((_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:Qi.tailorDBType(e.name)})}function generateTailorDBTypeManifestFromSnapshot(e,t={}){let n=Ar.camelize(e.pluralForm,!0),r={aggregation:e.settings?.aggregation??!1,bulkUpsert:t.suppressGqlOperations===!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.suppressGqlOperations===!0)&&(r.disableGqlOperations={create:t.suppressGqlOperations===!0||i?.create===!1,update:t.suppressGqlOperations===!0||i?.update===!1,delete:t.suppressGqlOperations===!0||i?.delete===!1,read:t.suppressGqlOperations===!0||i?.read===!1});let a=Object.fromEntries(Object.entries(e.fields).filter(([e])=>e!==`id`).map(([e,t])=>[e,convertFieldConfigToProto(t)])),o=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=new Map;if(e.indexes)for(let[t,n]of Object.entries(e.indexes))s.set(t,convertIndexToProto(n));let c=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.scale!==void 0&&{scale:e.scale}};return e.type===`nested`&&e.fields&&(t.fields=processNestedFieldsFromSnapshot(e.fields)),t}function processNestedFieldsFromSnapshot(e){let t=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:!1,unique:!1,foreignKey:!1,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=be.ALLOW;break;case`deny`:t=be.DENY;break;default:throw L(`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=ot.EQ;break;case`ne`:o=ot.NE;break;case`in`:o=ot.IN;break;case`nin`:o=ot.NIN;break;case`hasAny`:o=ot.HAS_ANY;break;case`nhasAny`:o=ot.NHAS_ANY;break;default:throw L(`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 L(`Unknown field-ref operand shape: ${JSON.stringify(e)}`)}return{kind:{case:`value`,value:Qn(ur,e)}}}function generateAllTypeManifestsFromSnapshot(e,t={}){let n=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(E.ALL);break;case`create`:t.push(E.CREATE);break;case`read`:t.push(E.READ);break;case`update`:t.push(E.UPDATE);break;case`delete`:t.push(E.DELETE);break;case`aggregate`:t.push(E.AGGREGATE);break;case`bulkUpsert`:t.push(E.BULK_UPSERT);break;default:throw L(`Unknown action: ${n}`)}let n;switch(e.permit){case`allow`:n=ge.ALLOW;break;case`deny`:n=ge.DENY;break;default:throw L(`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=De.EQ;break;case`ne`:o=De.NE;break;case`in`:o=De.IN;break;case`nin`:o=De.NIN;break;case`hasAny`:o=De.HAS_ANY;break;case`nhasAny`:o=De.NHAS_ANY;break;default:throw L(`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 R({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:Qn(ur,e)}}}async function bundleMigrationScript(e,t,n,r={},i){let a=V.resolve($t(),`migrations`);U.mkdirSync(a,{recursive:!0});let o=V.join(a,`migration_${t}_${n}.entry.js`),s=V.resolve(e).replace(/\\/g,`/`),c=I`
|
|
36
36
|
import { main as _migrationMain } from "${s}";
|
|
37
37
|
import { Kysely, TailordbDialect } from "@tailor-platform/sdk/kysely";
|
|
38
38
|
|
|
@@ -51,13 +51,13 @@ If a value is genuinely safe to keep in 'env', allow it where it is defined: ${a
|
|
|
51
51
|
});
|
|
52
52
|
return { success: true };
|
|
53
53
|
}
|
|
54
|
-
`;U.writeFileSync(o,c);let l=i??V.dirname(s),u=await
|
|
54
|
+
`;U.writeFileSync(o,c);let l=i??V.dirname(s),u=await Tt(l),d=wt({tsconfig:u}),f=await Or.build({plugins:[ht(o,l),Ut(),Et],input:o,write:!1,output:{format:`esm`,sourcemap:!1,minify:!1,codeSplitting:!1,globals:{tailordb:`tailordb`}},external:[`tailordb`],resolve:{conditionNames:[`node`,`import`]},tsconfig:u,treeshake:{moduleSideEffects:!1,annotations:!0,unknownGlobalSideEffects:!1},...d.options});return d.assertAllResolved(),{namespace:t,migrationNumber:n,bundledCode:f.output[0].code}}function formatMigrationScriptCommand(e){let{migrationNumber:t,namespace:n,configPath:r,noScript:i}=e,a=[`tailor`,`tailordb`,`migration`,`script`,formatMigrationNumber(t),`--namespace`,n],o=formatConfigArg(r);return o!==void 0&&a.push(o),i&&a.push(`--no-script`,`--reason`,`<reason>`),wn(a)}const zo=[`⠋`,`⠙`,`⠹`,`⠸`,`⠼`,`⠴`,`⠦`,`⠧`,`⠇`,`⠏`],Bo=`\x1B[?25h`,Vo=`\x1B[2K`,Ho=/\u001B\[[0-9;]*[a-zA-Z]/g;function visibleLength(e){return e.replace(Ho,``).length}const Uo=new Set;let Wo=!1,Go=!1;function installExitHook(){Wo||(Wo=!0,process.on(`exit`,()=>{for(let e of Uo)e.cleanupOnExit()}))}function installSignalHook(){if(Go)return;Go=!0;let handler=()=>{for(let e of Uo)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?this:(installExitHook(),installSignalHook(),Uo.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(Bo)),Uo.delete(this),this):this}succeed(e){return this.#s(A.success,e)}fail(e){return this.#s(A.error,e)}warn(e){return this.#s(A.warning,e)}cleanupOnExit(){this.#i&&=(clearInterval(this.#i),void 0),this.#n&&this.#t.write(Bo)}#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(Bo)),Uo.delete(this)),this.#u(`${e} ${this.text}`),this}#c(){this.#t.write(`\x1B[?2026h`),this.#l();let e=j.info(zo[this.#r]??k(zo[0],`spinner frames empty`));this.#r=(this.#r+1)%zo.length;let t=`${` `.repeat(this.#e)}${e} ${this.text}`;this.#t.write(lt(this.#t,t)),this.#t.write(`\x1B[?2026l`);let n=this.#t.columns||80;this.#a=Math.max(1,Math.ceil(visibleLength(t)/n))}#l(){if(this.#a!==0){this.#t.write(`\r`),this.#t.write(Vo);for(let e=1;e<this.#a;e++)this.#t.write(`\x1B[1A`),this.#t.write(Vo);this.#a=0}}#u(e){let t=` `.repeat(this.#e);this.#t.write(lt(this.#t,`${t}${e}\n`))}};function spinner(e){return new Spinner(e)}const Ko=65536;function migrationWorkflowResourceName(e,t){return`tailordb-migration--${e}--${formatMigrationNumber(t)}`}async function uploadMigrationFunction(e,t,n,r,i,a){let o=Buffer.from(r,`utf-8`),s={workspaceId:t,name:n,description:`Temporary function for a TailorDB migration`,sizeBytes:BigInt(o.length),contentHash:yr.createHash(`sha256`).update(r,`utf-8`).digest(`hex`)};async function*stream(){yield{payload:{case:`info`,value:s}};for(let e=0;e<o.length;e+=Ko)yield{payload:{case:`chunk`,value:o.subarray(e,Math.min(e+Ko,o.length))}}}await e.createFunctionRegistry(stream()),await writeMetadataLabelsDirect(e,await buildMetaRequest({trn:resourceTrn(t,`function_registry`,n),appName:i,appId:a}))}async function teardown(e,t,n,r){let i=[...r?[[`workflow`,()=>e.deleteWorkflow({workspaceId:t,workflowId:r})]]:[],[`job function`,()=>e.deleteWorkflowJobFunction({workspaceId:t,jobFunctionName:n})],[`function`,()=>e.deleteFunctionRegistry({workspaceId:t,name:n})]];for(let[e,t]of i)try{await t()}catch(t){if(Jt(t))continue;M.warn(`Could not remove the temporary migration ${e} '${n}': ${t instanceof Error?t.message:String(t)}. It is labeled as owned by this app and can be removed by a later deploy.`)}}async function reclaimLeftovers(e,t,n){await teardown(e,t,n,await findMigrationWorkflowId(e,t,n))}async function findMigrationWorkflowId(e,t,n){try{let{workflow:r}=await e.getWorkflowByName({workspaceId:t,workflowName:n});return r?.id}catch(e){if(Jt(e))return;throw e}}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=e.pollIntervalMs??3e3,d;try{await reclaimLeftovers(t,n,l),await uploadMigrationFunction(t,n,l,r,s,c);let{jobFunction:e}=await t.createWorkflowJobFunction({workspaceId:n,jobFunctionName:l,scriptRef:l,publishExecutionEvents:!1});await writeMetadataLabelsDirect(t,await buildMetaRequest({trn:resourceTrn(n,`workflow_job_function`,l),appName:s,appId:c}));let i=e?.version;if(i===void 0)throw L(`Temporary migration job function '${l}' was created without a version.`);let{workflow:a}=await t.createWorkflow({workspaceId:n,workflowName:l,mainJobFunctionName:l,jobFunctions:{[l]:i}});if(d=a?.id,!d)throw L(`Temporary migration workflow '${l}' was created without an id.`);await writeMetadataLabelsDirect(t,await buildMetaRequest({trn:resourceTrn(n,`workflow`,l),appName:s,appId:c}));let{executionId:f}=await t.startWorkflow({workspaceId:n,workflowId:d,authInvoker:o});return await waitForMigrationWorkflow(t,n,f,u)}finally{await teardown(t,n,l,d)}}async function waitForMigrationWorkflow(e,t,n,r){for(;;){let{execution:i}=await e.getWorkflowExecution({workspaceId:t,executionId:n});if(!i)throw R({code:`WORKFLOW_EXECUTION_NOT_FOUND`,message:`Migration workflow execution '${n}' not found.`});if(i.status===D.SUCCESS){let{logs:n}=await collectJobOutcomes(e,t,i);return{success:!0,logs:n}}if(i.status===D.FAILED){let n=await collectJobOutcomes(e,t,i);return{success:!1,logs:n.logs,error:extractFailureMessage(n)}}await new Promise(e=>setTimeout(e,r))}}async function collectJobOutcomes(e,t,n){let r=await Promise.all(n.jobExecutions.map(async n=>{if(n.executionId)try{let{execution:r}=await e.getFunctionExecution({workspaceId:t,executionId:n.executionId});if(!r)return;let i=r.error?.message.trim()||r.result.trim()||``;return{logs:r.logs,failure:i}}catch{return}}));return{logs:r.map(e=>e?.logs).filter(Boolean).join(`
|
|
55
55
|
`),failures:r.map(e=>e?.failure).filter(e=>!!e)}}function extractFailureMessage(e){return e.failures.at(-1)||e.logs.split(`
|
|
56
|
-
`).filter(e=>/error/i.test(e)).at(-1)?.trim()||`Migration workflow execution failed.`}async function getCurrentMigrationNumber(e,t,n){try{let r=resourceTrn(t,`tailordb`,n),{metadata:i}=await e.getMetadata({trn:r}),a=i?.labels[pa];return a?parseMigrationLabelNumber(a)??0:0}catch(e){if(Rt(e))return 0;throw e}}async function detectPendingMigrations(e,t,n,r,i){let a=[];for(let{namespace:o,migrationsDir:s}of n){let n=i?.get(o)??await getCurrentMigrationNumber(e,t,o),c=getMigrationFiles(s);for(let e of c){if(e.number<=n)continue;let t=getMigrationFilePath(s,e.number,`diff`);if(!U.existsSync(t))continue;let i=loadDiff(t),c=getMigrationFilePath(s,e.number,`migrate`),l=U.existsSync(c);if(i.requiresMigrationScript&&!l&&!i.scriptSkipped){let t={migrationNumber:e.number,namespace:o,configPath:r};throw R({code:`MIGRATION_SCRIPT_REQUIRED`,message:`Migration ${o}/${formatMigrationNumber(e.number)} requires a migration script but migrate.ts was not found.`,suggestion:`Add a script: ${formatMigrationScriptCommand(t)}\nOr record that no script is needed: ${formatMigrationScriptCommand({...t,noScript:!0})}`})}if(i.scriptSkipped){let t=`${o}/${formatMigrationNumber(e.number)}`;if(l)throw R({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: ${formatMigrationScriptCommand({migrationNumber:e.number,namespace:o,configPath:r})}\nOr keep the skip: delete migrate.ts`});M.info(`Migration ${t} runs without a script (skip acknowledged at ${i.scriptSkipped.acknowledgedAt}: ${i.scriptSkipped.reason})`)}a.push({number:e.number,scriptPath:c,hasScript:l,diffPath:t,namespace:o,migrationsDir:s,diff:i})}}return a.toSorted((e,t)=>e.namespace===t.namespace?e.number-t.number:e.namespace.localeCompare(t.namespace))}async function executeSingleMigration(e,t){let{client:n,workspaceId:r,invoker:i,env:a,configDir:o,appName:s,appId:c}=e,l=await executeMigrationAsWorkflow({client:n,workspaceId:r,code:(await bundleMigrationScript(t.scriptPath,t.namespace,t.number,a,o)).bundledCode,namespace:t.namespace,migrationNumber:t.number,invoker:i,appName:s,appId:c});return{namespace:t.namespace,migrationNumber:t.number,success:l.success,logs:l.logs,error:l.error}}async function updateMigrationLabel(e,t,n,r,i){await writeMetadataLabelsDirect(e,{trn:resourceTrn(t,`tailordb`,n),labels:{[pa]:sanitizeMigrationLabel(r),...i?{[ma]:i}:{}},remove:i?void 0:[ma]})}async function executeMigrations(e,t){let n=t.filter(e=>e.hasScript);if(n.length===0)return;let r=groupMigrationsByNamespace(n);for(let[t,n]of r){let r=e.dbConfig[t]?.migration,i=getMigrationMachineUser(r,e.machineUsers);if(!i)throw R({code:`MACHINE_USER_REQUIRED`,message:`No machine user available for migration execution in namespace '${t}'.`,suggestion:`Either configure 'migration.machineUser' in db config or define machine users in auth config.`});let a=Gn(Ie,{namespace:e.authNamespace,machineUserName:i}),o={client:e.client,workspaceId:e.workspaceId,invoker:a,env:e.env,configDir:e.configDir,appName:e.appName,appId:e.appId};M.info(`Using machine user: ${j.bold(i)} for namespace '${t}'`);for(let e of n){let t=`${e.namespace}/${formatMigrationNumber(e.number)}`,n=spinner().start(`Executing migration ${t} (this can take a while)...`),r=await executeSingleMigration(o,e);if(r.success)n.succeed(`Migration ${t} completed successfully`),r.logs&&r.logs.trim()&&M.log(`Logs:\n${r.logs}`);else throw n.fail(`Migration ${t} failed`),r.logs&&M.error(`Logs:\n${r.logs}`),R({code:`MIGRATION_FAILED`,message:r.error??`Migration failed`})}}}function getMigrationMachineUser(e,t){if(e?.machineUser)return e.machineUser;if(t&&t.length>0)return t[0]}function groupMigrationsByNamespace(e){let t=new Map;for(let n of e){let e=t.get(n.namespace)??[];e.push(n),t.set(n.namespace,e)}return t}function defineRecordEntry(e,t,n){Object.defineProperty(e,t,{value:n,enumerable:!0,writable:!0,configurable:!0})}const Bo=new Set([`field_added`,`field_modified`,`field_type_modified`,`field_removed`,`field_renamed`]);function isPreMigrationFieldChange(e){return Bo.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=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)??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)})}function relaxFieldsForPreMigration(e,t,n){for(let[r,i]of t){if(i.kind===`field_removed`){defineRecordEntry(e,r,n.toField(i.before));continue}if(i.kind===`field_renamed`){defineRecordEntry(e,i.previousFieldName,n.toField(i.before));let t=e[r];t&&(i.after.required&&(t.required=!1),(i.after.unique??!1)&&(t.unique=!1));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,n.toField(i.before));continue}let{before:o,after:s}=i;n.adjustNestedMembers?.(t,i),!o.required&&s.required&&(a.required=!1),!(o.unique??!1)&&(s.unique??!1)&&(a.unique=!1);let c=o.allowedValues??[],l=s.allowedValues??[],u=new Set(l.map(e=>e.value));if(c.filter(e=>!u.has(e.value)).length>0){let e=new Map;for(let t of c)e.set(t.value,t.description??``);for(let t of l)e.has(t.value)||e.set(t.value,t.description??``);a.allowedValues=Array.from(e.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=k(getProtoNestedMember(e,r.path.slice(0,-1))?.fields,`parent of removed nested member "${t}" missing from the Pre-phase field`),i=k(r.path.at(-1),`removed nested member path is empty`),a=processNestedFieldsFromSnapshot({[i]:r.before});defineRecordEntry(n,i,k(a[i],`restored nested member "${t}" missing`))}}function relaxRenamedNestedMembers(e,t){for(let n of t){let t=getProtoNestedMember(e,n.path);t?.required&&(t.required=!1),t?.unique&&(t.unique=!1)}}function buildPreMigrationIndexChangesMap(e){return buildPreMigrationIndexChangesMapFromDiffs(e.map(e=>e.diff))}function buildPreMigrationIndexChangesMapFromDiffs(e){let t=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)??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){if(i.kind===`index_added`){delete e[r];continue}i.kind===`index_modified`&&defineRecordEntry(e,r,n(i.before))}}async function captureMigrationRestrictionState(e,t,n){let r=new Map;for(let i of n){let n=await N(async(n,r)=>{let{tailordbTypes:a,nextPageToken:o}=await e.listTailorDBTypes({workspaceId:t,namespaceName:i,pageToken:n,pageSize:r});return[a,o]}),a=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=new Set;for(let n of e.diff.changes)t.add(n.tableName);return t}function getDeletedTableNames(e){let t=new Set;for(let n of e.diff.changes)n.kind===`table_removed`?t.add(n.tableName):n.kind===`table_renamed`&&t.add(n.previousTableName);return t}const Vo={created:new Set,updated:new Set,gqlPermissionsProcessed:new Set,reset(){this.created.clear(),this.updated.clear(),this.gqlPermissionsProcessed.clear()}},Ho={cache: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 R({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 buildSnapshotTypeManifest(e,t,n,r){let i=Ho.load(e).tables[t];if(!i)return;let a=n.find(t=>t.namespace===e.namespace),o=e.diff.changes.find(e=>e.kind===`table_scripts_modified`&&e.tableName===t);return generateTailorDBTypeManifestFromSnapshot(r?createPreMigrationSnapshotType(i,r,o):i,{suppressRecordEvents:!0,suppressGqlOperations:!0,namespaceGqlOperations:a?.config.gqlOperations})}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){let a=buildPreMigrationChangesMap([n]),o=buildPreMigrationIndexChangesMap([n]),s=getAffectedTableNames(n),c=new Set(Vo.created);for(let l of t.type.creates){let t=l.request.tailordbType?.name;if(!t||!s.has(t)||c.has(t))continue;let u=a.get(t),d=buildSnapshotTypeManifest(n,t,r,u);if(!d)continue;let f=structuredClone(l.request);f.tailordbType=d,u&&u.size>0&&f.tailordbType.schema?.fields&&applyPreMigrationFieldAdjustments(f.tailordbType.schema.fields,u);let p=o.get(t);p&&p.size>0&&f.tailordbType.schema?.indexes&&applyPreMigrationIndexAdjustments(f.tailordbType.schema.indexes,p),Vo.created.add(t),i.add(t),await e.createTailorDBType(f)}for(let l of t.type.creates){let t=l.request.tailordbType?.name;if(!t||!s.has(t)||!c.has(t))continue;let u=a.get(t),d=buildSnapshotTypeManifest(n,t,r,u);if(!d)continue;let f=structuredClone(d);u&&u.size>0&&f.schema?.fields&&applyPreMigrationFieldAdjustments(f.schema.fields,u);let p=o.get(t);p&&p.size>0&&f.schema?.indexes&&applyPreMigrationIndexAdjustments(f.schema.indexes,p),Vo.updated.add(t),i.add(t),await e.updateTailorDBType({workspaceId:l.request.workspaceId,namespaceName:l.request.namespaceName,tailordbType:f})}for(let c of t.type.updates){let t=c.request.tailordbType?.name;if(!t||!s.has(t))continue;let l=a.get(t),u=buildSnapshotTypeManifest(n,t,r,l);if(!u)continue;let d=structuredClone(c.request);d.tailordbType=u,l&&l.size>0&&d.tailordbType.schema?.fields&&applyPreMigrationFieldAdjustments(d.tailordbType.schema.fields,l);let f=o.get(t);f&&f.size>0&&d.tailordbType.schema?.indexes&&applyPreMigrationIndexAdjustments(d.tailordbType.schema.indexes,f),Vo.updated.add(t),i.add(t),await e.updateTailorDBType(d)}let l=new Set(Object.keys(Ho.load(n).tables)),permissionKey=e=>`${n.namespace}/${e}`,u=t.gqlPermission.creates.filter(e=>e.request.namespaceName===n.namespace&&l.has(e.name)&&!Vo.gqlPermissionsProcessed.has(permissionKey(e.name))),d=t.gqlPermission.updates.filter(e=>e.request.namespaceName===n.namespace&&l.has(e.name)&&!Vo.gqlPermissionsProcessed.has(permissionKey(e.name)));if(u.length+d.length>0){let a=new Set(u.map(e=>e.name)),o=t.type.creates.filter(e=>{let t=e.request.tailordbType?.name;return e.request.namespaceName===n.namespace&&t&&a.has(t)&&!Vo.created.has(t)});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;Vo.created.add(a),i.add(a);let s=structuredClone(t.request);s.tailordbType=o,await e.createTailorDBType(s)}await awaitAllSettledOrThrow([...u.map(t=>e.createTailorDBGQLPermission(t.request)),...d.map(t=>e.updateTailorDBGQLPermission(t.request))]);for(let e of[...u.map(e=>e.name),...d.map(e=>e.name)])Vo.gqlPermissionsProcessed.add(permissionKey(e))}}const Uo={types:new Set,gqlPermissions:new Set,reset(){this.types.clear(),this.gqlPermissions.clear()}};async function rollbackSingleMigrationAfterFailure(e,t,n,r,i){try{await rollbackSingleMigrationPrePhase(e,t,n,r,i)}catch(e){M.warn(`Failed to roll back migration ${t.namespace}/${formatMigrationNumber(t.number)}: ${e instanceof Error?e.message:String(e)}`)}}async function executeSingleMigrationPostPhase(e,t,n,r,i){let a=buildPreMigrationChangesMap([n]),o=buildPreMigrationIndexChangesMap([n]),s=new Set([...a.keys(),...o.keys()]),c=getAffectedTableNames(n);try{for(let a of t.type.creates){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 t.type.updates){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}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,d=new Set([...Object.keys(i.tables),...s?.keys()??[]]);for(let t of d)try{let l=i.tables[t],u=s?.get(t);if(s&&!u||c&&(!u||!acceptsMigrationWrites(u)))continue;let d=l?c?generateTailorDBTypeManifestFromSnapshot(l,{suppressRecordEvents:!0,suppressGqlOperations:!0,namespaceGqlOperations:a.config.gqlOperations}):generateTailorDBTypeManifestFromSnapshot(l,{subscribed:o.has(t),namespaceGqlOperations:a.config.gqlOperations}):u?.tailordbType?structuredClone(u.tailordbType):void 0;if(!d?.schema)continue;d.schema.settings??={};let f=d.schema.settings;c&&(f.bulkUpsert=!1,f.publishRecordEvents=!1,f.disableGqlOperations={create:!0,update:!0,delete:!0,read:!0}),!c&&u&&(f.bulkUpsert=u.bulkUpsert,f.publishRecordEvents=u.publishRecordEvents,f.disableGqlOperations=u.disableGqlOperations?{...u.disableGqlOperations}:void 0),await e.updateTailorDBType({workspaceId:n,namespaceName:r,tailordbType:d})}catch(e){if(!l)throw e;u??=e instanceof Error?e:Cn(e)}if(u!==void 0)throw u}function resolveMigrationSnapshotSettings(e,t,n){let r=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}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)??new Map,restricted:!0})}}async function restoreMigrationRestrictions(e,t,n,r,i,a){let o;for(let[s,c]of t){let t=r.find(e=>e.namespace===s);if(t)try{await rewriteRestrictedTables(e,{workspaceId:a,namespaceName:s,snapshot:c,input:t,executorUsedTables:i,settingsState:n?.get(s),restricted:!1,continueOnError:!0})}catch(e){o??=e instanceof Error?e:Cn(e)}}if(o!==void 0)throw o}async function executeSingleMigrationPostPhaseDeletions(e,t,n){let r=getDeletedTableNames(n);if(r.size>0){let n=t.gqlPermission.deletes.filter(e=>{let t=`${e.request.namespaceName}/${e.name}`;if(Uo.gqlPermissions.has(t))return!1;let n=e.name;return r.has(n)});for(let t of n)await e.deleteTailorDBGQLPermission(t.request),Uo.gqlPermissions.add(`${t.request.namespaceName}/${t.name}`);let i=t.type.deletes.filter(e=>{let t=e.name;return!t||Uo.types.has(t)?!1:r.has(t)});for(let t of i)await e.deleteTailorDBType(t.request),Uo.types.add(t.name)}}async function rollbackSingleMigrationPrePhase(e,t,n,r,i){if(t.number<=0||i.size===0)return;let a=reconstructSnapshotFromMigrations(t.migrationsDir,t.number-1);if(!a){M.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.`);return}let o=r.find(e=>e.namespace===t.namespace);M.warn(`Migration ${t.namespace}/${formatMigrationNumber(t.number)} failed; rolling back its pre-migration schema changes.`);let s=[...i].flatMap(e=>{let t=a.tables[e];return t?[{tableName:e,priorTable:t}]:[]}),c=[...i].filter(e=>!a.tables[e]);for(let{tableName:r,priorTable:i}of s)try{let r=generateTailorDBTypeManifestFromSnapshot(i,{suppressRecordEvents:!0,suppressGqlOperations:!0,namespaceGqlOperations:o?.config.gqlOperations});await e.updateTailorDBType({workspaceId:n,namespaceName:t.namespace,tailordbType:r})}catch(e){M.warn(`Failed to roll back 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){M.warn(`Failed to roll back table '${r}' in namespace '${t.namespace}': ${e instanceof Error?e.message:String(e)}`)}}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 N(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 N(async(r,i)=>{let{permissions:a,nextPageToken:o}=await e.listTailorDBGQLPermissions({workspaceId:t,namespaceName:n,pageToken:r,pageSize:i});return[a,o]})}async function fetchRemoteSchemaSnapshot(e,t,n){let[r,i]=await Promise.all([fetchRemoteTypes(e,t,n),fetchRemoteGqlPermissions(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 Wo=[`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 Wo)e[n]===!1&&(t[n]=!1);return definedWhenNotEmpty(t)}function appliedConfiguredDisabledGqlOperations(e,t){if(!e||!t)return;let n={};for(let r of Wo)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}}async function verifyRemoteSchema(e,t,n,r,i){let a=[];for(let{namespace:o,migrationsDir:s}of n){let n=await fetchRemoteMigrationState(e,resourceTrn(t,`tailordb`,o)),{metadataExists:c,number:l}=n;if(n.historyIdInvalid||l===null&&n.historyId!==null){a.push({namespace:o,remoteMigrationNumber:l??0,drifts:[],hasDrift:!1,checkpointMissingLocal:!0});continue}if(l===null){a.push({namespace:o,remoteMigrationNumber:0,drifts:[],hasDrift:!1,skipped:c?`no_migration_label`:`not_deployed`});continue}let u=getLatestMigrationNumber(s),d=reconstructSnapshotFromMigrations(s,0)?.rebaseline,f=d?n.historyId===d.historyId:n.historyId===null,p=d?n.historyId===d.replacedHistoryId:!1,m=d&&p&&l===d.replacedLatestMigration?{from:l,to:0,fromHistoryId:n.historyId,toHistoryId:d.historyId}:void 0;if(!f&&!m||l>u&&!m){let e=d&&p&&l<d.replacedLatestMigration?{replacedLatestMigration:d.replacedLatestMigration}:void 0;a.push({namespace:o,remoteMigrationNumber:l,drifts:[],hasDrift:!1,checkpointMissingLocal:!0,...e?{rebaselinePending:e}:{}});continue}let h=reconstructSnapshotFromMigrations(s,m?.to??l);if(!h){a.push({namespace:o,remoteMigrationNumber:l,drifts:[],hasDrift:!1,skipped:`no_snapshot`});continue}let[g,_]=await Promise.all([fetchRemoteTypes(e,t,o),fetchRemoteGqlPermissions(e,t,o)]),v=compareRemoteWithSnapshot(g,deployComparableSnapshot(h,g,namespaceGqlOperations(r,i,o)),_);a.push({namespace:o,remoteMigrationNumber:l,drifts:v,hasDrift:v.length>0,...m&&v.length===0?{checkpointRepair:m}:{}})}return a}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){M.info(`This may indicate:`),M.info(` - Another developer applied different migrations`,{mode:`plain`}),M.info(` - Manual schema changes were made directly`,{mode:`plain`}),M.info(` - Migration history is out of sync`,{mode:`plain`}),M.newline(),M.info(`To resolve:`),M.info(` - Run 'tailor tailordb migration status' to compare local vs remote.`,{mode:`plain`}),M.info(` - If remote is correct, update local tables and run 'migration generate'.`,{mode:`plain`}),M.info(` - If local migration history is correct, run 'migration sync <N>' to overwrite remote.`,{mode:`plain`}),M.info(` - If only bookkeeping is stale, run 'migration set <N>'.`,{mode:`plain`}),e&&isLikelyPreV2ScriptHashDrift(e)&&(M.newline(),M.info(`Every listed drift is '${Ao}'. Run 'migration sync <N>' above to add the missing hashes.`))}function hasRebaselinePending(e){return e.rebaselinePending!==void 0}function logMissingCheckpointGuidance(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);M.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}.`)}M.newline(),M.info(`To recover:`),M.info(` 1. Restore the pre-rebaseline migrations/ directory from git history (the commit before 'migration rebaseline' ran; rebaseline preserves committed files there).`,{mode:`plain`}),M.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`}),M.info(` 3. Switch back to the current migration files and deploy again — the automatic checkpoint reset to the new baseline then applies.`,{mode:`plain`})}t.length<e.length&&(t.length>0&&M.newline(),M.info(`Pull the latest migration files, or run 'tailor tailordb migration status' to compare.`))}function formatRemoteVerificationResults(e){let t=[];for(let n of e)n.hasDrift&&(t.push(`Namespace: ${n.namespace}`),t.push(` Remote migration: ${formatMigrationNumber(n.remoteMigrationNumber)}`),t.push(` Differences:`),t.push(formatSchemaDrifts(n.drifts)),t.push(``));return t.join(`
|
|
56
|
+
`).filter(e=>/error/i.test(e)).at(-1)?.trim()||`Migration workflow execution failed.`}async function getCurrentMigrationNumber(e,t,n){try{let r=resourceTrn(t,`tailordb`,n),{metadata:i}=await e.getMetadata({trn:r}),a=i?.labels[ya];return a?parseMigrationLabelNumber(a)??0:0}catch(e){if(Jt(e))return 0;throw e}}async function detectPendingMigrations(e,t,n,r,i){let a=[];for(let{namespace:o,migrationsDir:s}of n){let n=i?.get(o)??await getCurrentMigrationNumber(e,t,o),c=getMigrationFiles(s);for(let e of c){if(e.number<=n)continue;let t=getMigrationFilePath(s,e.number,`diff`);if(!U.existsSync(t))continue;let i=loadDiff(t),c=getMigrationFilePath(s,e.number,`migrate`),l=U.existsSync(c);if(i.requiresMigrationScript&&!l&&!i.scriptSkipped){let t={migrationNumber:e.number,namespace:o,configPath:r};throw R({code:`MIGRATION_SCRIPT_REQUIRED`,message:`Migration ${o}/${formatMigrationNumber(e.number)} requires a migration script but migrate.ts was not found.`,suggestion:`Add a script: ${formatMigrationScriptCommand(t)}\nOr record that no script is needed: ${formatMigrationScriptCommand({...t,noScript:!0})}`})}if(i.scriptSkipped){let t=`${o}/${formatMigrationNumber(e.number)}`;if(l)throw R({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: ${formatMigrationScriptCommand({migrationNumber:e.number,namespace:o,configPath:r})}\nOr keep the skip: delete migrate.ts`});M.info(`Migration ${t} runs without a script (skip acknowledged at ${i.scriptSkipped.acknowledgedAt}: ${i.scriptSkipped.reason})`)}a.push({number:e.number,scriptPath:c,hasScript:l,diffPath:t,namespace:o,migrationsDir:s,diff:i})}}return a.toSorted((e,t)=>e.namespace===t.namespace?e.number-t.number:e.namespace.localeCompare(t.namespace))}async function executeSingleMigration(e,t){let{client:n,workspaceId:r,invoker:i,env:a,configDir:o,appName:s,appId:c}=e,l=await executeMigrationAsWorkflow({client:n,workspaceId:r,code:(await bundleMigrationScript(t.scriptPath,t.namespace,t.number,a,o)).bundledCode,namespace:t.namespace,migrationNumber:t.number,invoker:i,appName:s,appId:c});return{namespace:t.namespace,migrationNumber:t.number,success:l.success,logs:l.logs,error:l.error}}async function updateMigrationLabel(e,t,n,r,i){await writeMetadataLabelsDirect(e,{trn:resourceTrn(t,`tailordb`,n),labels:{[ya]:sanitizeMigrationLabel(r),...i?{[ba]:i}:{}},remove:i?void 0:[ba]})}async function executeMigrations(e,t){let n=t.filter(e=>e.hasScript);if(n.length===0)return;let r=groupMigrationsByNamespace(n);for(let[t,n]of r){let r=e.dbConfig[t]?.migration,i=getMigrationMachineUser(r,e.machineUsers);if(!i)throw R({code:`MACHINE_USER_REQUIRED`,message:`No machine user available for migration execution in namespace '${t}'.`,suggestion:`Either configure 'migration.machineUser' in db config or define machine users in auth config.`});let a=Xn(Ie,{namespace:e.authNamespace,machineUserName:i}),o={client:e.client,workspaceId:e.workspaceId,invoker:a,env:e.env,configDir:e.configDir,appName:e.appName,appId:e.appId};M.info(`Using machine user: ${j.bold(i)} for namespace '${t}'`);for(let e of n){let t=`${e.namespace}/${formatMigrationNumber(e.number)}`,n=spinner().start(`Executing migration ${t} (this can take a while)...`),r=await executeSingleMigration(o,e);if(r.success)n.succeed(`Migration ${t} completed successfully`),r.logs&&r.logs.trim()&&M.log(`Logs:\n${r.logs}`);else throw n.fail(`Migration ${t} failed`),r.logs&&M.error(`Logs:\n${r.logs}`),R({code:`MIGRATION_FAILED`,message:r.error??`Migration failed`})}}}function getMigrationMachineUser(e,t){if(e?.machineUser)return e.machineUser;if(t&&t.length>0)return t[0]}function groupMigrationsByNamespace(e){let t=new Map;for(let n of e){let e=t.get(n.namespace)??[];e.push(n),t.set(n.namespace,e)}return t}function defineRecordEntry(e,t,n){Object.defineProperty(e,t,{value:n,enumerable:!0,writable:!0,configurable:!0})}const qo=new Set([`field_added`,`field_modified`,`field_type_modified`,`field_removed`,`field_renamed`]);function isPreMigrationFieldChange(e){return qo.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=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)??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)})}function relaxFieldsForPreMigration(e,t,n){for(let[r,i]of t){if(i.kind===`field_removed`){defineRecordEntry(e,r,n.toField(i.before));continue}if(i.kind===`field_renamed`){defineRecordEntry(e,i.previousFieldName,n.toField(i.before));let t=e[r];t&&(i.after.required&&(t.required=!1),(i.after.unique??!1)&&(t.unique=!1));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,n.toField(i.before));continue}let{before:o,after:s}=i;n.adjustNestedMembers?.(t,i),!o.required&&s.required&&(a.required=!1),!(o.unique??!1)&&(s.unique??!1)&&(a.unique=!1);let c=o.allowedValues??[],l=s.allowedValues??[],u=new Set(l.map(e=>e.value));if(c.filter(e=>!u.has(e.value)).length>0){let e=new Map;for(let t of c)e.set(t.value,t.description??``);for(let t of l)e.has(t.value)||e.set(t.value,t.description??``);a.allowedValues=Array.from(e.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=k(getProtoNestedMember(e,r.path.slice(0,-1))?.fields,`parent of removed nested member "${t}" missing from the Pre-phase field`),i=k(r.path.at(-1),`removed nested member path is empty`),a=processNestedFieldsFromSnapshot({[i]:r.before});defineRecordEntry(n,i,k(a[i],`restored nested member "${t}" missing`))}}function relaxRenamedNestedMembers(e,t){for(let n of t){let t=getProtoNestedMember(e,n.path);t?.required&&(t.required=!1),t?.unique&&(t.unique=!1)}}function buildPreMigrationIndexChangesMap(e){return buildPreMigrationIndexChangesMapFromDiffs(e.map(e=>e.diff))}function buildPreMigrationIndexChangesMapFromDiffs(e){let t=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)??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){if(i.kind===`index_added`){delete e[r];continue}i.kind===`index_modified`&&defineRecordEntry(e,r,n(i.before))}}async function captureMigrationRestrictionState(e,t,n){let r=new Map;for(let i of n){let n=await N(async(n,r)=>{let{tailordbTypes:a,nextPageToken:o}=await e.listTailorDBTypes({workspaceId:t,namespaceName:i,pageToken:n,pageSize:r});return[a,o]}),a=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=new Set;for(let n of e.diff.changes)t.add(n.tableName);return t}function getDeletedTableNames(e){let t=new Set;for(let n of e.diff.changes)n.kind===`table_removed`?t.add(n.tableName):n.kind===`table_renamed`&&t.add(n.previousTableName);return t}const Jo={created:new Set,updated:new Set,gqlPermissionsProcessed:new Set,reset(){this.created.clear(),this.updated.clear(),this.gqlPermissionsProcessed.clear()}},Yo={cache: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 R({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 buildSnapshotTypeManifest(e,t,n,r){let i=Yo.load(e).tables[t];if(!i)return;let a=n.find(t=>t.namespace===e.namespace),o=e.diff.changes.find(e=>e.kind===`table_scripts_modified`&&e.tableName===t);return generateTailorDBTypeManifestFromSnapshot(r?createPreMigrationSnapshotType(i,r,o):i,{suppressRecordEvents:!0,suppressGqlOperations:!0,namespaceGqlOperations:a?.config.gqlOperations})}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){let a=buildPreMigrationChangesMap([n]),o=buildPreMigrationIndexChangesMap([n]),s=getAffectedTableNames(n),c=new Set(Jo.created);for(let l of t.type.creates){let t=l.request.tailordbType?.name;if(!t||!s.has(t)||c.has(t))continue;let u=a.get(t),d=buildSnapshotTypeManifest(n,t,r,u);if(!d)continue;let f=structuredClone(l.request);f.tailordbType=d,u&&u.size>0&&f.tailordbType.schema?.fields&&applyPreMigrationFieldAdjustments(f.tailordbType.schema.fields,u);let p=o.get(t);p&&p.size>0&&f.tailordbType.schema?.indexes&&applyPreMigrationIndexAdjustments(f.tailordbType.schema.indexes,p),Jo.created.add(t),i.add(t),await e.createTailorDBType(f)}for(let l of t.type.creates){let t=l.request.tailordbType?.name;if(!t||!s.has(t)||!c.has(t))continue;let u=a.get(t),d=buildSnapshotTypeManifest(n,t,r,u);if(!d)continue;let f=structuredClone(d);u&&u.size>0&&f.schema?.fields&&applyPreMigrationFieldAdjustments(f.schema.fields,u);let p=o.get(t);p&&p.size>0&&f.schema?.indexes&&applyPreMigrationIndexAdjustments(f.schema.indexes,p),Jo.updated.add(t),i.add(t),await e.updateTailorDBType({workspaceId:l.request.workspaceId,namespaceName:l.request.namespaceName,tailordbType:f})}for(let c of t.type.updates){let t=c.request.tailordbType?.name;if(!t||!s.has(t))continue;let l=a.get(t),u=buildSnapshotTypeManifest(n,t,r,l);if(!u)continue;let d=structuredClone(c.request);d.tailordbType=u,l&&l.size>0&&d.tailordbType.schema?.fields&&applyPreMigrationFieldAdjustments(d.tailordbType.schema.fields,l);let f=o.get(t);f&&f.size>0&&d.tailordbType.schema?.indexes&&applyPreMigrationIndexAdjustments(d.tailordbType.schema.indexes,f),Jo.updated.add(t),i.add(t),await e.updateTailorDBType(d)}let l=new Set(Object.keys(Yo.load(n).tables)),permissionKey=e=>`${n.namespace}/${e}`,u=t.gqlPermission.creates.filter(e=>e.request.namespaceName===n.namespace&&l.has(e.name)&&!Jo.gqlPermissionsProcessed.has(permissionKey(e.name))),d=t.gqlPermission.updates.filter(e=>e.request.namespaceName===n.namespace&&l.has(e.name)&&!Jo.gqlPermissionsProcessed.has(permissionKey(e.name)));if(u.length+d.length>0){let a=new Set(u.map(e=>e.name)),o=t.type.creates.filter(e=>{let t=e.request.tailordbType?.name;return e.request.namespaceName===n.namespace&&t&&a.has(t)&&!Jo.created.has(t)});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;Jo.created.add(a),i.add(a);let s=structuredClone(t.request);s.tailordbType=o,await e.createTailorDBType(s)}await awaitAllSettledOrThrow([...u.map(t=>e.createTailorDBGQLPermission(t.request)),...d.map(t=>e.updateTailorDBGQLPermission(t.request))]);for(let e of[...u.map(e=>e.name),...d.map(e=>e.name)])Jo.gqlPermissionsProcessed.add(permissionKey(e))}}const Xo={types:new Set,gqlPermissions:new Set,reset(){this.types.clear(),this.gqlPermissions.clear()}};async function rollbackSingleMigrationAfterFailure(e,t,n,r,i){try{await rollbackSingleMigrationPrePhase(e,t,n,r,i)}catch(e){M.warn(`Failed to roll back migration ${t.namespace}/${formatMigrationNumber(t.number)}: ${e instanceof Error?e.message:String(e)}`)}}async function executeSingleMigrationPostPhase(e,t,n,r,i){let a=buildPreMigrationChangesMap([n]),o=buildPreMigrationIndexChangesMap([n]),s=new Set([...a.keys(),...o.keys()]),c=getAffectedTableNames(n);try{for(let a of t.type.creates){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 t.type.updates){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}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,d=new Set([...Object.keys(i.tables),...s?.keys()??[]]);for(let t of d)try{let l=i.tables[t],u=s?.get(t);if(s&&!u||c&&(!u||!acceptsMigrationWrites(u)))continue;let d=l?c?generateTailorDBTypeManifestFromSnapshot(l,{suppressRecordEvents:!0,suppressGqlOperations:!0,namespaceGqlOperations:a.config.gqlOperations}):generateTailorDBTypeManifestFromSnapshot(l,{subscribed:o.has(t),namespaceGqlOperations:a.config.gqlOperations}):u?.tailordbType?structuredClone(u.tailordbType):void 0;if(!d?.schema)continue;d.schema.settings??={};let f=d.schema.settings;c&&(f.bulkUpsert=!1,f.publishRecordEvents=!1,f.disableGqlOperations={create:!0,update:!0,delete:!0,read:!0}),!c&&u&&(f.bulkUpsert=u.bulkUpsert,f.publishRecordEvents=u.publishRecordEvents,f.disableGqlOperations=u.disableGqlOperations?{...u.disableGqlOperations}:void 0),await e.updateTailorDBType({workspaceId:n,namespaceName:r,tailordbType:d})}catch(e){if(!l)throw e;u??=e instanceof Error?e:Tn(e)}if(u!==void 0)throw u}function resolveMigrationSnapshotSettings(e,t,n){let r=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}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)??new Map,restricted:!0})}}async function restoreMigrationRestrictions(e,t,n,r,i,a){let o;for(let[s,c]of t){let t=r.find(e=>e.namespace===s);if(t)try{await rewriteRestrictedTables(e,{workspaceId:a,namespaceName:s,snapshot:c,input:t,executorUsedTables:i,settingsState:n?.get(s),restricted:!1,continueOnError:!0})}catch(e){o??=e instanceof Error?e:Tn(e)}}if(o!==void 0)throw o}async function executeSingleMigrationPostPhaseDeletions(e,t,n){let r=getDeletedTableNames(n);if(r.size>0){let n=t.gqlPermission.deletes.filter(e=>{let t=`${e.request.namespaceName}/${e.name}`;if(Xo.gqlPermissions.has(t))return!1;let n=e.name;return r.has(n)});for(let t of n)await e.deleteTailorDBGQLPermission(t.request),Xo.gqlPermissions.add(`${t.request.namespaceName}/${t.name}`);let i=t.type.deletes.filter(e=>{let t=e.name;return!t||Xo.types.has(t)?!1:r.has(t)});for(let t of i)await e.deleteTailorDBType(t.request),Xo.types.add(t.name)}}async function rollbackSingleMigrationPrePhase(e,t,n,r,i){if(t.number<=0||i.size===0)return;let a=reconstructSnapshotFromMigrations(t.migrationsDir,t.number-1);if(!a){M.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.`);return}let o=r.find(e=>e.namespace===t.namespace);M.warn(`Migration ${t.namespace}/${formatMigrationNumber(t.number)} failed; rolling back its pre-migration schema changes.`);let s=[...i].flatMap(e=>{let t=a.tables[e];return t?[{tableName:e,priorTable:t}]:[]}),c=[...i].filter(e=>!a.tables[e]);for(let{tableName:r,priorTable:i}of s)try{let r=generateTailorDBTypeManifestFromSnapshot(i,{suppressRecordEvents:!0,suppressGqlOperations:!0,namespaceGqlOperations:o?.config.gqlOperations});await e.updateTailorDBType({workspaceId:n,namespaceName:t.namespace,tailordbType:r})}catch(e){M.warn(`Failed to roll back 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){M.warn(`Failed to roll back table '${r}' in namespace '${t.namespace}': ${e instanceof Error?e.message:String(e)}`)}}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 N(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 N(async(r,i)=>{let{permissions:a,nextPageToken:o}=await e.listTailorDBGQLPermissions({workspaceId:t,namespaceName:n,pageToken:r,pageSize:i});return[a,o]})}async function fetchRemoteSchemaSnapshot(e,t,n){let[r,i]=await Promise.all([fetchRemoteTypes(e,t,n),fetchRemoteGqlPermissions(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 Zo=[`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 Zo)e[n]===!1&&(t[n]=!1);return definedWhenNotEmpty(t)}function appliedConfiguredDisabledGqlOperations(e,t){if(!e||!t)return;let n={};for(let r of Zo)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}}async function verifyRemoteSchema(e,t,n,r,i){let a=[];for(let{namespace:o,migrationsDir:s}of n){let n=await fetchRemoteMigrationState(e,resourceTrn(t,`tailordb`,o)),{metadataExists:c,number:l}=n;if(n.historyIdInvalid||l===null&&n.historyId!==null){a.push({namespace:o,remoteMigrationNumber:l??0,drifts:[],hasDrift:!1,checkpointMissingLocal:!0});continue}if(l===null){a.push({namespace:o,remoteMigrationNumber:0,drifts:[],hasDrift:!1,skipped:c?`no_migration_label`:`not_deployed`});continue}let u=getLatestMigrationNumber(s),d=reconstructSnapshotFromMigrations(s,0)?.rebaseline,f=d?n.historyId===d.historyId:n.historyId===null,p=d?n.historyId===d.replacedHistoryId:!1,m=d&&p&&l===d.replacedLatestMigration?{from:l,to:0,fromHistoryId:n.historyId,toHistoryId:d.historyId}:void 0;if(!f&&!m||l>u&&!m){let e=d&&p&&l<d.replacedLatestMigration?{replacedLatestMigration:d.replacedLatestMigration}:void 0;a.push({namespace:o,remoteMigrationNumber:l,drifts:[],hasDrift:!1,checkpointMissingLocal:!0,...e?{rebaselinePending:e}:{}});continue}let h=reconstructSnapshotFromMigrations(s,m?.to??l);if(!h){a.push({namespace:o,remoteMigrationNumber:l,drifts:[],hasDrift:!1,skipped:`no_snapshot`});continue}let[g,_]=await Promise.all([fetchRemoteTypes(e,t,o),fetchRemoteGqlPermissions(e,t,o)]),v=compareRemoteWithSnapshot(g,deployComparableSnapshot(h,g,namespaceGqlOperations(r,i,o)),_);a.push({namespace:o,remoteMigrationNumber:l,drifts:v,hasDrift:v.length>0,...m&&v.length===0?{checkpointRepair:m}:{}})}return a}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){M.info(`This may indicate:`),M.info(` - Another developer applied different migrations`,{mode:`plain`}),M.info(` - Manual schema changes were made directly`,{mode:`plain`}),M.info(` - Migration history is out of sync`,{mode:`plain`}),M.newline(),M.info(`To resolve:`),M.info(` - Run 'tailor tailordb migration status' to compare local vs remote.`,{mode:`plain`}),M.info(` - If remote is correct, update local tables and run 'migration generate'.`,{mode:`plain`}),M.info(` - If local migration history is correct, run 'migration sync <N>' to overwrite remote.`,{mode:`plain`}),M.info(` - If only bookkeeping is stale, run 'migration set <N>'.`,{mode:`plain`}),e&&isLikelyPreV2ScriptHashDrift(e)&&(M.newline(),M.info(`Every listed drift is '${Lo}'. Run 'migration sync <N>' above to add the missing hashes.`))}function hasRebaselinePending(e){return e.rebaselinePending!==void 0}function logMissingCheckpointGuidance(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);M.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}.`)}M.newline(),M.info(`To recover:`),M.info(` 1. Restore the pre-rebaseline migrations/ directory from git history (the commit before 'migration rebaseline' ran; rebaseline preserves committed files there).`,{mode:`plain`}),M.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`}),M.info(` 3. Switch back to the current migration files and deploy again — the automatic checkpoint reset to the new baseline then applies.`,{mode:`plain`})}t.length<e.length&&(t.length>0&&M.newline(),M.info(`Pull the latest migration files, or run 'tailor tailordb migration status' to compare.`))}function formatRemoteVerificationResults(e){let t=[];for(let n of e)n.hasDrift&&(t.push(`Namespace: ${n.namespace}`),t.push(` Remote migration: ${formatMigrationNumber(n.remoteMigrationNumber)}`),t.push(` Differences:`),t.push(formatSchemaDrifts(n.drifts)),t.push(``));return t.join(`
|
|
57
57
|
`)}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(`
|
|
58
|
-
`)}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])}async function validateAndDetectMigrations(e,t,n,r,i,a){let o=getNamespacesWithMigrations(r,V.dirname(r.path)),s=[],c=[],l=Object.create(null);if(o.length>0){for(let{namespace:e,migrationsDir:t}of o)assertValidMigrationFiles(t,e),l[e]=reconstructSnapshotFromMigrations(t)?.rebaseline?.historyId??null;if(!i){let i=await checkMigrationDiffs(n,o);if(i.some(e=>e.hasDiff))throw M.error(`Schema changes detected that are not in migration files:`),M.log(formatMigrationCheckResults(i)),M.newline(),M.info(`Run 'tailor tailordb migration generate' to create migration files.`),M.info(`Or use '--no-schema-check' to skip this check.`),R({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 s=await verifyRemoteSchema(e,t,o,r,a);c=s.flatMap(e=>e.checkpointRepair?[{namespace:e.namespace,...e.checkpointRepair}]:[]);let l=s.filter(e=>e.checkpointMissingLocal);if(l.length>0){M.error(`Remote migration checkpoint is not in the local migration history:`);for(let e of l)M.log(` ${e.namespace}: ${formatMigrationNumber(e.remoteMigrationNumber)}`);throw M.newline(),logMissingCheckpointGuidance(l),R({code:`MIGRATION_CHECKPOINT_UNKNOWN`,message:`Remote migration checkpoint verification failed`})}if(s.some(e=>e.hasDrift))throw M.error(`Remote schema drift detected:`),M.log(formatRemoteVerificationResults(s)),M.newline(),logRemoteDriftGuidance(s),M.newline(),M.info(`Use '--no-schema-check' to skip this check (not recommended).`),R({code:`MIGRATION_REMOTE_DRIFT`,message:`Remote schema verification failed`});for(let e of c)M.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.`)}let u=new Map(c.map(e=>[e.namespace,e.to]));if(s=await detectPendingMigrations(e,t,o,r.path,u),s.length>0){M.newline();let e=s.filter(e=>e.hasScript),t=s.filter(e=>!e.hasScript);M.info(`${s.length} pending migration(s) will be applied:`),t.length>0&&M.info(` • ${t.length} schema change(s) (applied automatically with schema deployment)`,{mode:`plain`}),e.length>0&&M.info(` • ${e.length} data migration(s) (requires migration script execution)`,{mode:`plain`})}}return{pendingMigrations:s,checkpointRepairs:c,namespacesWithMigrations:o,migrationFileState:captureMigrationFileState(o),migrationHistoryIds:l}}async function reconcileMigrationLabels(e,t,n,r){for(let{namespace:i,migrationsDir:a}of n){if(getMigrationFiles(a).length===0)continue;let n=getLatestMigrationNumber(a),o=r[i]??null,s=await fetchRemoteMigrationState(e,resourceTrn(t,`tailordb`,i)).catch(()=>null),c=s?.number??null;s&&c===n&&s.historyId===o||(await updateMigrationLabel(e,t,i,n,o??void 0),s?M.info(`Migration label for namespace ${i} reconciled: ${describeMigrationCheckpoint(c)} → ${formatMigrationNumber(n)}.`):M.info(`Migration label for namespace ${i} reconciled to ${formatMigrationNumber(n)}.`))}}function buildMigrationContextForScripts(e,t,n){let r=t.application.authService;if(!r)throw R({code:`AUTH_CONFIG_REQUIRED`,message:`Auth configuration is required to execute migration scripts.`});let i={};for(let e of n)e.namespace in i||(i[e.namespace]=t.config.db?.[e.namespace]);return{client:e,workspaceId:t.workspaceId,authNamespace:r.config.name,machineUsers:r.config.machineUsers?Object.keys(r.config.machineUsers):void 0,dbConfig:i,env:t.config.env??{},configDir:V.dirname(t.config.path),appName:t.application.name,appId:t.application.id}}async function validateTailorDBMigrationState(e,t){let{context:n}=t;if(n.migrationTestBaselines){let e=captureMigrationFileState(getNamespacesWithMigrations(n.config,V.dirname(n.config.path)));if(!migrationFileStatesEqual(n.migrationFileState,e))throw R({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:{}}}let r=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),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 R({code:`DEPLOY_PLAN_STALE`,message:`Remote migration checkpoint repair changed after deployment planning.`,suggestion:`Run the deployment again to review the updated repair.`});if(!migrationFileStatesEqual(n.migrationFileState,i.migrationFileState))throw R({code:`DEPLOY_PLAN_STALE`,message:`Migration files changed after deployment planning.`,suggestion:`Run the deployment again to create a fresh plan.`});return i}async function preflightTailorDB(e,t){await validateTailorDBMigrationState(e,t)}function includeUndeletedTables(e,t,n){let r=[...getDeletedTableNames(n)].flatMap(e=>{let n=t?.tables[e];return n?[[e,n]]:[]});return{...e,tables:{...e.tables,...Object.fromEntries(r)}}}function describeMigrationCheckpoint(e){return e==null?`<unset>`:formatMigrationNumber(e)}async function applyTailorDB(e,t,n=`create-update`){let{changeSet:r,context:i}=t;if(n===`create-update`){let{pendingMigrations:n,checkpointRepairs:a,namespacesWithMigrations:o,migrationHistoryIds:s}=await validateTailorDBMigrationState(e,t);for(let t of a)await updateMigrationLabel(e,i.workspaceId,t.namespace,t.to,t.toHistoryId),M.info(`Migration checkpoint for namespace ${t.namespace} reset: ${formatMigrationNumber(t.from)} → 0000.`);if(n.length>0){Vo.reset(),Uo.reset(),Ho.reset();let t=new Set(n.map(e=>e.namespace)),a=await captureMigrationRestrictionState(e,i.workspaceId,t);await executeServicesCreation(e,r);let isOutsideMigrations=e=>e!==void 0&&!t.has(e),o=new Map,c=new Map,l=new Set;for(let e of n){let t=o.get(e.namespace);(!t||e.number<t.number)&&o.set(e.namespace,e);let n=c.get(e.namespace)??new Set;for(let t of getDeletedTableNames(e))n.add(t);c.set(e.namespace,n);for(let t of Object.keys(Ho.load(e).tables))l.add(`${e.namespace}/${t}`)}let u=new Map;for(let[e,t]of o){let n=reconstructSnapshotFromMigrations(t.migrationsDir,t.number-1);if(!n)throw R({code:`MIGRATION_HISTORY_INVALID`,message:`Cannot reconstruct the schema state before migration ${formatMigrationNumber(t.number)} for namespace "${e}"`});u.set(e,n)}let d=new Set,f=new Set([...r.gqlPermission.creates,...r.gqlPermission.updates].filter(e=>{let n=e.request.namespaceName;return i.noSchemaCheck&&n!==void 0&&t.has(n)&&!l.has(`${n}/${e.name}`)}).map(e=>`${e.request.namespaceName}/${e.name}`));try{for(let t of r.type.creates){let n=t.request.namespaceName;if(isOutsideMigrations(n)){await e.createTailorDBType(t.request);continue}let r=t.request.tailordbType?.name;if(!n||!r)continue;let a=u.get(n)?.tables[r];if(!a){i.noSchemaCheck&&!l.has(`${n}/${r}`)&&d.add(`${n}/${r}`);continue}if(c.get(n)?.has(r))continue;let o=i.tailorDBInputs.find(e=>e.namespace===n);Vo.created.add(r),await e.createTailorDBType({workspaceId:t.request.workspaceId,namespaceName:n,tailordbType:generateTailorDBTypeManifestFromSnapshot(a,{suppressRecordEvents:!0,suppressGqlOperations:!0,namespaceGqlOperations:o?.config.gqlOperations})})}for(let t of r.type.updates)isOutsideMigrations(t.request.namespaceName)&&await e.updateTailorDBType(t.request)}catch(e){handleOptionalToRequiredError(e,[`Run 'tailor tailordb migration generate' to create migration files.`,`Migration scripts allow you to handle existing data before applying the schema change.`])}await Promise.all([...r.gqlPermission.creates.filter(e=>isOutsideMigrations(e.request.namespaceName)).map(t=>e.createTailorDBGQLPermission(t.request)),...r.gqlPermission.updates.filter(e=>isOutsideMigrations(e.request.namespaceName)).map(t=>e.updateTailorDBGQLPermission(t.request))]);let p=n.filter(e=>e.hasScript),m=p.length>0?buildMigrationContextForScripts(e,i,p):void 0;p.length>0&&(M.info(`Executing ${p.length} data migration(s)...`),M.newline());let h=new Map(u),g=new Map(a),_=new Map([...o].map(([e,t])=>[e,{number:t.number>0?t.number-1:null,historyId:s[e]??null}])),v;try{await applyMigrationRestrictions(e,u,a,i.tailorDBInputs,i.executorUsedTables,i.workspaceId);for(let t of n){let n=new Set;try{await z(`apply.tailorDB.migration.prePhase`,()=>executeSingleMigrationPrePhase(e,r,t,i.tailorDBInputs,n)),t.hasScript&&m&&await z(`apply.tailorDB.migration.script`,()=>executeMigrations(m,[t]))}catch(r){throw await rollbackSingleMigrationAfterFailure(e,t,i.workspaceId,i.tailorDBInputs,n),r}try{await z(`apply.tailorDB.migration.postPhase`,()=>executeSingleMigrationPostPhase(e,r,t,i.tailorDBInputs,n))}catch(r){throw await rollbackSingleMigrationAfterFailure(e,t,i.workspaceId,i.tailorDBInputs,n),r}let a=h.get(t.namespace),o=g.get(t.namespace),c=Ho.load(t);h.set(t.namespace,c);let l=s[t.namespace]??null;try{await updateMigrationLabel(e,i.workspaceId,t.namespace,t.number,l??void 0)}catch(n){let r;try{r=await fetchRemoteMigrationState(e,resourceTrn(i.workspaceId,`tailordb`,t.namespace))}catch(e){throw M.warn(`Could not verify migration checkpoint ${t.namespace}/${formatMigrationNumber(t.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 o=r.number??void 0,s=r.historyIdInvalid||r.historyId!==l?`${describeMigrationCheckpoint(r.number)} in a different migration history`:o!==void 0&&o>t.number?formatMigrationNumber(o):void 0;if(s!==void 0)throw h.delete(t.namespace),R({code:`MIGRATION_CHECKPOINT_CONFLICT`,message:`Migration checkpoint ${t.namespace}/${formatMigrationNumber(t.number)} advanced concurrently to ${s}. Leaving the post-migration schema unchanged and aborting this deployment.`,cause:n});if(o!==t.number)throw h.set(t.namespace,includeUndeletedTables(c,a,t)),M.warn(`Migration checkpoint ${t.namespace}/${formatMigrationNumber(t.number)} could not be confirmed after its update failed; remote remains at ${describeMigrationCheckpoint(o)}. Leaving the post-migration schema unchanged to avoid rolling back a concurrent deployment. Repair the checkpoint before retrying.`),n}_.set(t.namespace,{number:t.number,historyId:l});let u=i.tailorDBInputs.find(e=>e.namespace===t.namespace);if(u){let e=resolveMigrationSnapshotSettings(c,u,i.executorUsedTables);for(let[t,n]of o??[])a?.tables[t]||e.set(t,n);g.set(t.namespace,e)}try{await executeSingleMigrationPostPhaseDeletions(e,r,t)}catch(e){throw M.warn(`Migration checkpoint ${t.namespace}/${formatMigrationNumber(t.number)} was committed, but post-checkpoint cleanup failed. The leftover resources remain locked. Remove them manually before the next deployment; remote schema verification will fail closed until then.`),e}}p.length>0&&(M.newline(),M.success(`All data migrations completed successfully.`))}catch(e){v={error:e}}for(let[t,n]of _)try{let r=await fetchRemoteMigrationState(e,resourceTrn(i.workspaceId,`tailordb`,t));if(r.number===n.number&&!r.historyIdInvalid&&r.historyId===n.historyId)continue;h.delete(t);let a=R({code:`MIGRATION_CHECKPOINT_CONFLICT`,message:`Migration checkpoint ${t}/${describeMigrationCheckpoint(n.number)} advanced concurrently to ${describeMigrationCheckpoint(r.number)}. Skipping restoration for this namespace and aborting this deployment.`});v?M.warn(`${a.message} The original migration error is reported below.`):v={error:a}}catch(e){h.delete(t);let r=R({code:`MIGRATION_CHECKPOINT_UNVERIFIED`,message:`Could not verify ownership of migration checkpoint ${t}/${describeMigrationCheckpoint(n.number)} before restoring table settings: ${e instanceof Error?e.message:String(e)}. Skipping restoration for this namespace and aborting this deployment.`});v?M.warn(`${r.message} The original migration error is reported below.`):v={error:r}}try{await restoreMigrationRestrictions(e,h,g,i.tailorDBInputs,i.executorUsedTables,i.workspaceId)}catch(e){if(!v)throw e;M.warn(`Could not restore every TailorDB table after the migration failed: ${e instanceof Error?e.message:String(e)}. The original migration error is reported below.`)}if(v)throw v.error;for(let t of r.type.creates){let n=t.request.namespaceName,r=t.request.tailordbType?.name;n&&r&&d.has(`${n}/${r}`)&&await e.createTailorDBType(t.request)}await Promise.all([...r.gqlPermission.creates.filter(e=>f.has(`${e.request.namespaceName}/${e.name}`)).map(t=>e.createTailorDBGQLPermission(t.request)),...r.gqlPermission.updates.filter(e=>f.has(`${e.request.namespaceName}/${e.name}`)).map(t=>e.updateTailorDBGQLPermission(t.request))]);let y=r.gqlPermission.deletes.filter(e=>{let t=`${e.request.namespaceName}/${e.name}`;return!Uo.gqlPermissions.has(t)});y.length>0&&await Promise.all(y.map(t=>e.deleteTailorDBGQLPermission(t.request))),await Promise.all(r.type.deletes.filter(e=>isOutsideMigrations(e.request.namespaceName)&&!Uo.types.has(e.name)).map(t=>e.deleteTailorDBType(t.request))),await Promise.all([...r.type.creates,...r.type.updates,...r.type.unchanged].filter(e=>e.metaRequest&&!Uo.types.has(e.name)).flatMap(t=>t.metaRequest?[writeMetadataLabels(e,t.metaRequest)]:[]))}else{await Promise.all([...r.service.creates.map(async t=>{await e.createTailorDBService(t.request),await writeMetadataLabels(e,t.metaRequest)}),...r.service.updates.map(t=>writeMetadataLabels(e,t.metaRequest))]);try{for(let t of r.type.creates)await e.createTailorDBType(t.request),await writeMetadataLabels(e,t.metaRequest);for(let t of r.type.updates)await e.updateTailorDBType(t.request),await writeMetadataLabels(e,t.metaRequest);await Promise.all(r.type.unchanged.flatMap(t=>t.metaRequest?[writeMetadataLabels(e,t.metaRequest)]:[]))}catch(e){handleOptionalToRequiredError(e,[`Run 'tailor tailordb migration generate' to create migration files.`,`Migration scripts allow you to handle existing data before applying the schema change.`])}await Promise.all([...r.gqlPermission.creates.map(t=>e.createTailorDBGQLPermission(t.request)),...r.gqlPermission.updates.map(t=>e.updateTailorDBGQLPermission(t.request))]),await Promise.all(r.gqlPermission.deletes.map(t=>e.deleteTailorDBGQLPermission(t.request))),await Promise.all(r.type.deletes.map(t=>e.deleteTailorDBType(t.request)))}o.length>0&&(i.noSchemaCheck||n.length===0)&&await reconcileMigrationLabels(e,i.workspaceId,o,s)}else n===`delete-resources`?(await Promise.all(r.gqlPermission.deletes.map(t=>e.deleteTailorDBGQLPermission(t.request))),await Promise.all(r.type.deletes.map(t=>e.deleteTailorDBType(t.request)))):await Promise.all(r.service.deletes.map(t=>e.deleteTailorDBService(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 Set(n.map(itemKey)),a=t.map(t=>({action:e,symbol:Wi[e],name:t.name,labels:i.has(itemKey(t))?[`table`,`gqlPermission`]:[`table`],namespace:t.request?.namespaceName})),o=n.filter(e=>!r.has(itemKey(e))).map(t=>({action:e,symbol:Wi[e],name:t.name,labels:[`gqlPermission`],namespace:t.request?.namespaceName}));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)]}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$1(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}const Go={disableGqlOperations:{create:!1,update:!1,delete:!1,read:!1},emptyExpression:``,numericStringPaths:new Set([`schema.fields.*.serial.start`,`schema.fields.*.serial.maxValue`,`schema.settings.defaultQueryLimitSize`,`schema.settings.maxBulkUpsertSize`])};function normalizeComparableTailorDBType(e){let t=normalizeProtoConfig(toComparableProtoJson(et,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===Go.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$1(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,Go.disableGqlOperations)))return r}function matchesNumericStringPath(e){let t=e.map(e=>String(e)).join(`.`);return[...Go.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 planTailorDB(e){let{client:t,workspaceId:n,application:r,forRemoval:i,config:a,noSchemaCheck:o,forceApplyAll:s=!1}=e,c=[],l=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=l?.get(e.namespace);c.push(n?{...t,types:n.tables}:t)}let u=i?[]:Object.values(await r.executorService?.loadExecutors()??{}),d=new Set(e.executorUsedTailorDBTables??[]);for(let e of u)subscribesToEvents(e)&&e.trigger.kind===`tailordb`&&d.add(e.trigger.tableName);let f=new Map;for(let e of c)f.set(e.namespace,e.types);let p=e.migrationTestBaselines;if(l){for(let e of l.keys())if(!c.some(t=>t.namespace===e))throw R({code:`MIGRATION_TEST_SNAPSHOT_INVALID`,message:`Migration test snapshot targets unknown TailorDB namespace "${e}".`});let e=new Map;for(let t of c)for(let n of Object.keys(t.types)){let r=e.get(n);if(r)throw R({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 m=getNamespacesWithMigrations(a,V.dirname(a.path)),{namespacesWithMigrations:h,migrationFileState:g,checkpointRepairs:_}=i?{namespacesWithMigrations:[],migrationFileState:{},checkpointRepairs:[]}:p?{namespacesWithMigrations:m,migrationFileState:captureMigrationFileState(m),checkpointRepairs:[]}:await validateAndDetectMigrations(t,n,f,a,o??!1,c),{changeSet:v,conflicts:y,unmanaged:b,resourceOwners:x}=await planServices(t,n,r.name,r.id,c),S=v.deletes.map(e=>e.name),[C,w]=await Promise.all([planTypes(t,n,c,d,S,void 0,s,{appName:r.name,appId:r.id,dependentApps:e.dependentApps,runAppIds:e.runAppIds}),planGqlPermissions(t,n,c,S,s)]);return C.creates.sort(Jt),C.updates.sort(Jt),C.deletes.sort(Jt),{changeSet:{service:v,type:C,gqlPermission:w},conflicts:y,unmanaged:b,resourceOwners:x,context:{workspaceId:n,application:r,tailorDBInputs:c,executorUsedTables:d,config:a,noSchemaCheck:o??!1,...p?{migrationTestBaselines:p}:{},namespacesWithMigrations:h,migrationFileState:g,checkpointRepairs:_}}}async function planServices(e,t,n,r,i){let a=createChangeSet(`TailorDB services`),o=[],s=[],c=new Set,l=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=l[e.namespace],c=await buildMetaRequest({trn:resourceTrn(t,`tailordb`,e.namespace),appName:n,appId:r});i?(trackDesiredResourceOwnership({labels:i.allLabels,ownerLabel:i.label,appName:n,appId:r,resourceType:`TailorDB service`,resourceName:e.namespace,conflicts:o,unmanaged:s})&&hasMatchingSdkVersion(i.allLabels,c.labels)&&areTailorDBServicesEqual(i.resource,e)?a.unchanged.push({name:e.namespace}):a.updates.push({name:e.namespace,metaRequest:c}),delete l[e.namespace]):a.creates.push({name:e.namespace,request:{workspaceId:t,namespaceName:e.namespace,defaultTimezone:`UTC`},metaRequest:c})}return Object.entries(l).forEach(([e])=>{let i=l[e];trackRemainingResourceOwner({labels:i?.allLabels,ownerLabel:i?.label,appName:n,appId:r,resourceOwners:c})&&a.deletes.push({name:e,request:{workspaceId:t,namespaceName:e}})}),{changeSet:a,conflicts:o,unmanaged:s,resourceOwners:c}}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=>N(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:Ki.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);l?(!o&&areNormalizedEqual(normalizeComparableTailorDBType(l),normalizeComparableTailorDBType(s))?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)}),i.delete(n)):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=>N(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=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);r.has(s)?(!i&&u&&areNormalizedEqual(normalizeComparableGqlPermission(u.permission),normalizeComparableGqlPermission(l))?a.unchanged.push({name:s}):a.updates.push({name:s,request:{workspaceId:t,namespaceName:e.namespace,typeName:s,permission:l}}),r.delete(s)):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=>({resourceType:`workflow`,resourceName:t.name,run:()=>e.deleteWorkflow({workspaceId:t.workspaceId,workflowId:t.workflowId})}))),await deleteAllSettled(t.jobFunctionDeletes.map(t=>({resourceType:`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=k(e[r],`operation missing at index`),a=t.reason;if(!(a instanceof K&&a.code===G.NotFound)){if(a instanceof K&&a.code===G.FailedPrecondition){M.warn(`Skipped deleting ${i.resourceType} "${i.resourceName}" because it is still referenced.`);return}n.push(Cn(a))}});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=new Set,a=new Map){let o={},s=t.creates[0]||t.updates[0]||t.deletes[0];if(!s)return o;let{workspaceId:c}=s,l=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 At(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=parseDuration(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 Ko={workflowNames:new Set};function isSubscribed(e,t){return e.workflowNames.has(t)}function subscribedWorkflowJobNames(e){let{workflows:t,mainJobDeps:n,isSubscribed:r}=e,i=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=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=new Map;for(let e of a)s.set(e,resolvePublishEvents({explicit:i.get(e),subscribed:o.has(e),conflict:Ki.workflowJob(e)}));return s}function collectStaleJobFunctionNames(e,t){let n=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=new Set,s={}){let c=createChangeSet(`Workflows`),l=[],u=[],d=new Set,f=new Set,p=new Set,m=s.execution??Ko,{dependentApps:h,runAppIds:g}=s,everyJobDeclaresPublishEvents=e=>{let t=a[i[e]?.mainJob.name??``]??[],n=s.jobPublishEvents??new Map;return t.length>0&&t.every(e=>n.has(e))},_=await fetchExistingJobFunctions(e,t),v=resolveJobPublishEvents({workflows:i,mainJobDeps:a,subscribers:s.jobExecution??Ko,explicit:s.jobPublishEvents??new Map}),y=collectStaleJobFunctionNames(_,v),b=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)});for(let e of Object.values(i)){let i=b[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 d=a[e.mainJob.name];if(!d)throw R({code:`WORKFLOW_MAIN_JOB_NOT_FOUND`,message:`Job "${e.mainJob.name}" (mainJob of workflow "${e.name}") was not found.`,details:`Possible causes:
|
|
58
|
+
`)}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])}async function validateAndDetectMigrations(e,t,n,r,i,a){let o=getNamespacesWithMigrations(r,V.dirname(r.path)),s=[],c=[],l=Object.create(null);if(o.length>0){for(let{namespace:e,migrationsDir:t}of o)assertValidMigrationFiles(t,e),l[e]=reconstructSnapshotFromMigrations(t)?.rebaseline?.historyId??null;if(!i){let i=await checkMigrationDiffs(n,o);if(i.some(e=>e.hasDiff))throw M.error(`Schema changes detected that are not in migration files:`),M.log(formatMigrationCheckResults(i)),M.newline(),M.info(`Run 'tailor tailordb migration generate' to create migration files.`),M.info(`Or use '--no-schema-check' to skip this check.`),R({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 s=await verifyRemoteSchema(e,t,o,r,a);c=s.flatMap(e=>e.checkpointRepair?[{namespace:e.namespace,...e.checkpointRepair}]:[]);let l=s.filter(e=>e.checkpointMissingLocal);if(l.length>0){M.error(`Remote migration checkpoint is not in the local migration history:`);for(let e of l)M.log(` ${e.namespace}: ${formatMigrationNumber(e.remoteMigrationNumber)}`);throw M.newline(),logMissingCheckpointGuidance(l),R({code:`MIGRATION_CHECKPOINT_UNKNOWN`,message:`Remote migration checkpoint verification failed`})}if(s.some(e=>e.hasDrift))throw M.error(`Remote schema drift detected:`),M.log(formatRemoteVerificationResults(s)),M.newline(),logRemoteDriftGuidance(s),M.newline(),M.info(`Use '--no-schema-check' to skip this check (not recommended).`),R({code:`MIGRATION_REMOTE_DRIFT`,message:`Remote schema verification failed`});for(let e of c)M.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.`)}let u=new Map(c.map(e=>[e.namespace,e.to]));if(s=await detectPendingMigrations(e,t,o,r.path,u),s.length>0){M.newline();let e=s.filter(e=>e.hasScript),t=s.filter(e=>!e.hasScript);M.info(`${s.length} pending migration(s) will be applied:`),t.length>0&&M.info(` • ${t.length} schema change(s) (applied automatically with schema deployment)`,{mode:`plain`}),e.length>0&&M.info(` • ${e.length} data migration(s) (requires migration script execution)`,{mode:`plain`})}}return{pendingMigrations:s,checkpointRepairs:c,namespacesWithMigrations:o,migrationFileState:captureMigrationFileState(o),migrationHistoryIds:l}}async function reconcileMigrationLabels(e,t,n,r){for(let{namespace:i,migrationsDir:a}of n){if(getMigrationFiles(a).length===0)continue;let n=getLatestMigrationNumber(a),o=r[i]??null,s=await fetchRemoteMigrationState(e,resourceTrn(t,`tailordb`,i)).catch(()=>null),c=s?.number??null;s&&c===n&&s.historyId===o||(await updateMigrationLabel(e,t,i,n,o??void 0),s?M.info(`Migration label for namespace ${i} reconciled: ${describeMigrationCheckpoint(c)} → ${formatMigrationNumber(n)}.`):M.info(`Migration label for namespace ${i} reconciled to ${formatMigrationNumber(n)}.`))}}function buildMigrationContextForScripts(e,t,n){let r=t.application.authService;if(!r)throw R({code:`AUTH_CONFIG_REQUIRED`,message:`Auth configuration is required to execute migration scripts.`});let i={};for(let e of n)e.namespace in i||(i[e.namespace]=t.config.db?.[e.namespace]);return{client:e,workspaceId:t.workspaceId,authNamespace:r.config.name,machineUsers:r.config.machineUsers?Object.keys(r.config.machineUsers):void 0,dbConfig:i,env:t.config.env??{},configDir:V.dirname(t.config.path),appName:t.application.name,appId:t.application.id}}async function validateTailorDBMigrationState(e,t){let{context:n}=t;if(n.migrationTestBaselines){let e=captureMigrationFileState(getNamespacesWithMigrations(n.config,V.dirname(n.config.path)));if(!migrationFileStatesEqual(n.migrationFileState,e))throw R({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:{}}}let r=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),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 R({code:`DEPLOY_PLAN_STALE`,message:`Remote migration checkpoint repair changed after deployment planning.`,suggestion:`Run the deployment again to review the updated repair.`});if(!migrationFileStatesEqual(n.migrationFileState,i.migrationFileState))throw R({code:`DEPLOY_PLAN_STALE`,message:`Migration files changed after deployment planning.`,suggestion:`Run the deployment again to create a fresh plan.`});return i}async function preflightTailorDB(e,t){await validateTailorDBMigrationState(e,t)}function includeUndeletedTables(e,t,n){let r=[...getDeletedTableNames(n)].flatMap(e=>{let n=t?.tables[e];return n?[[e,n]]:[]});return{...e,tables:{...e.tables,...Object.fromEntries(r)}}}function describeMigrationCheckpoint(e){return e==null?`<unset>`:formatMigrationNumber(e)}async function applyTailorDB(e,t,n=`create-update`){let{changeSet:r,context:i}=t;if(n===`create-update`){let{pendingMigrations:n,checkpointRepairs:a,namespacesWithMigrations:o,migrationHistoryIds:s}=await validateTailorDBMigrationState(e,t);for(let t of a)await updateMigrationLabel(e,i.workspaceId,t.namespace,t.to,t.toHistoryId),M.info(`Migration checkpoint for namespace ${t.namespace} reset: ${formatMigrationNumber(t.from)} → 0000.`);if(n.length>0){Jo.reset(),Xo.reset(),Yo.reset();let t=new Set(n.map(e=>e.namespace)),a=await captureMigrationRestrictionState(e,i.workspaceId,t);await executeServicesCreation(e,r);let isOutsideMigrations=e=>e!==void 0&&!t.has(e),o=new Map,c=new Map,l=new Set;for(let e of n){let t=o.get(e.namespace);(!t||e.number<t.number)&&o.set(e.namespace,e);let n=c.get(e.namespace)??new Set;for(let t of getDeletedTableNames(e))n.add(t);c.set(e.namespace,n);for(let t of Object.keys(Yo.load(e).tables))l.add(`${e.namespace}/${t}`)}let u=new Map;for(let[e,t]of o){let n=reconstructSnapshotFromMigrations(t.migrationsDir,t.number-1);if(!n)throw R({code:`MIGRATION_HISTORY_INVALID`,message:`Cannot reconstruct the schema state before migration ${formatMigrationNumber(t.number)} for namespace "${e}"`});u.set(e,n)}let d=new Set,f=new Set([...r.gqlPermission.creates,...r.gqlPermission.updates].filter(e=>{let n=e.request.namespaceName;return i.noSchemaCheck&&n!==void 0&&t.has(n)&&!l.has(`${n}/${e.name}`)}).map(e=>`${e.request.namespaceName}/${e.name}`));try{for(let t of r.type.creates){let n=t.request.namespaceName;if(isOutsideMigrations(n)){await e.createTailorDBType(t.request);continue}let r=t.request.tailordbType?.name;if(!n||!r)continue;let a=u.get(n)?.tables[r];if(!a){i.noSchemaCheck&&!l.has(`${n}/${r}`)&&d.add(`${n}/${r}`);continue}if(c.get(n)?.has(r))continue;let o=i.tailorDBInputs.find(e=>e.namespace===n);Jo.created.add(r),await e.createTailorDBType({workspaceId:t.request.workspaceId,namespaceName:n,tailordbType:generateTailorDBTypeManifestFromSnapshot(a,{suppressRecordEvents:!0,suppressGqlOperations:!0,namespaceGqlOperations:o?.config.gqlOperations})})}for(let t of r.type.updates)isOutsideMigrations(t.request.namespaceName)&&await e.updateTailorDBType(t.request)}catch(e){handleOptionalToRequiredError(e,[`Run 'tailor tailordb migration generate' to create migration files.`,`Migration scripts allow you to handle existing data before applying the schema change.`])}await Promise.all([...r.gqlPermission.creates.filter(e=>isOutsideMigrations(e.request.namespaceName)).map(t=>e.createTailorDBGQLPermission(t.request)),...r.gqlPermission.updates.filter(e=>isOutsideMigrations(e.request.namespaceName)).map(t=>e.updateTailorDBGQLPermission(t.request))]);let p=n.filter(e=>e.hasScript),m=p.length>0?buildMigrationContextForScripts(e,i,p):void 0;p.length>0&&(M.info(`Executing ${p.length} data migration(s)...`),M.newline());let h=new Map(u),g=new Map(a),_=new Map([...o].map(([e,t])=>[e,{number:t.number>0?t.number-1:null,historyId:s[e]??null}])),v;try{await applyMigrationRestrictions(e,u,a,i.tailorDBInputs,i.executorUsedTables,i.workspaceId);for(let t of n){let n=new Set;try{await z(`apply.tailorDB.migration.prePhase`,()=>executeSingleMigrationPrePhase(e,r,t,i.tailorDBInputs,n)),t.hasScript&&m&&await z(`apply.tailorDB.migration.script`,()=>executeMigrations(m,[t]))}catch(r){throw await rollbackSingleMigrationAfterFailure(e,t,i.workspaceId,i.tailorDBInputs,n),r}try{await z(`apply.tailorDB.migration.postPhase`,()=>executeSingleMigrationPostPhase(e,r,t,i.tailorDBInputs,n))}catch(r){throw await rollbackSingleMigrationAfterFailure(e,t,i.workspaceId,i.tailorDBInputs,n),r}let a=h.get(t.namespace),o=g.get(t.namespace),c=Yo.load(t);h.set(t.namespace,c);let l=s[t.namespace]??null;try{await updateMigrationLabel(e,i.workspaceId,t.namespace,t.number,l??void 0)}catch(n){let r;try{r=await fetchRemoteMigrationState(e,resourceTrn(i.workspaceId,`tailordb`,t.namespace))}catch(e){throw M.warn(`Could not verify migration checkpoint ${t.namespace}/${formatMigrationNumber(t.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 o=r.number??void 0,s=r.historyIdInvalid||r.historyId!==l?`${describeMigrationCheckpoint(r.number)} in a different migration history`:o!==void 0&&o>t.number?formatMigrationNumber(o):void 0;if(s!==void 0)throw h.delete(t.namespace),R({code:`MIGRATION_CHECKPOINT_CONFLICT`,message:`Migration checkpoint ${t.namespace}/${formatMigrationNumber(t.number)} advanced concurrently to ${s}. Leaving the post-migration schema unchanged and aborting this deployment.`,cause:n});if(o!==t.number)throw h.set(t.namespace,includeUndeletedTables(c,a,t)),M.warn(`Migration checkpoint ${t.namespace}/${formatMigrationNumber(t.number)} could not be confirmed after its update failed; remote remains at ${describeMigrationCheckpoint(o)}. Leaving the post-migration schema unchanged to avoid rolling back a concurrent deployment. Repair the checkpoint before retrying.`),n}_.set(t.namespace,{number:t.number,historyId:l});let u=i.tailorDBInputs.find(e=>e.namespace===t.namespace);if(u){let e=resolveMigrationSnapshotSettings(c,u,i.executorUsedTables);for(let[t,n]of o??[])a?.tables[t]||e.set(t,n);g.set(t.namespace,e)}try{await executeSingleMigrationPostPhaseDeletions(e,r,t)}catch(e){throw M.warn(`Migration checkpoint ${t.namespace}/${formatMigrationNumber(t.number)} was committed, but post-checkpoint cleanup failed. The leftover resources remain locked. Remove them manually before the next deployment; remote schema verification will fail closed until then.`),e}}p.length>0&&(M.newline(),M.success(`All data migrations completed successfully.`))}catch(e){v={error:e}}for(let[t,n]of _)try{let r=await fetchRemoteMigrationState(e,resourceTrn(i.workspaceId,`tailordb`,t));if(r.number===n.number&&!r.historyIdInvalid&&r.historyId===n.historyId)continue;h.delete(t);let a=R({code:`MIGRATION_CHECKPOINT_CONFLICT`,message:`Migration checkpoint ${t}/${describeMigrationCheckpoint(n.number)} advanced concurrently to ${describeMigrationCheckpoint(r.number)}. Skipping restoration for this namespace and aborting this deployment.`});v?M.warn(`${a.message} The original migration error is reported below.`):v={error:a}}catch(e){h.delete(t);let r=R({code:`MIGRATION_CHECKPOINT_UNVERIFIED`,message:`Could not verify ownership of migration checkpoint ${t}/${describeMigrationCheckpoint(n.number)} before restoring table settings: ${e instanceof Error?e.message:String(e)}. Skipping restoration for this namespace and aborting this deployment.`});v?M.warn(`${r.message} The original migration error is reported below.`):v={error:r}}try{await restoreMigrationRestrictions(e,h,g,i.tailorDBInputs,i.executorUsedTables,i.workspaceId)}catch(e){if(!v)throw e;M.warn(`Could not restore every TailorDB table after the migration failed: ${e instanceof Error?e.message:String(e)}. The original migration error is reported below.`)}if(v)throw v.error;for(let t of r.type.creates){let n=t.request.namespaceName,r=t.request.tailordbType?.name;n&&r&&d.has(`${n}/${r}`)&&await e.createTailorDBType(t.request)}await Promise.all([...r.gqlPermission.creates.filter(e=>f.has(`${e.request.namespaceName}/${e.name}`)).map(t=>e.createTailorDBGQLPermission(t.request)),...r.gqlPermission.updates.filter(e=>f.has(`${e.request.namespaceName}/${e.name}`)).map(t=>e.updateTailorDBGQLPermission(t.request))]);let y=r.gqlPermission.deletes.filter(e=>{let t=`${e.request.namespaceName}/${e.name}`;return!Xo.gqlPermissions.has(t)});y.length>0&&await Promise.all(y.map(t=>e.deleteTailorDBGQLPermission(t.request))),await Promise.all(r.type.deletes.filter(e=>isOutsideMigrations(e.request.namespaceName)&&!Xo.types.has(e.name)).map(t=>e.deleteTailorDBType(t.request))),await Promise.all([...r.type.creates,...r.type.updates,...r.type.unchanged].filter(e=>e.metaRequest&&!Xo.types.has(e.name)).flatMap(t=>t.metaRequest?[writeMetadataLabels(e,t.metaRequest)]:[]))}else{await Promise.all([...r.service.creates.map(async t=>{await e.createTailorDBService(t.request),await writeMetadataLabels(e,t.metaRequest)}),...r.service.updates.map(t=>writeMetadataLabels(e,t.metaRequest))]);try{for(let t of r.type.creates)await e.createTailorDBType(t.request),await writeMetadataLabels(e,t.metaRequest);for(let t of r.type.updates)await e.updateTailorDBType(t.request),await writeMetadataLabels(e,t.metaRequest);await Promise.all(r.type.unchanged.flatMap(t=>t.metaRequest?[writeMetadataLabels(e,t.metaRequest)]:[]))}catch(e){handleOptionalToRequiredError(e,[`Run 'tailor tailordb migration generate' to create migration files.`,`Migration scripts allow you to handle existing data before applying the schema change.`])}await Promise.all([...r.gqlPermission.creates.map(t=>e.createTailorDBGQLPermission(t.request)),...r.gqlPermission.updates.map(t=>e.updateTailorDBGQLPermission(t.request))]),await Promise.all(r.gqlPermission.deletes.map(t=>e.deleteTailorDBGQLPermission(t.request))),await Promise.all(r.type.deletes.map(t=>e.deleteTailorDBType(t.request)))}o.length>0&&(i.noSchemaCheck||n.length===0)&&await reconcileMigrationLabels(e,i.workspaceId,o,s)}else n===`delete-resources`?(await Promise.all(r.gqlPermission.deletes.map(t=>e.deleteTailorDBGQLPermission(t.request))),await Promise.all(r.type.deletes.map(t=>e.deleteTailorDBType(t.request)))):await Promise.all(r.service.deletes.map(t=>e.deleteTailorDBService(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 Set(n.map(itemKey)),a=t.map(t=>({action:e,symbol:Xi[e],name:t.name,labels:i.has(itemKey(t))?[`table`,`gqlPermission`]:[`table`],namespace:t.request?.namespaceName})),o=n.filter(e=>!r.has(itemKey(e))).map(t=>({action:e,symbol:Xi[e],name:t.name,labels:[`gqlPermission`],namespace:t.request?.namespaceName}));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)]}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$1(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}const Qo={disableGqlOperations:{create:!1,update:!1,delete:!1,read:!1},emptyExpression:``,numericStringPaths:new Set([`schema.fields.*.serial.start`,`schema.fields.*.serial.maxValue`,`schema.settings.defaultQueryLimitSize`,`schema.settings.maxBulkUpsertSize`])};function normalizeComparableTailorDBType(e){let t=normalizeProtoConfig(toComparableProtoJson(et,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===Qo.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$1(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,Qo.disableGqlOperations)))return r}function matchesNumericStringPath(e){let t=e.map(e=>String(e)).join(`.`);return[...Qo.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 planTailorDB(e){let{client:t,workspaceId:n,application:r,forRemoval:i,config:a,noSchemaCheck:o,forceApplyAll:s=!1}=e,c=[],l=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=l?.get(e.namespace);c.push(n?{...t,types:n.tables}:t)}let u=i?[]:Object.values(await r.executorService?.loadExecutors()??{}),d=new Set(e.executorUsedTailorDBTables??[]);for(let e of u)subscribesToEvents(e)&&e.trigger.kind===`tailordb`&&d.add(e.trigger.tableName);let f=new Map;for(let e of c)f.set(e.namespace,e.types);let p=e.migrationTestBaselines;if(l){for(let e of l.keys())if(!c.some(t=>t.namespace===e))throw R({code:`MIGRATION_TEST_SNAPSHOT_INVALID`,message:`Migration test snapshot targets unknown TailorDB namespace "${e}".`});let e=new Map;for(let t of c)for(let n of Object.keys(t.types)){let r=e.get(n);if(r)throw R({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 m=getNamespacesWithMigrations(a,V.dirname(a.path)),{namespacesWithMigrations:h,migrationFileState:g,checkpointRepairs:_}=i?{namespacesWithMigrations:[],migrationFileState:{},checkpointRepairs:[]}:p?{namespacesWithMigrations:m,migrationFileState:captureMigrationFileState(m),checkpointRepairs:[]}:await validateAndDetectMigrations(t,n,f,a,o??!1,c),{changeSet:v,conflicts:y,unmanaged:b,resourceOwners:x}=await planServices(t,n,r.name,r.id,c),S=v.deletes.map(e=>e.name),[C,w]=await Promise.all([planTypes(t,n,c,d,S,void 0,s,{appName:r.name,appId:r.id,dependentApps:e.dependentApps,runAppIds:e.runAppIds}),planGqlPermissions(t,n,c,S,s)]);return C.creates.sort(Rt),C.updates.sort(Rt),C.deletes.sort(Rt),{changeSet:{service:v,type:C,gqlPermission:w},conflicts:y,unmanaged:b,resourceOwners:x,context:{workspaceId:n,application:r,tailorDBInputs:c,executorUsedTables:d,config:a,noSchemaCheck:o??!1,...p?{migrationTestBaselines:p}:{},namespacesWithMigrations:h,migrationFileState:g,checkpointRepairs:_}}}async function planServices(e,t,n,r,i){let a=createChangeSet(`TailorDB services`),o=[],s=[],c=new Set,l=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=l[e.namespace],c=await buildMetaRequest({trn:resourceTrn(t,`tailordb`,e.namespace),appName:n,appId:r});i?(trackDesiredResourceOwnership({labels:i.allLabels,ownerLabel:i.label,appName:n,appId:r,resourceType:`TailorDB service`,resourceName:e.namespace,conflicts:o,unmanaged:s})&&hasMatchingSdkVersion(i.allLabels,c.labels)&&areTailorDBServicesEqual(i.resource,e)?a.unchanged.push({name:e.namespace}):a.updates.push({name:e.namespace,metaRequest:c}),delete l[e.namespace]):a.creates.push({name:e.namespace,request:{workspaceId:t,namespaceName:e.namespace,defaultTimezone:`UTC`},metaRequest:c})}return Object.entries(l).forEach(([e])=>{let i=l[e];trackRemainingResourceOwner({labels:i?.allLabels,ownerLabel:i?.label,appName:n,appId:r,resourceOwners:c})&&a.deletes.push({name:e,request:{workspaceId:t,namespaceName:e}})}),{changeSet:a,conflicts:o,unmanaged:s,resourceOwners:c}}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=>N(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:Qi.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);l?(!o&&areNormalizedEqual(normalizeComparableTailorDBType(l),normalizeComparableTailorDBType(s))?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)}),i.delete(n)):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=>N(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=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);r.has(s)?(!i&&u&&areNormalizedEqual(normalizeComparableGqlPermission(u.permission),normalizeComparableGqlPermission(l))?a.unchanged.push({name:s}):a.updates.push({name:s,request:{workspaceId:t,namespaceName:e.namespace,typeName:s,permission:l}}),r.delete(s)):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=>({resourceType:`workflow`,resourceName:t.name,run:()=>e.deleteWorkflow({workspaceId:t.workspaceId,workflowId:t.workflowId})}))),await deleteAllSettled(t.jobFunctionDeletes.map(t=>({resourceType:`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=k(e[r],`operation missing at index`),a=t.reason;if(!(a instanceof K&&a.code===G.NotFound)){if(a instanceof K&&a.code===G.FailedPrecondition){M.warn(`Skipped deleting ${i.resourceType} "${i.resourceName}" because it is still referenced.`);return}n.push(Tn(a))}});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=new Set,a=new Map){let o={},s=t.creates[0]||t.updates[0]||t.deletes[0];if(!s)return o;let{workspaceId:c}=s,l=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 Mt(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=parseDuration(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 $o={workflowNames:new Set};function isSubscribed(e,t){return e.workflowNames.has(t)}function subscribedWorkflowJobNames(e){let{workflows:t,mainJobDeps:n,isSubscribed:r}=e,i=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=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=new Map;for(let e of a)s.set(e,resolvePublishEvents({explicit:i.get(e),subscribed:o.has(e),conflict:Qi.workflowJob(e)}));return s}function collectStaleJobFunctionNames(e,t){let n=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=new Set,s={}){let c=createChangeSet(`Workflows`),l=[],u=[],d=new Set,f=new Set,p=new Set,m=s.execution??$o,{dependentApps:h,runAppIds:g}=s,everyJobDeclaresPublishEvents=e=>{let t=a[i[e]?.mainJob.name??``]??[],n=s.jobPublishEvents??new Map;return t.length>0&&t.every(e=>n.has(e))},_=await fetchExistingJobFunctions(e,t),v=resolveJobPublishEvents({workflows:i,mainJobDeps:a,subscribers:s.jobExecution??$o,explicit:s.jobPublishEvents??new Map}),y=collectStaleJobFunctionNames(_,v),b=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)});for(let e of Object.values(i)){let i=b[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 d=a[e.mainJob.name];if(!d)throw R({code:`WORKFLOW_MAIN_JOB_NOT_FOUND`,message:`Job "${e.mainJob.name}" (mainJob of workflow "${e.name}") was not found.`,details:`Possible causes:
|
|
59
59
|
- The job is not exported as a named export
|
|
60
|
-
- 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}", ... })`});d.forEach(e=>p.add(e));let _={...e,publishEvents:resolvePublishEvents({explicit:e.publishEvents,subscribed:isSubscribed(m,e.name),conflict:Ki.workflow(e.name)})};if(i){if(trackDesiredResourceOwnership({labels:i.allLabels,ownerLabel:i.label,appName:n,appId:r,resourceType:`Workflow`,resourceName:e.name,conflicts:l,unmanaged:u})&&hasMatchingSdkVersion(i.allLabels,s.labels)&&canTreatWorkflowAsUnchanged({existing:i.resource,workflow:_,usedJobNames:d,unchangedJobFunctions:o,staleJobFunctionNames:y})){c.unchanged.push({name:e.name,metaRequest:s});for(let e of d)f.add(e)}else c.updates.push({name:e.name,workspaceId:t,workflow:_,usedJobNames:d,metaRequest:s});delete b[e.name]}else c.creates.push({name:e.name,workspaceId:t,workflow:_,usedJobNames:d,metaRequest:s})}let x=[];Object.values(b).forEach(e=>{if(!e)return;let i=trackRemainingResourceOwner({labels:e.allLabels,ownerLabel:e.label,appName:n,appId:r,resourceOwners:d}),a=getExistingWorkflowJobNames(e.resource);i?x.push({name:e.resource.name,workspaceId:t,workflowId:e.resource.id,usedJobNames:a,deletableJobNames:[]}):a.forEach(e=>p.add(e))});let S=await planWorkflowJobFunctionDeletes({client:e,workspaceId:t,appName:n,appId:r,existingJobFunctionNames:[..._.keys()],retainedWorkflowJobNames:p,resourceOwners:d}),C=new Set(S.map(e=>e.jobFunctionName));for(let e of x)c.deletes.push({...e,deletableJobNames:e.usedJobNames.filter(e=>!p.has(e)&&C.has(e))});return{changeSet:c,conflicts:l,unmanaged:u,resourceOwners:d,appName:n,appId:r,unchangedWorkflowJobNames:f,jobFunctionDeletes:S,jobFunctionPublishEvents:v}}async function fetchExistingJobFunctions(e,t){let n=await At(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,appName:r,appId:i,existingJobFunctionNames:a,retainedWorkflowJobNames:o,resourceOwners:s}=e,c=a.filter(e=>!o.has(e));return(await Promise.all(c.map(async e=>{let{metadata:a}=await t.getMetadata({trn:resourceTrn(n,`workflow_job_function`,e)});return trackRemainingResourceOwner({labels:a?.labels,ownerLabel:a?.labels[`sdk-name`],appName:r,appId:i,resourceOwners:s})?{workspaceId:n,jobFunctionName:e}:void 0}))).filter(e=>e!==void 0)}function formatWorkflowChangeEntries(e,t){return formatChangeEntriesWithFunctionRegistry(`workflow`,e,t,e=>`usedJobNames`in e?e.usedJobNames.map(e=>workflowJobFunctionName(e)):[])}function canTreatWorkflowAsUnchanged(e){let{existing:t,workflow:n,usedJobNames:r,unchangedJobFunctions:i,staleJobFunctionNames:a}=e;return!r.every(e=>i.has(e))||r.some(e=>a.has(e))?!1:areWorkflowsEqual(t,n,r)}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 R({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 Yt(declaredKey(e),e.matchType)}function validatePolicy(e){if(declaredKey(e).endsWith(`*`))throw R({code:`WORKFLOW_EXECUTION_POLICY_INVALID`,message:`Invalid workflow execution policy "${e.name}": ${zt}`});let t=rn.safeParse({name:e.name,key:toPlatformExecutionPolicyKey(e),concurrencyPolicy:e.concurrencyPolicy});if(!t.success)throw R({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=[],s=[],c=new Set,l=Object.values(i);for(let e of l)validatePolicy(e);let u=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)}),d=new Set;for(let e of l){if(d.has(e.name))throw R({code:`WORKFLOW_EXECUTION_POLICY_DUPLICATE`,message:`Duplicate workflow execution policy name "${e.name}". Each policy must have a unique name within the workspace.`});d.add(e.name);let i=await buildMetaRequest({trn:resourceTrn(t,`workflow_job_function_execution_policy`,e.name),appName:n,appId:r}),c=u[e.name];if(c){let l=trackDesiredResourceOwnership({labels:c.allLabels,ownerLabel:c.label,appName:n,appId:r,resourceType:`Workflow execution policy`,resourceName:e.name,conflicts:o,unmanaged:s}),d=c.resource.executionPolicyKey,f=toPlatformExecutionPolicyKey(e),p=normalizeComparableConcurrency(c.resource.concurrencyPolicy),m=normalizeComparableConcurrency(e.concurrencyPolicy);l&&hasMatchingSdkVersion(c.allLabels,i.labels)&&d===f&&areNormalizedEqual(p,m)?a.unchanged.push({name:e.name}):d===f?a.updates.push({name:e.name,workspaceId:t,policy:e,metaRequest:i}):a.replaces.push({name:e.name,workspaceId:t,policy:e,metaRequest:i}),delete u[e.name]}else a.creates.push({name:e.name,workspaceId:t,policy:e,metaRequest:i})}for(let[e,i]of Object.entries(u))i&&trackRemainingResourceOwner({labels:i.allLabels,ownerLabel:i.label,appName:n,appId:r,resourceOwners:c})&&a.deletes.push({name:e,workspaceId:t});return{changeSet:a,conflicts:o,unmanaged:s,resourceOwners:c}}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,...n}=e;return n}async function applyDeploymentPlans(e,t,n){let forEachDeployment=async e=>{for(let t of n)await e(t)},step=(e,t)=>z(e,()=>forEachDeployment(t));await z(`apply.preflight`,async()=>{await forEachDeployment(t=>preflightTailorDB(e,t.tailorDB))}),await withMetadataWriteBatch(e,async e=>{await z(`apply.createUpdateServices`,async()=>{await step(`apply.secretManager.createUpdate`,t=>applySecretManager(e,t.secretManager,`create-update`,t.application)),await step(`apply.functionRegistry.createUpdate`,n=>applyFunctionRegistry(e,t,n.functionRegistry,`create-update`)),await step(`apply.staticWebsite.createUpdate`,t=>applyStaticWebsite(e,t.staticWebsite,`create-update`)),await step(`apply.aiGateway.createUpdate`,t=>applyAIGateway(e,t.aiGateway,`create-update`)),await step(`apply.idp.createUpdate`,t=>applyIdP(e,t.idp,`create-update`)),await step(`apply.auth.createUpdatePrerequisites`,t=>applyAuth(e,t.auth,`create-update-prerequisites`)),await step(`apply.tailorDB.createUpdate`,t=>applyTailorDB(e,t.tailorDB,`create-update`)),await step(`apply.auth.createUpdateDependents`,t=>applyAuth(e,t.auth,`create-update-dependents`)),await step(`apply.pipeline.createUpdate`,t=>applyPipeline(e,t.pipeline,`create-update`))}),await z(`apply.deleteSubgraphResources`,async()=>{await forEachDeployment(t=>applyPipeline(e,t.pipeline,`delete-resources`)),await forEachDeployment(t=>applyAuth(e,t.auth,`delete-resources`)),await forEachDeployment(t=>applyIdP(e,t.idp,`delete-resources`))}),await z(`apply.createUpdateApplication`,async()=>{await forEachDeployment(t=>applyApplication(e,t.app,`create-update`))}),await z(`apply.createUpdateDependentServices`,async()=>{await step(`apply.executor.createUpdate`,t=>applyExecutor(e,t.executor,`create-update`)),await step(`apply.workflowExecutionPolicy.createUpdate`,t=>applyWorkflowJobFunctionExecutionPolicy(e,t.workflowExecutionPolicy,`create-update`)),await step(`apply.workflow.createUpdate`,t=>applyWorkflow(e,t.workflow,`create-update`))})}),await z(`apply.deleteDependentServices`,async()=>{await forEachDeployment(t=>applyWorkflow(e,t.workflow,`delete`)),await forEachDeployment(t=>applyWorkflowJobFunctionExecutionPolicy(e,t.workflowExecutionPolicy,`delete`)),await forEachDeployment(t=>applyExecutor(e,t.executor,`delete`)),await forEachDeployment(t=>applyStaticWebsite(e,t.staticWebsite,`delete`)),await forEachDeployment(t=>applyAIGateway(e,t.aiGateway,`delete`)),await forEachDeployment(t=>applySecretManager(e,t.secretManager,`delete`,t.application))}),await z(`apply.deleteApplication`,async()=>{await forEachDeployment(t=>applyApplication(e,t.app,`delete`))}),await z(`apply.deleteSubgraphServices`,async()=>{await forEachDeployment(t=>applyPipeline(e,t.pipeline,`delete-services`)),await forEachDeployment(t=>applyAuth(e,t.auth,`delete-services`)),await forEachDeployment(t=>applyIdP(e,t.idp,`delete-services`)),await forEachDeployment(t=>applyTailorDB(e,t.tailorDB,`delete-services`))}),await z(`apply.cleanup`,async()=>{await forEachDeployment(n=>applyFunctionRegistry(e,t,n.functionRegistry,`delete`))})}function setBundledScript(e,t,n,r){if(e.has(t))throw R({code:`DEPLOY_DUPLICATE_RESOURCE_NAME`,message:`Duplicate ${r} bundle name "${t}" across config files.`});e.set(t,n)}function addBundledScripts(e,t,n){for(let[r,i]of t)setBundledScript(e,r,i,n)}function mergeBundledScripts(e){let t={resolvers:new Map,executors:new Map,workflowJobs:new Map,authHooks:new Map};for(let n of e)addBundledScripts(t.resolvers,n.bundledScripts.resolvers,`resolver`),addBundledScripts(t.executors,n.bundledScripts.executors,`executor`),addBundledScripts(t.workflowJobs,n.bundledScripts.workflowJobs,`workflow job`),addBundledScripts(t.authHooks,n.bundledScripts.authHooks,`auth hook`);return t}async function confirmMigrationCheckpointRepairs(e,t){if(e.length!==0){M.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)))M.log(` ${t.namespace}:`),M.log(` Checkpoint: ${formatMigrationNumber(t.from)} → ${formatMigrationNumber(t.to)}`),M.log(` Migration history ID: ${t.fromHistoryId??`<unset>`} → ${t.toHistoryId}`);if(M.log(` The checkpoint reset itself changes only metadata.`),M.log(` This deployment may still apply pending schema or data migrations afterward.`),!t&&!await X.confirm({message:`Reset these migration checkpoints, align their history IDs, and continue with the deployment?`,default:!1}))throw R({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){M.success(`Re-tagging resources with the new id (--yes flag specified)...`,{mode:`plain`});return}if(!await X.confirm({message:`Re-tag these resources with the new id for "${t}"?\n${j.dim(`(The app id recorded for this config was removed since the previous deploy, so a new one was generated)`)}`,default:!1}))throw R({code:`DEPLOY_CANCELLED`,message:I`
|
|
60
|
+
- 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}", ... })`});d.forEach(e=>p.add(e));let _={...e,publishEvents:resolvePublishEvents({explicit:e.publishEvents,subscribed:isSubscribed(m,e.name),conflict:Qi.workflow(e.name)})};if(i){if(trackDesiredResourceOwnership({labels:i.allLabels,ownerLabel:i.label,appName:n,appId:r,resourceType:`Workflow`,resourceName:e.name,conflicts:l,unmanaged:u})&&hasMatchingSdkVersion(i.allLabels,s.labels)&&canTreatWorkflowAsUnchanged({existing:i.resource,workflow:_,usedJobNames:d,unchangedJobFunctions:o,staleJobFunctionNames:y})){c.unchanged.push({name:e.name,metaRequest:s});for(let e of d)f.add(e)}else c.updates.push({name:e.name,workspaceId:t,workflow:_,usedJobNames:d,metaRequest:s});delete b[e.name]}else c.creates.push({name:e.name,workspaceId:t,workflow:_,usedJobNames:d,metaRequest:s})}let x=[];Object.values(b).forEach(e=>{if(!e)return;let i=trackRemainingResourceOwner({labels:e.allLabels,ownerLabel:e.label,appName:n,appId:r,resourceOwners:d}),a=getExistingWorkflowJobNames(e.resource);i?x.push({name:e.resource.name,workspaceId:t,workflowId:e.resource.id,usedJobNames:a,deletableJobNames:[]}):a.forEach(e=>p.add(e))});let S=await planWorkflowJobFunctionDeletes({client:e,workspaceId:t,appName:n,appId:r,existingJobFunctionNames:[..._.keys()],retainedWorkflowJobNames:p,resourceOwners:d}),C=new Set(S.map(e=>e.jobFunctionName));for(let e of x)c.deletes.push({...e,deletableJobNames:e.usedJobNames.filter(e=>!p.has(e)&&C.has(e))});return{changeSet:c,conflicts:l,unmanaged:u,resourceOwners:d,appName:n,appId:r,unchangedWorkflowJobNames:f,jobFunctionDeletes:S,jobFunctionPublishEvents:v}}async function fetchExistingJobFunctions(e,t){let n=await Mt(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,appName:r,appId:i,existingJobFunctionNames:a,retainedWorkflowJobNames:o,resourceOwners:s}=e,c=a.filter(e=>!o.has(e));return(await Promise.all(c.map(async e=>{let{metadata:a}=await t.getMetadata({trn:resourceTrn(n,`workflow_job_function`,e)});return trackRemainingResourceOwner({labels:a?.labels,ownerLabel:a?.labels[`sdk-name`],appName:r,appId:i,resourceOwners:s})?{workspaceId:n,jobFunctionName:e}:void 0}))).filter(e=>e!==void 0)}function formatWorkflowChangeEntries(e,t){return formatChangeEntriesWithFunctionRegistry(`workflow`,e,t,e=>`usedJobNames`in e?e.usedJobNames.map(e=>workflowJobFunctionName(e)):[])}function canTreatWorkflowAsUnchanged(e){let{existing:t,workflow:n,usedJobNames:r,unchangedJobFunctions:i,staleJobFunctionNames:a}=e;return!r.every(e=>i.has(e))||r.some(e=>a.has(e))?!1:areWorkflowsEqual(t,n,r)}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 R({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 Xt(declaredKey(e),e.matchType)}function validatePolicy(e){if(declaredKey(e).endsWith(`*`))throw R({code:`WORKFLOW_EXECUTION_POLICY_INVALID`,message:`Invalid workflow execution policy "${e.name}": ${zt}`});let t=rn.safeParse({name:e.name,key:toPlatformExecutionPolicyKey(e),concurrencyPolicy:e.concurrencyPolicy});if(!t.success)throw R({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=[],s=[],c=new Set,l=Object.values(i);for(let e of l)validatePolicy(e);let u=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)}),d=new Set;for(let e of l){if(d.has(e.name))throw R({code:`WORKFLOW_EXECUTION_POLICY_DUPLICATE`,message:`Duplicate workflow execution policy name "${e.name}". Each policy must have a unique name within the workspace.`});d.add(e.name);let i=await buildMetaRequest({trn:resourceTrn(t,`workflow_job_function_execution_policy`,e.name),appName:n,appId:r}),c=u[e.name];if(c){let l=trackDesiredResourceOwnership({labels:c.allLabels,ownerLabel:c.label,appName:n,appId:r,resourceType:`Workflow execution policy`,resourceName:e.name,conflicts:o,unmanaged:s}),d=c.resource.executionPolicyKey,f=toPlatformExecutionPolicyKey(e),p=normalizeComparableConcurrency(c.resource.concurrencyPolicy),m=normalizeComparableConcurrency(e.concurrencyPolicy);l&&hasMatchingSdkVersion(c.allLabels,i.labels)&&d===f&&areNormalizedEqual(p,m)?a.unchanged.push({name:e.name}):d===f?a.updates.push({name:e.name,workspaceId:t,policy:e,metaRequest:i}):a.replaces.push({name:e.name,workspaceId:t,policy:e,metaRequest:i}),delete u[e.name]}else a.creates.push({name:e.name,workspaceId:t,policy:e,metaRequest:i})}for(let[e,i]of Object.entries(u))i&&trackRemainingResourceOwner({labels:i.allLabels,ownerLabel:i.label,appName:n,appId:r,resourceOwners:c})&&a.deletes.push({name:e,workspaceId:t});return{changeSet:a,conflicts:o,unmanaged:s,resourceOwners:c}}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,...n}=e;return n}async function applyDeploymentPlans(e,t,n){let forEachDeployment=async e=>{for(let t of n)await e(t)},step=(e,t)=>z(e,()=>forEachDeployment(t));await z(`apply.preflight`,async()=>{await forEachDeployment(t=>preflightTailorDB(e,t.tailorDB))}),await withMetadataWriteBatch(e,async e=>{await z(`apply.createUpdateServices`,async()=>{await step(`apply.secretManager.createUpdate`,t=>applySecretManager(e,t.secretManager,`create-update`,t.application)),await step(`apply.functionRegistry.createUpdate`,n=>applyFunctionRegistry(e,t,n.functionRegistry,`create-update`)),await step(`apply.staticWebsite.createUpdate`,t=>applyStaticWebsite(e,t.staticWebsite,`create-update`)),await step(`apply.aiGateway.createUpdate`,t=>applyAIGateway(e,t.aiGateway,`create-update`)),await step(`apply.idp.createUpdate`,t=>applyIdP(e,t.idp,`create-update`)),await step(`apply.auth.createUpdatePrerequisites`,t=>applyAuth(e,t.auth,`create-update-prerequisites`)),await step(`apply.tailorDB.createUpdate`,t=>applyTailorDB(e,t.tailorDB,`create-update`)),await step(`apply.auth.createUpdateDependents`,t=>applyAuth(e,t.auth,`create-update-dependents`)),await step(`apply.pipeline.createUpdate`,t=>applyPipeline(e,t.pipeline,`create-update`))}),await z(`apply.deleteSubgraphResources`,async()=>{await forEachDeployment(t=>applyPipeline(e,t.pipeline,`delete-resources`)),await forEachDeployment(t=>applyAuth(e,t.auth,`delete-resources`)),await forEachDeployment(t=>applyIdP(e,t.idp,`delete-resources`))}),await z(`apply.createUpdateApplication`,async()=>{await forEachDeployment(t=>applyApplication(e,t.app,`create-update`))}),await z(`apply.createUpdateDependentServices`,async()=>{await step(`apply.executor.createUpdate`,t=>applyExecutor(e,t.executor,`create-update`)),await step(`apply.workflowExecutionPolicy.createUpdate`,t=>applyWorkflowJobFunctionExecutionPolicy(e,t.workflowExecutionPolicy,`create-update`)),await step(`apply.workflow.createUpdate`,t=>applyWorkflow(e,t.workflow,`create-update`))})}),await z(`apply.deleteDependentServices`,async()=>{await forEachDeployment(t=>applyWorkflow(e,t.workflow,`delete`)),await forEachDeployment(t=>applyWorkflowJobFunctionExecutionPolicy(e,t.workflowExecutionPolicy,`delete`)),await forEachDeployment(t=>applyExecutor(e,t.executor,`delete`)),await forEachDeployment(t=>applyStaticWebsite(e,t.staticWebsite,`delete`)),await forEachDeployment(t=>applyAIGateway(e,t.aiGateway,`delete`)),await forEachDeployment(t=>applySecretManager(e,t.secretManager,`delete`,t.application))}),await z(`apply.deleteApplication`,async()=>{await forEachDeployment(t=>applyApplication(e,t.app,`delete`))}),await z(`apply.deleteSubgraphServices`,async()=>{await forEachDeployment(t=>applyPipeline(e,t.pipeline,`delete-services`)),await forEachDeployment(t=>applyAuth(e,t.auth,`delete-services`)),await forEachDeployment(t=>applyIdP(e,t.idp,`delete-services`)),await forEachDeployment(t=>applyTailorDB(e,t.tailorDB,`delete-services`))}),await z(`apply.cleanup`,async()=>{await forEachDeployment(n=>applyFunctionRegistry(e,t,n.functionRegistry,`delete`))})}function setBundledScript(e,t,n,r){if(e.has(t))throw R({code:`DEPLOY_DUPLICATE_RESOURCE_NAME`,message:`Duplicate ${r} bundle name "${t}" across config files.`});e.set(t,n)}function addBundledScripts(e,t,n){for(let[r,i]of t)setBundledScript(e,r,i,n)}function mergeBundledScripts(e){let t={resolvers:new Map,executors:new Map,workflowJobs:new Map,authHooks:new Map};for(let n of e)addBundledScripts(t.resolvers,n.bundledScripts.resolvers,`resolver`),addBundledScripts(t.executors,n.bundledScripts.executors,`executor`),addBundledScripts(t.workflowJobs,n.bundledScripts.workflowJobs,`workflow job`),addBundledScripts(t.authHooks,n.bundledScripts.authHooks,`auth hook`);return t}async function confirmMigrationCheckpointRepairs(e,t){if(e.length!==0){M.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)))M.log(` ${t.namespace}:`),M.log(` Checkpoint: ${formatMigrationNumber(t.from)} → ${formatMigrationNumber(t.to)}`),M.log(` Migration history ID: ${t.fromHistoryId??`<unset>`} → ${t.toHistoryId}`);if(M.log(` The checkpoint reset itself changes only metadata.`),M.log(` This deployment may still apply pending schema or data migrations afterward.`),!t&&!await X.confirm({message:`Reset these migration checkpoints, align their history IDs, and continue with the deployment?`,default:!1}))throw R({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){M.success(`Re-tagging resources with the new id (--yes flag specified)...`,{mode:`plain`});return}if(!await X.confirm({message:`Re-tag these resources with the new id for "${t}"?\n${j.dim(`(The app id recorded for this config was removed since the previous deploy, so a new one was generated)`)}`,default:!1}))throw R({code:`DEPLOY_CANCELLED`,message:I`
|
|
61
61
|
Apply cancelled. Resources remain tagged with the previous id.
|
|
62
62
|
To override, run again and confirm, or use --yes flag.
|
|
63
63
|
`})}function logIdMismatch(e,t){M.warn(e),M.log(` These resources are tagged with an id from an earlier deploy.`),M.newline(),M.log(` ${j.info(`Resources`)}:`);for(let e of t)M.log(` • ${j.bold(e.resourceType)} ${j.info(`"${e.resourceName}"`)}`)}async function confirmMissingConfigId(e,t,n){if(logIdMismatch(`No application id resolved for "${t}":`,e),n){M.success(`Managing these resources by name (--yes flag specified)...`,{mode:`plain`});return}if(!await X.confirm({message:`Drop that id and manage these resources by name for "${t}"?\n${j.dim(`(the config resolves without an 'id', so ownership falls back to the application name)`)}`,default:!1}))throw R({code:`DEPLOY_CANCELLED`,message:I`
|
|
@@ -75,7 +75,7 @@ If a value is genuinely safe to keep in 'env', allow it where it is defined: ${a
|
|
|
75
75
|
`})}}async function confirmMissingDependentApps(e,t){if(e.length!==0){M.warn(`Applications recorded as depending on this deploy are missing:`);for(let t of e)M.log(` • application id ${j.info(t.appId)} depends on ${j.bold(t.resource)} (${t.reason})`);if(M.newline(),M.log(` Applying without them turns off event publishing on the resources above:`),M.log(` nothing in this deploy subscribes to them, so the value resolves to false.`),M.log(` To keep it, add their configs to --config, or set publishEvents on`),M.log(` the resources above.`),t){M.warn(`Continuing without them (--yes flag specified); applying turns publishing off.`);return}if(!await X.confirm({message:`Continue without them?`,default:!1}))throw R({code:`DEPLOY_CANCELLED`,message:I`
|
|
76
76
|
Apply cancelled. Add the missing configs to --config, or set publishEvents
|
|
77
77
|
explicitly on the resources that should keep publishing.
|
|
78
|
-
`})}}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`,label:
|
|
78
|
+
`})}}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`,label:Zi.tailorDBType(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`,label:Zi.resolver(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`,label:Zi.idpService(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`,label:Zi.workflow(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`,label:Zi.workflowJobs(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,scope:n,label:r})=>recordedDependencies((await P(()=>t.getMetadata({trn:e})))?.metadata?.labels,n).filter(e=>!i.has(e.appId)).map(e=>({resource:r,appId:e.appId,reason:e.reason}))))).flat()}const es=H.object({outputPath:H.string(),contentHash:H.string()}),ts=H.object({kind:H.literal(`bundle`),inputHash:H.string(),dependencyPaths:H.array(H.string()),outputFiles:H.array(es),createdAt:H.string()}),ns=H.object({version:H.literal(1),sdkVersion:H.string(),lockfileHash:H.string().optional(),entries:H.record(H.string(),ts)});function createCacheStore(e){let t=null;function manifestPath(){return V.join(e.cacheDir,`manifest.json`)}function bundlesDir(){return V.join(e.cacheDir,`bundles`)}function bundlePath(e){return V.join(bundlesDir(),`${un(e)}.js`)}function loadManifest(){try{let e=U.readFileSync(manifestPath(),`utf-8`),n=ns.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){U.mkdirSync(e.cacheDir,{recursive:!0});let r=manifestPath(),i=V.join(e.cacheDir,`.manifest.${process.pid}.tmp`);try{U.writeFileSync(i,JSON.stringify(n,null,2),`utf-8`),U.renameSync(i,r)}catch(e){try{U.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();U.mkdirSync(n,{recursive:!0}),U.writeFileSync(bundlePath(e),t,`utf-8`)}function restoreBundleContent(e){try{return U.readFileSync(bundlePath(e),`utf-8`)}catch(e){if(e.code===`ENOENT`)return;throw e}}function clean(){U.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??V.resolve($t(),`cache`)}),n=t.loadManifest();return n&&(n.sdkVersion===e.sdkVersion?n.lockfileHash!==e.lockfileHash&&(M.debug(`Cache invalidated: lockfile changed`),t.clean()):(M.debug(`Cache invalidated: SDK version changed from ${n.sdkVersion} to ${e.sdkVersion}`),t.clean())),{enabled:!0,bundleCache:kt(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){let c=e?Object.entries(e).map(([e,{type:t,optional:n}])=>` ${e}${n?`?`:``}: ${t};`).join(`
|
|
79
79
|
`):``,l=!e||Object.keys(e).length===0?`{}`:`{
|
|
80
80
|
${c}
|
|
81
81
|
}`,u=`{
|
|
@@ -116,55 +116,55 @@ declare module "@tailor-platform/sdk" {
|
|
|
116
116
|
|
|
117
117
|
export {};
|
|
118
118
|
|
|
119
|
-
`}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.auth,i=r&&typeof r==`object`&&typeof r.name==`string`?[r.name]:void 0;if(!r||typeof r!=`object`)return{idpNames:t,aiGatewayNames:n,authNamespaceNames:i};let a=r.machineUsers,o=a&&typeof a==`object`?Object.keys(a):void 0,s=r.connections,c=s&&typeof s==`object`?Object.keys(s):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 r){let e=r.userProfile,a=e?.attributes,s=e?.type?.fields,l=e?.attributeList;return{attributes:a?Object.keys(a).reduce((e,t)=>(e[t]=inferAttributeType(s?.[t]),e),{}):void 0,attributeList:l,machineUserNames:o,idpNames:t,connectionNames:c,aiGatewayNames:n,authNamespaceNames:i}}if(`machineUserAttributes`in r){let e=r.machineUserAttributes;return e?{attributes:Object.entries(e).reduce((e,[t,n])=>(e[t]=inferAttributeType(n),e),{}),machineUserNames:o,idpNames:t,connectionNames:c,aiGatewayNames:n,authNamespaceNames:i}:{machineUserNames:o,idpNames:t,connectionNames:c,aiGatewayNames:n,authNamespaceNames:i}}return{machineUserNames:o,idpNames:t,connectionNames:c,aiGatewayNames:n,authNamespaceNames:i}}function resolveTypeDefinitionPath(e){let t=process.env.TAILOR_DTS_PATH;return t?V.resolve(t):V.join(V.dirname(V.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}=extractAttributesFromConfig(t);!e&&!r&&M.info(`No attributes found in configuration`,{mode:`plain`}),e&&M.debug(`Extracted Attributes: ${JSON.stringify(e)}`),r&&M.debug(`Extracted AttributeList: ${JSON.stringify(r)}`),i?.length&&M.debug(`Extracted MachineUserNames: ${JSON.stringify(i)}`),a?.length&&M.debug(`Extracted IdpNames: ${JSON.stringify(a)}`),o?.length&&M.debug(`Extracted ConnectionNames: ${JSON.stringify(o)}`),s?.length&&M.debug(`Extracted AIGatewayNames: ${JSON.stringify(s)}`),c?.length&&M.debug(`Extracted AuthNamespaceNames: ${JSON.stringify(c)}`);let l=t.env;l&&M.debug(`Extracted Env: ${JSON.stringify(l)}`);let u=generateTypeDefinition(e,r,l,i,a,o,s,c),d=resolveTypeDefinitionPath(n);U.mkdirSync(V.dirname(d),{recursive:!0}),U.writeFileSync(d,u);let f=V.relative(process.cwd(),d);M.newline(),M.success(`Generated type definitions: ${f}`,{mode:`plain`})}catch(e){M.error(`Error generating types`),M.error(String(e))}}const
|
|
119
|
+
`}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.auth,i=r&&typeof r==`object`&&typeof r.name==`string`?[r.name]:void 0;if(!r||typeof r!=`object`)return{idpNames:t,aiGatewayNames:n,authNamespaceNames:i};let a=r.machineUsers,o=a&&typeof a==`object`?Object.keys(a):void 0,s=r.connections,c=s&&typeof s==`object`?Object.keys(s):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 r){let e=r.userProfile,a=e?.attributes,s=e?.type?.fields,l=e?.attributeList;return{attributes:a?Object.keys(a).reduce((e,t)=>(e[t]=inferAttributeType(s?.[t]),e),{}):void 0,attributeList:l,machineUserNames:o,idpNames:t,connectionNames:c,aiGatewayNames:n,authNamespaceNames:i}}if(`machineUserAttributes`in r){let e=r.machineUserAttributes;return e?{attributes:Object.entries(e).reduce((e,[t,n])=>(e[t]=inferAttributeType(n),e),{}),machineUserNames:o,idpNames:t,connectionNames:c,aiGatewayNames:n,authNamespaceNames:i}:{machineUserNames:o,idpNames:t,connectionNames:c,aiGatewayNames:n,authNamespaceNames:i}}return{machineUserNames:o,idpNames:t,connectionNames:c,aiGatewayNames:n,authNamespaceNames:i}}function resolveTypeDefinitionPath(e){let t=process.env.TAILOR_DTS_PATH;return t?V.resolve(t):V.join(V.dirname(V.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}=extractAttributesFromConfig(t);!e&&!r&&M.info(`No attributes found in configuration`,{mode:`plain`}),e&&M.debug(`Extracted Attributes: ${JSON.stringify(e)}`),r&&M.debug(`Extracted AttributeList: ${JSON.stringify(r)}`),i?.length&&M.debug(`Extracted MachineUserNames: ${JSON.stringify(i)}`),a?.length&&M.debug(`Extracted IdpNames: ${JSON.stringify(a)}`),o?.length&&M.debug(`Extracted ConnectionNames: ${JSON.stringify(o)}`),s?.length&&M.debug(`Extracted AIGatewayNames: ${JSON.stringify(s)}`),c?.length&&M.debug(`Extracted AuthNamespaceNames: ${JSON.stringify(c)}`);let l=t.env;l&&M.debug(`Extracted Env: ${JSON.stringify(l)}`);let u=generateTypeDefinition(e,r,l,i,a,o,s,c),d=resolveTypeDefinitionPath(n);U.mkdirSync(V.dirname(d),{recursive:!0}),U.writeFileSync(d,u);let f=V.relative(process.cwd(),d);M.newline(),M.success(`Generated type definitions: ${f}`,{mode:`plain`})}catch(e){M.error(`Error generating types`),M.error(String(e))}}const rs=`To use this config for a separate app, delete it.`;function warnMissingAppId(e){e||(M.warn(`The config resolved without an 'id'.`),M.log(` Resources tagged with an id from an earlier deploy read as another application's:
|
|
120
120
|
deploy asks before taking them over, and remove leaves them in place. Only resources
|
|
121
121
|
carrying no id are matched by application name.
|
|
122
122
|
Add an 'id' to the object passed to defineConfig() — a config that re-exports it from
|
|
123
|
-
another file cannot have one injected automatically. 'tailor deploy' can add it for you.`))}const
|
|
124
|
-
`,n.start-1)+1,a=e.slice(i,n.start);if(!/^[\t ]*$/.test(a))return e.slice(0,n.start)+`${r}, `+e.slice(n.start);let o=`${
|
|
125
|
-
`,t.start)+1,o=e.slice(a).match(/^[\t ]*/)?.[0]??``,s=`${o} `,c=`\n${s}${
|
|
123
|
+
another file cannot have one injected automatically. 'tailor deploy' can add it for you.`))}const is=/^[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 U.promises.readFile(e,`utf-8`),{program:n}=kr(e,t),r=[];if(findDefineConfigCalls(n,r),r.length===0)return null;if(r.length>1)throw R({code:`CONFIG_ID_UNMANAGEABLE`,message:`Multiple defineConfig() calls found in ${e}. Only one is supported.`});let{configObj:i}=k(r[0],`defineConfig call site missing`);if(!i)throw R({code:`CONFIG_ID_UNMANAGEABLE`,message:`defineConfig() argument must be an inline object literal in ${e} so the SDK can manage the 'id' field.`});let a=findIdProperty(i);if(a){let t=a.value;if(t.type!==`Literal`)throw R({code:`CONFIG_ID_INVALID`,message:`'id' field in ${e} must be a string literal.`,suggestion:rs});let n=t.value;if(typeof n!=`string`||n===``)throw R({code:`CONFIG_ID_INVALID`,message:`'id' field in ${e} must be a non-empty string literal.`,suggestion:rs});if(!is.test(n))throw R({code:`CONFIG_ID_INVALID`,message:`'id' field in ${e} must be a UUID.`,suggestion:rs});return{id:n,injected:!1}}let o=crypto.randomUUID(),s=insertIdProperty(t,i,o);return await U.promises.writeFile(e,s,`utf-8`),M.info(`Generated app id and wrote to ${e}: ${o}`),{id:o,injected:!0}}async function readConfigId(e){let t=await U.promises.readFile(e,`utf-8`),{program:n}=kr(e,t),r=[];if(findDefineConfigCalls(n,r),r.length===0)return null;if(r.length>1)throw R({code:`CONFIG_ID_UNMANAGEABLE`,message:`Multiple defineConfig() calls found in ${e}. Only one is supported.`});let{configObj:i}=k(r[0],`defineConfig call site missing`);if(!i)throw R({code:`CONFIG_ID_UNMANAGEABLE`,message:`defineConfig() argument must be an inline object literal in ${e} so the SDK can manage the 'id' field.`});let a=findIdProperty(i);if(!a||a.value.type!==`Literal`)return{id:null};let o=a.value.value;return{id:typeof o==`string`&&o!==``?o:null}}async function assertConfigIdInCI(e){let t=await readConfigId(e);if(t!==null){if(!t.id)throw R({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(!is.test(t.id))throw R({code:`CONFIG_ID_INVALID`,message:`'id' in ${e} must be a UUID.`,suggestion:rs})}}async function ensureConfigIdForDeploy(e){let{configPath:t,dryRun:n,buildOnly:r}=e;if(r)return;let i=ut(process.env.TAILOR_CI_ALLOW_ID_INJECTION)===!0,a=Dr&&!i;if(n){a&&await assertConfigIdInCI(t);return}if(a){await assertConfigIdInCI(t);return}await ensureConfigId(t)}const as=`// 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=k(t.properties[0],`first property missing`),i=e.lastIndexOf(`
|
|
124
|
+
`,n.start-1)+1,a=e.slice(i,n.start);if(!/^[\t ]*$/.test(a))return e.slice(0,n.start)+`${r}, `+e.slice(n.start);let o=`${as}\n${a}${r},\n${a}`;return e.slice(0,n.start)+o+e.slice(n.start)}let i=t.start+1,a=e.lastIndexOf(`
|
|
125
|
+
`,t.start)+1,o=e.slice(a).match(/^[\t ]*/)?.[0]??``,s=`${o} `,c=`\n${s}${as}\n${s}${r},\n${o}`;return e.slice(0,i)+c+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(`
|
|
126
126
|
`,t.start-1)+1,a=e.indexOf(`
|
|
127
127
|
`,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(`
|
|
128
|
-
`,i-2)+1;e.slice(n,i).trim()===
|
|
128
|
+
`,i-2)+1;e.slice(n,i).trim()===as&&(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 U.promises.readFile(e,`utf-8`),{program:r}=kr(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 kr(e,l).errors.length>0?!1:(await U.promises.writeFile(e,l,`utf-8`),!0)}const Q=`.github/tailor.lock`,os=2,ss=`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===``||V.isAbsolute(e)||e.includes(`\\`)?!1:e.split(`/`).every(e=>e!==``&&e!==`.`&&e!==`..`)}function assertSafeLockPath(e){for(let t of[`.github`,Q])try{if(U.lstatSync(V.join(e,t)).isSymbolicLink())throw R({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 R({code:`APP_ID_LOCK_INVALID`,message:`${Q} has an invalid 'appIds' section: expected an object mapping config paths to app ids.`,suggestion:ss});let t=new Map;for(let[n,r]of Object.entries(e)){if(!isRepositoryRelativeKey(n))throw R({code:`APP_ID_LOCK_INVALID`,message:`${Q} 'appIds' key "${n}" must be a repository-relative config path (no absolute paths, "..", or backslashes).`,suggestion:ss});if(typeof r!=`string`||!is.test(r))throw R({code:`APP_ID_LOCK_INVALID`,message:`${Q} 'appIds' entry for "${n}" must be a UUID.`,suggestion:ss});let e=t.get(r.toLowerCase());if(e!==void 0)throw R({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=V.join(e,Q);if(!U.existsSync(t))return null;let n;try{n=U.readFileSync(t,`utf-8`)}catch(t){throw R({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 R({code:`APP_ID_LOCK_INVALID`,message:`${Q} is not valid JSON.`,suggestion:ss,cause:e})}if(!isPlainObject(r)||typeof r.version!=`number`)throw R({code:`APP_ID_LOCK_INVALID`,message:`${Q} has no valid 'version' field.`,suggestion:ss});if(r.version>2)throw R({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=V.dirname(e);for(;;){if(U.existsSync(V.join(t,`.github/tailor.lock`)))return readAppIdLock(t);let e=V.dirname(t);if(e===t||U.existsSync(V.join(t,`.git`)))return null;t=e}}function appIdLockKey(e,t){let n=V.relative(e,t);if(!isRepositoryRelativeKey(n))throw R({code:`CONFIG_OUTSIDE_REPOSITORY`,message:`${t} is outside the repository that holds ${Q} (${e}).`});return n}function warnConfigStillCarriesId(e){M.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){M.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){M.warn(`No app id is recorded for ${e} in ${Q}.`),M.log(` Resources tagged with an id from an earlier deploy read as another application's:
|
|
129
129
|
deploy asks before taking them over, and remove leaves them in place. Only resources
|
|
130
|
-
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)}`),R({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 R({code:`APP_ID_NOT_RECORDED`,message:`No app id is recorded for ${t}.`,suggestion:rekeyInstructions([e])});return M.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},a=!1,o=n.map(()=>void 0),s=[],c=new Map(Object.entries(i).map(([e,t])=>[t.toLowerCase(),e])),exists=e=>U.existsSync(V.join(t.root,e));n.forEach(({configPath:e,configId:n},l)=>{let u=appIdLockKey(t.root,e),d=i[u];if(d!==void 0){if(n!==void 0&&n.toLowerCase()!==d.toLowerCase())throw R({code:`APP_ID_CONFLICT`,message:`${Q} records app id "${d}" for ${u}, 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.`});let t=n!==void 0&&r===`write`;n!==void 0&&!t&&warnConfigStillCarriesId(u),o[l]={configPath:e,key:u,id:d,source:`lock`,removeConfigId:t};return}if(n!==void 0){if(!Zo.test(n))throw R({code:`CONFIG_ID_INVALID`,message:`'id' in ${e} must be a UUID.`,suggestion:`To use this config for a separate app, delete it.`});let t=c.get(n.toLowerCase()),s=t!==void 0&&t!==u&&!exists(t)?t:void 0;if(t!==void 0&&t!==u&&s===void 0)throw R({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.`});c.set(n.toLowerCase(),u);let d=r===`write`;d?(s!==void 0&&(delete i[s],M.info(`Keeping the app id of ${s} for ${u}: ${n}`)),i[u]=n,a=!0):warnUnrecordedConfigId(u),o[l]={configPath:e,key:u,id:n,source:`config`,removeConfigId:d};return}s.push({index:l,configPath:e,key:u})});let finish=()=>({appIds:i,changed:a,entries:o.map(e=>k(e,`app id entry missing`))});if(s.length===0)return finish();if(r===`read`){for(let{index:e,configPath:t,key:n}of s)warnMissingLockedAppId(n),o[e]={configPath:t,key:n,id:void 0,source:`none`,removeConfigId:!1};return finish()}let l=Object.keys(i).filter(e=>!exists(e)),u=[...new Set(s.map(({key:e})=>e))];if(r===`require`)throw missingInCIError(u,l);let d;if(l.length===1&&u.length===1){let e=k(l[0],`orphan missing`),t=k(u[0],`key missing`);await confirmMove(e,t)&&(d={from:e,key:t})}else if(l.length>0)throw R({code:`APP_ID_NOT_RECORDED`,message:`No app id is recorded for ${u.join(`, `)}.`,suggestion:rekeyInstructions(l)});for(let{index:e,configPath:t,key:n}of s){let r=i[n];if(r!==void 0){o[e]={configPath:t,key:n,id:r,source:`generated`,removeConfigId:!1};continue}let s;d?.key===n?(s=k(i[d.from],`orphaned app id missing`),delete i[d.from],M.info(`Keeping the app id of ${d.from} for ${n}: ${s}`)):(s=crypto.randomUUID(),M.info(`Generated app id for ${n}: ${s}`)),i[n]=s,a=!0;let c=d?.key===n?`lock`:`generated`;o[e]={configPath:t,key:n,id:s,source:c,removeConfigId:!1}}return finish()}function writeAppIds(e){let{lock:t,appIds:n}=e,r=readRawLock(t.root);if(r===null)throw R({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};U.writeFileSync(V.join(t.root,Q),`${JSON.stringify(a,null,2)}\n`,`utf-8`)}async function removeAdoptedConfigIds(e){let t=!1,n=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,M.info(`Moved the app id of ${r.key} from the config into ${Q}.`)):M.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=ut(process.env.TAILOR_CI_ALLOW_ID_INJECTION)===!0;return xr&&!t?`require`:e?`read`:`write`}function parseDeployConfigPaths(e){let t=e??process.env.TAILOR_PLATFORM_SDK_CONFIG_PATH;if(t===void 0)return[void 0];let n=t.split(`,`).map(e=>e.trim());if(n.some(e=>e.length===0))throw R({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:a,packageVersion:o,cacheDir:s}=e,{config:c,plugins:l}=n??k((await loadDeployConfigs({configPaths:[t],dryRun:r,buildOnly:i}))[0],`loaded config missing`),u=V.dirname(c.path),d=lr(`pnpm-lock.yaml`,{cwd:u})??lr(`package-lock.json`,{cwd:u})??lr(`yarn.lock`,{cwd:u})??lr(`bun.lock`,{cwd:u}),f=createCacheManager({enabled:!a,cacheDir:s,sdkVersion:o,lockfileHash:d?Et(d):void 0}),p;l.length>0&&(p=new En(l)),await z(`build.generateUserTypes`,()=>generateUserTypes({config:c,configPath:c.path}));let m,h,g,_;try{let e=await z(`build.loadApplication`,()=>Zt({config:c,pluginManager:p,bundleCache:f.bundleCache}));m=e.application,h=e.workflowBuildResult,g=e.httpAdapterBuildResult,_=e.bundledScripts}finally{f.finalize()}return{config:c,application:m,workflowBuildResult:h,httpAdapterBuildResult:g,bundledScripts:_}}function resolveExistingConfigPath(e){let t=loadConfigPath(e);if(!t)return;let n=V.resolve(process.cwd(),t);return U.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=>z(`build.prepareConfig`,async()=>{findAppIdLock(e)===null&&await ensureConfigIdForDeploy({configPath:e,dryRun:n,buildOnly:r})})))}async function loadPreparedDeployConfig(e){return z(`build.loadConfig`,()=>loadConfig(e.configPath))}async function resolveDeployAppIds(e){let{loaded:t,dryRun:n,buildOnly:r}=e;if(r)return[...t];let i=[...t],a=new Map;t.forEach((e,t)=>{let n=findAppIdLock(e.config.path);if(n===null){warnMissingAppId(e.config.id);return}let r=a.get(n.root)??{lock:n,indexes:[]};r.indexes.push(t),a.set(n.root,r)});let o=appIdPlanModeForDeploy(n);for(let{lock:e,indexes:n}of a.values()){let r=await resolveLockedAppIds({lock:e,mode:o,entries:n.map(e=>{let{config:n}=k(t[e],`loaded config missing`);return{configPath:n.path,configId:n.id}})});n.forEach((e,n)=>{let a=k(t[e],`loaded config missing`),o=k(r.entries[n],`planned app id entry missing`).id;i[e]={...a,config:{...a.config,id:o}}})}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,...i}=e;if(n!==void 0&&(n.length!==t.length||t.some((e,t)=>n[t]===void 0)))throw L(`loadedConfigs must contain exactly one entry for every configPath`);let a=r===void 0&&n===void 0?await loadDeployConfigs({configPaths:t,dryRun:e.dryRun,buildOnly:e.buildOnly}):n,o=r??buildDeploymentTarget;return Promise.all(t.map((e,t)=>o({...i,configPath:e,loadedConfig:a?.[t]})))}function addPossiblyAmbiguousNamespace(e,t,n){if(e.has(t)){e.get(t)!==n&&e.set(t,void 0);return}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 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:()=>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:()=>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:()=>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 R({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:new Set},n={workflowNames: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=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)??new Map;o.set(e,`publish-events`),t.set(a,o)}return t}function collectWorkflowJobPublishEvents(e){let t=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:Ki.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:Ki.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:Ki.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`?Gi.workflow(r.workflowName):Gi.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 R({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){for(let t of ts){let n=new Set;for(let r of e)for(let e of t.namesOf(r)){if(n.has(e))throw R({code:`DEPLOY_DUPLICATE_RESOURCE_NAME`,message:`Duplicate ${t.resourceLabel} name "${e}" across config files. ${t.resourceLabel} names must be unique across all configs in a single deploy.`});n.add(e)}}}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({resourceType:`TailorDB table`,resourceName:n.name});for(let n of e.staticWebsite.changeSet.deletes)t.push({resourceType:`StaticWebsite`,resourceName:n.name});for(let n of e.aiGateway.changeSet.deletes)t.push({resourceType:`AIGateway`,resourceName:n.name});for(let n of e.auth.changeSet.oauth2Client.deletes)t.push({resourceType:`OAuth2 client`,resourceName:n.name});for(let n of e.auth.changeSet.oauth2Client.replaces)t.push({resourceType:`OAuth2 client (client type change)`,resourceName:n.name});for(let n of e.auth.changeSet.connection.deletes)t.push({resourceType:`Auth connection`,resourceName:n.name});for(let n of e.secretManager.vaultChangeSet.deletes)t.push({resourceType:`Secret Manager vault`,resourceName:n.name});for(let n of e.secretManager.secretChangeSet.deletes)t.push({resourceType:`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){if(isManagedResourceClaimed(t,e,r)){M.debug(`Skipping delete of ${managedResourceKey(e,r)}: still managed by another config in this deploy.`);continue}e.changeSet.deletes[n]=r,n+=1}e.changeSet.deletes.length=n}function workflowJobFunctionItems(e){let t=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`],ts=[{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`},...ts.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},new Set));t.forEach((e,t)=>{let r=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=new Set;for(let n of e)for(let e of collectResourceOwners(deploymentPlanResults(n)))t.add(e);return t}function ownershipFilters(e){let t=new Map;for(let n of e)if(t.set(`${Ni}\0${n.name}`,{[Ni]:n.name}),n.id){let e=sdkAppIdLabelValue(n.id);t.set(`${Fi}\0${e}`,{[Fi]:e})}return[...t.values()]}async function createMetadataLookupClient(e){let{client:t,workspaceId:n,applications:r}=e,i=await Promise.all(ownershipFilters(r).map(e=>N(async(r,i)=>{let{results:a,nextPageToken:o}=await t.listMetadata({workspaceId:n,labels:e,pageToken:r,pageSize:i});return[a,o]}))),a=new Map;for(let e of i.flat())e.metadata&&a.set(e.trn,e.metadata);let o=new Map,getMetadata=(e,n)=>{let r=a.get(e.trn??``);if(r)return Promise.resolve(Gn(ne,{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),i=formatChangeSetEntries(e.workflowExecutionPolicy.changeSet,[`executionPolicy`]),a=formatAuthHookChangeEntries(e.auth.changeSet.authHook,e.functionRegistry.authHookFunctionChanges),o=formatTailorDBResourceChangeEntries(e.tailorDB.changeSet.type,e.tailorDB.changeSet.gqlPermission),s=e.tailorDB.context.checkpointRepairs.map(e=>({action:`update`,symbol:Wi.update,name:`migration checkpoint ${formatMigrationNumber(e.from)} → ${formatMigrationNumber(e.to)}`,labels:[`migrationCheckpoint`],namespace:e.namespace})),c=[...o,...s],l=[...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,u=[...formatChangeSetEntries(e.idp.changeSet.client,[`client`],namespaceOf)],d=[...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),...a,...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:f}=splitFunctionRegistryChanges(e.functionRegistry.changeSet),p=extractServiceActions(e.tailorDB.changeSet.service),m=extractServiceActions(e.pipeline.changeSet.service),h=extractServiceActions(e.idp.changeSet.service),g=extractServiceActions(e.auth.changeSet.service),_=[...c,...l,...t,...r,...i,...u,...d],v=summarizePlanResults(e,_,[...p,...m,...h,...g]),y=[...e.functionRegistry.unmanaged,...e.tailorDB.unmanaged,...e.staticWebsite.unmanaged,...e.aiGateway.unmanaged,...e.idp.unmanaged,...e.auth.unmanaged,...e.pipeline.unmanaged,...e.executor.unmanaged,...e.workflow.unmanaged,...e.secretManager.unmanaged],b=[...e.functionRegistry.conflicts,...e.tailorDB.conflicts,...e.staticWebsite.conflicts,...e.aiGateway.conflicts,...e.idp.conflicts,...e.auth.conflicts,...e.pipeline.conflicts,...e.executor.conflicts,...e.workflow.conflicts,...e.secretManager.conflicts],x=[..._,...p.map(({action:e,name:t})=>({action:e,name:t,labels:[`tailorDB`],namespace:void 0})),...m.map(({action:e,name:t})=>({action:e,name:t,labels:[`pipeline`],namespace:void 0})),...h.map(({action:e,name:t})=>({action:e,name:t,labels:[`idp`],namespace:void 0})),...g.map(({action:e,name:t})=>({action:e,name:t,labels:[`auth`],namespace:void 0})),...formatChangeSetEntries(f),...formatChangeSetEntries(e.staticWebsite.changeSet,[`staticWebsite`]),...formatChangeSetEntries(e.staticWebsite.customDomainChangeSet,[`customDomain`]),...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})=>({action:e,name:t,labels:n,namespace:r})),S=[...y.map(({resourceType:e,resourceName:t})=>({type:`unmanaged`,resourceType:e,name:t})),...e.secretManager.skippedSecrets.map(e=>({type:`skippedSecret`,resourceType:`secret`,name:e}))],C=b.map(({resourceType:e,resourceName:t,currentOwner:n})=>({resourceType:e,name:t,currentOwner:n})),w=[...buildGroupedDisplayLines(e.functionRegistry.changeSet.title,formatChangeSetEntries(f)),...e.staticWebsite.changeSet.lines(),...e.staticWebsite.customDomainChangeSet.lines(),...e.aiGateway.changeSet.lines(),...e.app.lines(),...buildGroupedDisplayLines(`TailorDB`,c,p),...buildGroupedDisplayLines(`Resolver`,l,m),...buildGroupedDisplayLines(`Executor`,t),...buildGroupedDisplayLines(`Workflow`,r),...buildGroupedDisplayLines(`IdP`,u,h),...buildGroupedDisplayLines(`Auth`,d,g),...e.secretManager.vaultChangeSet.lines(),...e.secretManager.secretChangeSet.lines()];if(y.length>0){w.push(j.bold(`Unmanaged resources (not in config):`));for(let{resourceType:e,resourceName:t}of y)w.push(` ${j.warning(`⚠`)} ${j.bold(e)} "${t}"`)}if(e.secretManager.skippedSecrets.length>0){w.push(j.bold(`Secret Manager secrets (skipped - no value provided):`));for(let t of e.secretManager.skippedSecrets)w.push(` ${j.dim(`○`)} ${t}`)}if(b.length>0){w.push(j.bold(`Owner conflicts (will require confirmation on apply):`));for(let{resourceType:e,resourceName:t,currentOwner:n}of b)w.push(` ${j.warning(`!`)} ${j.bold(e)} "${t}" — owned by "${n}"`)}return w.push(formatPlanSummary(v)),{summary:v,json:{summary:v,changes:x,warnings:S,conflicts:C},lines:w}}function printPlanResults(e,t){let n=buildPlanReport(e);if(M.jsonMode&&t?.dryRun)return M.out(n.json),n.summary;let r=n.lines.join(`
|
|
131
|
-
`);return t?.dryRun?M.out(r):M.log(r),n.summary}function summarizePlanResults(e,t,n){let r={create:0,update:0,delete:0,replace:0};for(let e of t)r[e.action]+=1;for(let e of n)r[e.action]+=1;let{otherChanges:i}=splitFunctionRegistryChanges(e.functionRegistry.changeSet),a=summarizeChangeSets([i,e.staticWebsite.changeSet,e.staticWebsite.customDomainChangeSet,e.aiGateway.changeSet,e.app,e.secretManager.vaultChangeSet,e.secretManager.secretChangeSet]);return r.create+=a.create,r.update+=a.update,r.delete+=a.delete,r.replace+=a.replace,r}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}),{create:0,update:0,delete:0,replace:0})}function printDeploymentPlans(e,t){if(M.jsonMode&&t?.dryRun){let t=e.map(e=>buildPlanReport(deploymentPlanResults(e))),n=sumPlanSummaries(t.map(e=>e.summary));return M.out({summary:n,changes:t.flatMap(e=>e.json.changes),warnings:t.flatMap(e=>e.json.warnings),conflicts:t.flatMap(e=>e.json.conflicts)}),n}return sumPlanSummaries(e.map(e=>printPlanResults(deploymentPlanResults(e),t)))}const ns=new Map;function validatorFor(e){let t=ns.get(e.typeName);if(t)return t;let n=Or({registry:Kn(e,...Dr(e))});return ns.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=Gn(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?Er(t.field):`(message)`,message:t.message});else l.kind===`error`&&M.warn(`Could not validate ${n} "${e.name}" (${r}): ${l.error.message}`)}}async function validatePlan(e){let{tailorDB:t,staticWebsite:n,aiGateway:i,idp:s,auth:c,pipeline:l,app:u,executor:d,workflow:f,workflowExecutionPolicy:p,secretManager:m}=e,h=[];function creates(e,t,n){validateItems({schema:e,kind:t,action:`create`,items:n,requestKey:`request`,violations:h})}function updates(e,t,n){validateItems({schema:e,kind:t,action:`update`,items:n,requestKey:`request`,violations:h})}function replaces(e,t,n){validateItems({schema:e,kind:t,action:`replace`,items:n,requestKey:`createRequest`,violations:h})}function inPlaceReplaces(e,t,n){validateItems({schema:e,kind:t,action:`replace`,items:n,requestKey:`updateRequest`,violations:h})}creates(Ce,`TailorDB service`,t.changeSet.service.creates),creates(Te,`TailorDB table`,t.changeSet.type.creates),updates(Ue,`TailorDB table`,t.changeSet.type.updates),creates(a,`StaticWebsite`,n.changeSet.creates),updates(nt,`StaticWebsite`,n.changeSet.updates),creates(ie,`StaticWebsite custom domain`,n.customDomainChangeSet.creates),creates(fe,`AIGateway`,i.changeSet.creates.map(e=>({name:e.name,request:{...e.request,cors:void 0}}))),updates(he,`AIGateway`,i.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(r,`IdP service`,s.changeSet.service.creates.map(substituteIdpReturnOrigins)),updates(ce,`IdP service`,s.changeSet.service.updates.map(substituteIdpReturnOrigins));let _=[...s.changeSet.client.creates.map(e=>({clientName:e.request.client?.name??``,namespaceName:e.request.namespaceName??``,workspaceId:e.request.workspaceId??``})),...s.changeSet.client.updates.map(e=>({clientName:e.name,namespaceName:e.namespaceName,workspaceId:e.workspaceId}))];creates(C,`IdP client secret`,_.map(e=>({name:e.clientName,request:{workspaceId:e.workspaceId,secretmanagerVaultName:idpClientVaultName(e.namespaceName,e.clientName)}}))),creates(o,`IdP client secret`,_.map(e=>({name:e.clientName,request:{workspaceId:e.workspaceId,secretmanagerVaultName:idpClientVaultName(e.namespaceName,e.clientName),secretmanagerSecretName:idpClientSecretName(e.namespaceName,e.clientName)}}))),creates($e,`Auth service`,c.changeSet.service.creates),updates(xe,`Auth service`,c.changeSet.service.updates),creates(ye,`Auth IDP config`,c.changeSet.idpConfig.creates),updates(ke,`Auth IDP config`,c.changeSet.idpConfig.updates),creates(Ee,`Auth user profile config`,c.changeSet.userProfileConfig.creates),updates(ae,`Auth user profile config`,c.changeSet.userProfileConfig.updates),creates(we,`Auth tenant config`,c.changeSet.tenantConfig.creates),updates(at,`Auth tenant config`,c.changeSet.tenantConfig.updates),creates(He,`Auth machine user`,c.changeSet.machineUser.creates),updates(Oe,`Auth machine user`,c.changeSet.machineUser.updates),creates(Me,`Auth hook`,c.changeSet.authHook.creates),updates(Re,`Auth hook`,c.changeSet.authHook.updates),creates(Se,`Auth SCIM config`,c.changeSet.scim.creates),updates(tt,`Auth SCIM config`,c.changeSet.scim.updates),creates(Le,`Auth SCIM resource`,c.changeSet.scimResource.creates),updates(st,`Auth SCIM resource`,c.changeSet.scimResource.updates),creates(Ye,`OAuth2 client`,c.changeSet.oauth2Client.creates),updates(_e,`OAuth2 client`,c.changeSet.oauth2Client.updates),replaces(Ye,`OAuth2 client`,c.changeSet.oauth2Client.replaces),creates(y,`Pipeline service`,l.changeSet.service.creates),updates(ee,`Pipeline service`,l.changeSet.service.updates),creates(Ne,`Resolver`,l.changeSet.resolver.creates),updates(x,`Resolver`,l.changeSet.resolver.updates),creates(de,`Executor`,d.changeSet.creates),updates(me,`Executor`,d.changeSet.updates),creates(ve,`Workflow`,f.changeSet.creates.map(e=>({name:e.name,request:buildWorkflowValidationShape(e.workspaceId,e.workflow)}))),updates(Je,`Workflow`,f.changeSet.updates.map(e=>({name:e.name,request:buildWorkflowValidationShape(e.workspaceId,e.workflow)})));let v=f.changeSet.creates[0]?.workspaceId??f.changeSet.updates[0]?.workspaceId??``;if(v){let e=new Set;for(let t of[...f.changeSet.creates,...f.changeSet.updates])for(let n of t.usedJobNames)e.add(n);for(let t of f.unchangedWorkflowJobNames)e.add(t);creates(Ae,`Workflow job function`,[...e].map(e=>({name:e,request:{workspaceId:v,jobFunctionName:e,scriptRef:e}})))}if(creates(Ge,`Workflow execution policy`,[...p.changeSet.creates,...p.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(Ve,`Workflow execution policy`,p.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(C,`Secret Manager vault`,m.vaultChangeSet.creates.map(e=>({name:e.name,request:vaultCreateRequest(e)}))),creates(o,`Secret Manager secret`,m.secretChangeSet.creates.map(e=>({name:e.name,request:secretCreateRequest(e)}))),updates(Fe,`Secret Manager secret`,m.secretChangeSet.updates.map(e=>({name:e.name,request:secretUpdateRequest(e)}))),creates(ue,`Application`,u.creates.map(e=>({name:e.name,request:{...e.request,cors:void 0}}))),updates(g,`Application`,[...u.updates,...u.unchanged].map(e=>({name:e.name,request:{...e.request,cors:void 0}}))),creates(qe,`Auth connection`,c.changeSet.connection.creates),inPlaceReplaces(We,`Auth connection`,c.changeSet.connection.replaces),h.length===0)return;let b=new Set(h.map(e=>`${e.kind}:${e.name}`));M.error(`Pre-flight validation found ${h.length} violation(s) across ${b.size} resource(s):`);for(let e of h)M.log(` ${j.resourceType(e.kind)} ${j.resourceName(e.name)} (${e.action}) — ${j.bold(e.fieldPath)}: ${e.message}`);throw R({code:`DEPLOY_VALIDATION_FAILED`,message:`${h.length} validation error(s) found in ${b.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 Error(formatIssues(n.error.issues));return n.data}const rs=H.string().min(1,`Profile must not be empty`),is=H.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=is.safeParse(e);return t.success?!0:formatIssues(t.error.issues)}const as=/^(\d+)(s|m|h|d)$/,os={s:1e3,m:6e4,h:36e5,d:864e5},ss=H.string().regex(as,{message:`Invalid duration format. Expected a number with a unit: '30m', '24h', '7d'`});function parseAge(e){let t=e.match(as);if(!t?.[1]||!t[2])throw R({code:`PRUNE_AGE_INVALID`,message:`invalid age format: ${e}`,command:`workspace prune`});let n=t[2];return parseInt(t[1],10)*os[n]}const cs=`sdk-expires-at`,ls=/^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(ls);if(!t?.[1])return;let n=Number(t[1]);if(!Number.isSafeInteger(n))return;let r=new Date(n*1e3);return Number.isNaN(r.getTime())?void 0:r}function readWorkspaceExpiry(e,t){let n=e?.[cs];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:Cn(e)}}}async function writeWorkspaceExpiry(e,t,n){await writeMetadataLabelsDirect(e,{trn:workspaceTrn(t),labels:{[cs]:encodeExpiresAt(n)}})}async function clearWorkspaceExpiry(e,t){await writeMetadataLabelsDirect(e,{trn:workspaceTrn(t),remove:[cs]})}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=en();return Promise.all(t.map(async t=>reportedExpiry(await r(()=>fetchWorkspaceExpiry(e,t,n)))))}function formatTimestamp(e){if(!e)return null;let t=W(e);return Number.isNaN(t.getTime())?null:t}function formatTable(e,t){return ft(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`:ar(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 K&&(e.code===G.NotFound||e.code===G.PermissionDenied))return;M.warn(`Failed to resolve workspace folder name: ${e}`);return}}function createWorkspaceFolderNameResolver(e){let t=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=fr(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 us=createWorkspaceNameTransformer(`name`,`folderName`),ds=H.object({name:is,region:H.string(),deleteProtection:H.boolean().optional(),organizationId:H.uuid().optional(),folderId:H.uuid().optional(),ttl:ss.optional(),profile:rs.optional()}),validateRegion=async(e,t)=>{let n=await t.listAvailableWorkspaceRegions({});if(!n.regions.includes(e))throw R({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{...mt(e)?{}:{platform_url:Mt(e)},...t?{oauth2_client_id:St(e)}:{},...n?{console_url:nn(n)}:{}}}async function createWorkspace$1(e){let t=validateCreateWorkspaceOptions(e),n=await loadAccessToken({profile:t.profile}),r=await loadPlatformClientConfig({profile:t.profile}),i=await P(n,r);return await validateRegion(t.region,i),createValidatedWorkspaceWithClient(i,t)}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=k(n.workspace,`createWorkspace response missing workspace`),i=t.ttl===void 0?void 0:await recordTtl(e,r.id,t.ttl,r.createTime),a=await workspaceInfoWithFolderName(e,r);return i?{...a,ttl:i}:a}async function recordTtl(e,t,n,r){let i=r?W(r):new Date,a=new Date(i.getTime()+parseAge(n));try{return await writeWorkspaceExpiry(e,t,a),{state:`written`,expiresAt:a}}catch(e){return{state:`unconfirmed`,expiresAt:a,requested:n,message:e instanceof Error?e.message:String(e)}}}function validateCreateWorkspaceOptions(e){return parseOptions(ds,e)}const fs=Y({name:`create`,description:`Create a new Tailor Platform workspace.`,args:H.strictObject({name:B(is,{alias:`n`,description:`Workspace name`}),region:B(H.string(),{alias:`r`,description:`Workspace region (us-west, asia-northeast)`}),"delete-protection":B(H.boolean().default(!1),{alias:`d`,description:`Enable delete protection`}),"organization-id":B(H.string().optional(),{alias:`o`,description:`Organization ID to workspace associate with`,env:`TAILOR_PLATFORM_ORGANIZATION_ID`}),"folder-id":B(H.string().optional(),{alias:`f`,description:`Folder ID to workspace associate with`,env:`TAILOR_PLATFORM_FOLDER_ID`}),ttl:B(ss.optional(),{description:"Record on the workspace itself when it becomes prunable, such as 30m, 24h, or 7d. `workspace prune --expired` deletes it once that has passed"}),"profile-name":B(H.string().optional(),{alias:`p`,description:`Profile name to create`}),profile:B(rs.optional(),{description:`Workspace profile used for authentication and Platform selection`,env:`TAILOR_PLATFORM_PROFILE`}),"profile-user":B(H.string().optional(),{description:`User email address or machine user client ID for the profile (defaults to current user)`}),permission:B(H.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 readPlatformConfig();if(r.profiles[t])throw R({code:`PROFILE_EXISTS`,message:`Profile "${t}" already exists.`});let i=e.profile,a=i?r.profiles[i]:void 0,o=a?platformConfigFromProfile(a):void 0,s=e[`profile-user`]||a?.user||r.current_user;if(!s)throw R({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=resolveConfigUser(r,s,o);if(!c)throw R({code:`USER_NOT_FOUND`,message:`User "${s}" not found.`,suggestion:`Verify the user name and log in.`,next:{command:`tailor`,args:[`login`,...recoveryContextArgs({profile:i})]}});n={name:t,user:c,platformSettings:profilePlatformSettings(o)}}let r=await createWorkspace$1({name:e.name,region:e.region,deleteProtection:e[`delete-protection`],organizationId:e[`organization-id`],folderId:e[`folder-id`],ttl:e.ttl,profile:e.profile}),i;if(n){let t=await readPlatformConfig(),a=n.platformSettings;t.profiles[n.name]={user:n.user,workspace_id:r.id,...e.permission===`read`?{readonly:!0}:{},...a},writePlatformConfig(t),i={name:n.name,user:n.user,workspaceId:r.id,permission:e.permission,...a.platform_url?{platformUrl:a.platform_url}:{},...a.oauth2_client_id?{oauth2ClientId:a.oauth2_client_id}:{},...a.console_url?{consoleUrl:a.console_url}:{}},e.json||M.success(`Profile "${n.name}" created successfully.`)}let{ttl:a,...o}=r;if(e.json||(M.success(`Workspace "${workspaceDisplayName(r)}" created successfully.`),a?.state===`written`&&M.info(`Workspace becomes prunable at ${a.expiresAt.toISOString()}.`)),e.json&&i?M.out({...o,profile:i}):(M.out(o,{display:{name:us,folderName:null}}),i&&(M.out(`Profile:`),M.out(i))),a?.state===`unconfirmed`)throw R({code:`WORKSPACE_TTL_WRITE_FAILED`,message:`Workspace "${workspaceDisplayName(r)}" was created, but --ttl could not be confirmed: ${a.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:r.id,requestedExpiresAt:a.expiresAt.toISOString(),...i?{profileCreated:i.name}:{}},next:{command:`tailor`,args:[`workspace`,`ttl`,`set`,`--ttl`,a.requested,...recoveryContextArgs({workspaceId:r.id,profile:e.profile})]}})}});async function listWorkspaces(e){let t=rs.optional().parse(e?.profile),n=await loadAccessToken({profile:t}),r=await loadPlatformClientConfig({profile:t});return listWorkspacesWithClient(await P(n,r),e)}async function listWorkspacesWithExpiry(e){let t=rs.optional().parse(e?.profile),n=await loadAccessToken({profile:t}),r=await loadPlatformClientConfig({profile:t}),i=await P(n,r),a=await listWorkspacesWithClient(i,e),o=await fetchReportedExpiries(i,a.map(({id:e})=>e),new Date);return a.map((e,t)=>{let n=o[t];return{...e,expiresAt:n===void 0?`unavailable`:n}})}async function listWorkspacesWithClient(e,t){let n=toPageDirection(t?.order);return workspaceInfosWithFolderNames(e,await jt(async(t,r)=>{let{workspaces:i,nextPageToken:a}=await e.listWorkspaces({pageToken:t,pageSize:r,pageDirection:n});return[i,a]},{limit:t?.limit}))}const ps=Y({name:`list`,description:`List all Tailor Platform workspaces.`,args:H.strictObject({...paginationArgs(),profile:B(rs.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});M.out(t,{display:{name:us,folderName:null,organizationId:null,folderId:null,updatedAt:null}})}}),ms=H.object({version:H.literal(1),platformUrl:H.url(),applicationId:H.string().min(1).optional(),workspaceId:H.uuid()});function defaultConfigPath(){return Un(process.cwd(),`tailor.config.ts`)}function contextPath(e){return Hn(Vn(e),$t(),`${Bn(e)}.context.json`)}async function loadWorkspaceContext(e,t=defaultConfigPath(),n){let r;try{r=await Ar(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=ms.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=ms.parse({...e,...n===void 0?{}:{applicationId:n}}),i=Hn(Vn(t),$t()),a=contextPath(t),o=`${JSON.stringify(r,null,2)}\n`;try{if(await Ar(a,`utf8`)===o)return}catch{}let s=`${a}.${process.pid}.${hr()}.tmp`;await kr(i,{recursive:!0});try{await Nr(s,o,{mode:384}),await jr(s,a)}catch(e){throw await Mr(s,{force:!0}).catch(()=>void 0),e}}function suggestedWorkspaceName(){let e=Bn(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 createDeployArgs(e,t,n){return[...deployArgs(e),`--create-workspace`,`--workspace-name`,t,`--workspace-region`,n,...e.organizationId?[`--organization-id`,e.organizationId]:[],...e.folderId?[`--folder-id`,e.folderId]:[]]}function selectDeployArgs(e){return[...deployArgs(e),`--workspace-id`,`<workspace-id>`]}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 R({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 R({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),...recoveryContextArgs({workspaceId:e.workspaceId})]),context:{workspaceId:e.workspaceId,configPaths:t.contextTargets?.map(({configPath:e})=>e)}});M.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),M.info(`Using workspace: ${workspaceLabel(n)}`),{client:e,workspaceId:n.id}}function useRememberedWorkspace(e,t){return M.warn(`Using saved workspace selection: ${workspaceLabel(t)}`),{client:e,workspaceId:t.id}}const hs=`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:hs}]});if(i===hs)return createWorkspaceForDeploy(e,t,r);let a=n.find(({id:e})=>e===i);if(!a)throw L(`Selected workspace was not found`);return useWorkspace(e,t,a,r)}function invalidCreateOptionsError(e,t,n,r){return R({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 createWorkspace(e,t,n,r,i){let a=n.workspaceName,o=n.workspaceRegion,s=canPrompt();if(s)a??=await X.text({message:`Workspace name`,default:suggestedWorkspaceName(),validate:validateWorkspaceName}),o??=await X.select({message:`Workspace region`,choices:r.map(e=>({name:e,value:e}))});else{let e=[...a===void 0?[`--workspace-name`]:[],...o===void 0?[`--workspace-region`]:[]];if(e.length>0)throw R({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(n,a??`<name>`,o??`<region>`)),context:{missingOptions:e}})}if(!a||!o)throw L(`Workspace creation options were not resolved`);let c=i;if(!c){try{c=validateCreateWorkspaceOptions({name:a,region:o,organizationId:n.organizationId,folderId:n.folderId})}catch(e){throw invalidCreateOptionsError(n,a,o,e instanceof Error?e.message:String(e))}if(!r.includes(o))throw invalidCreateOptionsError(n,a,o,`Region must be one of: ${r.join(`, `)}.`)}if(s){let e=[n.organizationId?`organization: ${n.organizationId}`:void 0,n.folderId?`folder: ${n.folderId}`:void 0].filter(e=>e!==void 0);if(!await X.confirm({message:`Create workspace "${a}" in ${o}${e.length>0?` (${e.join(`, `)})`:``}?`,default:!0}))throw R({code:`WORKSPACE_CREATION_CANCELLED`,message:`Workspace creation was cancelled.`})}let l;try{l=await createValidatedWorkspaceWithClient(e,c)}catch(e){throw e instanceof K&&![G.Canceled,G.Unknown,G.DeadlineExceeded,G.Aborted,G.Internal,G.Unavailable,G.DataLoss].includes(e.code)?e:R({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(n),`--json`])})}return await rememberWorkspaceContext({version:1,platformUrl:t,workspaceId:l.id},n),M.success(`Created workspace: ${workspaceLabel(l)}`),M.info(`Reuse this workspace with: ${Sn([`tailor`,`deploy`,...recoveryContextArgs({workspaceId:l.id,profile:n.profile})])}`),M.info(`Or set TAILOR_PLATFORM_WORKSPACE_ID=${l.id}.`),{client:e,workspaceId:l.id}}async function createWorkspaceForDeploy(e,t,n,r,i){let a=r??(await e.listAvailableWorkspaceRegions({})).regions;if(n.dryRun)throw R({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:a}});return createWorkspace(e,t,n,a,i)}async function resolveDeployWorkspace(e={}){let t=[e.workspaceName===void 0?void 0:`--workspace-name`,e.workspaceRegion===void 0?void 0:`--workspace-region`].filter(e=>e!==void 0);if(!e.createWorkspace&&t.length>0)throw R({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(e,e.workspaceName??`<name>`,e.workspaceRegion??`<region>`)),context:{options:t}});if(e.createWorkspace&&e.workspaceName!==void 0){let t=validateWorkspaceName(e.workspaceName);if(t!==!0)throw invalidCreateOptionsError(e,e.workspaceName,e.workspaceRegion??`<region>`,t)}if(e.createWorkspace&&e.workspaceRegion===``)throw invalidCreateOptionsError(e,e.workspaceName??`<name>`,e.workspaceRegion,`Region must not be empty.`);let n=await tryLoadWorkspaceId({workspaceId:e.workspaceId,profile:e.profile}),r=await loadAccessToken({profile:e.profile}),i=await loadPlatformClientConfig({profile:e.profile,allowMissingProfile:n!==void 0}),a=Mt(i),o=await P(r,i);if(n){let t;try{t=await o.getWorkspace({workspaceId:n})}catch(e){throw e instanceof K&&e.code===G.NotFound?R({code:`WORKSPACE_NOT_FOUND`,message:`Workspace "${n}" was not found.`}):e}if(!t.workspace)throw R({code:`WORKSPACE_NOT_FOUND`,message:`Workspace "${n}" was not found.`});return useWorkspace(o,a,workspaceInfo(t.workspace),e,`warn`)}let s;if(e.createWorkspace&&e.workspaceName!==void 0&&e.workspaceRegion!==void 0)try{s=validateCreateWorkspaceOptions({name:e.workspaceName,region:e.workspaceRegion,organizationId:e.organizationId,folderId:e.folderId})}catch(t){throw invalidCreateOptionsError(e,e.workspaceName,e.workspaceRegion,t instanceof Error?t.message:String(t))}let[c,l]=await Promise.all([loadProjectContexts(a,e.contextTargets),listWorkspacesWithClient(o)]),u=canPrompt(),d=new Set(c.map(({workspaceId:e})=>e)),f=d.size===1?l.find(({id:e})=>d.has(e)):void 0;if(f&&(!e.createWorkspace||workspaceMatchesRequestedIdentity(f,e))){let t=projectContextTargets(e.contextTargets)?.length??1;return c.length===t?useRememberedWorkspace(o,f):useWorkspace(o,a,f,e)}let p=l.length===1?l[0]:void 0,m=p!==void 0&&s!==void 0&&workspaceMatchesRequestedIdentity(p,e),h;if(s&&!m&&(h=await o.listAvailableWorkspaceRegions({}),!h.regions.includes(s.region)))throw invalidCreateOptionsError(e,s.name,s.region,`Region must be one of: ${h.regions.join(`, `)}.`);if(l.length===0&&(u||e.createWorkspace||c.length===0)){let t=h?.regions??(await o.listAvailableWorkspaceRegions({})).regions;if(e.dryRun||u||e.createWorkspace)return createWorkspaceForDeploy(o,a,e,t,s);throw R({code:`WORKSPACE_NOT_FOUND`,message:`No workspaces are available for this account.`,suggestion:`Create one during deploy by providing the workspace name and one of the available regions.`,next:executableAction(createDeployArgs(e,`<name>`,`<region>`)),context:{availableRegions:t}})}if(d.size>1){let t=e.createWorkspace===!0&&e.workspaceName!==void 0&&e.workspaceRegion!==void 0&&l.length===0;if(!u&&!t)throw R({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(e)),context:{savedWorkspaceIds:[...d]}});if(l.length>0&&!e.createWorkspace)return chooseWorkspace(o,a,l,e)}if(!f&&c.length>0){let t=e.createWorkspace===!0&&e.workspaceName!==void 0&&e.workspaceRegion!==void 0&&l.length<=1;if(!u&&!t)throw R({code:`WORKSPACE_CONTEXT_STALE`,message:`The saved project workspace is no longer available.`,suggestion:`Choose an available workspace explicitly before deploying.`,next:executableAction(selectDeployArgs(e)),context:{savedWorkspaceIds:[...d],workspaces:l.map(workspaceIdentity)}});if(l.length>0&&u&&!e.createWorkspace)return chooseWorkspace(o,a,l,e)}if(l.length===1){let[t]=l;if(!t)throw L(`Workspace discovery returned an invalid result`);if(e.createWorkspace&&!workspaceMatchesRequestedIdentity(t,e))throw R({code:`WORKSPACE_CREATE_CONFLICT`,message:`The existing workspace does not match the requested workspace.`,suggestion:`Use the existing workspace, or run the explicit workspace create command to create another one.`,next:executableAction([`workspace`,`create`,...workspaceCommandArgs(e),...e.workspaceCommandJson?[`--json`]:[],`--name`,e.workspaceName??`<name>`,`--region`,e.workspaceRegion??`<region>`,...e.organizationId?[`--organization-id`,e.organizationId]:[],...e.folderId?[`--folder-id`,e.folderId]:[]]),context:{existingWorkspace:workspaceIdentity(t)}});return u&&!e.createWorkspace?chooseWorkspace(o,a,l,e):useWorkspace(o,a,t,e)}if(l.length>1){if(!u)throw R({code:`WORKSPACE_SELECTION_REQUIRED`,message:`Multiple workspaces are available.`,suggestion:`Choose one explicitly for non-interactive deployment.`,next:executableAction(selectDeployArgs(e)),context:{workspaces:l.map(workspaceIdentity)}});return chooseWorkspace(o,a,l,e)}throw L(`Workspace discovery returned an invalid result`)}function collectExpectedLocalStaticWebsiteNames(e){let t=new Set;for(let n of e)for(let e of n.application.staticWebsiteServices)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=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=>F(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?.envFile?[`--env-file`,V.resolve(process.cwd(),t.envFile)]:[],...t?.envFileIfExists?[`--env-file-if-exists`,V.resolve(process.cwd(),t.envFileIfExists)]:[],...recoveryContextArgs({profile:e?.profile})]}function recoveryOutputArgs(e){return[...e?.verbose?[`--verbose`]:[],...e?.json||M.jsonMode?[`--json`]:[]]}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`]:[],...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=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 R({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,migrationTestBaselines:s,migrationTestSnapshots:c}=e,{config:l,application:u,workflowBuildResult:d,httpAdapterBuildResult:f,bundledScripts:p}=t,m=ownedSubscriptions(r.eventSubscriptions,t),h=u.tailorDBServices.map(e=>{let t=c?.get(e.namespace);return t?{...e,types:t.tables,typeSourceInfo:{}}:e});await z(`plan.validateTailorDBTypeNames`,()=>Dt({client:i,workspaceId:a,tailorDBServices:h,externalTailorDBNamespaces:u.externalTailorDBNamespaces,plannedExternalTailorDBServices:collectPlannedExternalTailorDBServices(t,n)}));let g=u.workflowService,_=collectFunctionEntries(u,filterBundledWorkflowJobs(g?.jobs??[],d?.usedJobNames??[]),p),v=await z(`plan.detectSdkVersionChange`,()=>shouldForceApplyAll(i,a,u,_));return z(`plan`,async()=>{let e=n.map(e=>e.application),p=collectVisibleTailorDBTypeNamespaces(u,e),h=collectVisibleResolverNamespaces(u,e),y=collectVisibleIdpNames(u,e),b={client:i,workspaceId:a,application:u,forRemoval:!1,config:l,noSchemaCheck:o,migrationTestBaselines:s,migrationTestSnapshots:c,forceApplyAll:v,...r,idpUserTriggerTargets:subscribedIdps(m),executorUsedTailorDBTables:subscribedTailorDBTables(m),executorUsedResolvers:subscribedResolvers(m),dependentApps:collectDependentApps(m),tailorDBTypeNamespaces:p,resolverNamespaces:h,idpNames:y},x=await z(`plan.functionRegistry`,()=>planFunctionRegistry(i,a,u.name,u.id,_)),S=new Set(x.changeSet.unchanged.filter(e=>e.name.startsWith(Ui)).map(e=>e.name.slice(10))),[C,w,ee,te,ne,re,ie,ae,oe,se,ce]=await Promise.all([z(`plan.tailorDB`,()=>planTailorDB(b)),z(`plan.staticWebsite`,()=>planStaticWebsite(b)),z(`plan.aiGateway`,()=>planAIGateway(b)),z(`plan.idp`,()=>planIdP(b)),z(`plan.auth`,()=>planAuth(b)),z(`plan.pipeline`,()=>planPipeline(b)),z(`plan.application`,()=>planApplication(b,f)),z(`plan.executor`,()=>planExecutor(b)),z(`plan.workflow`,()=>planWorkflow(i,a,u.name,u.id,g?.workflows??{},d?.mainJobDeps??{},S,{...subscribedWorkflows(m),jobPublishEvents:collectWorkflowJobPublishEvents(t),dependentApps:b.dependentApps,runAppIds:b.runAppIds})),z(`plan.workflowExecutionPolicy`,()=>planWorkflowJobFunctionExecutionPolicy(i,a,u.name,u.id,l.workflow?.executionPolicies??{})),z(`plan.secretManager`,()=>planSecretManager(b))]);return{application:u,functionRegistry:x,tailorDB:C,staticWebsite:w,aiGateway:ee,idp:te,auth:ne,pipeline:re,app:ie,executor:ae,workflow:oe,workflowExecutionPolicy:se,secretManager:ce}})}async function planDeploymentTargets(e){let{targets:t,planTarget:n=planDeploymentTarget,...r}=e;return Promise.all(t.map(e=>n({...r,target:e,targets:t})))}async function confirmDeploymentPlans(e){let{deployments:t,yes:n,dryRun:r=!1,missingDependentApps:i=[]}=e;r||await confirmMigrationCheckpointRepairs(t.flatMap(e=>e.tailorDB.context.checkpointRepairs),n),await confirmMissingDependentApps(i,n);let a=new Set(t.map(e=>e.application.name)),o=collectDeploymentResourceOwners(t),s=new Set,c=[];for(let e of t){let t=deploymentPlanResults(e),r=collectOwnerConflicts(t);await confirmOwnerConflict(r,e.application.name,n,e.application.id),await confirmUnmanagedResources(collectUnmanagedResources(t),e.application.name,n),c.push(...collectImportantResourceDeletions(t));let i=computeRenamedAppDeletions({conflicts:r,resourceOwners:o,protectedAppNames:a});for(let t of i)s.has(t)||(s.add(t),e.app.deletes.push({name:t,request:{workspaceId:e.tailorDB.context.workspaceId,applicationName:t}}))}await confirmImportantResourceDeletion(c,n)}async function validateDeploymentPlans(e){for(let t of e)await validatePlan(deploymentPlanResults(t))}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 z(`deploy`,async i=>{i.setAttribute(`deploy.dry_run`,t?.dryRun??!1),mn(),e();let a=parseDeployConfigPaths(t?.configPath),o=t?.dryRun??!1,s=t?.buildOnly??ut(process.env.TAILOR_DEPLOY_BUILD_ONLY)===!0,c=s?[]:await z(`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||M.jsonMode}),f=await z(`build`,async()=>{let e=t?.noCache??!1,n=await vn(),r=V.resolve($t(),`cache`);return t?.cleanCache&&(U.rmSync(r,{recursive:!0,force:!0}),M.info(`Bundle cache cleaned`)),await buildDeploymentTargets({configPaths:a,loadedConfigs:s?void 0:c,dryRun:o,buildOnly:s,noCache:e,packageVersion:n.version??`unknown`,cacheDir:r})});if(s)return{bundledScripts:mergeBundledScripts(f)};if(assertUniqueGlobalResourceNames(f),!d)throw L(`Workspace was not resolved`);let{client:p,workspaceId:m}=d;i.setAttribute(`app.name`,f.map(e=>e.application.name).join(`,`)),i.setAttribute(`workspace.id`,m);let h=f.map(e=>({...e,application:adjustApplicationForMigrationTest(e.application,r)})),g=await z(`plan.metadataLookup`,()=>createMetadataLookupClient({client:p,workspaceId:m,applications:h.map(({application:e})=>e)})),_=collectDeployRunPlanInputs(h,!t?.dryRun),v=await planDeploymentTargets({targets:h,runInputs:_,client:g,workspaceId:m,noSchemaCheck:t?.noSchemaCheck,migrationTestBaselines:r?.migrationTestBaselines,migrationTestSnapshots:r?.migrationTestSnapshots}),y=t?.yes??!1;dropCrossDeploymentManagedDeletes(v);let b=(await Promise.all(h.map(e=>fetchMissingDependentApps({client:g,workspaceId:m,application:e.application,runAppIds:_.runAppIds??new Set,subscribedKeys:subscribedResourceKeys(_.eventSubscriptions,e),jobsByWorkflow:e.workflowBuildResult?.mainJobDeps??{}})))).flat();await z(`confirm`,async()=>{await confirmDeploymentPlans({deployments:v,yes:y,dryRun:o,missingDependentApps:b})});let x=printDeploymentPlans(v,{dryRun:t?.dryRun});if(t?.noValidate?M.warn(`Client-side validation skipped (--no-validate).`):await validateDeploymentPlans(v),o){M.info(`Dry run enabled. No changes applied.`);return}await applyDeploymentPlans(p,m,v),r?.suppressResultOutput||(M.jsonMode?M.out({summary:x,status:`applied`}):M.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})}function deployMigrationTestTarget(e,t){return deployInternal(e,void 0,{migrationTestSnapshots:t,suppressResultOutput:!0})}function deployFromCLI(e,t){return deployInternal(e,t)}function colorizeExecutorJobStatus(e){switch(e){case`PENDING`:return j.dim(e);case`RUNNING`:return j.info(e);case`SUCCESS`:return j.success(e);case`FAILED`:return j.error(e);case`CANCELED`:return j.warning(e);default:return e}}function isExecutorJobTerminalStatus(e){return isExecutorJobSuccessStatus(e)||isExecutorJobFailureStatus(e)}function isExecutorJobSuccessStatus(e){return e===T.SUCCESS}function isExecutorJobFailureStatus(e){return e===T.FAILED||e===T.CANCELED}function isExecutorJobTransientStatus(e){return e===T.UNSPECIFIED||e===T.PENDING||e===T.RUNNING}function classifyExecutorJobStatus(e){return isExecutorJobSuccessStatus(e)?`success`:isExecutorJobTerminalStatus(e)?`failure`:(isExecutorJobTransientStatus(e),`transient`)}function parseExecutorJobStatus(e){switch(e.toUpperCase()){case`PENDING`:return T.PENDING;case`RUNNING`:return T.RUNNING;case`SUCCESS`:return T.SUCCESS;case`FAILED`:return T.FAILED;case`CANCELED`:return T.CANCELED;default:throw R({code:`EXECUTOR_STATUS_INVALID`,message:`Invalid status: ${e}. Valid values: PENDING, RUNNING, SUCCESS, FAILED, CANCELED`})}}function executorTargetTypeToString(e){switch(e){case O.WEBHOOK:return`WEBHOOK`;case O.TAILOR_GRAPHQL:return`GRAPHQL`;case O.FUNCTION:return`FUNCTION`;case O.JOB_FUNCTION:return`JOB_FUNCTION`;case O.WORKFLOW:return`WORKFLOW`;default:return`UNSPECIFIED`}}function executorTriggerTypeToString(e){switch(e){case Be.SCHEDULE:return`SCHEDULE`;case Be.EVENT:return`EVENT`;case Be.INCOMING_WEBHOOK:return`INCOMING_WEBHOOK`;default:return`UNSPECIFIED`}}function executorJobStatusToString(e){switch(e){case T.PENDING:return`PENDING`;case T.RUNNING:return`RUNNING`;case T.SUCCESS:return`SUCCESS`;case T.FAILED:return`FAILED`;case T.CANCELED:return`CANCELED`;default:return`UNSPECIFIED`}}function toExecutorJobListInfo(e){return{id:e.id,executorName:e.executorName,status:executorJobStatusToString(e.status),createdAt:e.createdAt?W(e.createdAt).toISOString():`N/A`}}function toExecutorJobInfo(e){return{id:e.id,executorName:e.executorName,status:executorJobStatusToString(e.status),scheduledAt:e.scheduledAt?W(e.scheduledAt).toISOString():`N/A`,createdAt:e.createdAt?W(e.createdAt).toISOString():`N/A`,updatedAt:e.updatedAt?W(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?W(e.startedAt).toISOString():`N/A`,finishedAt:e.finishedAt?W(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 gs={name:B(H.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 R({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 K&&e.code===G.NotFound?R({code:`EXECUTOR_NOT_FOUND`,message:`Executor '${t}' not found.`,cause:e}):e}}const _s=Y({name:`get`,description:`Get executor details`,args:H.strictObject({...J,...gs}),run:async e=>{let t=await getExecutor({executor:{name:e.name},workspaceId:e[`workspace-id`],profile:e.profile});M.out(t,{display:{triggerConfig:null,targetConfig:null}})}});function functionExecutionStatusToString(e){switch(e){case h.RUNNING:return`RUNNING`;case h.SUCCESS:return`SUCCESS`;case h.FAILED:return`FAILED`;case h.SUSPEND:return`SUSPEND`;case h.CANCELING:return`CANCELING`;case h.CANCELED:return`CANCELED`;default:return`UNSPECIFIED`}}function colorizeFunctionExecutionStatus(e){switch(e){case`RUNNING`:return j.info(e);case`SUCCESS`:return j.success(e);case`FAILED`:return j.error(e);default:return e}}function isFunctionExecutionTerminalStatus(e){return e===h.SUCCESS||e===h.FAILED||e===h.CANCELED}function functionLogSeverityToString(e){switch(e){case p.LOG:return`LOG`;case p.DEBUG:return`DEBUG`;case p.INFO:return`INFO`;case p.WARNING:return`WARNING`;case p.ERROR:return`ERROR`;default:return`UNSPECIFIED`}}function toFunctionLogEntryInfo(e){return{message:e.message,severity:functionLogSeverityToString(e.severity),timestamp:e.timestamp?W(e.timestamp):null}}function colorizeLogSeverity(e){let t=`[${e}]`;switch(e){case`ERROR`:return j.error(t);case`WARNING`:return j.warning(t);case`DEBUG`:return j.dim(t);default:return t}}function formatFunctionLogEntry(e){let t=e.timestamp?e.timestamp.toISOString():`N/A`;return`${j.dim(t)} ${colorizeLogSeverity(e.severity)} ${e.message}`}function formatFunctionLogLines(e,t){return e&&e.length>0?e.map(formatFunctionLogEntry):t?t.split(`
|
|
132
|
-
`):[]}function formatWaitError(e){return e instanceof Error?e.message:String(e)}function isRetryableWaitError(e){return e instanceof K?e.code===G.Aborted||e.code===G.ResourceExhausted||e.code===G.Unavailable:!1}const vs=H.enum([`success`,`suspended`,`terminal`]),ys={name:B(H.string(),{positional:!0,description:`Workflow name`})},bs={interval:B(Gr.default(`3s`),{alias:`i`,description:`Polling interval when waiting (e.g., '3s', '500ms', '1m')`}),timeout:B(Gr.default(`10m`),{alias:`t`,description:`Maximum time to wait (e.g., '30s', '10m')`}),until:B(vs.default(`terminal`),{alias:`u`,description:`Wait target (success, suspended, terminal)`}),logs:B(H.boolean().default(!1),{alias:`l`,description:`Display job execution logs after completion`})},xs={wait:B(H.boolean().default(!1),{alias:`W`,description:`Wait for execution to complete`}),...bs};function isWorkflowExecutionSuccessStatus(e){return e===D.SUCCESS}function isWorkflowJobExecutionSuspendedStatus(e){return e===Qe.SUSPEND||e===Qe.WAITING}function isWorkflowExecutionSuspendedStatus(e){return e===D.PENDING_RESUME||e===D.WAITING}function isWorkflowExecutionFailureStatus(e){return e===D.FAILED}function isWorkflowExecutionTransientStatus(e){return e===D.UNSPECIFIED||e===D.PENDING||e===D.RUNNING||e===D.PENDING_RETRY}function isWorkflowExecutionTerminalStatus(e){return isWorkflowExecutionSuccessStatus(e)||isWorkflowExecutionFailureStatus(e)||isWorkflowExecutionSuspendedStatus(e)}function classifyWorkflowExecutionStatus(e){return isWorkflowExecutionTerminalStatus(e.status)?isWorkflowExecutionSuccessStatus(e.status)?{statusClass:`success`,status:e.status}:isWorkflowExecutionFailureStatus(e.status)?{statusClass:`failure`,status:e.status}:{statusClass:`suspended`,status:e.status}:e.jobExecutions.some(e=>isWorkflowJobExecutionSuspendedStatus(e.status))?{statusClass:`suspended`,status:e.status}:(isWorkflowExecutionTransientStatus(e.status),{statusClass:`transient`,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 workflowExecutionStatusToString(e){switch(e){case D.PENDING:return`PENDING`;case D.PENDING_RESUME:return`PENDING_RESUME`;case D.RUNNING:return`RUNNING`;case D.SUCCESS:return`SUCCESS`;case D.FAILED:return`FAILED`;case D.PENDING_RETRY:return`PENDING_RETRY`;case D.WAITING:return`WAITING`;default:return`UNSPECIFIED`}}function workflowJobExecutionStatusToString(e){switch(e){case Qe.RUNNING:return`RUNNING`;case Qe.SUSPEND:return`SUSPEND`;case Qe.SUCCESS:return`SUCCESS`;case Qe.FAILED:return`FAILED`;case Qe.WAITING:return`WAITING`;default:return`UNSPECIFIED`}}function toWorkflowListInfo(e){return{name:e.name,mainJob:e.mainJobFunctionName,jobFunctions:Object.keys(e.jobFunctions).length,updatedAt:e.updatedAt?W(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?W(e.createdAt):null,updatedAt:e.updatedAt?W(e.updatedAt):null}}function toWorkflowJobExecutionInfo(e){return{id:e.id,stackedJobName:e.stackedJobName,status:workflowJobExecutionStatusToString(e.status),executionId:e.executionId,startedAt:e.startedAt?W(e.startedAt):null,finishedAt:e.finishedAt?W(e.finishedAt):null}}function toWorkflowExecutionInfo(e){return{id:e.id,workflowName:e.workflowName,status:workflowExecutionStatusToString(e.status),jobExecutions:e.jobExecutions.length,startedAt:e.startedAt?W(e.startedAt):null,finishedAt:e.finishedAt?W(e.finishedAt):null}}function formatTime$1(e){return e.toLocaleTimeString(`en-US`,{hour12:!1})}function colorizeStatus(e){let t=D[e];switch(e){case D.PENDING:case D.UNSPECIFIED:return j.dim(t);case D.PENDING_RESUME:case D.PENDING_RETRY:case D.WAITING:return j.warning(t);case D.RUNNING:return j.info(t);case D.SUCCESS:return j.success(t);case D.FAILED:return j.error(t);default:return t}}function getActiveJobs(e){return e.jobExecutions.filter(e=>e.status===Qe.RUNNING||e.status===Qe.SUSPEND||e.status===Qe.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.`),R({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(),M.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(),M.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(new Date)})`),hasReachedWorkflowWaitTarget(u,n)||u.statusClass===`failure`||n===`suspended`&&u.statusClass===`success`)return t.status===D.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(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 Fr(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 R({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 R({code:`WORKFLOW_EXECUTION_FAILED`,message:`Workflow execution '${e.id}' failed.`,context:n});if(t===`success`&&e.statusClass!==`success`)return R({code:`WORKFLOW_EXECUTION_NOT_SUCCESSFUL`,message:`Workflow execution '${e.id}' reached ${e.status} before success.`,context:n});if(t===`suspended`&&e.statusClass!==`suspended`)return R({code:`WORKFLOW_EXECUTION_NOT_SUSPENDED`,message:`Workflow execution '${e.id}' reached ${e.status} before suspension.`,context:n})}function parseStatus(e){switch(e.toUpperCase()){case`PENDING`:return D.PENDING;case`PENDING_RESUME`:return D.PENDING_RESUME;case`RUNNING`:return D.RUNNING;case`SUCCESS`:return D.SUCCESS;case`FAILED`:return D.FAILED;case`PENDING_RETRY`:return D.PENDING_RETRY;case`WAITING`:return D.WAITING;case`UNSPECIFIED`:return D.UNSPECIFIED;default:throw R({code:`WORKFLOW_STATUS_INVALID`,message:`Invalid status: ${e}. Valid values: UNSPECIFIED, PENDING, PENDING_RESUME, RUNNING, SUCCESS, FAILED, PENDING_RETRY, WAITING`,command:`workflow executions`})}}async function listWorkflowExecutions(e){let t=e?.workflow?.name,{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:e?.profile,workspaceId:e?.workspaceId}),i=[];if(e?.status){let t=parseStatus(e.status);i.push(Gn(Ke,{condition:Gn(Ze,{field:`status`,operator:ze.EQ,value:{kind:{case:`numberValue`,value:t}}})}))}let a=i.length>0?Gn(Ke,{and:i}):void 0,o=toPageDirection(e?.order??`desc`);return(await jt(async(e,i)=>{let{executions:s,nextPageToken:c}=await n.listWorkflowExecutions({workspaceId:r,workflowName:t??``,pageToken:e,pageSize:i,pageDirection:o,filter:a});return[s,c]},{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 K&&t.code===G.NotFound||M.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 R({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,logs:n.logs||void 0,logEntries:n.logEntries.length>0?n.logEntries.map(toFunctionLogEntryInfo):void 0,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(M.out(formatKeyValueTable(t)),e.jobDetails&&e.jobDetails.length>0){M.log(j.bold(`
|
|
130
|
+
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)}`),R({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 R({code:`APP_ID_NOT_RECORDED`,message:`No app id is recorded for ${t}.`,suggestion:rekeyInstructions([e])});return M.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},a=!1,o=n.map(()=>void 0),s=[],c=new Map(Object.entries(i).map(([e,t])=>[t.toLowerCase(),e])),exists=e=>U.existsSync(V.join(t.root,e));n.forEach(({configPath:e,configId:n},l)=>{let u=appIdLockKey(t.root,e),d=i[u];if(d!==void 0){if(n!==void 0&&n.toLowerCase()!==d.toLowerCase())throw R({code:`APP_ID_CONFLICT`,message:`${Q} records app id "${d}" for ${u}, 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.`});let t=n!==void 0&&r===`write`;n!==void 0&&!t&&warnConfigStillCarriesId(u),o[l]={configPath:e,key:u,id:d,source:`lock`,removeConfigId:t};return}if(n!==void 0){if(!is.test(n))throw R({code:`CONFIG_ID_INVALID`,message:`'id' in ${e} must be a UUID.`,suggestion:`To use this config for a separate app, delete it.`});let t=c.get(n.toLowerCase()),s=t!==void 0&&t!==u&&!exists(t)?t:void 0;if(t!==void 0&&t!==u&&s===void 0)throw R({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.`});c.set(n.toLowerCase(),u);let d=r===`write`;d?(s!==void 0&&(delete i[s],M.info(`Keeping the app id of ${s} for ${u}: ${n}`)),i[u]=n,a=!0):warnUnrecordedConfigId(u),o[l]={configPath:e,key:u,id:n,source:`config`,removeConfigId:d};return}s.push({index:l,configPath:e,key:u})});let finish=()=>({appIds:i,changed:a,entries:o.map(e=>k(e,`app id entry missing`))});if(s.length===0)return finish();if(r===`read`){for(let{index:e,configPath:t,key:n}of s)warnMissingLockedAppId(n),o[e]={configPath:t,key:n,id:void 0,source:`none`,removeConfigId:!1};return finish()}let l=Object.keys(i).filter(e=>!exists(e)),u=[...new Set(s.map(({key:e})=>e))];if(r===`require`)throw missingInCIError(u,l);let d;if(l.length===1&&u.length===1){let e=k(l[0],`orphan missing`),t=k(u[0],`key missing`);await confirmMove(e,t)&&(d={from:e,key:t})}else if(l.length>0)throw R({code:`APP_ID_NOT_RECORDED`,message:`No app id is recorded for ${u.join(`, `)}.`,suggestion:rekeyInstructions(l)});for(let{index:e,configPath:t,key:n}of s){let r=i[n];if(r!==void 0){o[e]={configPath:t,key:n,id:r,source:`generated`,removeConfigId:!1};continue}let s;d?.key===n?(s=k(i[d.from],`orphaned app id missing`),delete i[d.from],M.info(`Keeping the app id of ${d.from} for ${n}: ${s}`)):(s=crypto.randomUUID(),M.info(`Generated app id for ${n}: ${s}`)),i[n]=s,a=!0;let c=d?.key===n?`lock`:`generated`;o[e]={configPath:t,key:n,id:s,source:c,removeConfigId:!1}}return finish()}function writeAppIds(e){let{lock:t,appIds:n}=e,r=readRawLock(t.root);if(r===null)throw R({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};U.writeFileSync(V.join(t.root,Q),`${JSON.stringify(a,null,2)}\n`,`utf-8`)}async function removeAdoptedConfigIds(e){let t=!1,n=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,M.info(`Moved the app id of ${r.key} from the config into ${Q}.`)):M.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=ut(process.env.TAILOR_CI_ALLOW_ID_INJECTION)===!0;return Dr&&!t?`require`:e?`read`:`write`}function parseDeployConfigPaths(e){let t=e??process.env.TAILOR_PLATFORM_SDK_CONFIG_PATH;if(t===void 0)return[void 0];let n=t.split(`,`).map(e=>e.trim());if(n.some(e=>e.length===0))throw R({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:a,packageVersion:o,cacheDir:s}=e,{config:c,plugins:l}=n??k((await loadDeployConfigs({configPaths:[t],dryRun:r,buildOnly:i}))[0],`loaded config missing`),u=V.dirname(c.path),d=hr(`pnpm-lock.yaml`,{cwd:u})??hr(`package-lock.json`,{cwd:u})??hr(`yarn.lock`,{cwd:u})??hr(`bun.lock`,{cwd:u}),f=createCacheManager({enabled:!a,cacheDir:s,sdkVersion:o,lockfileHash:d?gt(d):void 0}),p;l.length>0&&(p=new On(l)),await z(`build.generateUserTypes`,()=>generateUserTypes({config:c,configPath:c.path}));let m,h,g,_;try{let e=await z(`build.loadApplication`,()=>Zt({config:c,pluginManager:p,bundleCache:f.bundleCache}));m=e.application,h=e.workflowBuildResult,g=e.httpAdapterBuildResult,_=e.bundledScripts}finally{f.finalize()}return{config:c,application:m,workflowBuildResult:h,httpAdapterBuildResult:g,bundledScripts:_}}function resolveExistingConfigPath(e){let t=loadConfigPath(e);if(!t)return;let n=V.resolve(process.cwd(),t);return U.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=>z(`build.prepareConfig`,async()=>{findAppIdLock(e)===null&&await ensureConfigIdForDeploy({configPath:e,dryRun:n,buildOnly:r})})))}async function loadPreparedDeployConfig(e){return z(`build.loadConfig`,()=>loadConfig(e.configPath))}async function resolveDeployAppIds(e){let{loaded:t,dryRun:n,buildOnly:r}=e;if(r)return[...t];let i=[...t],a=new Map;t.forEach((e,t)=>{let n=findAppIdLock(e.config.path);if(n===null){warnMissingAppId(e.config.id);return}let r=a.get(n.root)??{lock:n,indexes:[]};r.indexes.push(t),a.set(n.root,r)});let o=appIdPlanModeForDeploy(n);for(let{lock:e,indexes:n}of a.values()){let r=await resolveLockedAppIds({lock:e,mode:o,entries:n.map(e=>{let{config:n}=k(t[e],`loaded config missing`);return{configPath:n.path,configId:n.id}})});n.forEach((e,n)=>{let a=k(t[e],`loaded config missing`),o=k(r.entries[n],`planned app id entry missing`).id;i[e]={...a,config:{...a.config,id:o}}})}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,...i}=e;if(n!==void 0&&(n.length!==t.length||t.some((e,t)=>n[t]===void 0)))throw L(`loadedConfigs must contain exactly one entry for every configPath`);let a=r===void 0&&n===void 0?await loadDeployConfigs({configPaths:t,dryRun:e.dryRun,buildOnly:e.buildOnly}):n,o=r??buildDeploymentTarget;return Promise.all(t.map((e,t)=>o({...i,configPath:e,loadedConfig:a?.[t]})))}function addPossiblyAmbiguousNamespace(e,t,n){if(e.has(t)){e.get(t)!==n&&e.set(t,void 0);return}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 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:()=>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:()=>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:()=>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 R({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:new Set},n={workflowNames: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=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)??new Map;o.set(e,`publish-events`),t.set(a,o)}return t}function collectWorkflowJobPublishEvents(e){let t=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:Qi.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:Qi.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:Qi.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`?Zi.workflow(r.workflowName):Zi.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 R({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){for(let t of cs){let n=new Set;for(let r of e)for(let e of t.namesOf(r)){if(n.has(e))throw R({code:`DEPLOY_DUPLICATE_RESOURCE_NAME`,message:`Duplicate ${t.resourceLabel} name "${e}" across config files. ${t.resourceLabel} names must be unique across all configs in a single deploy.`});n.add(e)}}}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({resourceType:`TailorDB table`,resourceName:n.name});for(let n of e.staticWebsite.changeSet.deletes)t.push({resourceType:`StaticWebsite`,resourceName:n.name});for(let n of e.aiGateway.changeSet.deletes)t.push({resourceType:`AIGateway`,resourceName:n.name});for(let n of e.auth.changeSet.oauth2Client.deletes)t.push({resourceType:`OAuth2 client`,resourceName:n.name});for(let n of e.auth.changeSet.oauth2Client.replaces)t.push({resourceType:`OAuth2 client (client type change)`,resourceName:n.name});for(let n of e.auth.changeSet.connection.deletes)t.push({resourceType:`Auth connection`,resourceName:n.name});for(let n of e.secretManager.vaultChangeSet.deletes)t.push({resourceType:`Secret Manager vault`,resourceName:n.name});for(let n of e.secretManager.secretChangeSet.deletes)t.push({resourceType:`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){if(isManagedResourceClaimed(t,e,r)){M.debug(`Skipping delete of ${managedResourceKey(e,r)}: still managed by another config in this deploy.`);continue}e.changeSet.deletes[n]=r,n+=1}e.changeSet.deletes.length=n}function workflowJobFunctionItems(e){let t=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`],cs=[{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`},...cs.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},new Set));t.forEach((e,t)=>{let r=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=new Set;for(let n of e)for(let e of collectResourceOwners(deploymentPlanResults(n)))t.add(e);return t}function ownershipFilters(e){let t=new Map;for(let n of e)if(t.set(`${zi}\0${n.name}`,{[zi]:n.name}),n.id){let e=sdkAppIdLabelValue(n.id);t.set(`${Vi}\0${e}`,{[Vi]:e})}return[...t.values()]}async function createMetadataLookupClient(e){let{client:t,workspaceId:n,applications:r}=e,i=await Promise.all(ownershipFilters(r).map(e=>N(async(r,i)=>{let{results:a,nextPageToken:o}=await t.listMetadata({workspaceId:n,labels:e,pageToken:r,pageSize:i});return[a,o]}))),a=new Map;for(let e of i.flat())e.metadata&&a.set(e.trn,e.metadata);let o=new Map,getMetadata=(e,n)=>{let r=a.get(e.trn??``);if(r)return Promise.resolve(Xn(ne,{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),i=formatChangeSetEntries(e.workflowExecutionPolicy.changeSet,[`executionPolicy`]),a=formatAuthHookChangeEntries(e.auth.changeSet.authHook,e.functionRegistry.authHookFunctionChanges),o=formatTailorDBResourceChangeEntries(e.tailorDB.changeSet.type,e.tailorDB.changeSet.gqlPermission),s=e.tailorDB.context.checkpointRepairs.map(e=>({action:`update`,symbol:Xi.update,name:`migration checkpoint ${formatMigrationNumber(e.from)} → ${formatMigrationNumber(e.to)}`,labels:[`migrationCheckpoint`],namespace:e.namespace})),c=[...o,...s],l=[...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,u=[...formatChangeSetEntries(e.idp.changeSet.client,[`client`],namespaceOf)],d=[...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),...a,...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:f}=splitFunctionRegistryChanges(e.functionRegistry.changeSet),p=extractServiceActions(e.tailorDB.changeSet.service),m=extractServiceActions(e.pipeline.changeSet.service),h=extractServiceActions(e.idp.changeSet.service),g=extractServiceActions(e.auth.changeSet.service),_=[...c,...l,...t,...r,...i,...u,...d],v=summarizePlanResults(e,_,[...p,...m,...h,...g]),y=[...e.functionRegistry.unmanaged,...e.tailorDB.unmanaged,...e.staticWebsite.unmanaged,...e.aiGateway.unmanaged,...e.idp.unmanaged,...e.auth.unmanaged,...e.pipeline.unmanaged,...e.executor.unmanaged,...e.workflow.unmanaged,...e.secretManager.unmanaged],b=[...e.functionRegistry.conflicts,...e.tailorDB.conflicts,...e.staticWebsite.conflicts,...e.aiGateway.conflicts,...e.idp.conflicts,...e.auth.conflicts,...e.pipeline.conflicts,...e.executor.conflicts,...e.workflow.conflicts,...e.secretManager.conflicts],x=[..._,...p.map(({action:e,name:t})=>({action:e,name:t,labels:[`tailorDB`],namespace:void 0})),...m.map(({action:e,name:t})=>({action:e,name:t,labels:[`pipeline`],namespace:void 0})),...h.map(({action:e,name:t})=>({action:e,name:t,labels:[`idp`],namespace:void 0})),...g.map(({action:e,name:t})=>({action:e,name:t,labels:[`auth`],namespace:void 0})),...formatChangeSetEntries(f),...formatChangeSetEntries(e.staticWebsite.changeSet,[`staticWebsite`]),...formatChangeSetEntries(e.staticWebsite.customDomainChangeSet,[`customDomain`]),...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})=>({action:e,name:t,labels:n,namespace:r})),S=[...y.map(({resourceType:e,resourceName:t})=>({type:`unmanaged`,resourceType:e,name:t})),...e.secretManager.skippedSecrets.map(e=>({type:`skippedSecret`,resourceType:`secret`,name:e}))],C=b.map(({resourceType:e,resourceName:t,currentOwner:n})=>({resourceType:e,name:t,currentOwner:n})),w=[...buildGroupedDisplayLines(e.functionRegistry.changeSet.title,formatChangeSetEntries(f)),...e.staticWebsite.changeSet.lines(),...e.staticWebsite.customDomainChangeSet.lines(),...e.aiGateway.changeSet.lines(),...e.app.lines(),...buildGroupedDisplayLines(`TailorDB`,c,p),...buildGroupedDisplayLines(`Resolver`,l,m),...buildGroupedDisplayLines(`Executor`,t),...buildGroupedDisplayLines(`Workflow`,r),...buildGroupedDisplayLines(`IdP`,u,h),...buildGroupedDisplayLines(`Auth`,d,g),...e.secretManager.vaultChangeSet.lines(),...e.secretManager.secretChangeSet.lines()];if(y.length>0){w.push(j.bold(`Unmanaged resources (not in config):`));for(let{resourceType:e,resourceName:t}of y)w.push(` ${j.warning(`⚠`)} ${j.bold(e)} "${t}"`)}if(e.secretManager.skippedSecrets.length>0){w.push(j.bold(`Secret Manager secrets (skipped - no value provided):`));for(let t of e.secretManager.skippedSecrets)w.push(` ${j.dim(`○`)} ${t}`)}if(b.length>0){w.push(j.bold(`Owner conflicts (will require confirmation on apply):`));for(let{resourceType:e,resourceName:t,currentOwner:n}of b)w.push(` ${j.warning(`!`)} ${j.bold(e)} "${t}" — owned by "${n}"`)}return w.push(formatPlanSummary(v)),{summary:v,json:{summary:v,changes:x,warnings:S,conflicts:C},lines:w}}function printPlanResults(e,t){let n=buildPlanReport(e);if(M.jsonMode&&t?.dryRun)return M.out(n.json),n.summary;let r=n.lines.join(`
|
|
131
|
+
`);return t?.dryRun?M.out(r):M.log(r),n.summary}function summarizePlanResults(e,t,n){let r={create:0,update:0,delete:0,replace:0};for(let e of t)r[e.action]+=1;for(let e of n)r[e.action]+=1;let{otherChanges:i}=splitFunctionRegistryChanges(e.functionRegistry.changeSet),a=summarizeChangeSets([i,e.staticWebsite.changeSet,e.staticWebsite.customDomainChangeSet,e.aiGateway.changeSet,e.app,e.secretManager.vaultChangeSet,e.secretManager.secretChangeSet]);return r.create+=a.create,r.update+=a.update,r.delete+=a.delete,r.replace+=a.replace,r}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}),{create:0,update:0,delete:0,replace:0})}function printDeploymentPlans(e,t){if(M.jsonMode&&t?.dryRun){let t=e.map(e=>buildPlanReport(deploymentPlanResults(e))),n=sumPlanSummaries(t.map(e=>e.summary));return M.out({summary:n,changes:t.flatMap(e=>e.json.changes),warnings:t.flatMap(e=>e.json.warnings),conflicts:t.flatMap(e=>e.json.conflicts)}),n}return sumPlanSummaries(e.map(e=>printPlanResults(deploymentPlanResults(e),t)))}const ls=new Map;function validatorFor(e){let t=ls.get(e.typeName);if(t)return t;let n=Pr({registry:Zn(e,...Nr(e))});return ls.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=Xn(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?Mr(t.field):`(message)`,message:t.message});else l.kind===`error`&&M.warn(`Could not validate ${n} "${e.name}" (${r}): ${l.error.message}`)}}async function validatePlan(e){let{tailorDB:t,staticWebsite:n,aiGateway:i,idp:s,auth:c,pipeline:l,app:u,executor:d,workflow:f,workflowExecutionPolicy:p,secretManager:m}=e,h=[];function creates(e,t,n){validateItems({schema:e,kind:t,action:`create`,items:n,requestKey:`request`,violations:h})}function updates(e,t,n){validateItems({schema:e,kind:t,action:`update`,items:n,requestKey:`request`,violations:h})}function replaces(e,t,n){validateItems({schema:e,kind:t,action:`replace`,items:n,requestKey:`createRequest`,violations:h})}function inPlaceReplaces(e,t,n){validateItems({schema:e,kind:t,action:`replace`,items:n,requestKey:`updateRequest`,violations:h})}creates(Ce,`TailorDB service`,t.changeSet.service.creates),creates(Te,`TailorDB table`,t.changeSet.type.creates),updates(Ue,`TailorDB table`,t.changeSet.type.updates),creates(a,`StaticWebsite`,n.changeSet.creates),updates(nt,`StaticWebsite`,n.changeSet.updates),creates(ie,`StaticWebsite custom domain`,n.customDomainChangeSet.creates),creates(fe,`AIGateway`,i.changeSet.creates.map(e=>({name:e.name,request:{...e.request,cors:void 0}}))),updates(he,`AIGateway`,i.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(r,`IdP service`,s.changeSet.service.creates.map(substituteIdpReturnOrigins)),updates(ce,`IdP service`,s.changeSet.service.updates.map(substituteIdpReturnOrigins));let _=[...s.changeSet.client.creates.map(e=>({clientName:e.request.client?.name??``,namespaceName:e.request.namespaceName??``,workspaceId:e.request.workspaceId??``})),...s.changeSet.client.updates.map(e=>({clientName:e.name,namespaceName:e.namespaceName,workspaceId:e.workspaceId}))];creates(C,`IdP client secret`,_.map(e=>({name:e.clientName,request:{workspaceId:e.workspaceId,secretmanagerVaultName:idpClientVaultName(e.namespaceName,e.clientName)}}))),creates(o,`IdP client secret`,_.map(e=>({name:e.clientName,request:{workspaceId:e.workspaceId,secretmanagerVaultName:idpClientVaultName(e.namespaceName,e.clientName),secretmanagerSecretName:idpClientSecretName(e.namespaceName,e.clientName)}}))),creates($e,`Auth service`,c.changeSet.service.creates),updates(xe,`Auth service`,c.changeSet.service.updates),creates(ye,`Auth IDP config`,c.changeSet.idpConfig.creates),updates(ke,`Auth IDP config`,c.changeSet.idpConfig.updates),creates(Ee,`Auth user profile config`,c.changeSet.userProfileConfig.creates),updates(ae,`Auth user profile config`,c.changeSet.userProfileConfig.updates),creates(we,`Auth tenant config`,c.changeSet.tenantConfig.creates),updates(at,`Auth tenant config`,c.changeSet.tenantConfig.updates),creates(He,`Auth machine user`,c.changeSet.machineUser.creates),updates(Oe,`Auth machine user`,c.changeSet.machineUser.updates),creates(Me,`Auth hook`,c.changeSet.authHook.creates),updates(Re,`Auth hook`,c.changeSet.authHook.updates),creates(Se,`Auth SCIM config`,c.changeSet.scim.creates),updates(tt,`Auth SCIM config`,c.changeSet.scim.updates),creates(Le,`Auth SCIM resource`,c.changeSet.scimResource.creates),updates(st,`Auth SCIM resource`,c.changeSet.scimResource.updates),creates(Ye,`OAuth2 client`,c.changeSet.oauth2Client.creates),updates(_e,`OAuth2 client`,c.changeSet.oauth2Client.updates),replaces(Ye,`OAuth2 client`,c.changeSet.oauth2Client.replaces),creates(y,`Pipeline service`,l.changeSet.service.creates),updates(ee,`Pipeline service`,l.changeSet.service.updates),creates(Ne,`Resolver`,l.changeSet.resolver.creates),updates(x,`Resolver`,l.changeSet.resolver.updates),creates(de,`Executor`,d.changeSet.creates),updates(me,`Executor`,d.changeSet.updates),creates(ve,`Workflow`,f.changeSet.creates.map(e=>({name:e.name,request:buildWorkflowValidationShape(e.workspaceId,e.workflow)}))),updates(Je,`Workflow`,f.changeSet.updates.map(e=>({name:e.name,request:buildWorkflowValidationShape(e.workspaceId,e.workflow)})));let v=f.changeSet.creates[0]?.workspaceId??f.changeSet.updates[0]?.workspaceId??``;if(v){let e=new Set;for(let t of[...f.changeSet.creates,...f.changeSet.updates])for(let n of t.usedJobNames)e.add(n);for(let t of f.unchangedWorkflowJobNames)e.add(t);creates(Ae,`Workflow job function`,[...e].map(e=>({name:e,request:{workspaceId:v,jobFunctionName:e,scriptRef:e}})))}if(creates(Ge,`Workflow execution policy`,[...p.changeSet.creates,...p.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(Ve,`Workflow execution policy`,p.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(C,`Secret Manager vault`,m.vaultChangeSet.creates.map(e=>({name:e.name,request:vaultCreateRequest(e)}))),creates(o,`Secret Manager secret`,m.secretChangeSet.creates.map(e=>({name:e.name,request:secretCreateRequest(e)}))),updates(Fe,`Secret Manager secret`,m.secretChangeSet.updates.map(e=>({name:e.name,request:secretUpdateRequest(e)}))),creates(ue,`Application`,u.creates.map(e=>({name:e.name,request:{...e.request,cors:void 0}}))),updates(g,`Application`,[...u.updates,...u.unchanged].map(e=>({name:e.name,request:{...e.request,cors:void 0}}))),creates(qe,`Auth connection`,c.changeSet.connection.creates),inPlaceReplaces(We,`Auth connection`,c.changeSet.connection.replaces),h.length===0)return;let b=new Set(h.map(e=>`${e.kind}:${e.name}`));M.error(`Pre-flight validation found ${h.length} violation(s) across ${b.size} resource(s):`);for(let e of h)M.log(` ${j.resourceType(e.kind)} ${j.resourceName(e.name)} (${e.action}) — ${j.bold(e.fieldPath)}: ${e.message}`);throw R({code:`DEPLOY_VALIDATION_FAILED`,message:`${h.length} validation error(s) found in ${b.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 Error(formatIssues(n.error.issues));return n.data}const us=H.string().min(1,`Profile must not be empty`),ds=H.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=ds.safeParse(e);return t.success?!0:formatIssues(t.error.issues)}const fs=/^(\d+)(s|m|h|d)$/,ps={s:1e3,m:6e4,h:36e5,d:864e5},ms=H.string().regex(fs,{message:`Invalid duration format. Expected a number with a unit: '30m', '24h', '7d'`});function parseAge(e){let t=e.match(fs);if(!t?.[1]||!t[2])throw R({code:`PRUNE_AGE_INVALID`,message:`invalid age format: ${e}`,command:`workspace prune`});let n=t[2];return parseInt(t[1],10)*ps[n]}const hs=`sdk-expires-at`,gs=/^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(gs);if(!t?.[1])return;let n=Number(t[1]);if(!Number.isSafeInteger(n))return;let r=new Date(n*1e3);return Number.isNaN(r.getTime())?void 0:r}function readWorkspaceExpiry(e,t){let n=e?.[hs];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:Tn(e)}}}async function writeWorkspaceExpiry(e,t,n){await writeMetadataLabelsDirect(e,{trn:workspaceTrn(t),labels:{[hs]:encodeExpiresAt(n)}})}async function clearWorkspaceExpiry(e,t){await writeMetadataLabelsDirect(e,{trn:workspaceTrn(t),remove:[hs]})}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=Kt();return Promise.all(t.map(async t=>reportedExpiry(await r(()=>fetchWorkspaceExpiry(e,t,n)))))}function formatTimestamp(e){if(!e)return null;let t=W(e);return Number.isNaN(t.getTime())?null:t}function formatTable(e,t){return ft(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`:dr(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 K&&(e.code===G.NotFound||e.code===G.PermissionDenied))return;M.warn(`Failed to resolve workspace folder name: ${e}`);return}}function createWorkspaceFolderNameResolver(e){let t=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=vr(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 _s=createWorkspaceNameTransformer(`name`,`folderName`),vs=H.object({name:ds,region:H.string(),deleteProtection:H.boolean().optional(),organizationId:H.uuid().optional(),folderId:H.uuid().optional(),ttl:ms.optional(),profile:us.optional()}),validateRegion=async(e,t)=>{let n=await t.listAvailableWorkspaceRegions({});if(!n.regions.includes(e))throw R({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{...nn(e)?{}:{platform_url:Ot(e)},...t?{oauth2_client_id:Nt(e)}:{},...n?{console_url:Qt(n)}:{}}}async function createWorkspace$1(e){let t=validateCreateWorkspaceOptions(e),n=await loadAccessToken({profile:t.profile}),r=await loadPlatformClientConfig({profile:t.profile}),i=await F(n,r);return await validateRegion(t.region,i),createValidatedWorkspaceWithClient(i,t)}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=k(n.workspace,`createWorkspace response missing workspace`),i=t.ttl===void 0?void 0:await recordTtl(e,r.id,t.ttl,r.createTime),a=await workspaceInfoWithFolderName(e,r);return i?{...a,ttl:i}:a}async function recordTtl(e,t,n,r){let i=r?W(r):new Date,a=new Date(i.getTime()+parseAge(n));try{return await writeWorkspaceExpiry(e,t,a),{state:`written`,expiresAt:a}}catch(e){return{state:`unconfirmed`,expiresAt:a,requested:n,message:e instanceof Error?e.message:String(e)}}}function validateCreateWorkspaceOptions(e){return parseOptions(vs,e)}const ys=Y({name:`create`,description:`Create a new Tailor Platform workspace.`,args:H.strictObject({name:B(ds,{alias:`n`,description:`Workspace name`}),region:B(H.string(),{alias:`r`,description:`Workspace region (us-west, asia-northeast)`}),"delete-protection":B(H.boolean().default(!1),{alias:`d`,description:`Enable delete protection`}),"organization-id":B(H.string().optional(),{alias:`o`,description:`Organization ID to workspace associate with`,env:`TAILOR_PLATFORM_ORGANIZATION_ID`}),"folder-id":B(H.string().optional(),{alias:`f`,description:`Folder ID to workspace associate with`,env:`TAILOR_PLATFORM_FOLDER_ID`}),ttl:B(ms.optional(),{description:"Record on the workspace itself when it becomes prunable, such as 30m, 24h, or 7d. `workspace prune --expired` deletes it once that has passed"}),"profile-name":B(H.string().optional(),{alias:`p`,description:`Profile name to create`}),profile:B(us.optional(),{description:`Workspace profile used for authentication and Platform selection`,env:`TAILOR_PLATFORM_PROFILE`}),"profile-user":B(H.string().optional(),{description:`User email address or machine user client ID for the profile (defaults to current user)`}),permission:B(H.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 readPlatformConfig();if(r.profiles[t])throw R({code:`PROFILE_EXISTS`,message:`Profile "${t}" already exists.`});let i=e.profile,a=i?r.profiles[i]:void 0,o=a?platformConfigFromProfile(a):void 0,s=e[`profile-user`]||a?.user||r.current_user;if(!s)throw R({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=resolveConfigUser(r,s,o);if(!c)throw R({code:`USER_NOT_FOUND`,message:`User "${s}" not found.`,suggestion:`Verify the user name and log in.`,next:{command:`tailor`,args:[`login`,...recoveryContextArgs({profile:i})]}});n={name:t,user:c,platformSettings:profilePlatformSettings(o)}}let r=await createWorkspace$1({name:e.name,region:e.region,deleteProtection:e[`delete-protection`],organizationId:e[`organization-id`],folderId:e[`folder-id`],ttl:e.ttl,profile:e.profile}),i;if(n){let t=await readPlatformConfig(),a=n.platformSettings;t.profiles[n.name]={user:n.user,workspace_id:r.id,...e.permission===`read`?{readonly:!0}:{},...a},writePlatformConfig(t),i={name:n.name,user:n.user,workspaceId:r.id,permission:e.permission,...a.platform_url?{platformUrl:a.platform_url}:{},...a.oauth2_client_id?{oauth2ClientId:a.oauth2_client_id}:{},...a.console_url?{consoleUrl:a.console_url}:{}},e.json||M.success(`Profile "${n.name}" created successfully.`)}let{ttl:a,...o}=r;if(e.json||(M.success(`Workspace "${workspaceDisplayName(r)}" created successfully.`),a?.state===`written`&&M.info(`Workspace becomes prunable at ${a.expiresAt.toISOString()}.`)),e.json&&i?M.out({...o,profile:i}):(M.out(o,{display:{name:_s,folderName:null}}),i&&(M.out(`Profile:`),M.out(i))),a?.state===`unconfirmed`)throw R({code:`WORKSPACE_TTL_WRITE_FAILED`,message:`Workspace "${workspaceDisplayName(r)}" was created, but --ttl could not be confirmed: ${a.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:r.id,requestedExpiresAt:a.expiresAt.toISOString(),...i?{profileCreated:i.name}:{}},next:{command:`tailor`,args:[`workspace`,`ttl`,`set`,`--ttl`,a.requested,...recoveryContextArgs({workspaceId:r.id,profile:e.profile})]}})}});async function listWorkspaces(e){let t=us.optional().parse(e?.profile),n=await loadAccessToken({profile:t}),r=await loadPlatformClientConfig({profile:t});return listWorkspacesWithClient(await F(n,r),e)}async function listWorkspacesWithExpiry(e){let t=us.optional().parse(e?.profile),n=await loadAccessToken({profile:t}),r=await loadPlatformClientConfig({profile:t}),i=await F(n,r),a=await listWorkspacesWithClient(i,e),o=await fetchReportedExpiries(i,a.map(({id:e})=>e),new Date);return a.map((e,t)=>{let n=o[t];return{...e,expiresAt:n===void 0?`unavailable`:n}})}async function listWorkspacesWithClient(e,t){let n=toPageDirection(t?.order);return workspaceInfosWithFolderNames(e,await Ct(async(t,r)=>{let{workspaces:i,nextPageToken:a}=await e.listWorkspaces({pageToken:t,pageSize:r,pageDirection:n});return[i,a]},{limit:t?.limit}))}const bs=Y({name:`list`,description:`List all Tailor Platform workspaces.`,args:H.strictObject({...paginationArgs(),profile:B(us.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});M.out(t,{display:{name:_s,folderName:null,organizationId:null,folderId:null,updatedAt:null}})}}),xs=H.object({version:H.literal(1),platformUrl:H.url(),applicationId:H.string().min(1).optional(),workspaceId:H.uuid()});function defaultConfigPath(){return qn(process.cwd(),`tailor.config.ts`)}function contextPath(e){return Gn(Un(e),$t(),`${Hn(e)}.context.json`)}async function loadWorkspaceContext(e,t=defaultConfigPath(),n){let r;try{r=await Ir(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=xs.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=xs.parse({...e,...n===void 0?{}:{applicationId:n}}),i=Gn(Un(t),$t()),a=contextPath(t),o=`${JSON.stringify(r,null,2)}\n`;try{if(await Ir(a,`utf8`)===o)return}catch{}let s=`${a}.${process.pid}.${xr()}.tmp`;await Fr(i,{recursive:!0});try{await zr(s,o,{mode:384}),await Lr(s,a)}catch(e){throw await Rr(s,{force:!0}).catch(()=>void 0),e}}function suggestedWorkspaceName(){let e=Hn(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 createDeployArgs(e,t,n){return[...deployArgs(e),`--create-workspace`,`--workspace-name`,t,`--workspace-region`,n,...e.organizationId?[`--organization-id`,e.organizationId]:[],...e.folderId?[`--folder-id`,e.folderId]:[]]}function selectDeployArgs(e){return[...deployArgs(e),`--workspace-id`,`<workspace-id>`]}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 R({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 R({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),...recoveryContextArgs({workspaceId:e.workspaceId})]),context:{workspaceId:e.workspaceId,configPaths:t.contextTargets?.map(({configPath:e})=>e)}});M.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),M.info(`Using workspace: ${workspaceLabel(n)}`),{client:e,workspaceId:n.id}}function useRememberedWorkspace(e,t){return M.warn(`Using saved workspace selection: ${workspaceLabel(t)}`),{client:e,workspaceId:t.id}}const Ss=`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:Ss}]});if(i===Ss)return createWorkspaceForDeploy(e,t,r);let a=n.find(({id:e})=>e===i);if(!a)throw L(`Selected workspace was not found`);return useWorkspace(e,t,a,r)}function invalidCreateOptionsError(e,t,n,r){return R({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 createWorkspace(e,t,n,r,i){let a=n.workspaceName,o=n.workspaceRegion,s=canPrompt();if(s)a??=await X.text({message:`Workspace name`,default:suggestedWorkspaceName(),validate:validateWorkspaceName}),o??=await X.select({message:`Workspace region`,choices:r.map(e=>({name:e,value:e}))});else{let e=[...a===void 0?[`--workspace-name`]:[],...o===void 0?[`--workspace-region`]:[]];if(e.length>0)throw R({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(n,a??`<name>`,o??`<region>`)),context:{missingOptions:e}})}if(!a||!o)throw L(`Workspace creation options were not resolved`);let c=i;if(!c){try{c=validateCreateWorkspaceOptions({name:a,region:o,organizationId:n.organizationId,folderId:n.folderId})}catch(e){throw invalidCreateOptionsError(n,a,o,e instanceof Error?e.message:String(e))}if(!r.includes(o))throw invalidCreateOptionsError(n,a,o,`Region must be one of: ${r.join(`, `)}.`)}if(s){let e=[n.organizationId?`organization: ${n.organizationId}`:void 0,n.folderId?`folder: ${n.folderId}`:void 0].filter(e=>e!==void 0);if(!await X.confirm({message:`Create workspace "${a}" in ${o}${e.length>0?` (${e.join(`, `)})`:``}?`,default:!0}))throw R({code:`WORKSPACE_CREATION_CANCELLED`,message:`Workspace creation was cancelled.`})}let l;try{l=await createValidatedWorkspaceWithClient(e,c)}catch(e){throw e instanceof K&&![G.Canceled,G.Unknown,G.DeadlineExceeded,G.Aborted,G.Internal,G.Unavailable,G.DataLoss].includes(e.code)?e:R({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(n),`--json`])})}return await rememberWorkspaceContext({version:1,platformUrl:t,workspaceId:l.id},n),M.success(`Created workspace: ${workspaceLabel(l)}`),M.info(`Reuse this workspace with: ${wn([`tailor`,`deploy`,...recoveryContextArgs({workspaceId:l.id,profile:n.profile})])}`),M.info(`Or set TAILOR_PLATFORM_WORKSPACE_ID=${l.id}.`),{client:e,workspaceId:l.id}}async function createWorkspaceForDeploy(e,t,n,r,i){let a=r??(await e.listAvailableWorkspaceRegions({})).regions;if(n.dryRun)throw R({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:a}});return createWorkspace(e,t,n,a,i)}async function resolveDeployWorkspace(e={}){let t=[e.workspaceName===void 0?void 0:`--workspace-name`,e.workspaceRegion===void 0?void 0:`--workspace-region`].filter(e=>e!==void 0);if(!e.createWorkspace&&t.length>0)throw R({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(e,e.workspaceName??`<name>`,e.workspaceRegion??`<region>`)),context:{options:t}});if(e.createWorkspace&&e.workspaceName!==void 0){let t=validateWorkspaceName(e.workspaceName);if(t!==!0)throw invalidCreateOptionsError(e,e.workspaceName,e.workspaceRegion??`<region>`,t)}if(e.createWorkspace&&e.workspaceRegion===``)throw invalidCreateOptionsError(e,e.workspaceName??`<name>`,e.workspaceRegion,`Region must not be empty.`);let n=await tryLoadWorkspaceId({workspaceId:e.workspaceId,profile:e.profile}),r=await loadAccessToken({profile:e.profile}),i=await loadPlatformClientConfig({profile:e.profile,allowMissingProfile:n!==void 0}),a=Ot(i),o=await F(r,i);if(n){let t;try{t=await o.getWorkspace({workspaceId:n})}catch(e){throw e instanceof K&&e.code===G.NotFound?R({code:`WORKSPACE_NOT_FOUND`,message:`Workspace "${n}" was not found.`}):e}if(!t.workspace)throw R({code:`WORKSPACE_NOT_FOUND`,message:`Workspace "${n}" was not found.`});return useWorkspace(o,a,workspaceInfo(t.workspace),e,`warn`)}let s;if(e.createWorkspace&&e.workspaceName!==void 0&&e.workspaceRegion!==void 0)try{s=validateCreateWorkspaceOptions({name:e.workspaceName,region:e.workspaceRegion,organizationId:e.organizationId,folderId:e.folderId})}catch(t){throw invalidCreateOptionsError(e,e.workspaceName,e.workspaceRegion,t instanceof Error?t.message:String(t))}let[c,l]=await Promise.all([loadProjectContexts(a,e.contextTargets),listWorkspacesWithClient(o)]),u=canPrompt(),d=new Set(c.map(({workspaceId:e})=>e)),f=d.size===1?l.find(({id:e})=>d.has(e)):void 0;if(f&&(!e.createWorkspace||workspaceMatchesRequestedIdentity(f,e))){let t=projectContextTargets(e.contextTargets)?.length??1;return c.length===t?useRememberedWorkspace(o,f):useWorkspace(o,a,f,e)}let p=l.length===1?l[0]:void 0,m=p!==void 0&&s!==void 0&&workspaceMatchesRequestedIdentity(p,e),h;if(s&&!m&&(h=await o.listAvailableWorkspaceRegions({}),!h.regions.includes(s.region)))throw invalidCreateOptionsError(e,s.name,s.region,`Region must be one of: ${h.regions.join(`, `)}.`);if(l.length===0&&(u||e.createWorkspace||c.length===0)){let t=h?.regions??(await o.listAvailableWorkspaceRegions({})).regions;if(e.dryRun||u||e.createWorkspace)return createWorkspaceForDeploy(o,a,e,t,s);throw R({code:`WORKSPACE_NOT_FOUND`,message:`No workspaces are available for this account.`,suggestion:`Create one during deploy by providing the workspace name and one of the available regions.`,next:executableAction(createDeployArgs(e,`<name>`,`<region>`)),context:{availableRegions:t}})}if(d.size>1){let t=e.createWorkspace===!0&&e.workspaceName!==void 0&&e.workspaceRegion!==void 0&&l.length===0;if(!u&&!t)throw R({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(e)),context:{savedWorkspaceIds:[...d]}});if(l.length>0&&!e.createWorkspace)return chooseWorkspace(o,a,l,e)}if(!f&&c.length>0){let t=e.createWorkspace===!0&&e.workspaceName!==void 0&&e.workspaceRegion!==void 0&&l.length<=1;if(!u&&!t)throw R({code:`WORKSPACE_CONTEXT_STALE`,message:`The saved project workspace is no longer available.`,suggestion:`Choose an available workspace explicitly before deploying.`,next:executableAction(selectDeployArgs(e)),context:{savedWorkspaceIds:[...d],workspaces:l.map(workspaceIdentity)}});if(l.length>0&&u&&!e.createWorkspace)return chooseWorkspace(o,a,l,e)}if(l.length===1){let[t]=l;if(!t)throw L(`Workspace discovery returned an invalid result`);if(e.createWorkspace&&!workspaceMatchesRequestedIdentity(t,e))throw R({code:`WORKSPACE_CREATE_CONFLICT`,message:`The existing workspace does not match the requested workspace.`,suggestion:`Use the existing workspace, or run the explicit workspace create command to create another one.`,next:executableAction([`workspace`,`create`,...workspaceCommandArgs(e),...e.workspaceCommandJson?[`--json`]:[],`--name`,e.workspaceName??`<name>`,`--region`,e.workspaceRegion??`<region>`,...e.organizationId?[`--organization-id`,e.organizationId]:[],...e.folderId?[`--folder-id`,e.folderId]:[]]),context:{existingWorkspace:workspaceIdentity(t)}});return u&&!e.createWorkspace?chooseWorkspace(o,a,l,e):useWorkspace(o,a,t,e)}if(l.length>1){if(!u)throw R({code:`WORKSPACE_SELECTION_REQUIRED`,message:`Multiple workspaces are available.`,suggestion:`Choose one explicitly for non-interactive deployment.`,next:executableAction(selectDeployArgs(e)),context:{workspaces:l.map(workspaceIdentity)}});return chooseWorkspace(o,a,l,e)}throw L(`Workspace discovery returned an invalid result`)}function collectExpectedLocalStaticWebsiteNames(e){let t=new Set;for(let n of e)for(let e of n.application.staticWebsiteServices)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=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?.envFile?[`--env-file`,V.resolve(process.cwd(),t.envFile)]:[],...t?.envFileIfExists?[`--env-file-if-exists`,V.resolve(process.cwd(),t.envFileIfExists)]:[],...recoveryContextArgs({profile:e?.profile})]}function recoveryOutputArgs(e){return[...e?.verbose?[`--verbose`]:[],...e?.json||M.jsonMode?[`--json`]:[]]}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`]:[],...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=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 R({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,migrationTestBaselines:s,migrationTestSnapshots:c}=e,{config:l,application:u,workflowBuildResult:d,httpAdapterBuildResult:f,bundledScripts:p}=t,m=ownedSubscriptions(r.eventSubscriptions,t),h=u.tailorDBServices.map(e=>{let t=c?.get(e.namespace);return t?{...e,types:t.tables,typeSourceInfo:{}}:e});await z(`plan.validateTailorDBTypeNames`,()=>At({client:i,workspaceId:a,tailorDBServices:h,externalTailorDBNamespaces:u.externalTailorDBNamespaces,plannedExternalTailorDBServices:collectPlannedExternalTailorDBServices(t,n)}));let g=u.workflowService,_=collectFunctionEntries(u,filterBundledWorkflowJobs(g?.jobs??[],d?.usedJobNames??[]),p),v=await z(`plan.detectSdkVersionChange`,()=>shouldForceApplyAll(i,a,u,_));return z(`plan`,async()=>{let e=n.map(e=>e.application),p=collectVisibleTailorDBTypeNamespaces(u,e),h=collectVisibleResolverNamespaces(u,e),y=collectVisibleIdpNames(u,e),b={client:i,workspaceId:a,application:u,forRemoval:!1,config:l,noSchemaCheck:o,migrationTestBaselines:s,migrationTestSnapshots:c,forceApplyAll:v,...r,idpUserTriggerTargets:subscribedIdps(m),executorUsedTailorDBTables:subscribedTailorDBTables(m),executorUsedResolvers:subscribedResolvers(m),dependentApps:collectDependentApps(m),tailorDBTypeNamespaces:p,resolverNamespaces:h,idpNames:y},x=await z(`plan.functionRegistry`,()=>planFunctionRegistry(i,a,u.name,u.id,_)),S=new Set(x.changeSet.unchanged.filter(e=>e.name.startsWith(Yi)).map(e=>e.name.slice(10))),[C,w,ee,te,ne,re,ie,ae,oe,se,ce]=await Promise.all([z(`plan.tailorDB`,()=>planTailorDB(b)),z(`plan.staticWebsite`,()=>planStaticWebsite(b)),z(`plan.aiGateway`,()=>planAIGateway(b)),z(`plan.idp`,()=>planIdP(b)),z(`plan.auth`,()=>planAuth(b)),z(`plan.pipeline`,()=>planPipeline(b)),z(`plan.application`,()=>planApplication(b,f)),z(`plan.executor`,()=>planExecutor(b)),z(`plan.workflow`,()=>planWorkflow(i,a,u.name,u.id,g?.workflows??{},d?.mainJobDeps??{},S,{...subscribedWorkflows(m),jobPublishEvents:collectWorkflowJobPublishEvents(t),dependentApps:b.dependentApps,runAppIds:b.runAppIds})),z(`plan.workflowExecutionPolicy`,()=>planWorkflowJobFunctionExecutionPolicy(i,a,u.name,u.id,l.workflow?.executionPolicies??{})),z(`plan.secretManager`,()=>planSecretManager(b))]);return{application:u,functionRegistry:x,tailorDB:C,staticWebsite:w,aiGateway:ee,idp:te,auth:ne,pipeline:re,app:ie,executor:ae,workflow:oe,workflowExecutionPolicy:se,secretManager:ce}})}async function planDeploymentTargets(e){let{targets:t,planTarget:n=planDeploymentTarget,...r}=e;return Promise.all(t.map(e=>n({...r,target:e,targets:t})))}async function confirmDeploymentPlans(e){let{deployments:t,yes:n,dryRun:r=!1,missingDependentApps:i=[]}=e;r||await confirmMigrationCheckpointRepairs(t.flatMap(e=>e.tailorDB.context.checkpointRepairs),n),await confirmMissingDependentApps(i,n);let a=new Set(t.map(e=>e.application.name)),o=collectDeploymentResourceOwners(t),s=new Set,c=[];for(let e of t){let t=deploymentPlanResults(e),r=collectOwnerConflicts(t);await confirmOwnerConflict(r,e.application.name,n,e.application.id),await confirmUnmanagedResources(collectUnmanagedResources(t),e.application.name,n),c.push(...collectImportantResourceDeletions(t));let i=computeRenamedAppDeletions({conflicts:r,resourceOwners:o,protectedAppNames:a});for(let t of i)s.has(t)||(s.add(t),e.app.deletes.push({name:t,request:{workspaceId:e.tailorDB.context.workspaceId,applicationName:t}}))}await confirmImportantResourceDeletion(c,n)}async function validateDeploymentPlans(e){for(let t of e)await validatePlan(deploymentPlanResults(t))}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 z(`deploy`,async i=>{i.setAttribute(`deploy.dry_run`,t?.dryRun??!1),gn(),e();let a=parseDeployConfigPaths(t?.configPath),o=t?.dryRun??!1,s=t?.buildOnly??ut(process.env.TAILOR_DEPLOY_BUILD_ONLY)===!0,c=s?[]:await z(`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||M.jsonMode}),f=await z(`build`,async()=>{let e=t?.noCache??!1,n=await bn(),r=V.resolve($t(),`cache`);return t?.cleanCache&&(U.rmSync(r,{recursive:!0,force:!0}),M.info(`Bundle cache cleaned`)),await buildDeploymentTargets({configPaths:a,loadedConfigs:s?void 0:c,dryRun:o,buildOnly:s,noCache:e,packageVersion:n.version??`unknown`,cacheDir:r})});if(s)return{bundledScripts:mergeBundledScripts(f)};if(assertUniqueGlobalResourceNames(f),!d)throw L(`Workspace was not resolved`);let{client:p,workspaceId:m}=d;i.setAttribute(`app.name`,f.map(e=>e.application.name).join(`,`)),i.setAttribute(`workspace.id`,m);let h=f.map(e=>({...e,application:adjustApplicationForMigrationTest(e.application,r)})),g=await z(`plan.metadataLookup`,()=>createMetadataLookupClient({client:p,workspaceId:m,applications:h.map(({application:e})=>e)})),_=collectDeployRunPlanInputs(h,!t?.dryRun),v=await planDeploymentTargets({targets:h,runInputs:_,client:g,workspaceId:m,noSchemaCheck:t?.noSchemaCheck,migrationTestBaselines:r?.migrationTestBaselines,migrationTestSnapshots:r?.migrationTestSnapshots}),y=t?.yes??!1;dropCrossDeploymentManagedDeletes(v);let b=(await Promise.all(h.map(e=>fetchMissingDependentApps({client:g,workspaceId:m,application:e.application,runAppIds:_.runAppIds??new Set,subscribedKeys:subscribedResourceKeys(_.eventSubscriptions,e),jobsByWorkflow:e.workflowBuildResult?.mainJobDeps??{}})))).flat();await z(`confirm`,async()=>{await confirmDeploymentPlans({deployments:v,yes:y,dryRun:o,missingDependentApps:b})});let x=printDeploymentPlans(v,{dryRun:t?.dryRun});if(t?.noValidate?M.warn(`Client-side validation skipped (--no-validate).`):await validateDeploymentPlans(v),o){M.info(`Dry run enabled. No changes applied.`);return}await applyDeploymentPlans(p,m,v),r?.suppressResultOutput||(M.jsonMode?M.out({summary:x,status:`applied`}):M.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})}function deployMigrationTestTarget(e,t){return deployInternal(e,void 0,{migrationTestSnapshots:t,suppressResultOutput:!0})}function deployFromCLI(e,t){return deployInternal(e,t)}function colorizeExecutorJobStatus(e){switch(e){case`PENDING`:return j.dim(e);case`RUNNING`:return j.info(e);case`SUCCESS`:return j.success(e);case`FAILED`:return j.error(e);case`CANCELED`:return j.warning(e);default:return e}}function isExecutorJobTerminalStatus(e){return isExecutorJobSuccessStatus(e)||isExecutorJobFailureStatus(e)}function isExecutorJobSuccessStatus(e){return e===T.SUCCESS}function isExecutorJobFailureStatus(e){return e===T.FAILED||e===T.CANCELED}function isExecutorJobTransientStatus(e){return e===T.UNSPECIFIED||e===T.PENDING||e===T.RUNNING}function classifyExecutorJobStatus(e){return isExecutorJobSuccessStatus(e)?`success`:isExecutorJobTerminalStatus(e)?`failure`:(isExecutorJobTransientStatus(e),`transient`)}function parseExecutorJobStatus(e){switch(e.toUpperCase()){case`PENDING`:return T.PENDING;case`RUNNING`:return T.RUNNING;case`SUCCESS`:return T.SUCCESS;case`FAILED`:return T.FAILED;case`CANCELED`:return T.CANCELED;default:throw R({code:`EXECUTOR_STATUS_INVALID`,message:`Invalid status: ${e}. Valid values: PENDING, RUNNING, SUCCESS, FAILED, CANCELED`})}}function executorTargetTypeToString(e){switch(e){case O.WEBHOOK:return`WEBHOOK`;case O.TAILOR_GRAPHQL:return`GRAPHQL`;case O.FUNCTION:return`FUNCTION`;case O.JOB_FUNCTION:return`JOB_FUNCTION`;case O.WORKFLOW:return`WORKFLOW`;default:return`UNSPECIFIED`}}function executorTriggerTypeToString(e){switch(e){case Be.SCHEDULE:return`SCHEDULE`;case Be.EVENT:return`EVENT`;case Be.INCOMING_WEBHOOK:return`INCOMING_WEBHOOK`;default:return`UNSPECIFIED`}}function executorJobStatusToString(e){switch(e){case T.PENDING:return`PENDING`;case T.RUNNING:return`RUNNING`;case T.SUCCESS:return`SUCCESS`;case T.FAILED:return`FAILED`;case T.CANCELED:return`CANCELED`;default:return`UNSPECIFIED`}}function toExecutorJobListInfo(e){return{id:e.id,executorName:e.executorName,status:executorJobStatusToString(e.status),createdAt:e.createdAt?W(e.createdAt).toISOString():`N/A`}}function toExecutorJobInfo(e){return{id:e.id,executorName:e.executorName,status:executorJobStatusToString(e.status),scheduledAt:e.scheduledAt?W(e.scheduledAt).toISOString():`N/A`,createdAt:e.createdAt?W(e.createdAt).toISOString():`N/A`,updatedAt:e.updatedAt?W(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?W(e.startedAt).toISOString():`N/A`,finishedAt:e.finishedAt?W(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 Cs={name:B(H.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 R({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 K&&e.code===G.NotFound?R({code:`EXECUTOR_NOT_FOUND`,message:`Executor '${t}' not found.`,cause:e}):e}}const ws=Y({name:`get`,description:`Get executor details`,args:H.strictObject({...J,...Cs}),run:async e=>{let t=await getExecutor({executor:{name:e.name},workspaceId:e[`workspace-id`],profile:e.profile});M.out(t,{display:{triggerConfig:null,targetConfig:null}})}});function functionExecutionStatusToString(e){switch(e){case h.RUNNING:return`RUNNING`;case h.SUCCESS:return`SUCCESS`;case h.FAILED:return`FAILED`;case h.SUSPEND:return`SUSPEND`;case h.CANCELING:return`CANCELING`;case h.CANCELED:return`CANCELED`;default:return`UNSPECIFIED`}}function colorizeFunctionExecutionStatus(e){switch(e){case`RUNNING`:return j.info(e);case`SUCCESS`:return j.success(e);case`FAILED`:return j.error(e);default:return e}}function isFunctionExecutionTerminalStatus(e){return e===h.SUCCESS||e===h.FAILED||e===h.CANCELED}function functionLogSeverityToString(e){switch(e){case p.LOG:return`LOG`;case p.DEBUG:return`DEBUG`;case p.INFO:return`INFO`;case p.WARNING:return`WARNING`;case p.ERROR:return`ERROR`;default:return`UNSPECIFIED`}}function toFunctionLogEntryInfo(e){return{message:e.message,severity:functionLogSeverityToString(e.severity),timestamp:e.timestamp?W(e.timestamp):null}}function colorizeLogSeverity(e){let t=`[${e}]`;switch(e){case`ERROR`:return j.error(t);case`WARNING`:return j.warning(t);case`DEBUG`:return j.dim(t);default:return t}}function formatFunctionLogEntry(e){let t=e.timestamp?e.timestamp.toISOString():`N/A`;return`${j.dim(t)} ${colorizeLogSeverity(e.severity)} ${e.message}`}function formatFunctionLogLines(e,t){return e&&e.length>0?e.map(formatFunctionLogEntry):t?t.split(`
|
|
132
|
+
`):[]}function formatWaitError(e){return e instanceof Error?e.message:String(e)}function isRetryableWaitError(e){return e instanceof K?e.code===G.Aborted||e.code===G.ResourceExhausted||e.code===G.Unavailable:!1}const Ts=H.enum([`success`,`suspended`,`terminal`]),Es={name:B(H.string(),{positional:!0,description:`Workflow name`})},Ds={interval:B(Zr.default(`3s`),{alias:`i`,description:`Polling interval when waiting (e.g., '3s', '500ms', '1m')`}),timeout:B(Zr.default(`10m`),{alias:`t`,description:`Maximum time to wait (e.g., '30s', '10m')`}),until:B(Ts.default(`terminal`),{alias:`u`,description:`Wait target (success, suspended, terminal)`}),logs:B(H.boolean().default(!1),{alias:`l`,description:`Display job execution logs after completion`})},Os={wait:B(H.boolean().default(!1),{alias:`W`,description:`Wait for execution to complete`}),...Ds};function isWorkflowExecutionSuccessStatus(e){return e===D.SUCCESS}function isWorkflowJobExecutionSuspendedStatus(e){return e===Qe.SUSPEND||e===Qe.WAITING}function isWorkflowExecutionSuspendedStatus(e){return e===D.PENDING_RESUME||e===D.WAITING}function isWorkflowExecutionFailureStatus(e){return e===D.FAILED}function isWorkflowExecutionTransientStatus(e){return e===D.UNSPECIFIED||e===D.PENDING||e===D.RUNNING||e===D.PENDING_RETRY}function isWorkflowExecutionTerminalStatus(e){return isWorkflowExecutionSuccessStatus(e)||isWorkflowExecutionFailureStatus(e)||isWorkflowExecutionSuspendedStatus(e)}function classifyWorkflowExecutionStatus(e){return isWorkflowExecutionTerminalStatus(e.status)?isWorkflowExecutionSuccessStatus(e.status)?{statusClass:`success`,status:e.status}:isWorkflowExecutionFailureStatus(e.status)?{statusClass:`failure`,status:e.status}:{statusClass:`suspended`,status:e.status}:e.jobExecutions.some(e=>isWorkflowJobExecutionSuspendedStatus(e.status))?{statusClass:`suspended`,status:e.status}:(isWorkflowExecutionTransientStatus(e.status),{statusClass:`transient`,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 workflowExecutionStatusToString(e){switch(e){case D.PENDING:return`PENDING`;case D.PENDING_RESUME:return`PENDING_RESUME`;case D.RUNNING:return`RUNNING`;case D.SUCCESS:return`SUCCESS`;case D.FAILED:return`FAILED`;case D.PENDING_RETRY:return`PENDING_RETRY`;case D.WAITING:return`WAITING`;default:return`UNSPECIFIED`}}function workflowJobExecutionStatusToString(e){switch(e){case Qe.RUNNING:return`RUNNING`;case Qe.SUSPEND:return`SUSPEND`;case Qe.SUCCESS:return`SUCCESS`;case Qe.FAILED:return`FAILED`;case Qe.WAITING:return`WAITING`;default:return`UNSPECIFIED`}}function toWorkflowListInfo(e){return{name:e.name,mainJob:e.mainJobFunctionName,jobFunctions:Object.keys(e.jobFunctions).length,updatedAt:e.updatedAt?W(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?W(e.createdAt):null,updatedAt:e.updatedAt?W(e.updatedAt):null}}function toWorkflowJobExecutionInfo(e){return{id:e.id,stackedJobName:e.stackedJobName,status:workflowJobExecutionStatusToString(e.status),executionId:e.executionId,startedAt:e.startedAt?W(e.startedAt):null,finishedAt:e.finishedAt?W(e.finishedAt):null}}function toWorkflowExecutionInfo(e){return{id:e.id,workflowName:e.workflowName,status:workflowExecutionStatusToString(e.status),jobExecutions:e.jobExecutions.length,startedAt:e.startedAt?W(e.startedAt):null,finishedAt:e.finishedAt?W(e.finishedAt):null}}function formatTime$1(e){return e.toLocaleTimeString(`en-US`,{hour12:!1})}function colorizeStatus(e){let t=D[e];switch(e){case D.PENDING:case D.UNSPECIFIED:return j.dim(t);case D.PENDING_RESUME:case D.PENDING_RETRY:case D.WAITING:return j.warning(t);case D.RUNNING:return j.info(t);case D.SUCCESS:return j.success(t);case D.FAILED:return j.error(t);default:return t}}function getActiveJobs(e){return e.jobExecutions.filter(e=>e.status===Qe.RUNNING||e.status===Qe.SUSPEND||e.status===Qe.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.`),R({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(),M.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(),M.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(new Date)})`),hasReachedWorkflowWaitTarget(u,n)||u.statusClass===`failure`||n===`suspended`&&u.statusClass===`success`)return t.status===D.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(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 Vr(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 R({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 R({code:`WORKFLOW_EXECUTION_FAILED`,message:`Workflow execution '${e.id}' failed.`,context:n});if(t===`success`&&e.statusClass!==`success`)return R({code:`WORKFLOW_EXECUTION_NOT_SUCCESSFUL`,message:`Workflow execution '${e.id}' reached ${e.status} before success.`,context:n});if(t===`suspended`&&e.statusClass!==`suspended`)return R({code:`WORKFLOW_EXECUTION_NOT_SUSPENDED`,message:`Workflow execution '${e.id}' reached ${e.status} before suspension.`,context:n})}function parseStatus(e){switch(e.toUpperCase()){case`PENDING`:return D.PENDING;case`PENDING_RESUME`:return D.PENDING_RESUME;case`RUNNING`:return D.RUNNING;case`SUCCESS`:return D.SUCCESS;case`FAILED`:return D.FAILED;case`PENDING_RETRY`:return D.PENDING_RETRY;case`WAITING`:return D.WAITING;case`UNSPECIFIED`:return D.UNSPECIFIED;default:throw R({code:`WORKFLOW_STATUS_INVALID`,message:`Invalid status: ${e}. Valid values: UNSPECIFIED, PENDING, PENDING_RESUME, RUNNING, SUCCESS, FAILED, PENDING_RETRY, WAITING`,command:`workflow executions`})}}async function listWorkflowExecutions(e){let t=e?.workflow?.name,{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:e?.profile,workspaceId:e?.workspaceId}),i=[];if(e?.status){let t=parseStatus(e.status);i.push(Xn(Ke,{condition:Xn(Ze,{field:`status`,operator:ze.EQ,value:{kind:{case:`numberValue`,value:t}}})}))}let a=i.length>0?Xn(Ke,{and:i}):void 0,o=toPageDirection(e?.order??`desc`);return(await Ct(async(e,i)=>{let{executions:s,nextPageToken:c}=await n.listWorkflowExecutions({workspaceId:r,workflowName:t??``,pageToken:e,pageSize:i,pageDirection:o,filter:a});return[s,c]},{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 K&&t.code===G.NotFound||M.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 R({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,logs:n.logs||void 0,logEntries:n.logEntries.length>0?n.logEntries.map(toFunctionLogEntryInfo):void 0,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(M.out(formatKeyValueTable(t)),e.jobDetails&&e.jobDetails.length>0){M.log(j.bold(`
|
|
133
133
|
Job Executions:`));for(let t of e.jobDetails){M.log(j.info(`\n--- ${t.stackedJobName} ---`)),M.log(` Status: ${t.status}`),M.log(` Started: ${formatDate(t.startedAt)}`),M.log(` Finished: ${formatDate(t.finishedAt)}`);let e=formatFunctionLogLines(t.logEntries,t.logs);if(e.length>0){M.log(j.warning(`
|
|
134
134
|
Logs:`));for(let t of e)M.log(` ${t}`)}if(t.result){M.log(j.success(`
|
|
135
135
|
Result:`));try{let e=JSON.parse(t.result);M.log(` ${JSON.stringify(e,null,2).split(`
|
|
136
136
|
`).join(`
|
|
137
|
-
`)}`)}catch{M.log(` ${t.result}`)}}}}}const Ss=Y({name:`executions`,description:`List or get workflow executions.`,args:H.strictObject({...J,...ni,"execution-id":B(H.string().optional(),{positional:!0,description:`Execution ID (if provided, shows details)`}),"workflow-name":B(H.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:B(H.string().optional(),{alias:`s`,description:`Filter by status (list mode only)`}),...xs,logs:B(H.boolean().default(!1),{description:`Display job execution logs (detail mode only)`})}),run:async e=>{let t=M.jsonMode||e.json;if(e.executionId){let n=parseDuration(e.interval);if(t||M.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:parseDuration(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};M.out(n)}else M.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):M.out(r)}else{let t=await 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:e.limit});M.out(t)}}});async function resolveWorkflow(e,t,n){let{workflow:r}=await e.getWorkflowByName({workspaceId:t,workflowName:n});if(!r)throw R({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 K&&e.code===G.NotFound?R({code:`WORKFLOW_NOT_FOUND`,message:`Workflow '${t}' not found.`,cause:e}):e}}const Cs=Y({name:`get`,description:`Get workflow details.`,args:H.strictObject({...J,...ys}),run:async e=>{let t=await getWorkflow({workflow:{name:e.name},workspaceId:e[`workspace-id`],profile:e.profile});M.out(t)}});async function startWorkflowCore(e){let{client:t,workspaceId:n,workflowName:r}=e;try{let i=await resolveWorkflow(t,n,r),a=Gn(Ie,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 K&&e.code===G.NotFound?R({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 R({code:`AUTH_CONFIG_REQUIRED`,message:`Application ${t.name} does not have an auth configuration.`});return r}async function startWorkflowByName(e){let t=await loadMachineUserName({machineUser:e.machineUser,machineUserSource:e.machineUserSource,profile:e.profile});if(!t)throw R({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 ws=Y({name:`start`,description:`Start a workflow execution.`,args:H.strictObject({...$r,...ys,"machine-user":B(H.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:B(H.string().optional(),{alias:`a`,description:`Workflow argument (JSON string)`}),...xs}),run:async e=>{let{executionId:t,wait:n}=await startWorkflowByName({name:e.name,machineUser:e[`machine-user`],machineUserSource:resolveMachineUserInputSource(e[`machine-user`]),arg:e.arg,workspaceId:e[`workspace-id`],profile:e.profile,configPath:e.config,interval:parseDuration(e.interval)}),r=M.jsonMode;if(M.info(`Execution ID: ${t}`,{mode:`stream`}),e.wait){let i=await n({showProgress:!r,timeout:parseDuration(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});M.out({...i,jobDetails:n.jobDetails})}else M.out(i);let a=getWorkflowWaitFailure(i,e.until);if(a)throw a}else M.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:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId}),i=[];if(e.status){let t=parseExecutorJobStatus(e.status);i.push(Gn(Ke,{condition:Gn(Ze,{field:`status`,operator:ze.EQ,value:{kind:{case:`numberValue`,value:t}}})}))}let a=i.length>0?Gn(Ke,{and:i}):void 0,o=toPageDirection(e.order??`desc`);try{return(await jt(async(e,i)=>{let{jobs:s,nextPageToken:c}=await n.listExecutorJobs({workspaceId:r,executorName:t,pageToken:e,pageSize:i,pageDirection:o,filter:a});return[s,c]},{limit:e.limit})).map(toExecutorJobListInfo)}catch(e){throw e instanceof K&&e.code===G.NotFound?R({code:`EXECUTOR_NOT_FOUND`,message:`Executor '${t}' not found.`,cause:e}):e}}async function getExecutorJob(e){let t=e.executor.name,{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId});try{let{job:i}=await n.getExecutorJob({workspaceId:r,executorName:t,jobId:e.jobId});if(!i)throw R({code:`EXECUTOR_JOB_NOT_FOUND`,message:`Job '${e.jobId}' not found.`});let a=toExecutorJobInfo(i);if(e.attempts){let t=await At(async(t,i)=>{let{attempts:a,nextPageToken:o}=await n.listExecutorJobAttempts({workspaceId:r,jobId:e.jobId,pageToken:t,pageSize:i,pageDirection:je.DESC});return[a,o]});return{...a,attempts:t.map(toExecutorJobAttemptInfo)}}return a}catch(n){throw n instanceof K&&n.code===G.NotFound?R({code:`EXECUTOR_JOB_NOT_FOUND`,message:`Job '${e.jobId}' not found for executor '${t}'.`,cause:n}):n}}async function watchExecutorJob(e){let t=e.executor.name,{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId}),i=e.interval??3e3,a=e.timeout,o=e.showProgress??!M.jsonMode,s=Date.now(),c=o?spinner().start(`Waiting for executor job to complete...`):null,l=0,u=null,remainingTimeout=()=>{if(a!==void 0)return a-(Date.now()-s)},withWaitMetadata=(e,t)=>({...e,elapsedMs:Date.now()-s,attempts:l,timedOut:t,lastError:u}),timeoutResult=(n,r)=>withWaitMetadata({job:r?toExecutorJobInfo(r):createUnknownExecutorJob(t,e.jobId),targetType:n},!0);try{let{executor:a}=await n.getExecutorExecutor({workspaceId:r,name:t});if(!a)throw R({code:`EXECUTOR_NOT_FOUND`,message:`Executor '${t}' not found.`});let s=a.targetType,d=executorTargetTypeToString(s),f;for(;;){let a=remainingTimeout();if(a!==void 0&&a<=0)return c?.fail(`Executor job wait timed out.`),timeoutResult(d,f);try{if(l+=1,f=(await n.getExecutorJob({workspaceId:r,executorName:t,jobId:e.jobId})).job,!f)throw R({code:`EXECUTOR_JOB_NOT_FOUND`,message:`Job '${e.jobId}' not found.`});if(u=null,classifyExecutorJobStatus(f.status)!==`transient`)break}catch(e){if(!isRetryableWaitError(e))throw e;u=formatWaitError(e),c&&(c.text=`Retrying executor job poll... (${formatTime(new Date)})`)}let o=remainingTimeout();if(o!==void 0&&o<=0)return c?.fail(`Executor job wait timed out.`),timeoutResult(d,f);c&&(c.text=`Waiting for executor job... (${formatTime(new Date)})`),await Pr(o===void 0?i:Math.min(i,o))}let p=toExecutorJobInfo(f),m=colorizeExecutorJobStatus(p.status);f.status===T.SUCCESS?c?.succeed(`Executor job completed: ${m}`):c?.fail(`Executor job completed: ${m}`);let g=(await At(async(t,i)=>{let{attempts:a,nextPageToken:o}=await n.listExecutorJobAttempts({workspaceId:r,jobId:e.jobId,pageToken:t,pageSize:i,pageDirection:je.DESC});return[a,o]})).map(toExecutorJobAttemptInfo),_={...p,attempts:g},v=g[0]?.operationReference;if(v)switch(s){case O.WORKFLOW:c?.stop();try{let t=remainingTimeout();if(t!==void 0&&t<=0)return withWaitMetadata({job:_,targetType:d,workflowExecutionId:v},!0);let a=await waitForWorkflowExecution({client:n,workspaceId:r,executionId:v,interval:i,timeout:t,showProgress:o,trackJobs:!0});l+=a.attempts,u=a.lastError;let s;if(e.logs)try{let{execution:t}=await getWorkflowExecution({executionId:v,workspaceId:e.workspaceId,profile:e.profile,logs:!0});t.jobDetails&&(s=t.jobDetails.filter(e=>e.logs||e.result).map(e=>({jobName:e.stackedJobName||e.id,logs:e.logs,result:e.result})))}catch(e){M.warn(`Could not fetch workflow execution logs: ${e instanceof Error?e.message:e}`)}return withWaitMetadata({job:_,targetType:d,workflowExecutionId:v,workflowStatus:a.status,workflowJobLogs:s},a.timedOut)}catch(e){return M.warn(`Could not track workflow execution: ${e instanceof Error?e.message:e}`),withWaitMetadata({job:_,targetType:d,workflowExecutionId:v},!1)}case O.FUNCTION:case O.JOB_FUNCTION:c?.start(`Waiting for function execution ${v}...`);try{let t;for(;;){let a=remainingTimeout();if(a!==void 0&&a<=0)return c?.fail(`Function execution wait timed out.`),withWaitMetadata({job:_,targetType:d,functionExecutionId:v,functionStatus:t},!0);try{l+=1;let{execution:i}=await n.getFunctionExecution({workspaceId:r,executionId:v});if(!i)throw R({code:`FUNCTION_EXECUTION_NOT_FOUND`,message:`Function execution '${v}' not found.`});if(u=null,t=functionExecutionStatusToString(i.status),isFunctionExecutionTerminalStatus(i.status)){let n=colorizeFunctionExecutionStatus(t);return i.status===h.SUCCESS?c?.succeed(`Function execution completed: ${n}`):c?.fail(`Function execution completed: ${n}`),withWaitMetadata({job:_,targetType:d,functionExecutionId:v,functionStatus:t,functionLogs:e.logs&&i.logs||void 0},!1)}}catch(e){if(!isRetryableWaitError(e))throw e;u=formatWaitError(e),c&&(c.text=`Retrying function execution poll... (${formatTime(new Date)})`)}let o=remainingTimeout();if(o!==void 0&&o<=0)return c?.fail(`Function execution wait timed out.`),withWaitMetadata({job:_,targetType:d,functionExecutionId:v,functionStatus:t},!0);c&&(c.text=`Waiting for function execution... (${formatTime(new Date)})`),await Pr(o===void 0?i:Math.min(i,o))}}catch(e){return c?.warn(`Could not track function execution: ${e instanceof Error?e.message:e}`),withWaitMetadata({job:_,targetType:d,functionExecutionId:v},!1)}}return withWaitMetadata({job:_,targetType:d},!1)}finally{c?.stop()}}function getExecutorWaitFailure(e){let t={jobId:e.job.id,status:e.job.status,workflowExecutionId:e.workflowExecutionId,functionExecutionId:e.functionExecutionId};if(e.timedOut)return R({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 R({code:`EXECUTOR_JOB_FAILED`,message:`Executor job '${e.job.id}' completed with status ${e.job.status}.`,context:t});if(e.workflowStatus===`FAILED`)return R({code:`WORKFLOW_EXECUTION_FAILED`,message:`Workflow execution '${e.workflowExecutionId}' failed.`,context:t});if(e.functionStatus===`FAILED`)return R({code:`FUNCTION_EXECUTION_FAILED`,message:`Function execution '${e.functionExecutionId}' failed.`,context:t});if(e.functionStatus===`CANCELED`)return R({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(M.log(formatKeyValueTable(t)),e.attempts&&e.attempts.length>0){M.log(j.bold(`
|
|
137
|
+
`)}`)}catch{M.log(` ${t.result}`)}}}}}const ks=Y({name:`executions`,description:`List or get workflow executions.`,args:H.strictObject({...J,...ci,"execution-id":B(H.string().optional(),{positional:!0,description:`Execution ID (if provided, shows details)`}),"workflow-name":B(H.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:B(H.string().optional(),{alias:`s`,description:`Filter by status (list mode only)`}),...Os,logs:B(H.boolean().default(!1),{description:`Display job execution logs (detail mode only)`})}),run:async e=>{let t=M.jsonMode||e.json;if(e.executionId){let n=parseDuration(e.interval);if(t||M.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:parseDuration(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};M.out(n)}else M.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):M.out(r)}else{let t=await 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:e.limit});M.out(t)}}});async function resolveWorkflow(e,t,n){let{workflow:r}=await e.getWorkflowByName({workspaceId:t,workflowName:n});if(!r)throw R({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 K&&e.code===G.NotFound?R({code:`WORKFLOW_NOT_FOUND`,message:`Workflow '${t}' not found.`,cause:e}):e}}const As=Y({name:`get`,description:`Get workflow details.`,args:H.strictObject({...J,...Es}),run:async e=>{let t=await getWorkflow({workflow:{name:e.name},workspaceId:e[`workspace-id`],profile:e.profile});M.out(t)}});async function startWorkflowCore(e){let{client:t,workspaceId:n,workflowName:r}=e;try{let i=await resolveWorkflow(t,n,r),a=Xn(Ie,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 K&&e.code===G.NotFound?R({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 R({code:`AUTH_CONFIG_REQUIRED`,message:`Application ${t.name} does not have an auth configuration.`});return r}async function startWorkflowByName(e){let t=await loadMachineUserName({machineUser:e.machineUser,machineUserSource:e.machineUserSource,profile:e.profile});if(!t)throw R({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 js=Y({name:`start`,description:`Start a workflow execution.`,args:H.strictObject({...ai,...Es,"machine-user":B(H.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:B(H.string().optional(),{alias:`a`,description:`Workflow argument (JSON string)`}),...Os}),run:async e=>{let{executionId:t,wait:n}=await startWorkflowByName({name:e.name,machineUser:e[`machine-user`],machineUserSource:resolveMachineUserInputSource(e[`machine-user`]),arg:e.arg,workspaceId:e[`workspace-id`],profile:e.profile,configPath:e.config,interval:parseDuration(e.interval)}),r=M.jsonMode;if(M.info(`Execution ID: ${t}`,{mode:`stream`}),e.wait){let i=await n({showProgress:!r,timeout:parseDuration(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});M.out({...i,jobDetails:n.jobDetails})}else M.out(i);let a=getWorkflowWaitFailure(i,e.until);if(a)throw a}else M.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:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId}),i=[];if(e.status){let t=parseExecutorJobStatus(e.status);i.push(Xn(Ke,{condition:Xn(Ze,{field:`status`,operator:ze.EQ,value:{kind:{case:`numberValue`,value:t}}})}))}let a=i.length>0?Xn(Ke,{and:i}):void 0,o=toPageDirection(e.order??`desc`);try{return(await Ct(async(e,i)=>{let{jobs:s,nextPageToken:c}=await n.listExecutorJobs({workspaceId:r,executorName:t,pageToken:e,pageSize:i,pageDirection:o,filter:a});return[s,c]},{limit:e.limit})).map(toExecutorJobListInfo)}catch(e){throw e instanceof K&&e.code===G.NotFound?R({code:`EXECUTOR_NOT_FOUND`,message:`Executor '${t}' not found.`,cause:e}):e}}async function getExecutorJob(e){let t=e.executor.name,{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId});try{let{job:i}=await n.getExecutorJob({workspaceId:r,executorName:t,jobId:e.jobId});if(!i)throw R({code:`EXECUTOR_JOB_NOT_FOUND`,message:`Job '${e.jobId}' not found.`});let a=toExecutorJobInfo(i);if(e.attempts){let t=await Mt(async(t,i)=>{let{attempts:a,nextPageToken:o}=await n.listExecutorJobAttempts({workspaceId:r,jobId:e.jobId,pageToken:t,pageSize:i,pageDirection:je.DESC});return[a,o]});return{...a,attempts:t.map(toExecutorJobAttemptInfo)}}return a}catch(n){throw n instanceof K&&n.code===G.NotFound?R({code:`EXECUTOR_JOB_NOT_FOUND`,message:`Job '${e.jobId}' not found for executor '${t}'.`,cause:n}):n}}async function watchExecutorJob(e){let t=e.executor.name,{client:n,workspaceId:r}=await loadOperatorWorkspaceContext({profile:e.profile,workspaceId:e.workspaceId}),i=e.interval??3e3,a=e.timeout,o=e.showProgress??!M.jsonMode,s=Date.now(),c=o?spinner().start(`Waiting for executor job to complete...`):null,l=0,u=null,remainingTimeout=()=>{if(a!==void 0)return a-(Date.now()-s)},withWaitMetadata=(e,t)=>({...e,elapsedMs:Date.now()-s,attempts:l,timedOut:t,lastError:u}),timeoutResult=(n,r)=>withWaitMetadata({job:r?toExecutorJobInfo(r):createUnknownExecutorJob(t,e.jobId),targetType:n},!0);try{let{executor:a}=await n.getExecutorExecutor({workspaceId:r,name:t});if(!a)throw R({code:`EXECUTOR_NOT_FOUND`,message:`Executor '${t}' not found.`});let s=a.targetType,d=executorTargetTypeToString(s),f;for(;;){let a=remainingTimeout();if(a!==void 0&&a<=0)return c?.fail(`Executor job wait timed out.`),timeoutResult(d,f);try{if(l+=1,f=(await n.getExecutorJob({workspaceId:r,executorName:t,jobId:e.jobId})).job,!f)throw R({code:`EXECUTOR_JOB_NOT_FOUND`,message:`Job '${e.jobId}' not found.`});if(u=null,classifyExecutorJobStatus(f.status)!==`transient`)break}catch(e){if(!isRetryableWaitError(e))throw e;u=formatWaitError(e),c&&(c.text=`Retrying executor job poll... (${formatTime(new Date)})`)}let o=remainingTimeout();if(o!==void 0&&o<=0)return c?.fail(`Executor job wait timed out.`),timeoutResult(d,f);c&&(c.text=`Waiting for executor job... (${formatTime(new Date)})`),await Br(o===void 0?i:Math.min(i,o))}let p=toExecutorJobInfo(f),m=colorizeExecutorJobStatus(p.status);f.status===T.SUCCESS?c?.succeed(`Executor job completed: ${m}`):c?.fail(`Executor job completed: ${m}`);let g=(await Mt(async(t,i)=>{let{attempts:a,nextPageToken:o}=await n.listExecutorJobAttempts({workspaceId:r,jobId:e.jobId,pageToken:t,pageSize:i,pageDirection:je.DESC});return[a,o]})).map(toExecutorJobAttemptInfo),_={...p,attempts:g},v=g[0]?.operationReference;if(v)switch(s){case O.WORKFLOW:c?.stop();try{let t=remainingTimeout();if(t!==void 0&&t<=0)return withWaitMetadata({job:_,targetType:d,workflowExecutionId:v},!0);let a=await waitForWorkflowExecution({client:n,workspaceId:r,executionId:v,interval:i,timeout:t,showProgress:o,trackJobs:!0});l+=a.attempts,u=a.lastError;let s;if(e.logs)try{let{execution:t}=await getWorkflowExecution({executionId:v,workspaceId:e.workspaceId,profile:e.profile,logs:!0});t.jobDetails&&(s=t.jobDetails.filter(e=>e.logs||e.result).map(e=>({jobName:e.stackedJobName||e.id,logs:e.logs,result:e.result})))}catch(e){M.warn(`Could not fetch workflow execution logs: ${e instanceof Error?e.message:e}`)}return withWaitMetadata({job:_,targetType:d,workflowExecutionId:v,workflowStatus:a.status,workflowJobLogs:s},a.timedOut)}catch(e){return M.warn(`Could not track workflow execution: ${e instanceof Error?e.message:e}`),withWaitMetadata({job:_,targetType:d,workflowExecutionId:v},!1)}case O.FUNCTION:case O.JOB_FUNCTION:c?.start(`Waiting for function execution ${v}...`);try{let t;for(;;){let a=remainingTimeout();if(a!==void 0&&a<=0)return c?.fail(`Function execution wait timed out.`),withWaitMetadata({job:_,targetType:d,functionExecutionId:v,functionStatus:t},!0);try{l+=1;let{execution:i}=await n.getFunctionExecution({workspaceId:r,executionId:v});if(!i)throw R({code:`FUNCTION_EXECUTION_NOT_FOUND`,message:`Function execution '${v}' not found.`});if(u=null,t=functionExecutionStatusToString(i.status),isFunctionExecutionTerminalStatus(i.status)){let n=colorizeFunctionExecutionStatus(t);return i.status===h.SUCCESS?c?.succeed(`Function execution completed: ${n}`):c?.fail(`Function execution completed: ${n}`),withWaitMetadata({job:_,targetType:d,functionExecutionId:v,functionStatus:t,functionLogs:e.logs&&i.logs||void 0},!1)}}catch(e){if(!isRetryableWaitError(e))throw e;u=formatWaitError(e),c&&(c.text=`Retrying function execution poll... (${formatTime(new Date)})`)}let o=remainingTimeout();if(o!==void 0&&o<=0)return c?.fail(`Function execution wait timed out.`),withWaitMetadata({job:_,targetType:d,functionExecutionId:v,functionStatus:t},!0);c&&(c.text=`Waiting for function execution... (${formatTime(new Date)})`),await Br(o===void 0?i:Math.min(i,o))}}catch(e){return c?.warn(`Could not track function execution: ${e instanceof Error?e.message:e}`),withWaitMetadata({job:_,targetType:d,functionExecutionId:v},!1)}}return withWaitMetadata({job:_,targetType:d},!1)}finally{c?.stop()}}function getExecutorWaitFailure(e){let t={jobId:e.job.id,status:e.job.status,workflowExecutionId:e.workflowExecutionId,functionExecutionId:e.functionExecutionId};if(e.timedOut)return R({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 R({code:`EXECUTOR_JOB_FAILED`,message:`Executor job '${e.job.id}' completed with status ${e.job.status}.`,context:t});if(e.workflowStatus===`FAILED`)return R({code:`WORKFLOW_EXECUTION_FAILED`,message:`Workflow execution '${e.workflowExecutionId}' failed.`,context:t});if(e.functionStatus===`FAILED`)return R({code:`FUNCTION_EXECUTION_FAILED`,message:`Function execution '${e.functionExecutionId}' failed.`,context:t});if(e.functionStatus===`CANCELED`)return R({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(M.log(formatKeyValueTable(t)),e.attempts&&e.attempts.length>0){M.log(j.bold(`
|
|
138
138
|
Attempts:`));for(let t of e.attempts)if(M.log(j.info(`\n--- Attempt ${t.id} ---`)),M.log(` Status: ${t.status}`),M.log(` Started: ${t.startedAt}`),M.log(` Finished: ${t.finishedAt}`),t.error){M.log(j.error(`
|
|
139
139
|
Error:`));let e=t.error.split(`
|
|
140
|
-
`);for(let t of e)M.log(` ${t}`)}}}const
|
|
140
|
+
`);for(let t of e)M.log(` ${t}`)}}}const Ms=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:H.strictObject({...J,"executor-name":B(H.string(),{positional:!0,description:`Executor name`}),"job-id":B(H.string().optional(),{positional:!0,description:`Job ID (if provided, shows job details)`}),status:B(H.string().optional(),{alias:`s`,description:`Filter by status (PENDING, RUNNING, SUCCESS, FAILED, CANCELED) (list mode only)`}),attempts:B(H.boolean().default(!1),{description:`Show job attempts (only with job ID) (detail mode only)`}),wait:B(H.boolean().default(!1),{alias:`W`,description:`Wait for job completion and downstream execution (workflow/function) if applicable (detail mode only)`}),interval:B(Zr.default(`3s`),{alias:`i`,description:`Polling interval when using --wait (e.g., '3s', '500ms', '1m')`}),timeout:B(Zr.default(`5m`),{alias:`t`,description:`Maximum time to wait when using --wait (e.g., '30s', '5m')`}),...ci,limit:B($r.default(50),{description:`Maximum number of jobs to list (0: unlimited, default: 50) (list mode only)`}),logs:B(H.boolean().default(!1),{alias:`l`,description:`Display function execution logs after completion (requires --wait)`})}),run:async e=>{let t=M.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:parseDuration(e.interval),timeout:parseDuration(e.timeout),logs:e.logs,showProgress:!t});if(t)M.out(n);else{if(M.log(j.bold(`Target Type: ${n.targetType}\n`)),printJobWithAttempts(n.job),n.workflowExecutionId&&(M.log(j.bold(`
|
|
141
141
|
Workflow Execution:`)),M.log(` ID: ${n.workflowExecutionId}`),n.workflowStatus&&M.log(` Status: ${n.workflowStatus}`),n.workflowJobLogs&&n.workflowJobLogs.length>0))for(let e of n.workflowJobLogs){if(M.log(j.bold(`\n Job: ${e.jobName}`)),e.logs){M.log(j.dim(` Logs:`));for(let t of e.logs.split(`
|
|
142
142
|
`))M.log(` ${t}`)}if(e.result){M.log(j.dim(` Result:`));try{let t=JSON.parse(e.result),n=JSON.stringify(t,null,2);for(let e of n.split(`
|
|
143
143
|
`))M.log(` ${e}`)}catch{M.log(` ${e.result}`)}}}if(n.functionExecutionId&&(M.log(j.bold(`
|
|
144
144
|
Function Execution:`)),M.log(` ID: ${n.functionExecutionId}`),n.functionStatus&&M.log(` Status: ${n.functionStatus}`),n.functionLogs)){M.log(j.dim(` Logs:`));for(let e of n.functionLogs.split(`
|
|
145
|
-
`))M.log(` ${e}`)}}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):M.out(n)}else{e.wait&&M.warn(`--wait flag is ignored in list mode. Specify a job ID to wait.`);let t=await listExecutorJobs({executor:{name:e.executorName},status:e.status,order:e.order,limit:e.limit,workspaceId:e[`workspace-id`],profile:e.profile});M.out(t)}}});async function listExecutors(e){let{client:t,workspaceId:n}=await loadOperatorWorkspaceContext({profile:e?.profile,workspaceId:e?.workspaceId}),r=toPageDirection(e?.order);return(await
|
|
145
|
+
`))M.log(` ${e}`)}}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):M.out(n)}else{e.wait&&M.warn(`--wait flag is ignored in list mode. Specify a job ID to wait.`);let t=await listExecutorJobs({executor:{name:e.executorName},status:e.status,order:e.order,limit:e.limit,workspaceId:e[`workspace-id`],profile:e.profile});M.out(t)}}});async function listExecutors(e){let{client:t,workspaceId:n}=await loadOperatorWorkspaceContext({profile:e?.profile,workspaceId:e?.workspaceId}),r=toPageDirection(e?.order);return(await Ct(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 Ns=Y({name:`list`,description:`List all executors`,args:H.strictObject({...J,...paginationArgs()}),run:async e=>{let t=M.jsonMode,n=await listExecutors({workspaceId:e[`workspace-id`],profile:e.profile,order:e.order,limit:e.limit});if(n.length===0){M.info(`No executors found.`),t&&M.out([]);return}if(M.out(n,{display:{disabled:e=>e?j.warning(`true`):j.dim(`false`)}}),!t&&n.some(e=>e.triggerType===`webhook`)){let t=wn([`tailor`,`executor`,`webhook`,`list`,...recoveryContextArgs({profile:e.profile,workspaceId:e[`workspace-id`]})]);M.info(`To see webhook URLs, run: ${t}`)}}}),Ps=H.string().transform(e=>{try{return JSON.parse(e)}catch{throw R({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`}),Fs=H.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 K&&t.code===G.NotFound?R({code:`EXECUTOR_NOT_FOUND`,message:`Executor '${e.executorName}' not found.`,cause:t}):t instanceof K&&t.code===G.InvalidArgument?R({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 R({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 Is=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:H.strictObject({...J,"executor-name":B(H.string(),{positional:!0,description:`Executor name`}),data:B(Ps.optional(),{alias:`d`,description:`Request body (JSON string)`}),header:B(Fs.array().optional(),{alias:`H`,overrideBuiltinAlias:!0,description:`Request header (format: 'Key: Value', can be specified multiple times)`}),wait:B(H.boolean().default(!1),{alias:`W`,description:`Wait for job completion and downstream execution (workflow/function) if applicable`}),interval:B(Zr.default(`3s`),{alias:`i`,description:`Polling interval when using --wait (e.g., '3s', '500ms', '1m')`}),timeout:B(Zr.default(`5m`),{alias:`t`,description:`Maximum time to wait when using --wait (e.g., '30s', '5m')`}),logs:B(H.boolean().default(!1),{alias:`l`,description:`Display function execution logs after completion (requires --wait)`})}),run:async e=>{let t=M.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 R({code:`EXECUTOR_NOT_FOUND`,message:`Executor '${e.executorName}' not found.`});if(i.triggerType===Be.EVENT)throw R({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===Be.SCHEDULE&&(e.data||e.header))throw R({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){M.success(`Executor '${e.executorName}' triggered successfully.`),e.wait&&M.warn(`Cannot watch: job ID not available. The API may need to be updated.`);return}if(M.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:parseDuration(e.interval),timeout:parseDuration(e.timeout),logs:e.logs,showProgress:!t});if(t)M.out(n);else{if(M.log(j.bold(`\nTarget Type: ${n.targetType}`)),M.log(`Job Status: ${n.job.status}`),n.workflowExecutionId&&(M.log(j.bold(`
|
|
146
146
|
Workflow Execution:`)),M.log(` ID: ${n.workflowExecutionId}`),n.workflowStatus&&M.log(` Status: ${n.workflowStatus}`),n.workflowJobLogs&&n.workflowJobLogs.length>0))for(let e of n.workflowJobLogs){if(M.log(j.bold(`\n Job: ${e.jobName}`)),e.logs){M.log(j.dim(` Logs:`));for(let t of e.logs.split(`
|
|
147
147
|
`))M.log(` ${t}`)}if(e.result){M.log(j.dim(` Result:`));try{let t=JSON.parse(e.result),n=JSON.stringify(t,null,2);for(let e of n.split(`
|
|
148
148
|
`))M.log(` ${e}`)}catch{M.log(` ${e.result}`)}}}if(n.functionExecutionId&&(M.log(j.bold(`
|
|
149
149
|
Function Execution:`)),M.log(` ID: ${n.functionExecutionId}`),n.functionStatus&&M.log(` Status: ${n.functionStatus}`),n.functionLogs)){M.log(j.dim(` Logs:`));for(let e of n.functionLogs.split(`
|
|
150
|
-
`))M.log(` ${e}`)}}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=toPageDirection(e?.order);return(await
|
|
151
|
-
`),context:{hook:e,failures:n.map(({plugin:e,reason:t})=>({plugin:e,error:errorToJson(t,{includeStack:M.verbose}).error}))}})}async function writeGeneratedFiles(e,t){await Promise.all(t.files.map(async t=>(U.mkdirSync(V.dirname(t.path),{recursive:!0}),new Promise((n,r)=>{if(t.skipIfExists&&U.existsSync(t.path)){let r=V.relative(process.cwd(),t.path);return M.debug(`${e} | skip existing: ${r}`),n()}U.writeFile(t.path,t.content,i=>{if(i){let e=V.relative(process.cwd(),t.path);M.error(`Error writing file ${j.bold(e)}`),M.error(String(i)),r(i)}else{let i=V.relative(process.cwd(),t.path);M.debug(`${e} | generate: ${j.success(i)}`),t.executable?U.chmod(t.path,493,e=>{if(e){let n=V.relative(process.cwd(),t.path);M.error(`Error setting executable permission on ${j.bold(n)}`),M.error(String(e)),r(e)}else n()}):n()}})})))),t.files.length>0&&M.log(`${e} | generation complete`)}return{application:t,baseDir:i,services:a,async generate(){M.newline(),M.log(`Generation for application: ${j.highlight(t.config.name)}`);let e=t;await z(`generate.loadTailorDBTypes`,async t=>{t.setAttribute(`generate.namespace_count`,e.tailorDBServices.length);for(let t of e.tailorDBServices){let e=t.namespace;await z(`generate.loadTypes.${e}`,async()=>{try{await t.loadTypes(),await t.processNamespacePlugins(),a.tailordb[e]={types:t.types,sourceInfo:t.typeSourceInfo,pluginAttachments:t.pluginAttachments}}catch(t){throw M.error(`Error loading tables for TailorDB service ${j.bold(e)}`),M.error(String(t)),t}})}try{sn({tailorDBServices:e.tailorDBServices})}catch(e){throw M.error(`Error validating TailorDB table names`),M.error(String(e)),e}});let{pluginExecutorFiles:i,executorService:s}=await z(`generate.pluginFiles`,async()=>{let t=Kt(r,e.tailorDBServices,n.path);return{pluginExecutorFiles:t,executorService:e.executorService??(t.length>0?pn({config:{files:[]},baseDir:V.dirname(n.path)}):void 0)}});if(e.authService){let t=e.authService;await z(`generate.resolveAuthNamespaces`,async()=>t.resolveNamespaces())}(e.tailorDBServices.length>0||i.length>0)&&M.newline(),o.some(e=>e.onTailorDBReady!=null)&&(await z(`generate.onTailorDBReady`,async()=>{await runPluginHook(`onTailorDBReady`)}),M.newline()),await z(`generate.loadResolvers`,async()=>{for(let t of e.resolverServices){let e=t.namespace;await z(`generate.loadResolvers.${e}`,async()=>{try{await t.loadResolvers();let n={};a.resolver[e]=n,Object.entries(t.resolvers).forEach(([e,t])=>{n[t.name]=t})}catch(t){throw M.error(`Error loading resolvers for Resolver service ${j.bold(e)}`),M.error(String(t)),t}})}}),o.some(e=>e.onResolverReady!=null)&&(await z(`generate.onResolversReady`,async()=>{await runPluginHook(`onResolverReady`)}),M.newline()),await z(`generate.loadExecutors`,async()=>{s&&(await s.loadExecutors(),i.length>0&&await s.loadPluginExecutorFiles([...i]));let e=s?.executors??{};Object.entries(e).forEach(([e,t])=>{a.executor[e]=t})}),o.some(e=>e.onExecutorReady!=null)&&(await z(`generate.onExecutorsReady`,async()=>{await runPluginHook(`onExecutorReady`)}),M.newline())}}}async function generate$1(e){return z(`generate`,async t=>{let{config:n,plugins:r}=await z(`generate.loadConfig`,async()=>loadConfig(e?.configPath));await z(`generate.generateUserTypes`,async()=>generateUserTypes({config:n,configPath:n.path}));let i;r.length>0&&(i=new En(r));let a=tn({config:n,pluginManager:i});t.setAttribute(`app.name`,a.config.name),await createGenerationManager({application:a,config:n,pluginManager:i}).generate()})}function machineUserInfo(e){return M.registerSecret(e.clientSecret),{name:e.name,clientId:e.clientId,clientSecret:e.clientSecret,createdAt:e.createdAt?W(e.createdAt):null,updatedAt:e.updatedAt?W(e.updatedAt):null,attributes:Object.fromEntries(Object.entries(e.attributeMap).map(([e,t])=>[e,Jn(ir,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 R({code:`AUTH_CONFIG_REQUIRED`,message:`Application ${r.name} does not have an auth configuration.`});let a=toPageDirection(e?.order);return(await jt(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 Is=Y({name:`list`,description:`List all machine users in the application.`,args:H.strictObject({...$r,...paginationArgs()}),run:async e=>{let t=await listMachineUsers({workspaceId:e[`workspace-id`],profile:e.profile,configPath:e.config,order:e.order,limit:e.limit});M.out(t,{display:{createdAt:null,updatedAt:null}})}});async function getMachineUserTokenInternal(e){let t=await loadMachineUserName({machineUser:e.name,machineUserSource:e.nameSource,profile:e.profile});if(!t)throw R({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 R({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 R({code:`MACHINE_USER_NOT_FOUND`,message:`Machine user ${t} not found.`});let s=await kt(a.url,o.clientId,o.clientSecret),c=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 Ls=Y({name:`token`,description:`Get an access token for a machine user.`,args:H.strictObject({...$r,name:B(H.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:resolveMachineUserInputSource(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};M.out(n)}}),grantTypeToString=e=>{switch(e){case Pe.AUTHORIZATION_CODE:return`authorization_code`;case Pe.REFRESH_TOKEN:return`refresh_token`;default:return`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?W(e.createdAt):null}}function toOAuth2ClientCredentials(e){return M.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?W(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 R({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(k(r,`oauth2Client missing in response`))}catch(t){throw t instanceof K&&t.code===G.NotFound?R({code:`OAUTH2_CLIENT_NOT_FOUND`,message:`OAuth2 client '${e.name}' not found.`,cause:t}):t}}const Rs=Y({name:`get`,description:`Get OAuth2 client credentials (including client secret).`,args:H.strictObject({...$r,name:B(H.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});M.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 R({code:`AUTH_CONFIG_REQUIRED`,message:`Application ${r.name} does not have an auth configuration.`});let a=toPageDirection(e?.order);return(await jt(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 zs=Y({name:`list`,description:`List all OAuth2 clients in the application.`,args:H.strictObject({...$r,...paginationArgs()}),run:async e=>{let t=await listOAuth2Clients({workspaceId:e[`workspace-id`],profile:e.profile,configPath:e.config,order:e.order,limit:e.limit});M.out(t)}}),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)}),Bs=H.object({organizationId:H.uuid({message:`organization-id must be a valid UUID`}),parentFolderId:H.string().optional(),name:H.string().min(1,`Name must not be empty`)});async function createFolder(e){let t=parseOptions(Bs,e),n=await loadAccessToken(),r=await(await P(n)).createOrganizationFolder({organizationId:t.organizationId,parentFolderId:t.parentFolderId??``,folderName:t.name});if(!r.folder)throw L(`Failed to create folder.`);return folderInfo(r.folder)}const Vs=Y({name:`create`,description:`Create a new folder in an organization.`,args:H.strictObject({...ti,"parent-folder-id":B(H.string().optional(),{description:`Parent folder ID`}),name:B(H.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||M.success(`Folder "${t.name}" created successfully.`),M.out(t)}}),Hs=H.object({organizationId:H.uuid({message:`organization-id must be a valid UUID`}),folderId:H.uuid({message:`folder-id must be a valid UUID`})});async function deleteFolder(e){let t=parseOptions(Hs,e),n=await loadAccessToken();await(await P(n)).deleteOrganizationFolder({organizationId:t.organizationId,folderId:t.folderId})}const Us=Y({name:`delete`,description:`Delete a folder from an organization.`,args:H.strictObject({...ti,...ri,...ei}),run:async e=>{await assertWritable();let t=await loadAccessToken(),n=await P(t),r;try{r=await n.getOrganizationFolder({organizationId:e[`organization-id`],folderId:e[`folder-id`]})}catch(t){throw t instanceof K&&t.code===G.NotFound?R({code:`FOLDER_NOT_FOUND`,message:`Folder "${e[`folder-id`]}" not found.`,cause:t}):t}if(!r.folder)throw R({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}"?`})){M.info(`Folder deletion cancelled.`);return}await n.deleteOrganizationFolder({organizationId:e[`organization-id`],folderId:e[`folder-id`]}),M.success(`Folder "${i}" deleted successfully.`)}}),Ws=H.object({organizationId:H.uuid({message:`organization-id must be a valid UUID`}),folderId:H.uuid({message:`folder-id must be a valid UUID`})});async function getFolder(e){let t=parseOptions(Ws,e),n=await loadAccessToken(),r=await(await P(n)).getOrganizationFolder({organizationId:t.organizationId,folderId:t.folderId});if(!r.folder)throw R({code:`FOLDER_NOT_FOUND`,message:`Folder "${t.folderId}" not found.`});return folderInfo(r.folder)}const Gs=Y({name:`get`,description:`Show detailed information about a folder.`,args:H.strictObject({...ti,...ri}),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)};M.out(n)}}),Ks=H.object({organizationId:H.uuid({message:`organization-id must be a valid UUID`}),parentFolderId:H.string().optional(),order:Jr.optional(),limit:H.number().int().nonnegative().optional()});async function listFolders(e){let{organizationId:t,parentFolderId:n,order:r,limit:i}=parseOptions(Ks,e),a=await loadAccessToken(),o=await P(a),s=toPageDirection(r);return(await jt(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 qs=Y({name:`list`,description:`List folders in an organization.`,args:H.strictObject({...ti,"parent-folder-id":B(H.string().optional(),{description:`Parent folder ID to list children of`}),...paginationArgs()}),run:async e=>{let t=await listFolders({organizationId:e[`organization-id`],parentFolderId:e[`parent-folder-id`],order:e.order,limit:e.limit});M.out(t,{display:{updatedAt:null}})}}),Js=H.object({organizationId:H.uuid({message:`organization-id must be a valid UUID`}),folderId:H.uuid({message:`folder-id must be a valid UUID`}),name:H.string().min(1,`Name must not be empty`)});async function updateFolder(e){let t=parseOptions(Js,e),n=await loadAccessToken(),r=await(await P(n)).updateOrganizationFolder({organizationId:t.organizationId,folderId:t.folderId,folderName:t.name});if(!r.folder)throw L(`Failed to update folder "${t.folderId}".`);return folderInfo(r.folder)}const Ys=Y({name:`update`,description:`Update a folder's name.`,args:H.strictObject({...ti,...ri,name:B(H.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||M.success(`Folder "${t.name}" updated successfully.`),M.out(t)}}),Xs=H.object({organizationId:H.uuid({message:`organization-id must be a valid UUID`})});async function getOrganization(e){let t=parseOptions(Xs,e),n=await loadAccessToken(),r=await(await P(n)).getOrganization({organizationId:t.organizationId});if(!r.organization)throw R({code:`ORGANIZATION_NOT_FOUND`,message:`Organization "${t.organizationId}" not found.`});return organizationInfo(r.organization)}const Zs=Y({name:`get`,description:`Show detailed information about an organization.`,args:H.strictObject({...ti}),run:async e=>{let t=await getOrganization({organizationId:e[`organization-id`]}),n=e.json?t:{...t,createdAt:humanizeRelativeTime(t.createdAt),updatedAt:humanizeRelativeTime(t.updatedAt)};M.out(n)}});async function listOrganizations(e){let t=e?.limit,n=await loadAccessToken(),{userOrganizations:r}=await(await P(n)).listUserOrganizations({}),i=r.map(userOrganizationInfo);return t===void 0?i:i.slice(0,t)}const Qs=Y({name:`list`,description:`List organizations you belong to.`,args:H.strictObject({limit:B(Kr.optional(),{alias:`l`,description:`Maximum number of organizations to list`})}),run:async e=>{let t=await listOrganizations({limit:e.limit});M.out(t)}});async function fetchChildFolders(e,t,n,r,i){if(i!==void 0&&r>=i)return[];let a=await At(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 At(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 loadAccessToken(),n=await P(t),r;if(e?.organizationId){if(r=(await listOrganizations()).filter(t=>t.organizationId===e.organizationId),r.length===0)throw R({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 $s=Y({name:`tree`,description:`Display organization folder hierarchy as a tree.`,args:H.strictObject({"organization-id":B(H.string().optional(),{alias:`o`,description:`Organization ID (show all if omitted)`,env:`TAILOR_PLATFORM_ORGANIZATION_ID`}),depth:B(Kr.optional(),{alias:`d`,description:`Maximum folder depth to display`})}),run:async e=>{let t=await loadAccessToken(),n=await P(t),r;if(e[`organization-id`]){if(r=(await listOrganizations()).filter(t=>t.organizationId===e[`organization-id`]),r.length===0)throw R({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})}M.out(t);return}let i=[];for(let t of r)i.push(await buildOrgTree(n,t,e.depth));M.log(i.join(`
|
|
152
|
-
`))}}),
|
|
153
|
-
`)),o.tailorDB.changeSet.service.deletes.length===0&&o.staticWebsite.changeSet.deletes.length===0&&o.aiGateway.changeSet.deletes.length===0&&o.idp.changeSet.service.deletes.length===0&&o.auth.changeSet.service.deletes.length===0&&o.pipeline.changeSet.service.deletes.length===0&&o.app.deletes.length===0&&o.executor.changeSet.deletes.length===0&&o.workflow.changeSet.deletes.length===0&&o.workflowExecutionPolicy.changeSet.deletes.length===0&&o.functionRegistry.changeSet.deletes.length===0&&o.secretManager.vaultChangeSet.deletes.length===0&&o.secretManager.secretChangeSet.deletes.length===0?{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`),{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
|
|
150
|
+
`))M.log(` ${e}`)}}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=toPageDirection(e?.order);return(await Ct(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 Ls=Y({name:`list`,description:`List executors with incoming webhook triggers`,args:H.strictObject({...J,...paginationArgs()}),run:async e=>{let t=M.jsonMode,n=await listWebhookExecutors({workspaceId:e[`workspace-id`],profile:e.profile,order:e.order,limit:e.limit});if(n.length===0){M.info(`No webhook executors found.`),t&&M.out([]);return}if(M.out(n,{display:{disabled:e=>e?j.warning(`true`):j.dim(`false`)}}),!t){let t=wn([`tailor`,`executor`,`trigger`,`<name>`,`-d`,`{"key":"value"}`,...recoveryContextArgs({profile:e.profile,workspaceId:e[`workspace-id`]})]);M.info(`To test a webhook, run: ${t}`)}}}),Rs=Bn({name:`webhook`,description:`Manage executor webhooks`,subCommands:{list:Ls},async run(){await runDefaultSubCommand(Ls)}}),functionRegistryInfo=e=>({name:e.name,description:e.description,sizeBytes:e.sizeBytes.toString(),contentHash:e.contentHash,createdAt:formatTimestamp(e.createdAt),updatedAt:formatTimestamp(e.updatedAt)}),zs=H.object({workspaceId:H.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:H.string().optional(),name:H.string().min(1,{message:`name is required`})});async function loadOptions$12(e){let t=parseOptions(zs,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 R({code:`FUNCTION_NOT_FOUND`,message:i});return functionRegistryInfo(e.function)}catch(e){throw e instanceof K&&e.code===G.NotFound?R({code:`FUNCTION_NOT_FOUND`,message:i,cause:e}):e}}const Bs=Y({name:`get`,description:`Get a function registry by name`,args:H.strictObject({...J,name:B(H.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)};M.out(n)}}),Vs=H.object({workspaceId:H.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:H.string().optional(),order:H.enum([`asc`,`desc`]).optional(),limit:H.coerce.number().int().nonnegative().optional()});async function loadOptions$11(e){let t=parseOptions(Vs,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=toPageDirection(r);return(await Ct(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 K&&e.code===G.NotFound)return[[],``];throw e}},{limit:i})).map(functionRegistryInfo)}const Hs=Y({name:`list`,description:`List function registries in a workspace`,args:H.strictObject({...J,...paginationArgs()}),run:async e=>{let t=M.jsonMode,n=await listFunctionRegistries({workspaceId:e[`workspace-id`],profile:e.profile,order:e.order,limit:e.limit}),r=t?n:n.map(({createdAt:e,updatedAt:t,...n})=>({...n,createdAt:humanizeRelativeTime(e),updatedAt:humanizeRelativeTime(t)}));M.out(r)}});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(i.status===h.SUCCESS||i.status===h.FAILED||i.status===h.CANCELED)return{status:i.status,logs:i.logs,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===h.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===h.CANCELED?`Script execution was canceled`:`Script execution failed with unknown error`)}}function extractAllNamespaces(e){let t=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=new Set;if(e.db)for(let[n,r]of Object.entries(e.db))`external`in r||t.add(n);return Array.from(t)}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 On(n):void 0,i=tn({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}}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}}function redactStringValues(e,t){if(typeof t==`string`)return dt(t);if(typeof t==`number`||typeof t==`boolean`||t===null){let e=JSON.stringify(t),n=dt(e);return n===e?t:n}return t}function errorToJson(e,t){let n=baseErrorToJson(e,t);if(!(e instanceof Error))return n;let{causes:r,context:i,location:a,...o}=Yt(e);return{error:{...n.error,...o,...i||r?{context:{...i,...Object.fromEntries(Object.entries(r??{}).map(([e,n])=>[e,errorToJson(n,t).error]))}}:{}}}}function baseErrorToJson(e,t){if(Cn(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 K){let n=G[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=Sn(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){let n=errorToJson(e,t);try{return JSON.stringify(n,redactStringValues)}catch{let e={...n.error};return delete e.context,delete e.stack,JSON.stringify({error:e},redactStringValues)}}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=V.join($t(),`generated`);U.mkdirSync(i,{recursive:!0});let a={tailordb:{},resolver:{},executor:{}},o=r?.getPluginsWithGenerationHooks()??[];function buildTailorDBData(){return Object.entries(a.tailordb).map(([e,t])=>({namespace:e,tables:t.types,sourceInfo:new Map(Object.entries(t.sourceInfo)),pluginAttachments:t.pluginAttachments}))}function buildResolverData(){return Object.entries(a.resolver).map(([e,t])=>({namespace:e,resolvers:t}))}async function runPluginPhaseHook(e,r){if(!e[r])return;let o=V.join(i,e.id),s=getAuthInput(t),c=buildTailorDBData(),l;switch(r){case`onTailorDBReady`:l=await k(e.onTailorDBReady,`plugin.onTailorDBReady hook missing`)({tailordb:c,auth:s,baseDir:o,configPath:n.path,pluginConfig:e.pluginConfig});break;case`onResolverReady`:l=await k(e.onResolverReady,`plugin.onResolverReady hook missing`)({tailordb:c,resolvers:buildResolverData(),auth:s,baseDir:o,configPath:n.path,pluginConfig:e.pluginConfig});break;case`onExecutorReady`:l=await k(e.onExecutorReady,`plugin.onExecutorReady hook missing`)({tailordb:c,resolvers:buildResolverData(),executors:{...a.executor},auth:s,baseDir:o,configPath:n.path,pluginConfig:e.pluginConfig})}await writeGeneratedFiles(e.id,l)}async function runPluginHook(e){let t=o.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 M.error(`Error processing plugin ${j.bold(t.id)} (${e})`),M.error(String(n)),n}}))).flatMap((e,n)=>e.status===`rejected`?[{plugin:k(t[n],`Plugin result has no matching plugin`).id,reason:e.reason}]:[]);if(n.length>0)throw R({code:`PLUGIN_GENERATION_FAILED`,message:`Plugin generation failed during ${e}.`,details:n.map(({plugin:e,reason:t})=>`${e}: ${Cn(t)?lr(t.format()):String(t)}`).join(`
|
|
151
|
+
`),context:{hook:e,failures:n.map(({plugin:e,reason:t})=>({plugin:e,error:errorToJson(t,{includeStack:M.verbose}).error}))}})}async function writeGeneratedFiles(e,t){await Promise.all(t.files.map(async t=>(U.mkdirSync(V.dirname(t.path),{recursive:!0}),new Promise((n,r)=>{if(t.skipIfExists&&U.existsSync(t.path)){let r=V.relative(process.cwd(),t.path);return M.debug(`${e} | skip existing: ${r}`),n()}U.writeFile(t.path,t.content,i=>{if(i){let e=V.relative(process.cwd(),t.path);M.error(`Error writing file ${j.bold(e)}`),M.error(String(i)),r(i)}else{let i=V.relative(process.cwd(),t.path);M.debug(`${e} | generate: ${j.success(i)}`),t.executable?U.chmod(t.path,493,e=>{if(e){let n=V.relative(process.cwd(),t.path);M.error(`Error setting executable permission on ${j.bold(n)}`),M.error(String(e)),r(e)}else n()}):n()}})})))),t.files.length>0&&M.log(`${e} | generation complete`)}return{application:t,baseDir:i,services:a,async generate(){M.newline(),M.log(`Generation for application: ${j.highlight(t.config.name)}`);let e=t;await z(`generate.loadTailorDBTypes`,async t=>{t.setAttribute(`generate.namespace_count`,e.tailorDBServices.length);for(let t of e.tailorDBServices){let e=t.namespace;await z(`generate.loadTypes.${e}`,async()=>{try{await t.loadTypes(),await t.processNamespacePlugins(),a.tailordb[e]={types:t.types,sourceInfo:t.typeSourceInfo,pluginAttachments:t.pluginAttachments}}catch(t){throw M.error(`Error loading tables for TailorDB service ${j.bold(e)}`),M.error(String(t)),t}})}try{cn({tailorDBServices:e.tailorDBServices})}catch(e){throw M.error(`Error validating TailorDB table names`),M.error(String(e)),e}});let{pluginExecutorFiles:i,executorService:s}=await z(`generate.pluginFiles`,async()=>{let t=qt(r,e.tailorDBServices,n.path);return{pluginExecutorFiles:t,executorService:e.executorService??(t.length>0?hn({config:{files:[]},baseDir:V.dirname(n.path)}):void 0)}});if(e.authService){let t=e.authService;await z(`generate.resolveAuthNamespaces`,async()=>t.resolveNamespaces())}(e.tailorDBServices.length>0||i.length>0)&&M.newline(),o.some(e=>e.onTailorDBReady!=null)&&(await z(`generate.onTailorDBReady`,async()=>{await runPluginHook(`onTailorDBReady`)}),M.newline()),await z(`generate.loadResolvers`,async()=>{for(let t of e.resolverServices){let e=t.namespace;await z(`generate.loadResolvers.${e}`,async()=>{try{await t.loadResolvers();let n={};a.resolver[e]=n,Object.entries(t.resolvers).forEach(([e,t])=>{n[t.name]=t})}catch(t){throw M.error(`Error loading resolvers for Resolver service ${j.bold(e)}`),M.error(String(t)),t}})}}),o.some(e=>e.onResolverReady!=null)&&(await z(`generate.onResolversReady`,async()=>{await runPluginHook(`onResolverReady`)}),M.newline()),await z(`generate.loadExecutors`,async()=>{s&&(await s.loadExecutors(),i.length>0&&await s.loadPluginExecutorFiles([...i]));let e=s?.executors??{};Object.entries(e).forEach(([e,t])=>{a.executor[e]=t})}),o.some(e=>e.onExecutorReady!=null)&&(await z(`generate.onExecutorsReady`,async()=>{await runPluginHook(`onExecutorReady`)}),M.newline())}}}async function generate$1(e){return z(`generate`,async t=>{let{config:n,plugins:r}=await z(`generate.loadConfig`,async()=>loadConfig(e?.configPath));await z(`generate.generateUserTypes`,async()=>generateUserTypes({config:n,configPath:n.path}));let i;r.length>0&&(i=new On(r));let a=tn({config:n,pluginManager:i});t.setAttribute(`app.name`,a.config.name),await createGenerationManager({application:a,config:n,pluginManager:i}).generate()})}function machineUserInfo(e){return M.registerSecret(e.clientSecret),{name:e.name,clientId:e.clientId,clientSecret:e.clientSecret,createdAt:e.createdAt?W(e.createdAt):null,updatedAt:e.updatedAt?W(e.updatedAt):null,attributes:Object.fromEntries(Object.entries(e.attributeMap).map(([e,t])=>[e,$n(ur,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 R({code:`AUTH_CONFIG_REQUIRED`,message:`Application ${r.name} does not have an auth configuration.`});let a=toPageDirection(e?.order);return(await Ct(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 Us=Y({name:`list`,description:`List all machine users in the application.`,args:H.strictObject({...ai,...paginationArgs()}),run:async e=>{let t=await listMachineUsers({workspaceId:e[`workspace-id`],profile:e.profile,configPath:e.config,order:e.order,limit:e.limit});M.out(t,{display:{createdAt:null,updatedAt:null}})}});async function getMachineUserTokenInternal(e){let t=await loadMachineUserName({machineUser:e.name,machineUserSource:e.nameSource,profile:e.profile});if(!t)throw R({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 R({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 R({code:`MACHINE_USER_NOT_FOUND`,message:`Machine user ${t} not found.`});let s=await bt(a.url,o.clientId,o.clientSecret),c=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 Ws=Y({name:`token`,description:`Get an access token for a machine user.`,args:H.strictObject({...ai,name:B(H.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:resolveMachineUserInputSource(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};M.out(n)}}),grantTypeToString=e=>{switch(e){case Pe.AUTHORIZATION_CODE:return`authorization_code`;case Pe.REFRESH_TOKEN:return`refresh_token`;default:return`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?W(e.createdAt):null}}function toOAuth2ClientCredentials(e){return M.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?W(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 R({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(k(r,`oauth2Client missing in response`))}catch(t){throw t instanceof K&&t.code===G.NotFound?R({code:`OAUTH2_CLIENT_NOT_FOUND`,message:`OAuth2 client '${e.name}' not found.`,cause:t}):t}}const Gs=Y({name:`get`,description:`Get OAuth2 client credentials (including client secret).`,args:H.strictObject({...ai,name:B(H.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});M.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 R({code:`AUTH_CONFIG_REQUIRED`,message:`Application ${r.name} does not have an auth configuration.`});let a=toPageDirection(e?.order);return(await Ct(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 Ks=Y({name:`list`,description:`List all OAuth2 clients in the application.`,args:H.strictObject({...ai,...paginationArgs()}),run:async e=>{let t=await listOAuth2Clients({workspaceId:e[`workspace-id`],profile:e.profile,configPath:e.config,order:e.order,limit:e.limit});M.out(t)}}),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)}),qs=H.object({organizationId:H.uuid({message:`organization-id must be a valid UUID`}),parentFolderId:H.string().optional(),name:H.string().min(1,`Name must not be empty`)});async function createFolder(e){let t=parseOptions(qs,e),n=await loadAccessToken(),r=await(await F(n)).createOrganizationFolder({organizationId:t.organizationId,parentFolderId:t.parentFolderId??``,folderName:t.name});if(!r.folder)throw L(`Failed to create folder.`);return folderInfo(r.folder)}const Js=Y({name:`create`,description:`Create a new folder in an organization.`,args:H.strictObject({...si,"parent-folder-id":B(H.string().optional(),{description:`Parent folder ID`}),name:B(H.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||M.success(`Folder "${t.name}" created successfully.`),M.out(t)}}),Ys=H.object({organizationId:H.uuid({message:`organization-id must be a valid UUID`}),folderId:H.uuid({message:`folder-id must be a valid UUID`})});async function deleteFolder(e){let t=parseOptions(Ys,e),n=await loadAccessToken();await(await F(n)).deleteOrganizationFolder({organizationId:t.organizationId,folderId:t.folderId})}const Xs=Y({name:`delete`,description:`Delete a folder from an organization.`,args:H.strictObject({...si,...li,...oi}),run:async e=>{await assertWritable();let t=await loadAccessToken(),n=await F(t),r;try{r=await n.getOrganizationFolder({organizationId:e[`organization-id`],folderId:e[`folder-id`]})}catch(t){throw t instanceof K&&t.code===G.NotFound?R({code:`FOLDER_NOT_FOUND`,message:`Folder "${e[`folder-id`]}" not found.`,cause:t}):t}if(!r.folder)throw R({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}"?`})){M.info(`Folder deletion cancelled.`);return}await n.deleteOrganizationFolder({organizationId:e[`organization-id`],folderId:e[`folder-id`]}),M.success(`Folder "${i}" deleted successfully.`)}}),Zs=H.object({organizationId:H.uuid({message:`organization-id must be a valid UUID`}),folderId:H.uuid({message:`folder-id must be a valid UUID`})});async function getFolder(e){let t=parseOptions(Zs,e),n=await loadAccessToken(),r=await(await F(n)).getOrganizationFolder({organizationId:t.organizationId,folderId:t.folderId});if(!r.folder)throw R({code:`FOLDER_NOT_FOUND`,message:`Folder "${t.folderId}" not found.`});return folderInfo(r.folder)}const Qs=Y({name:`get`,description:`Show detailed information about a folder.`,args:H.strictObject({...si,...li}),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)};M.out(n)}}),$s=H.object({organizationId:H.uuid({message:`organization-id must be a valid UUID`}),parentFolderId:H.string().optional(),order:ei.optional(),limit:H.number().int().nonnegative().optional()});async function listFolders(e){let{organizationId:t,parentFolderId:n,order:r,limit:i}=parseOptions($s,e),a=await loadAccessToken(),o=await F(a),s=toPageDirection(r);return(await Ct(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 ec=Y({name:`list`,description:`List folders in an organization.`,args:H.strictObject({...si,"parent-folder-id":B(H.string().optional(),{description:`Parent folder ID to list children of`}),...paginationArgs()}),run:async e=>{let t=await listFolders({organizationId:e[`organization-id`],parentFolderId:e[`parent-folder-id`],order:e.order,limit:e.limit});M.out(t,{display:{updatedAt:null}})}}),tc=H.object({organizationId:H.uuid({message:`organization-id must be a valid UUID`}),folderId:H.uuid({message:`folder-id must be a valid UUID`}),name:H.string().min(1,`Name must not be empty`)});async function updateFolder(e){let t=parseOptions(tc,e),n=await loadAccessToken(),r=await(await F(n)).updateOrganizationFolder({organizationId:t.organizationId,folderId:t.folderId,folderName:t.name});if(!r.folder)throw L(`Failed to update folder "${t.folderId}".`);return folderInfo(r.folder)}const nc=Y({name:`update`,description:`Update a folder's name.`,args:H.strictObject({...si,...li,name:B(H.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||M.success(`Folder "${t.name}" updated successfully.`),M.out(t)}}),rc=H.object({organizationId:H.uuid({message:`organization-id must be a valid UUID`})});async function getOrganization(e){let t=parseOptions(rc,e),n=await loadAccessToken(),r=await(await F(n)).getOrganization({organizationId:t.organizationId});if(!r.organization)throw R({code:`ORGANIZATION_NOT_FOUND`,message:`Organization "${t.organizationId}" not found.`});return organizationInfo(r.organization)}const ic=Y({name:`get`,description:`Show detailed information about an organization.`,args:H.strictObject({...si}),run:async e=>{let t=await getOrganization({organizationId:e[`organization-id`]}),n=e.json?t:{...t,createdAt:humanizeRelativeTime(t.createdAt),updatedAt:humanizeRelativeTime(t.updatedAt)};M.out(n)}});async function listOrganizations(e){let t=e?.limit,n=await loadAccessToken(),{userOrganizations:r}=await(await F(n)).listUserOrganizations({}),i=r.map(userOrganizationInfo);return t===void 0?i:i.slice(0,t)}const ac=Y({name:`list`,description:`List organizations you belong to.`,args:H.strictObject({limit:B(Qr.optional(),{alias:`l`,description:`Maximum number of organizations to list`})}),run:async e=>{let t=await listOrganizations({limit:e.limit});M.out(t)}});async function fetchChildFolders(e,t,n,r,i){if(i!==void 0&&r>=i)return[];let a=await Mt(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 Mt(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 loadAccessToken(),n=await F(t),r;if(e?.organizationId){if(r=(await listOrganizations()).filter(t=>t.organizationId===e.organizationId),r.length===0)throw R({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 oc=Y({name:`tree`,description:`Display organization folder hierarchy as a tree.`,args:H.strictObject({"organization-id":B(H.string().optional(),{alias:`o`,description:`Organization ID (show all if omitted)`,env:`TAILOR_PLATFORM_ORGANIZATION_ID`}),depth:B(Qr.optional(),{alias:`d`,description:`Maximum folder depth to display`})}),run:async e=>{let t=await loadAccessToken(),n=await F(t),r;if(e[`organization-id`]){if(r=(await listOrganizations()).filter(t=>t.organizationId===e[`organization-id`]),r.length===0)throw R({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})}M.out(t);return}let i=[];for(let t of r)i.push(await buildOrgTree(n,t,e.depth));M.log(i.join(`
|
|
152
|
+
`))}}),sc=H.object({organizationId:H.uuid({message:`organization-id must be a valid UUID`}),name:H.string().min(1,`Name must not be empty`)});async function updateOrganization(e){let t=parseOptions(sc,e),n=await loadAccessToken(),r=await(await F(n)).updateOrganization({organizationId:t.organizationId,organizationName:t.name});if(!r.organization)throw L(`Failed to update organization "${t.organizationId}".`);return organizationInfo(r.organization)}const cc=Y({name:`update`,description:`Update an organization's name.`,args:H.strictObject({...si,name:B(H.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||M.success(`Organization "${t.name}" updated successfully.`),M.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:tn({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)},s=Object.values(o).some(e=>`resourceOwners`in e&&e.resourceOwners.has(n.name)),c=[...o.functionRegistry.changeSet.lines(),...o.staticWebsite.changeSet.lines(),...o.aiGateway.changeSet.lines(),...o.app.lines(),...o.tailorDB.changeSet.service.lines(),...o.tailorDB.changeSet.type.lines(),...o.tailorDB.changeSet.gqlPermission.lines(),...o.pipeline.changeSet.service.lines(),...o.pipeline.changeSet.resolver.lines(),...o.executor.changeSet.lines(),...o.workflow.changeSet.lines(),...o.workflowExecutionPolicy.changeSet.lines(),...o.idp.changeSet.service.lines(),...o.idp.changeSet.client.lines(),...o.auth.changeSet.service.lines(),...o.auth.changeSet.idpConfig.lines(),...o.auth.changeSet.userProfileConfig.lines(),...o.auth.changeSet.tenantConfig.lines(),...o.auth.changeSet.machineUser.lines(),...o.auth.changeSet.oauth2Client.lines(),...o.auth.changeSet.authHook.lines(),...o.auth.changeSet.scim.lines(),...o.auth.changeSet.scimResource.lines(),...o.auth.changeSet.connection.lines(),...o.secretManager.vaultChangeSet.lines(),...o.secretManager.secretChangeSet.lines()];return c.length>0&&M.log(c.join(`
|
|
153
|
+
`)),o.tailorDB.changeSet.service.deletes.length===0&&o.staticWebsite.changeSet.deletes.length===0&&o.aiGateway.changeSet.deletes.length===0&&o.idp.changeSet.service.deletes.length===0&&o.auth.changeSet.service.deletes.length===0&&o.pipeline.changeSet.service.deletes.length===0&&o.app.deletes.length===0&&o.executor.changeSet.deletes.length===0&&o.workflow.changeSet.deletes.length===0&&o.workflowExecutionPolicy.changeSet.deletes.length===0&&o.functionRegistry.changeSet.deletes.length===0&&o.secretManager.vaultChangeSet.deletes.length===0&&o.secretManager.secretChangeSet.deletes.length===0?{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`),{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 lc=Y({name:`remove`,description:`Remove all resources managed by the application from the workspace.`,args:H.strictObject({...ai,...oi}),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});M.info(`Planning removal of resources managed by "${r.name}"...`),M.newline();let{leftBehind:a}=await execRemove(t,n,r,i,async()=>{if(e.yes)M.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 R({code:`REMOVE_CANCELLED`,message:I`
|
|
154
154
|
Remove cancelled. No resources were deleted.
|
|
155
155
|
To override, run again and confirm, or use --yes flag.
|
|
156
156
|
`})});if(a){M.warn(I`
|
|
157
157
|
Resources tagged with "${r.name}" were left in place: they carry an application id this config does not match.
|
|
158
158
|
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.
|
|
159
|
-
`);return}M.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?W(e.createTime):null,updatedAt:e.updateTime?W(e.updateTime):null}}async function fetchAIGateways(e,t,n){return(await Promise.all(n.map(async n=>{try{let{aigateway:r}=await e.getAIGateway({workspaceId:t,aigatewayName:n});return r?{name:r.name,url:r.url}:void 0}catch(e){if(e instanceof K&&e.code===G.NotFound)return;throw e}}))).filter(e=>e!==void 0)}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))]:[],[a,o,s]=await Promise.all([t.getWorkspace({workspaceId:n}),t.getApplication({workspaceId:n,applicationName:r.name}),fetchAIGateways(t,n,i)]),{name:c,...l}=applicationInfo(k(o.application,`application "${r.name}" not found in workspace`)),u=a.workspace,d=u?await resolveWorkspaceFolderName(t,u):``;return{name:c,workspaceId:n,workspaceName:u?.name??``,...d?{workspaceFolderName:d}:{},workspaceRegion:u?.region??``,...l,aiGateways:s}}const
|
|
160
|
-
`)}}}async function withTimeout(e,t,n){let r=new AbortController;try{return await Promise.race([e,Fr(t,void 0,{signal:r.signal}).then(()=>{throw Error(n)})])}finally{r.abort()}}const ac=new Set([`.DS_Store`,`thumbs.db`,`desktop.ini`]);function shouldIgnoreFile(e){let t=V.basename(e).toLowerCase();return ac.has(t)}async function deployStaticWebsite(e,t,n,r,i=!0){let{deploymentId:a}=await e.createDeployment({workspaceId:t,name:n});if(!a)throw L(`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 L(`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 M.warn(`No files found under ${r}`),[];let o=fr(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=V.join(e,t),r=await Lr.promises.readdir(n,{withFileTypes:!0}),i=[];for(let n of r){let r=V.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=V.join(r,i),s=Rr(i);if(!s){a.push(`${i} (unsupported content type; no MIME mapping found)`);return}let c=s,l=Lr.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 K&&e.code===G.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){M.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)M.log(` - ${t}`)}}const oc=Y({name:`deploy`,description:`Deploy a static website from a local build directory.`,args:H.strictObject({...J,name:B(H.string(),{alias:`n`,description:`Static website name`}),dir:B(H.string(),{alias:`d`,description:`Path to the static website files`,completion:{type:`directory`}})}),run:async e=>{await assertWritable({profile:e.profile}),M.info(`Deploying static website "${e.name}" from directory: ${e.dir}`);let t=await loadAccessToken({profile:e.profile}),n=await P(t),r=e.name,i=V.resolve(process.cwd(),e.dir),a=await loadWorkspaceId({workspaceId:e[`workspace-id`],profile:e.profile});if(!Lr.existsSync(i)||!Lr.statSync(i).isDirectory())throw R({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?M.out({name:r,workspaceId:a,url:o,skippedFiles:s}):(M.success(`Static website "${r}" deployed successfully. URL: ${o}`),logSkippedFiles(s))}});function logBetaWarning(e){M.warn(`The '${e}' command is a beta feature and may introduce breaking changes in future releases.`),M.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=Ir(n,[...r,e],{stdio:`inherit`,detached:!1});a.once(`error`,e=>i(e)),a.once(`close`,e=>{if(e==null||e===0){t();return}i(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 R({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 sc=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=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||!sc.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||!sc.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}=Cr(`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||(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=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=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=new Map,n=new Map,r=new Map,i=new Map,a=new Map;for(let o of e.changes)if(o.kind===`field_modified`||o.kind===`field_type_modified`){let{before:e,after:n}=o;if(!e.required&&n.required&&(t.has(o.tableName)||t.set(o.tableName,new Set),k(t.get(o.tableName),`optionalToRequired entry missing`).add(o.fieldName)),e.type===`enum`&&n.type===`enum`){let t=(e.allowedValues??[]).map(e=>e.value),i=(n.allowedValues??[]).map(e=>e.value),a=new Set(t),s=new Set(i);(t.some(e=>!s.has(e))||i.some(e=>!a.has(e)))&&(r.has(o.tableName)||r.set(o.tableName,new Map),k(r.get(o.tableName),`enumValueChanges entry missing`).set(o.fieldName,{beforeValues:t,afterValues:i,afterRequired:n.required}))}}else if(o.kind===`field_added`){let{after:e}=o;e.required&&(n.has(o.tableName)||n.set(o.tableName,new Map),k(n.get(o.tableName),`addedRequiredFields entry missing`).set(o.fieldName,e))}else o.kind===`field_renamed`?(i.has(o.tableName)||i.set(o.tableName,new Map),k(i.get(o.tableName),`renamedFields entry missing`).set(o.fieldName,o.after)):o.kind===`table_renamed`&&a.set(o.tableName,o.after);return{optionalToRequired:t,addedRequiredFields:n,enumValueChanges:r,renamedFields:i,clearedFields:new Map,renamedTypes:a}}function generateDbTypesFromSnapshot(e,t,n=[]){let r=t?extractBreakingChangeFields(t):{optionalToRequired:new Map,addedRequiredFields:new Map,enumValueChanges:new Map,renamedFields:new Map,clearedFields:new Map,renamedTypes:new Map};for(let e of n){let t=r.renamedFields.get(e.tableName)??new Map;t.set(e.tempFieldName,{...e.after,required:!1,unique:!1}),r.renamedFields.set(e.tableName,t);let n=r.clearedFields.get(e.tableName)??new Set;n.add(e.fieldName),r.clearedFields.set(e.tableName,n)}let i=[...Object.values(e.tables),...r.renamedTypes.values()];if(i.length===0)return generateEmptyDbTypes(e.namespace);let a=new Set,o=!1,s=[];for(let e of i){let t=generateTableType(e,r);t.usedTimestamp&&a.add(`Timestamp`),o||=t.usedArrayColumnType,s.push(t.typeDef)}let c=[`type ColumnType`,`type Transaction as KyselyTransaction`];o&&c.push(`type ArrayColumnType`);let l=[];return a.has(`Timestamp`)&&l.push(`type Timestamp = ColumnType<Date, Date | string, Date | string>;`),l.push(`type Generated<T> = T extends ColumnType<infer S, infer I, infer U>
|
|
159
|
+
`);return}M.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?W(e.createTime):null,updatedAt:e.updateTime?W(e.updateTime):null}}async function fetchAIGateways(e,t,n){return(await Promise.all(n.map(async n=>{try{let{aigateway:r}=await e.getAIGateway({workspaceId:t,aigatewayName:n});return r?{name:r.name,url:r.url}:void 0}catch(e){if(e instanceof K&&e.code===G.NotFound)return;throw e}}))).filter(e=>e!==void 0)}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))]:[],[a,o,s]=await Promise.all([t.getWorkspace({workspaceId:n}),t.getApplication({workspaceId:n,applicationName:r.name}),fetchAIGateways(t,n,i)]),{name:c,...l}=applicationInfo(k(o.application,`application "${r.name}" not found in workspace`)),u=a.workspace,d=u?await resolveWorkspaceFolderName(t,u):``;return{name:c,workspaceId:n,workspaceName:u?.name??``,...d?{workspaceFolderName:d}:{},workspaceRegion:u?.region??``,...l,aiGateways:s}}const uc=createWorkspaceNameTransformer(`workspaceName`,`workspaceFolderName`),dc=Y({name:`show`,description:`Show information about the deployed application.`,args:H.strictObject({...ai}),run:async e=>{let t=await show({workspaceId:e[`workspace-id`],profile:e.profile,configPath:e.config});M.out(t,{display:{workspaceName:uc,workspaceFolderName:null}})}});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(`
|
|
160
|
+
`)}}}async function withTimeout(e,t,n){let r=new AbortController;try{return await Promise.race([e,Vr(t,void 0,{signal:r.signal}).then(()=>{throw Error(n)})])}finally{r.abort()}}const fc=new Set([`.DS_Store`,`thumbs.db`,`desktop.ini`]);function shouldIgnoreFile(e){let t=V.basename(e).toLowerCase();return fc.has(t)}async function deployStaticWebsite(e,t,n,r,i=!0){let{deploymentId:a}=await e.createDeployment({workspaceId:t,name:n});if(!a)throw L(`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 L(`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 M.warn(`No files found under ${r}`),[];let o=vr(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=V.join(e,t),r=await Ur.promises.readdir(n,{withFileTypes:!0}),i=[];for(let n of r){let r=V.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=V.join(r,i),s=Wr(i);if(!s){a.push(`${i} (unsupported content type; no MIME mapping found)`);return}let c=s,l=Ur.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 K&&e.code===G.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){M.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)M.log(` - ${t}`)}}const pc=Y({name:`deploy`,description:`Deploy a static website from a local build directory.`,args:H.strictObject({...J,name:B(H.string(),{alias:`n`,description:`Static website name`}),dir:B(H.string(),{alias:`d`,description:`Path to the static website files`,completion:{type:`directory`}})}),run:async e=>{await assertWritable({profile:e.profile}),M.info(`Deploying static website "${e.name}" from directory: ${e.dir}`);let t=await loadAccessToken({profile:e.profile}),n=await F(t),r=e.name,i=V.resolve(process.cwd(),e.dir),a=await loadWorkspaceId({workspaceId:e[`workspace-id`],profile:e.profile});if(!Ur.existsSync(i)||!Ur.statSync(i).isDirectory())throw R({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?M.out({name:r,workspaceId:a,url:o,skippedFiles:s}):(M.success(`Static website "${r}" deployed successfully. URL: ${o}`),logSkippedFiles(s))}});function logBetaWarning(e){M.warn(`The '${e}' command is a beta feature and may introduce breaking changes in future releases.`),M.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=Hr(n,[...r,e],{stdio:`inherit`,detached:!1});a.once(`error`,e=>i(e)),a.once(`close`,e=>{if(e==null||e===0){t();return}i(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 R({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 mc=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=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||!mc.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||!mc.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}=kr(`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||(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=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=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=new Map,n=new Map,r=new Map,i=new Map,a=new Map;for(let o of e.changes)if(o.kind===`field_modified`||o.kind===`field_type_modified`){let{before:e,after:n}=o;if(!e.required&&n.required&&(t.has(o.tableName)||t.set(o.tableName,new Set),k(t.get(o.tableName),`optionalToRequired entry missing`).add(o.fieldName)),e.type===`enum`&&n.type===`enum`){let t=(e.allowedValues??[]).map(e=>e.value),i=(n.allowedValues??[]).map(e=>e.value),a=new Set(t),s=new Set(i);(t.some(e=>!s.has(e))||i.some(e=>!a.has(e)))&&(r.has(o.tableName)||r.set(o.tableName,new Map),k(r.get(o.tableName),`enumValueChanges entry missing`).set(o.fieldName,{beforeValues:t,afterValues:i,afterRequired:n.required}))}}else if(o.kind===`field_added`){let{after:e}=o;e.required&&(n.has(o.tableName)||n.set(o.tableName,new Map),k(n.get(o.tableName),`addedRequiredFields entry missing`).set(o.fieldName,e))}else o.kind===`field_renamed`?(i.has(o.tableName)||i.set(o.tableName,new Map),k(i.get(o.tableName),`renamedFields entry missing`).set(o.fieldName,o.after)):o.kind===`table_renamed`&&a.set(o.tableName,o.after);return{optionalToRequired:t,addedRequiredFields:n,enumValueChanges:r,renamedFields:i,clearedFields:new Map,renamedTypes:a}}function generateDbTypesFromSnapshot(e,t,n=[]){let r=t?extractBreakingChangeFields(t):{optionalToRequired:new Map,addedRequiredFields:new Map,enumValueChanges:new Map,renamedFields:new Map,clearedFields:new Map,renamedTypes:new Map};for(let e of n){let t=r.renamedFields.get(e.tableName)??new Map;t.set(e.tempFieldName,{...e.after,required:!1,unique:!1}),r.renamedFields.set(e.tableName,t);let n=r.clearedFields.get(e.tableName)??new Set;n.add(e.fieldName),r.clearedFields.set(e.tableName,n)}let i=[...Object.values(e.tables),...r.renamedTypes.values()];if(i.length===0)return generateEmptyDbTypes(e.namespace);let a=new Set,o=!1,s=[];for(let e of i){let t=generateTableType(e,r);t.usedTimestamp&&a.add(`Timestamp`),o||=t.usedArrayColumnType,s.push(t.typeDef)}let c=[`type ColumnType`,`type Transaction as KyselyTransaction`];o&&c.push(`type ArrayColumnType`);let l=[];return a.has(`Timestamp`)&&l.push(`type Timestamp = ColumnType<Date, Date | string, Date | string>;`),l.push(`type Generated<T> = T extends ColumnType<infer S, infer I, infer U>
|
|
161
161
|
? ColumnType<S, I | undefined, U>
|
|
162
162
|
: ColumnType<T, T | undefined, T>;`),a.has(`Serial`)&&l.push(`type Serial<T = string | number> = ColumnType<T, never, never>;`),[`/**`,` * 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 { ${c.join(`, `)} } from "@tailor-platform/sdk/kysely";`,`import type { Env } from "@tailor-platform/sdk";`,``,...l,``,`export interface Database {`,...s,`}`,``,`export type Transaction = KyselyTransaction<Database>;`,``,"/** Context passed as the second argument to the migration's `main` function. */",`export type MigrationContext = {`,` env: keyof Env extends never ? Record<string, string | number | boolean> : Env;`,`};`].join(`
|
|
163
163
|
`)+`
|
|
164
164
|
`}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>;`,``,"/** Context passed as the second argument to the migration's `main` function. */",`export type MigrationContext = {`,` env: keyof Env extends never ? Record<string, string | number | boolean> : Env;`,`};`].join(`
|
|
165
165
|
`)+`
|
|
166
166
|
`}function generateTableType(e,t){let n=[],r=!1,i=!1,a=!1;n.push(` id: Generated<string>;`);let o=t.optionalToRequired.get(e.name)||new Set,s=t.addedRequiredFields.get(e.name)||new Map,c=t.enumValueChanges.get(e.name)||new Map,l=t.clearedFields.get(e.name)??new Set;for(let[t,s]of Object.entries(e.fields)){if(t===`id`)continue;let e=generateFieldType(s,o.has(t),c.get(t)),u=l.has(t),d=u?generateClearableFieldType(s):e;n.push(` ${t}: ${d.type};`),r||=d.usedTimestamp,i=i||e.usedColumnType||u,a||=!u&&e.usedArrayColumnType}for(let[e,t]of s){let o=generateFieldType(t,!0,void 0);n.push(` ${e}: ${o.type};`),r||=o.usedTimestamp,i||=o.usedColumnType,a||=o.usedArrayColumnType}let u=t.renamedFields.get(e.name)||new Map;for(let[e,t]of u){let o=generateFieldType(t,t.required,void 0);n.push(` ${e}: ${o.type};`),r||=o.usedTimestamp,i||=o.usedColumnType,a||=o.usedArrayColumnType}return{typeDef:` ${e.name}: {\n${n.join(`
|
|
167
|
-
`)}\n }`,usedTimestamp:r,usedColumnType:i,usedArrayColumnType:a}}function mapToTsType(e,t){if(e===`nested`)return{type:`Record<string, unknown>`,usedTimestamp:!1};if(e===`enum`&&t&&t.length>0)return{type:`(${formatEnumUnion(t.map(e=>e.value))})`,usedTimestamp:!1};if(e===`enum`)return{type:`string`,usedTimestamp:!1};let n=
|
|
167
|
+
`)}\n }`,usedTimestamp:r,usedColumnType:i,usedArrayColumnType:a}}function mapToTsType(e,t){if(e===`nested`)return{type:`Record<string, unknown>`,usedTimestamp:!1};if(e===`enum`&&t&&t.length>0)return{type:`(${formatEnumUnion(t.map(e=>e.value))})`,usedTimestamp:!1};if(e===`enum`)return{type:`string`,usedTimestamp:!1};let n=An(e);return{type:n,usedTimestamp:n===`Timestamp`}}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=[...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}>`}function generateClearableFieldType(e){let{type:t}=mapToTsType(e.type,e.allowedValues),n=kn.get(t);if(n){let t=e.array?`${n.select}[]`:n.select,r=e.array?`(${n.write})[]`:n.write;return{type:`ColumnType<${t} | null, ${r} | null, ${r} | null>`,usedTimestamp:!1}}let r=e.array?`${t}[]`:t;return{type:`ColumnType<${r} | null, ${r} | null, ${r} | null>`,usedTimestamp:!1}}function generateOptionalToRequiredDateColumnType(e){if(e.type!==`date`&&e.type!==`datetime`)return null;let t=kn.get(An(e.type));if(!t)return null;let n=e.array?`${t.select}[]`:t.select,r=e.array?`(${t.write})[]`:t.write;return`ColumnType<${n} | null, ${r}, ${r}>`}function generateFieldType(e,t,n){if(n)return{type:generateEnumChangeColumnType(n,e),usedTimestamp:!1,usedColumnType:!0,usedArrayColumnType:!1};let r,i=!1;if(e.type===`enum`){let t=e.allowedValues?.map(e=>e.value)??[];r=t.length>0?formatEnumUnion(t):`string`}else{let t=mapToTsType(e.type);r=t.type,i=t.usedTimestamp}if(t){let t=generateOptionalToRequiredDateColumnType(e);if(t)return{type:t,usedTimestamp:!1,usedColumnType:!0,usedArrayColumnType:!1}}let a=r;if(e.array){if(kn.has(r)){let t=`ArrayColumnType<${r}>`;return{type:e.required?t:`${t} | null`,usedTimestamp:i,usedColumnType:!1,usedArrayColumnType:!0}}a=e.type===`enum`&&e.allowedValues&&e.allowedValues.length>0?`(${r})[]`:`${r}[]`}return t?{type:`ColumnType<${a} | null, ${a}, ${a}>`,usedTimestamp:i,usedColumnType:!0,usedArrayColumnType:!1}:(e.required||(a=`${a} | null`),{type:a,usedTimestamp:i,usedColumnType:!1,usedArrayColumnType:!1})}async function writeDbTypesFile(e,t,n,r,i=[]){let a=generateDbTypesFromSnapshot(e,r,i),o=getMigrationFilePath(t,n,`db`);return await q.writeFile(o,a),o}function toDDLTable(e){return{name:e.name,fields:e.fields,indexes:e.indexes}}function buildPreMigrationTables(e,t){let n=applyDiffToSnapshot(e,t),r=buildPreMigrationChangesMapFromDiffs([t]),i=buildPreMigrationIndexChangesMapFromDiffs([t]),a=Object.values(n.tables).map(e=>{let t=copySnapshotRecord(e.fields),n=r.get(e.name);n&&applyPreMigrationFieldAdjustmentsToSnapshot(t,n);let a=copySnapshotRecord(e.indexes),o=i.get(e.name);return o&&applyPreMigrationIndexAdjustmentsToSnapshot(a,o),{name:e.name,fields:t,indexes:a}});for(let e of t.changes)(e.kind===`table_removed`||e.kind===`table_renamed`)&&a.push(toDDLTable(e.before));return a}function generateMigrationPgliteSchema(e,t){return jn([{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 q.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 writeMigrationTypeFiles(e){let{previousSnapshot:t,diff:n,migrationsDir:r,migrationNumber:i,expandPlans:a=[]}=e;return{dbTypesPath:await writeDbTypesFile(t,r,i,n,a),...await tryWritePgliteSchemaFile(t,n,r,i)}}const hc=`TODO(tailor-migration-review)`;async function fileExists(e){try{return await q.access(e),!0}catch{return!1}}async function ensureFileNotExists(e){if(await fileExists(e))throw R({code:`MIGRATION_FILE_EXISTS`,message:`Migration file already exists: ${e}`})}async function generateSchemaFile(e,t,n){let r=getMigrationDirPath(t,n);await q.mkdir(r,{recursive:!0});let i=getMigrationFilePath(t,n,`schema`);return await ensureFileNotExists(i),await q.writeFile(i,JSON.stringify(e,null,2)),{filePath:i,migrationNumber:n}}async function generateDiffFiles(e,t,n,r,i,a=[]){let o=getMigrationDirPath(t,n);await q.mkdir(o,{recursive:!0});let s=getMigrationFilePath(t,n,`diff`),c=getMigrationFilePath(t,n,`migrate`),l=getMigrationFilePath(t,n,`db`),u=getMigrationFilePath(t,n,`pgliteSchema`),d=e.requiresMigrationScript;await ensureFileNotExists(s),d&&(await ensureFileNotExists(c),await ensureFileNotExists(l),await ensureFileNotExists(u));let f=i?{...e,description:i}:e;await q.writeFile(s,JSON.stringify(f,null,2));let p={diffFilePath:s,migrationNumber:n};if(d){let e=generateMigrationScript(f,a);await q.writeFile(c,e),p.migrateFilePath=c;let i=await writeMigrationTypeFiles({previousSnapshot:r,diff:f,migrationsDir:t,migrationNumber:n,expandPlans:a});p.dbTypesFilePath=i.dbTypesPath,p.pgliteSchemaFilePath=i.pgliteSchemaPath,p.pgliteSchemaError=i.pgliteSchemaError}return p}async function generateDataOnlyMigrationFiles(e){let{migrationsDir:t,migrationNumber:n,snapshot:r,description:i}=e,a=getMigrationDirPath(t,n);await q.mkdir(a,{recursive:!0});let o=getMigrationFilePath(t,n,`diff`),s=getMigrationFilePath(t,n,`migrate`),c=getMigrationFilePath(t,n,`db`);await ensureFileNotExists(o),await ensureFileNotExists(s),await ensureFileNotExists(c),await ensureFileNotExists(getMigrationFilePath(t,n,`pgliteSchema`));let l=i?{...e.diff,description:i}:e.diff;await q.writeFile(o,JSON.stringify(l,null,2)),await q.writeFile(s,generateDataOnlyMigrationScript(l.namespace));let u=await writeMigrationTypeFiles({previousSnapshot:r,diff:l,migrationsDir:t,migrationNumber:n});return{diffFilePath:o,migrateFilePath:s,dbTypesFilePath:c,pgliteSchemaFilePath:u.pgliteSchemaPath,pgliteSchemaError:u.pgliteSchemaError,migrationNumber:n}}function generateDataOnlyMigrationScript(e){return`/**
|
|
168
168
|
* Data-only migration script for ${e}
|
|
169
169
|
*
|
|
170
170
|
* This migration carries no schema change; it exists to run this script.
|
|
@@ -180,7 +180,7 @@ export async function main(trx: Transaction): Promise<void> {
|
|
|
180
180
|
// TODO: Implement the data transformation for this migration
|
|
181
181
|
}
|
|
182
182
|
`}function generateMigrationScript(e,t=[]){let n=[],r=new Map(e.changes.filter(e=>e.kind===`table_renamed`).map(e=>[e.previousTableName,e.tableName]));for(let e of t)n.push(generateExpandConversionScript(e));for(let t of e.changes){let e=generateDecimalScaleChangeScript(t);if(n.push(...generateChangeScripts(t,e!==null,r)),e){n.push(e);let r=generateUniqueConstraintScript(t);r&&n.push(r)}}n.length===0&&n.push(` // No data migration needed for this schema change
|
|
183
|
-
// Add custom data transformations if required`);let i=e.changes.some(e=>e.kind===`field_modified`&&e.memberRenames?.length)?`\n${
|
|
183
|
+
// Add custom data transformations if required`);let i=e.changes.some(e=>e.kind===`field_modified`&&e.memberRenames?.length)?`\n${gc}`:``;return`/**
|
|
184
184
|
* Migration script for ${e.namespace}
|
|
185
185
|
*
|
|
186
186
|
* This script runs between the Pre-migration and Post-migration phases of
|
|
@@ -370,7 +370,7 @@ ${a}
|
|
|
370
370
|
}
|
|
371
371
|
lastId = rows[rows.length - 1]!.id;
|
|
372
372
|
}
|
|
373
|
-
}`}const
|
|
373
|
+
}`}const gc=`/**
|
|
374
374
|
* Return a copy of a nested value with the member at \`path\` also stored under
|
|
375
375
|
* \`newName\`, descending into arrays at every level.
|
|
376
376
|
*
|
|
@@ -454,7 +454,7 @@ ${i.map(e=>` ${e}: eb
|
|
|
454
454
|
if (rows.length === 0) break;
|
|
455
455
|
|
|
456
456
|
for (const row of rows) {
|
|
457
|
-
// ${
|
|
457
|
+
// ${hc}: Remove this marker and the \`never\` annotation after reviewing the normalization.
|
|
458
458
|
// Keep the value accepted by the active ${e.before.type} type and castable to ${e.after.type}.
|
|
459
459
|
const sourceValue = row.${e.fieldName};
|
|
460
460
|
if (sourceValue === null) continue;
|
|
@@ -471,7 +471,7 @@ ${i.map(e=>` ${e}: eb
|
|
|
471
471
|
}`}function generateExpandConversionValue(e){if(isSingleValueToArrayChange(e.before,e.after))return` // Store the ${e.before.type} value as the only element of the ${formatFieldShape(e.after)} field.
|
|
472
472
|
const sourceValue = row.${e.fieldName};
|
|
473
473
|
if (sourceValue === null) continue;
|
|
474
|
-
const convertedValue = [sourceValue];`;let t=e.after.array?`an element of the ${formatFieldShape(e.after)} field`:`the ${e.after.type} type`;return` // ${
|
|
474
|
+
const convertedValue = [sourceValue];`;let t=e.after.array?`an element of the ${formatFieldShape(e.after)} field`:`the ${e.after.type} type`;return` // ${hc}: Remove this marker and the \`never\` annotation after reviewing the conversion.
|
|
475
475
|
// Produce a value accepted by ${t} from the stored ${e.before.type} value.
|
|
476
476
|
const sourceValue = row.${e.fieldName};
|
|
477
477
|
const convertedValue: never = sourceValue;`}function generateExpandConversionScript(e){let t=(e.after.array??!1)&&!isSingleValueToArrayChange(e.before,e.after);return` // Convert ${e.tableName}.${e.fieldName} into ${e.tempFieldName}, which the next migration renames back to ${e.fieldName}
|
|
@@ -563,11 +563,11 @@ ${n===`throw`?` if (records.length > 1) {
|
|
|
563
563
|
}
|
|
564
564
|
lastId = rows[rows.length - 1]!.id;
|
|
565
565
|
}
|
|
566
|
-
}`}function markMigrationScriptSkipped(e){let{migrationsDir:t,migrationNumber:n,reason:r}=e,i=formatMigrationNumber(n),a=r.trim();if(!a)throw R({code:`MIGRATION_SCRIPT_REASON_REQUIRED`,message:`Migration script skip reason must not be empty.`,command:`tailordb migration script`});let o=getMigrationFilePath(t,n,`diff`);if(!U.existsSync(o))throw R({code:`MIGRATION_NOT_FOUND`,message:`Migration ${i} not found in ${t}. Expected ${o}.`});let s=loadDiff(o);if(!s.requiresMigrationScript&&!s.hasWarnings)throw R({code:`MIGRATION_SCRIPT_NOT_REQUIRED`,message:`Migration ${i} does not require a migration script and has no data-loss warnings; nothing to skip.`});if(s.scriptSkipped)throw R({code:`MIGRATION_SCRIPT_SKIP_EXISTS`,message:`Migration ${i} already has a script skip recorded (${s.scriptSkipped.acknowledgedAt}: ${s.scriptSkipped.reason}).`});let c=getMigrationFilePath(t,n,`migrate`);if(U.existsSync(c))throw R({code:`MIGRATION_SCRIPT_EXISTS`,message:`Migration script exists at ${c}.`,suggestion:`Delete migrate.ts first if this migration should run without a script.`});let l={reason:a,acknowledgedAt:new Date().toISOString()},u=JSON.parse(U.readFileSync(o,`utf-8`));return u.scriptSkipped=l,U.writeFileSync(o,JSON.stringify(u,null,2)),l}function clearMigrationScriptSkipped(e){let t=JSON.parse(U.readFileSync(e,`utf-8`));Object.hasOwn(t,`scriptSkipped`)&&(delete t.scriptSkipped,U.writeFileSync(e,JSON.stringify(t,null,2)))}async function addMigrationScriptFiles(e){let{migrationsDir:t,migrationNumber:n,withTest:r=!1,pgliteAvailable:i=!1}=e,a=formatMigrationNumber(n),o=getMigrationFilePath(t,n,`diff`);if(!U.existsSync(o))throw R({code:`MIGRATION_NOT_FOUND`,message:`Migration ${a} not found in ${t}. Expected ${o}.`});let s=loadDiff(o),c=getMigrationFilePath(t,n,`migrate`),l=U.existsSync(c),u={};if(l&&s.scriptSkipped){if(clearMigrationScriptSkipped(o),u.clearedScriptSkip=!0,!r)return u}else if(l&&!r)throw R({code:`MIGRATION_SCRIPT_EXISTS`,message:`Migration script already exists at ${c}.`});let d=getMigrationFilePath(t,n,`test`),f=getMigrationFilePath(t,n,`pgliteTest`),p=getMigrationFilePath(t,n,`pgliteSchema`),m=r&&!U.existsSync(d),h=r&&i&&!U.existsSync(f);if(r&&!m&&!h)throw R({code:`MIGRATION_TEST_EXISTS`,message:i?`Migration tests already exist at ${d} and ${f}.`:`Migration test already exists at ${d}.`});if(l&&r){let e=getMigrationFilePath(t,n,`db`);if(!U.existsSync(e))throw R({code:`GENERATED_TYPES_NOT_FOUND`,message:`Generated types not found at ${e}.`,suggestion:`The test scaffold imports Database from ./db; restore db.ts before adding a test.`})}let g=!l||r&&!U.existsSync(p),_=g?reconstructSnapshotFromMigrations(t,n-1):null;if(g&&!_)throw R({code:`MIGRATION_HISTORY_INVALID`,message:`Could not reconstruct previous schema for migration ${a}.`,suggestion:`Make sure migration 0 exists.`});if(!l&&_){await q.writeFile(c,generateMigrationScript(s)),u.migratePath=c;let e=await writeMigrationTypeFiles({previousSnapshot:_,diff:s,migrationsDir:t,migrationNumber:n});u.dbTypesPath=e.dbTypesPath,u.pgliteSchemaPath=e.pgliteSchemaPath,u.pgliteSchemaError=e.pgliteSchemaError,clearMigrationScriptSkipped(o)}else r&&_&&Object.assign(u,await tryWritePgliteSchemaFile(_,s,t,n));return m&&(await q.writeFile(d,generateMigrationTestScript(s)),u.testPath=d),u.pgliteTestRequested=h,h&&U.existsSync(p)&&(await q.writeFile(f,generateMigrationPgliteTestScript(s)),u.pgliteTestPath=f),u}function isPgliteAvailable(e){let t=V.resolve(e);for(;;){if(U.existsSync(V.join(t,`node_modules`,`@electric-sql`,`pglite`,`package.json`)))return!0;let e=V.dirname(t);if(e===t)return!1;t=e}}async function script(e){logBetaWarning(`tailordb migration`);let t=parseMigrationNumberArg(e.number);if(t===0)throw R({code:`MIGRATION_SCRIPT_NOT_ALLOWED`,message:`Migration ${e.number} is the initial schema snapshot and cannot have a migration script.`});let{config:n}=await loadConfig(e.configPath),r=getNamespacesWithMigrations(n,V.dirname(n.path));if(r.length===0)throw migrationConfigNotFoundError();let i=resolveTargetNamespace(r,e.namespace),{migrationsDir:a}=k(r.find(e=>e.namespace===i),`namespace with migrations not found`);if(e.noScript){if(e.withTest)throw R({code:`MIGRATION_SCRIPT_OPTIONS_CONFLICT`,message:`--with-test cannot be used together with --no-script.`,command:`tailordb migration script`});let n=e.reason?.trim();if(!n)throw R({code:`MIGRATION_SCRIPT_REASON_REQUIRED`,message:`--reason is required with --no-script.`,command:`tailordb migration script`});let r=markMigrationScriptSkipped({migrationsDir:a,migrationNumber:t,reason:n});M.success(`Recorded that migration ${j.bold(e.number)} in namespace ${j.bold(i)} intentionally has no migration script`),M.info(` Reason: ${r.reason}`),M.info(` Diff file: ${getMigrationFilePath(a,t,`diff`)}`);return}if(e.reason!==void 0)throw R({code:`MIGRATION_SCRIPT_OPTIONS_CONFLICT`,message:`--reason can only be used together with --no-script.`,command:`tailordb migration script`});let o=isPgliteAvailable(a),s=await addMigrationScriptFiles({migrationsDir:a,migrationNumber:t,withTest:e.withTest,pgliteAvailable:o});if(s.clearedScriptSkip&&(M.success(`Cleared the stale script skip record for migration ${j.bold(e.number)} in namespace ${j.bold(i)}`),!s.testPath&&!s.pgliteTestRequested)){M.info(` Migration script: ${getMigrationFilePath(a,t,`migrate`)}`);return}let c=[s.testPath,s.pgliteTestPath].filter(Boolean).length,l=[s.migratePath&&`migration script`,c>0&&(c>1?`migration tests`:`migration test`)].filter(Boolean).join(` and `),u=`for migration ${j.bold(e.number)} in namespace ${j.bold(i)}`;l?M.success(`Added ${l} ${u}`):M.warn(`Added no files ${u}`),s.migratePath&&(M.info(` Migration script: ${s.migratePath}`),M.info(` DB types: ${s.dbTypesPath}`)),s.pgliteSchemaPath&&M.info(` PGlite schema: ${s.pgliteSchemaPath}`),s.pgliteSchemaError&&M.warn(` PGlite schema skipped: ${s.pgliteSchemaError}`),s.testPath&&M.info(` Migration test: ${s.testPath}`),s.pgliteTestPath?M.info(` PGlite test: ${s.pgliteTestPath}`):s.testPath&&!o?M.info(` Install @electric-sql/pglite as a devDependency to also scaffold a PGlite test (migrate.pglite.test.ts).`):s.pgliteTestRequested&&s.pgliteSchemaError&&M.info(` PGlite test skipped: it needs the db.pglite.ts that could not be generated.`),M.newline(),s.migratePath&&(M.log(`Edit the script to implement your data migration logic.`),M.log(`It will be executed by 'tailor deploy' between Pre and Post phases.`)),s.testPath&&M.log(`Fill in the test with the rows to stage and the statements to assert.`);let d=s.migratePath??s.testPath;if(!d)return;let f=getConfiguredEditorCommand();if(f){M.newline(),M.info(`Opening ${V.basename(d)} in ${f}...`);try{await openInConfiguredEditor(d)}catch{return}}}function resolveTargetNamespace(e,t){if(t){if(!e.some(e=>e.namespace===t))throw R({code:`TAILORDB_NAMESPACE_NOT_FOUND`,message:`Namespace "${t}" not found or does not have migrations configured`});return t}if(e.length===1){let[t]=e;return k(t,`namespace with migrations missing`).namespace}throw R({code:`MIGRATION_NAMESPACE_REQUIRED`,message:`Multiple TailorDB services found. Please specify namespace with --namespace flag: ${e.map(e=>e.namespace).join(`, `)}`,command:`tailordb migration script`})}const uc=Y({name:`script`,description:`Add a migration script (migrate.ts) template to an existing migration directory, or record with --no-script that a migration intentionally has none.`,notes:"When `migrate.ts` already exists, running the command clears a previously recorded `--no-script` acknowledgment, and `--with-test` adds only the tests that do not exist yet (writing `db.pglite.ts` if it is missing). `migrate.pglite.test.ts` is scaffolded only when `@electric-sql/pglite` is installed in the project.",args:H.strictObject({...Zr,number:B(H.string(),{positional:!0,description:`Migration number to add a script to (e.g., 0001 or 1)`}),namespace:B(H.string().optional(),{alias:`n`,description:`Target TailorDB namespace (required if multiple namespaces exist)`}),"no-script":B(H.boolean().optional(),{description:`Record that this migration intentionally runs without a migration script (requires --reason)`}),reason:B(H.string().optional(),{description:`Reason why no migration script is needed (used with --no-script)`}),"with-test":B(H.boolean().optional(),{description:`Also add the migrate.test.ts and migrate.pglite.test.ts scaffolds`})}),run:async e=>{await script({configPath:e.config,number:e.number,namespace:e.namespace,noScript:e[`no-script`],reason:e.reason,withTest:e[`with-test`]})}});function getUnsupportedMigrationHintLines(){return[`These changes require a manual 3-step migration process:`,` Migration 1: Add an optional temporary field with the desired structure`,` If the old field is required, make the old field optional`,` For each non-null old value, copy and convert it to the temporary field`,` and set the old field to null in the same update`,` Verify every old value is null before continuing`,` Migration 2: Remove the old field`,` Migration 3: Add the field with the original name and new structure,`,` migrate data from the temporary field, then remove it`,` Important: Reusing the name while stored old values remain can make subsequent reads fail`]}async function handleInitOption(e,t){let n=e.filter(({migrationsDir:e})=>U.existsSync(e));if(n.length===0){M.info(`No existing migration directories found.`);return}M.newline(),M.warn(`This will DELETE all existing migration files:`);for(let{namespace:e,migrationsDir:t}of n)M.log(` - ${e}: ${t}`);M.newline(),t||(await X.confirm({message:`Are you sure you want to delete these directories and start fresh?`,default:!1})||(M.info(`Operation cancelled.`),process.exit(0)),M.newline());for(let{namespace:e,migrationsDir:t}of n)try{await q.rm(t,{recursive:!0,force:!0}),M.success(`Deleted migration directory for ${j.bold(e)}`)}catch(e){throw M.error(`Failed to delete ${t}: ${e}`),e}M.newline(),M.info(`Migration directories cleared. Generating initial snapshot...`),M.newline()}async function generate(e){logBetaWarning(`tailordb migration`);let{config:t,plugins:n}=await loadConfig(e.configPath),r=getNamespacesWithMigrations(t,V.dirname(t.path));if(r.length===0){M.warn(`No TailorDB namespaces with migrations config found.`),M.info(`Add "migration: { directory: \\"./migrations\\" }" to your db config to enable migrations.`);return}let i=[],a=[],o=[];for(let t of e.renames??[]){let e=targetDepth(t);e>=2?o.push({raw:t,spec:parseNestedMemberRenameOption(t)}):e===1?i.push({raw:t,spec:parseRenameOption(t)}):a.push({raw:t,spec:parseTypeRenameOption(t)})}let s=[],c=[],l=[];for(let t of e.drops??[]){let e=targetDepth(t);e>=2?l.push({raw:t,spec:parseNestedMemberDropOption(t)}):e===1?s.push({raw:t,spec:parseDropOption(t)}):c.push({raw:t,spec:parseTypeDropOption(t)})}let u=(e.expandContracts??[]).map(e=>({raw:e,spec:parseExpandContractOption(e)})),d=i.length>0||a.length>0||o.length>0||s.length>0||c.length>0||l.length>0;if(e.init&&(d||u.length>0))throw R({code:`MIGRATION_GENERATE_OPTIONS_CONFLICT`,message:`--rename, --drop, and --expand-contract cannot be used together with --init.`,command:`tailordb migration generate`});let f=new Set(s.map(({spec:e})=>`${e.tableName}.${e.fieldName}`)),p=i.filter(({spec:e})=>f.has(`${e.tableName}.${e.previousFieldName}`));if(p.length>0)throw R({code:`MIGRATION_RENAME_DROP_CONFLICT`,message:`--rename and --drop conflict for: ${p.map(({spec:e})=>`${e.tableName}.${e.previousFieldName}`).join(`, `)}`,command:`tailordb migration generate`});let m=new Set(l.map(({spec:e})=>nestedMemberKey(e))),h=o.filter(({spec:e})=>m.has(nestedMemberKey({...e,path:e.previousPath})));if(h.length>0)throw R({code:`MIGRATION_RENAME_DROP_CONFLICT`,message:`--rename and --drop conflict for: ${h.map(({spec:e})=>nestedMemberKey({...e,path:e.previousPath})).join(`, `)}`,command:`tailordb migration generate`});let g=new Set(c.map(({spec:e})=>e.tableName)),_=a.filter(({spec:e})=>g.has(e.previousTableName));if(_.length>0)throw R({code:`MIGRATION_RENAME_DROP_CONFLICT`,message:`--rename and --drop conflict for: ${_.map(({spec:e})=>e.previousTableName).join(`, `)}`,command:`tailordb migration generate`});if(e.namespace!==void 0&&!e.dataOnly)throw R({code:`MIGRATION_GENERATE_OPTIONS_CONFLICT`,message:`--namespace can only be used together with --data-only.`,command:`tailordb migration generate`});if(e.dataOnly&&(e.init||d||u.length>0))throw R({code:`MIGRATION_GENERATE_OPTIONS_CONFLICT`,message:`--init, --rename, --drop, and --expand-contract cannot be used together with --data-only.`,command:`tailordb migration generate`});let v=e.dataOnly?resolveTargetNamespace(r,e.namespace):void 0,y=v===void 0?r:r.filter(({namespace:e})=>e===v);e.init&&await handleInitOption(r,e.yes);let b;n.length>0&&(b=new En(n));let{defineApplication:x}=await import(`./application-Oh5dMmb5.mjs`),S=x({config:t,pluginManager:b}),C=[];for(let{namespace:e,migrationsDir:t}of y){M.info(`Processing namespace: ${j.bold(e)}`),assertValidMigrationFiles(t,e);let n=S.tailorDBServices.find(t=>t.namespace===e);if(!n){M.warn(`No TailorDB service found for namespace "${e}"`);continue}await n.loadTypes(),await n.processNamespacePlugins();let r=n.types;C.push({namespace:e,migrationsDir:t,currentSnapshot:createSnapshotFromLocalTypes(r,e),previousSnapshot:reconstructSnapshotFromMigrations(t)})}if(v!==void 0){await generateDataOnlyMigration(C,v,e);return}let w=matchFlagsToNamespaces(i,C,renameSpecApplies,`--rename does not match a removed + added field pair`),ee=matchFlagsToNamespaces(a,C,typeRenameSpecApplies,`--rename does not match a removed + added table pair`),te=matchFlagsToNamespaces(s,C,dropSpecApplies,`--drop does not match a removed field`),ne=matchFlagsToNamespaces(c,C,typeDropSpecApplies,`--drop does not match a removed table`),re=matchFlagsToNamespaces(o,C,nestedMemberRenameSpecApplies,`--rename does not match a removed + added nested member pair`),ie=matchFlagsToNamespaces(l,C,nestedMemberDropSpecApplies,`--drop does not match a removed nested member`),ae=new Map,oe=new Set,se=[];for(let{namespace:e,previousSnapshot:t,currentSnapshot:n}of C){if(!t)continue;let r=[];for(let i of u){let{spec:a}=i,o=t.tables[a.tableName]?.fields[a.fieldName],s=n.tables[a.tableName]?.fields[a.fieldName];if(!o||!s||!hasFieldShapeChange(o,s))continue;oe.add(i);let c=getExpandContractEligibility({previous:t,current:n,tableName:a.tableName,fieldName:a.fieldName});if(!c.eligible){se.push(`--expand-contract cannot convert ${i.raw} (namespace: ${e}): ${c.reason}`);continue}r.push(i)}ae.set(e,new Set(r.map(({spec:e})=>fieldKey(e.tableName,e.fieldName))))}let ce=u.filter(e=>!oe.has(e));if(ce.length>0)throw R({code:`MIGRATION_EXPAND_CONTRACT_UNMATCHED`,message:`--expand-contract does not match a field whose type or array-ness changed: ${ce.map(e=>e.raw).join(`, `)}`,command:`tailordb migration generate`});if(se.length>0)throw R({code:`MIGRATION_EXPAND_CONTRACT_INELIGIBLE`,message:se.join(`
|
|
566
|
+
}`}function markMigrationScriptSkipped(e){let{migrationsDir:t,migrationNumber:n,reason:r}=e,i=formatMigrationNumber(n),a=r.trim();if(!a)throw R({code:`MIGRATION_SCRIPT_REASON_REQUIRED`,message:`Migration script skip reason must not be empty.`,command:`tailordb migration script`});let o=getMigrationFilePath(t,n,`diff`);if(!U.existsSync(o))throw R({code:`MIGRATION_NOT_FOUND`,message:`Migration ${i} not found in ${t}. Expected ${o}.`});let s=loadDiff(o);if(!s.requiresMigrationScript&&!s.hasWarnings)throw R({code:`MIGRATION_SCRIPT_NOT_REQUIRED`,message:`Migration ${i} does not require a migration script and has no data-loss warnings; nothing to skip.`});if(s.scriptSkipped)throw R({code:`MIGRATION_SCRIPT_SKIP_EXISTS`,message:`Migration ${i} already has a script skip recorded (${s.scriptSkipped.acknowledgedAt}: ${s.scriptSkipped.reason}).`});let c=getMigrationFilePath(t,n,`migrate`);if(U.existsSync(c))throw R({code:`MIGRATION_SCRIPT_EXISTS`,message:`Migration script exists at ${c}.`,suggestion:`Delete migrate.ts first if this migration should run without a script.`});let l={reason:a,acknowledgedAt:new Date().toISOString()},u=JSON.parse(U.readFileSync(o,`utf-8`));return u.scriptSkipped=l,U.writeFileSync(o,JSON.stringify(u,null,2)),l}function clearMigrationScriptSkipped(e){let t=JSON.parse(U.readFileSync(e,`utf-8`));Object.hasOwn(t,`scriptSkipped`)&&(delete t.scriptSkipped,U.writeFileSync(e,JSON.stringify(t,null,2)))}async function addMigrationScriptFiles(e){let{migrationsDir:t,migrationNumber:n,withTest:r=!1,pgliteAvailable:i=!1}=e,a=formatMigrationNumber(n),o=getMigrationFilePath(t,n,`diff`);if(!U.existsSync(o))throw R({code:`MIGRATION_NOT_FOUND`,message:`Migration ${a} not found in ${t}. Expected ${o}.`});let s=loadDiff(o),c=getMigrationFilePath(t,n,`migrate`),l=U.existsSync(c),u={};if(l&&s.scriptSkipped){if(clearMigrationScriptSkipped(o),u.clearedScriptSkip=!0,!r)return u}else if(l&&!r)throw R({code:`MIGRATION_SCRIPT_EXISTS`,message:`Migration script already exists at ${c}.`});let d=getMigrationFilePath(t,n,`test`),f=getMigrationFilePath(t,n,`pgliteTest`),p=getMigrationFilePath(t,n,`pgliteSchema`),m=r&&!U.existsSync(d),h=r&&i&&!U.existsSync(f);if(r&&!m&&!h)throw R({code:`MIGRATION_TEST_EXISTS`,message:i?`Migration tests already exist at ${d} and ${f}.`:`Migration test already exists at ${d}.`});if(l&&r){let e=getMigrationFilePath(t,n,`db`);if(!U.existsSync(e))throw R({code:`GENERATED_TYPES_NOT_FOUND`,message:`Generated types not found at ${e}.`,suggestion:`The test scaffold imports Database from ./db; restore db.ts before adding a test.`})}let g=!l||r&&!U.existsSync(p),_=g?reconstructSnapshotFromMigrations(t,n-1):null;if(g&&!_)throw R({code:`MIGRATION_HISTORY_INVALID`,message:`Could not reconstruct previous schema for migration ${a}.`,suggestion:`Make sure migration 0 exists.`});if(!l&&_){await q.writeFile(c,generateMigrationScript(s)),u.migratePath=c;let e=await writeMigrationTypeFiles({previousSnapshot:_,diff:s,migrationsDir:t,migrationNumber:n});u.dbTypesPath=e.dbTypesPath,u.pgliteSchemaPath=e.pgliteSchemaPath,u.pgliteSchemaError=e.pgliteSchemaError,clearMigrationScriptSkipped(o)}else r&&_&&Object.assign(u,await tryWritePgliteSchemaFile(_,s,t,n));return m&&(await q.writeFile(d,generateMigrationTestScript(s)),u.testPath=d),u.pgliteTestRequested=h,h&&U.existsSync(p)&&(await q.writeFile(f,generateMigrationPgliteTestScript(s)),u.pgliteTestPath=f),u}function isPgliteAvailable(e){let t=V.resolve(e);for(;;){if(U.existsSync(V.join(t,`node_modules`,`@electric-sql`,`pglite`,`package.json`)))return!0;let e=V.dirname(t);if(e===t)return!1;t=e}}async function script(e){logBetaWarning(`tailordb migration`);let t=parseMigrationNumberArg(e.number);if(t===0)throw R({code:`MIGRATION_SCRIPT_NOT_ALLOWED`,message:`Migration ${e.number} is the initial schema snapshot and cannot have a migration script.`});let{config:n}=await loadConfig(e.configPath),r=getNamespacesWithMigrations(n,V.dirname(n.path));if(r.length===0)throw migrationConfigNotFoundError();let i=resolveTargetNamespace(r,e.namespace),{migrationsDir:a}=k(r.find(e=>e.namespace===i),`namespace with migrations not found`);if(e.noScript){if(e.withTest)throw R({code:`MIGRATION_SCRIPT_OPTIONS_CONFLICT`,message:`--with-test cannot be used together with --no-script.`,command:`tailordb migration script`});let n=e.reason?.trim();if(!n)throw R({code:`MIGRATION_SCRIPT_REASON_REQUIRED`,message:`--reason is required with --no-script.`,command:`tailordb migration script`});let r=markMigrationScriptSkipped({migrationsDir:a,migrationNumber:t,reason:n});M.success(`Recorded that migration ${j.bold(e.number)} in namespace ${j.bold(i)} intentionally has no migration script`),M.info(` Reason: ${r.reason}`),M.info(` Diff file: ${getMigrationFilePath(a,t,`diff`)}`);return}if(e.reason!==void 0)throw R({code:`MIGRATION_SCRIPT_OPTIONS_CONFLICT`,message:`--reason can only be used together with --no-script.`,command:`tailordb migration script`});let o=isPgliteAvailable(a),s=await addMigrationScriptFiles({migrationsDir:a,migrationNumber:t,withTest:e.withTest,pgliteAvailable:o});if(s.clearedScriptSkip&&(M.success(`Cleared the stale script skip record for migration ${j.bold(e.number)} in namespace ${j.bold(i)}`),!s.testPath&&!s.pgliteTestRequested)){M.info(` Migration script: ${getMigrationFilePath(a,t,`migrate`)}`);return}let c=[s.testPath,s.pgliteTestPath].filter(Boolean).length,l=[s.migratePath&&`migration script`,c>0&&(c>1?`migration tests`:`migration test`)].filter(Boolean).join(` and `),u=`for migration ${j.bold(e.number)} in namespace ${j.bold(i)}`;l?M.success(`Added ${l} ${u}`):M.warn(`Added no files ${u}`),s.migratePath&&(M.info(` Migration script: ${s.migratePath}`),M.info(` DB types: ${s.dbTypesPath}`)),s.pgliteSchemaPath&&M.info(` PGlite schema: ${s.pgliteSchemaPath}`),s.pgliteSchemaError&&M.warn(` PGlite schema skipped: ${s.pgliteSchemaError}`),s.testPath&&M.info(` Migration test: ${s.testPath}`),s.pgliteTestPath?M.info(` PGlite test: ${s.pgliteTestPath}`):s.testPath&&!o?M.info(` Install @electric-sql/pglite as a devDependency to also scaffold a PGlite test (migrate.pglite.test.ts).`):s.pgliteTestRequested&&s.pgliteSchemaError&&M.info(` PGlite test skipped: it needs the db.pglite.ts that could not be generated.`),M.newline(),s.migratePath&&(M.log(`Edit the script to implement your data migration logic.`),M.log(`It will be executed by 'tailor deploy' between Pre and Post phases.`)),s.testPath&&M.log(`Fill in the test with the rows to stage and the statements to assert.`);let d=s.migratePath??s.testPath;if(!d)return;let f=getConfiguredEditorCommand();if(f){M.newline(),M.info(`Opening ${V.basename(d)} in ${f}...`);try{await openInConfiguredEditor(d)}catch{return}}}function resolveTargetNamespace(e,t){if(t){if(!e.some(e=>e.namespace===t))throw R({code:`TAILORDB_NAMESPACE_NOT_FOUND`,message:`Namespace "${t}" not found or does not have migrations configured`});return t}if(e.length===1){let[t]=e;return k(t,`namespace with migrations missing`).namespace}throw R({code:`MIGRATION_NAMESPACE_REQUIRED`,message:`Multiple TailorDB services found. Please specify namespace with --namespace flag: ${e.map(e=>e.namespace).join(`, `)}`,command:`tailordb migration script`})}const _c=Y({name:`script`,description:`Add a migration script (migrate.ts) template to an existing migration directory, or record with --no-script that a migration intentionally has none.`,notes:"When `migrate.ts` already exists, running the command clears a previously recorded `--no-script` acknowledgment, and `--with-test` adds only the tests that do not exist yet (writing `db.pglite.ts` if it is missing). `migrate.pglite.test.ts` is scaffolded only when `@electric-sql/pglite` is installed in the project.",args:H.strictObject({...ri,number:B(H.string(),{positional:!0,description:`Migration number to add a script to (e.g., 0001 or 1)`}),namespace:B(H.string().optional(),{alias:`n`,description:`Target TailorDB namespace (required if multiple namespaces exist)`}),"no-script":B(H.boolean().optional(),{description:`Record that this migration intentionally runs without a migration script (requires --reason)`}),reason:B(H.string().optional(),{description:`Reason why no migration script is needed (used with --no-script)`}),"with-test":B(H.boolean().optional(),{description:`Also add the migrate.test.ts and migrate.pglite.test.ts scaffolds`})}),run:async e=>{await script({configPath:e.config,number:e.number,namespace:e.namespace,noScript:e[`no-script`],reason:e.reason,withTest:e[`with-test`]})}});function getUnsupportedMigrationHintLines(){return[`These changes require a manual 3-step migration process:`,` Migration 1: Add an optional temporary field with the desired structure`,` If the old field is required, make the old field optional`,` For each non-null old value, copy and convert it to the temporary field`,` and set the old field to null in the same update`,` Verify every old value is null before continuing`,` Migration 2: Remove the old field`,` Migration 3: Add the field with the original name and new structure,`,` migrate data from the temporary field, then remove it`,` Important: Reusing the name while stored old values remain can make subsequent reads fail`]}async function handleInitOption(e,t){let n=e.filter(({migrationsDir:e})=>U.existsSync(e));if(n.length===0){M.info(`No existing migration directories found.`);return}M.newline(),M.warn(`This will DELETE all existing migration files:`);for(let{namespace:e,migrationsDir:t}of n)M.log(` - ${e}: ${t}`);M.newline(),t||(await X.confirm({message:`Are you sure you want to delete these directories and start fresh?`,default:!1})||(M.info(`Operation cancelled.`),process.exit(0)),M.newline());for(let{namespace:e,migrationsDir:t}of n)try{await q.rm(t,{recursive:!0,force:!0}),M.success(`Deleted migration directory for ${j.bold(e)}`)}catch(e){throw M.error(`Failed to delete ${t}: ${e}`),e}M.newline(),M.info(`Migration directories cleared. Generating initial snapshot...`),M.newline()}async function generate(e){logBetaWarning(`tailordb migration`);let{config:t,plugins:n}=await loadConfig(e.configPath),r=getNamespacesWithMigrations(t,V.dirname(t.path));if(r.length===0){M.warn(`No TailorDB namespaces with migrations config found.`),M.info(`Add "migration: { directory: \\"./migrations\\" }" to your db config to enable migrations.`);return}let i=[],a=[],o=[];for(let t of e.renames??[]){let e=targetDepth(t);e>=2?o.push({raw:t,spec:parseNestedMemberRenameOption(t)}):e===1?i.push({raw:t,spec:parseRenameOption(t)}):a.push({raw:t,spec:parseTypeRenameOption(t)})}let s=[],c=[],l=[];for(let t of e.drops??[]){let e=targetDepth(t);e>=2?l.push({raw:t,spec:parseNestedMemberDropOption(t)}):e===1?s.push({raw:t,spec:parseDropOption(t)}):c.push({raw:t,spec:parseTypeDropOption(t)})}let u=(e.expandContracts??[]).map(e=>({raw:e,spec:parseExpandContractOption(e)})),d=i.length>0||a.length>0||o.length>0||s.length>0||c.length>0||l.length>0;if(e.init&&(d||u.length>0))throw R({code:`MIGRATION_GENERATE_OPTIONS_CONFLICT`,message:`--rename, --drop, and --expand-contract cannot be used together with --init.`,command:`tailordb migration generate`});let f=new Set(s.map(({spec:e})=>`${e.tableName}.${e.fieldName}`)),p=i.filter(({spec:e})=>f.has(`${e.tableName}.${e.previousFieldName}`));if(p.length>0)throw R({code:`MIGRATION_RENAME_DROP_CONFLICT`,message:`--rename and --drop conflict for: ${p.map(({spec:e})=>`${e.tableName}.${e.previousFieldName}`).join(`, `)}`,command:`tailordb migration generate`});let m=new Set(l.map(({spec:e})=>nestedMemberKey(e))),h=o.filter(({spec:e})=>m.has(nestedMemberKey({...e,path:e.previousPath})));if(h.length>0)throw R({code:`MIGRATION_RENAME_DROP_CONFLICT`,message:`--rename and --drop conflict for: ${h.map(({spec:e})=>nestedMemberKey({...e,path:e.previousPath})).join(`, `)}`,command:`tailordb migration generate`});let g=new Set(c.map(({spec:e})=>e.tableName)),_=a.filter(({spec:e})=>g.has(e.previousTableName));if(_.length>0)throw R({code:`MIGRATION_RENAME_DROP_CONFLICT`,message:`--rename and --drop conflict for: ${_.map(({spec:e})=>e.previousTableName).join(`, `)}`,command:`tailordb migration generate`});if(e.namespace!==void 0&&!e.dataOnly)throw R({code:`MIGRATION_GENERATE_OPTIONS_CONFLICT`,message:`--namespace can only be used together with --data-only.`,command:`tailordb migration generate`});if(e.dataOnly&&(e.init||d||u.length>0))throw R({code:`MIGRATION_GENERATE_OPTIONS_CONFLICT`,message:`--init, --rename, --drop, and --expand-contract cannot be used together with --data-only.`,command:`tailordb migration generate`});let v=e.dataOnly?resolveTargetNamespace(r,e.namespace):void 0,y=v===void 0?r:r.filter(({namespace:e})=>e===v);e.init&&await handleInitOption(r,e.yes);let b;n.length>0&&(b=new On(n));let{defineApplication:x}=await import(`./application-KZRJHv2j.mjs`),S=x({config:t,pluginManager:b}),C=[];for(let{namespace:e,migrationsDir:t}of y){M.info(`Processing namespace: ${j.bold(e)}`),assertValidMigrationFiles(t,e);let n=S.tailorDBServices.find(t=>t.namespace===e);if(!n){M.warn(`No TailorDB service found for namespace "${e}"`);continue}await n.loadTypes(),await n.processNamespacePlugins();let r=n.types;C.push({namespace:e,migrationsDir:t,currentSnapshot:createSnapshotFromLocalTypes(r,e),previousSnapshot:reconstructSnapshotFromMigrations(t)})}if(v!==void 0){await generateDataOnlyMigration(C,v,e);return}let w=matchFlagsToNamespaces(i,C,renameSpecApplies,`--rename does not match a removed + added field pair`),ee=matchFlagsToNamespaces(a,C,typeRenameSpecApplies,`--rename does not match a removed + added table pair`),te=matchFlagsToNamespaces(s,C,dropSpecApplies,`--drop does not match a removed field`),ne=matchFlagsToNamespaces(c,C,typeDropSpecApplies,`--drop does not match a removed table`),re=matchFlagsToNamespaces(o,C,nestedMemberRenameSpecApplies,`--rename does not match a removed + added nested member pair`),ie=matchFlagsToNamespaces(l,C,nestedMemberDropSpecApplies,`--drop does not match a removed nested member`),ae=new Map,oe=new Set,se=[];for(let{namespace:e,previousSnapshot:t,currentSnapshot:n}of C){if(!t)continue;let r=[];for(let i of u){let{spec:a}=i,o=t.tables[a.tableName]?.fields[a.fieldName],s=n.tables[a.tableName]?.fields[a.fieldName];if(!o||!s||!hasFieldShapeChange(o,s))continue;oe.add(i);let c=getExpandContractEligibility({previous:t,current:n,tableName:a.tableName,fieldName:a.fieldName});if(!c.eligible){se.push(`--expand-contract cannot convert ${i.raw} (namespace: ${e}): ${c.reason}`);continue}r.push(i)}ae.set(e,new Set(r.map(({spec:e})=>fieldKey(e.tableName,e.fieldName))))}let ce=u.filter(e=>!oe.has(e));if(ce.length>0)throw R({code:`MIGRATION_EXPAND_CONTRACT_UNMATCHED`,message:`--expand-contract does not match a field whose type or array-ness changed: ${ce.map(e=>e.raw).join(`, `)}`,command:`tailordb migration generate`});if(se.length>0)throw R({code:`MIGRATION_EXPAND_CONTRACT_INELIGIBLE`,message:se.join(`
|
|
567
567
|
`)});let le=[];for(let t of C){let{namespace:n,previousSnapshot:r,currentSnapshot:i}=t;if(!r)continue;let a=compareSnapshots(r,i);if(!hasChanges(a)){t.diff=a;continue}let o=await resolveRenames(r,i,a,e,{fieldRenames:w.get(n)??[],typeRenames:ee.get(n)??[],fieldDrops:te.get(n)??[],typeDrops:ne.get(n)??[],nestedMemberRenames:re.get(n)??[],nestedMemberDrops:ie.get(n)??[]});t.diff=o.diff,le.push(...o.unresolved),t.expandPlans=await resolveExpandContractPlans({previousSnapshot:r,currentSnapshot:i,diff:o.diff,options:e,confirmedKeys:ae.get(n)??new Set})}if(le.length>0){let e=le.map(({namespace:e,label:t,targets:n})=>` - ${t} → ${n.join(`, `)}? (namespace: ${e})`).join(`
|
|
568
568
|
`);throw R({code:`MIGRATION_RENAME_UNRESOLVED`,message:`Possible rename(s) detected:\n${e}`,suggestion:`Re-run with --rename "Table.oldField:newField" (field), --rename "OldTable:NewTable" (table), or --rename "Table.field.oldMember:newMember" (nested member) to record a rename and scaffold a data copy script, or --drop "Table.field" / --drop "Table" / --drop "Table.field.member" to confirm the removal.`,command:`tailordb migration generate`})}for(let{migrationsDir:t,currentSnapshot:n,previousSnapshot:r,diff:i,expandPlans:a}of C)r?await generateDiffFromSnapshot(r,k(i,`Migration diff was not resolved during preflight`),t,e,n,a??[]):await generateInitialSnapshot(n,t)}async function generateDataOnlyMigration(e,t,n){let r=e.find(e=>e.namespace===t);if(!r)throw R({code:`TAILORDB_NAMESPACE_NOT_FOUND`,message:`No TailorDB service found for namespace "${t}"`});let{migrationsDir:i,previousSnapshot:a,currentSnapshot:o}=r;if(!a)throw R({code:`MIGRATION_BASELINE_NOT_FOUND`,message:`Namespace "${t}" has no migration baseline.`,suggestion:`Create the initial schema snapshot first.`});let s=compareSnapshots(a,o);if(hasChanges(s))throw M.newline(),M.log(formatMigrationDiff(s)),M.newline(),R({code:`MIGRATION_SCHEMA_CHANGES_PENDING`,message:`Namespace "${t}" has schema changes that are not in migration files.`,suggestion:`Generate the schema migration first by running without --data-only.`});let c=getNextMigrationNumber(i),l=await generateDataOnlyMigrationFiles({diff:{...s,requiresMigrationScript:!0},migrationsDir:i,migrationNumber:c,snapshot:a,description:n.name});M.success(`Generated data-only migration ${j.bold(formatMigrationNumber(l.migrationNumber))}`),M.info(` Diff file: ${l.diffFilePath}`),M.info(` Migration script: ${l.migrateFilePath}`),M.info(` DB types: ${l.dbTypesFilePath}`),logPgliteSchemaResult(l),M.newline(),M.log(`This migration carries no schema changes.`),M.log(`Edit the script to implement the data transformation before running 'tailor deploy'.`),await openMigrationScriptInEditor(l.migrateFilePath)}function logPgliteSchemaResult(e){e.pgliteSchemaFilePath&&M.info(` PGlite schema: ${e.pgliteSchemaFilePath}`),e.pgliteSchemaError&&M.warn(` PGlite schema skipped: ${e.pgliteSchemaError}`)}async function openMigrationScriptInEditor(e){let t=getConfiguredEditorCommand();if(t){try{await q.access(e)}catch{return}M.newline(),M.info(`Opening ${V.basename(e)} in ${t}...`);try{await openInConfiguredEditor(e)}catch{return}}}async function resolveExpandContractPlans(e){let{previousSnapshot:t,currentSnapshot:n,diff:r,options:i,confirmedKeys:a}=e,o=new Set(a);if(!i.yes&&canPrompt())for(let e of r.changes){if(!isExpandContractCandidate(e))continue;let r=fieldKey(e.tableName,e.fieldName);o.has(r)||canConvertField({previous:t,current:n,tableName:e.tableName,fieldName:e.fieldName})&&(M.newline(),M.info(`${e.tableName}.${e.fieldName} changes from ${formatFieldShape(e.before)} to ${formatFieldShape(e.after)}, which cannot be applied in one step.`),await X.confirm({message:`Generate two migrations to convert ${e.tableName}.${e.fieldName} through a temporary field?`,default:!0})&&o.add(r))}return planExpandContract({previous:t,current:n,diff:r,confirmed:o}).plans}async function generateInitialSnapshot(e,t){let n=await generateSchemaFile(e,t,0);M.success(`Generated initial schema snapshot`),M.info(` File: ${n.filePath}`),M.info(` Tables: ${Object.keys(e.tables).length}`),M.log(`
|
|
569
569
|
This is the baseline schema. Future changes will be tracked as diffs.`)}function targetDepth(e){return(e.split(`:`)[0]??``).split(`.`).length-1}function nestedMemberKey(e){return`${e.tableName}.${e.fieldName}.${e.path.join(`.`)}`}function matchFlagsToNamespaces(e,t,n,r){let i=new Map,a=new Set;for(let{namespace:r,previousSnapshot:o,currentSnapshot:s}of t){if(!o)continue;let t=e.filter(({spec:e})=>n(e,o,s));for(let e of t)a.add(e);i.set(r,t.map(e=>e.spec))}let o=e.filter(e=>!a.has(e));if(o.length>0)throw R({code:`MIGRATION_FLAG_UNMATCHED`,message:`${r}: ${o.map(e=>e.raw).join(`, `)}`,command:`tailordb migration generate`});return i}function availableNestedMemberRenameTargets(e,t){let n=e.previousPath.slice(0,-1);return e.added.filter(r=>!t.has(nestedMemberKey({...e,path:[...n,r]})))}async function promptNestedMemberRenameCandidate(e,t){let n=nestedMemberKey({...e,path:e.previousPath}),r=e.previousPath[e.previousPath.length-1]??``,[i]=t;return t.length===1&&i?await X.confirm({message:`${n} was removed and ${i} was added with a compatible type. Was it renamed to ${i}?`,default:!0})?i:void 0:await X.select({message:`${n} was removed. Was it renamed to one of these added members?`,choices:[...t.map(e=>({name:`Yes, renamed to ${e}`,value:e})),{name:`No, ${r} was removed`,value:null}]})??void 0}function availableRenameTargets(e,t){return e.added.filter(n=>!t.has(`${e.tableName}.${n.fieldName}`)).map(e=>e.fieldName)}async function promptRenameCandidate(e,t){let n=`${e.tableName}.${e.removed.fieldName}`,[r]=t;return t.length===1&&r?await X.confirm({message:`${n} was removed and ${r} was added with a compatible type. Was it renamed to ${r}?`,default:!0})?r:void 0:await X.select({message:`${n} was removed. Was it renamed to one of these added fields?`,choices:[...t.map(e=>({name:`Yes, renamed to ${e}`,value:e})),{name:`No, ${e.removed.fieldName} was removed`,value:null}]})??void 0}function availableTypeRenameTargets(e,t){return e.added.filter(e=>!t.has(e.tableName)).map(e=>e.tableName)}async function promptTypeRenameCandidate(e,t){let n=e.removed.tableName,[r]=t;return t.length===1&&r?await X.confirm({message:`${n} was removed and ${r} was added with a compatible schema. Was it renamed to ${r}?`,default:!0})?r:void 0:await X.select({message:`${n} was removed. Was it renamed to one of these added tables?`,choices:[...t.map(e=>({name:`Yes, renamed to ${e}`,value:e})),{name:`No, ${n} was removed`,value:null}]})??void 0}async function resolveRenames(e,t,n,r,i){let a=[...i.fieldRenames],o=new Set(a.flatMap(e=>[`${e.tableName}.${e.previousFieldName}`,`${e.tableName}.${e.fieldName}`])),s=new Set(i.fieldDrops.map(e=>`${e.tableName}.${e.fieldName}`)),c=[...i.typeRenames],l=new Set(c.flatMap(e=>[e.previousTableName,e.tableName])),u=new Set(i.typeDrops.map(e=>e.tableName)),d=[...i.nestedMemberRenames],f=new Set(d.flatMap(e=>[nestedMemberKey({...e,path:e.previousPath}),nestedMemberKey(e)])),p=new Set(i.nestedMemberDrops.map(e=>nestedMemberKey(e))),m=findTypeRenameCandidates(n).filter(e=>!u.has(e.removed.tableName)&&!l.has(e.removed.tableName)&&availableTypeRenameTargets(e,l).length>0),h=findRenameCandidates(n).filter(e=>!s.has(`${e.tableName}.${e.removed.fieldName}`)&&!o.has(`${e.tableName}.${e.removed.fieldName}`)&&availableRenameTargets(e,o).length>0),g=findNestedMemberRenameCandidates(n).filter(e=>{let t=nestedMemberKey({...e,path:e.previousPath});return!p.has(t)&&!f.has(t)&&availableNestedMemberRenameTargets(e,f).length>0}),_=[];if(r.yes||!canPrompt()){for(let e of m)_.push({namespace:n.namespace,label:e.removed.tableName,targets:availableTypeRenameTargets(e,l)});for(let e of h)_.push({namespace:n.namespace,label:`${e.tableName}.${e.removed.fieldName}`,targets:availableRenameTargets(e,o)});for(let e of g)_.push({namespace:n.namespace,label:nestedMemberKey({...e,path:e.previousPath}),targets:availableNestedMemberRenameTargets(e,f)})}else{for(let e of m){let t=availableTypeRenameTargets(e,l);if(t.length===0)continue;let n=await promptTypeRenameCandidate(e,t);n&&(c.push({previousTableName:e.removed.tableName,tableName:n}),l.add(e.removed.tableName),l.add(n))}for(let e of h){let t=availableRenameTargets(e,o);if(t.length===0)continue;let n=await promptRenameCandidate(e,t);n&&(a.push({tableName:e.tableName,previousFieldName:e.removed.fieldName,fieldName:n}),o.add(`${e.tableName}.${e.removed.fieldName}`),o.add(`${e.tableName}.${n}`))}for(let e of g){let t=availableNestedMemberRenameTargets(e,f);if(t.length===0)continue;let n=await promptNestedMemberRenameCandidate(e,t);if(n){let t={tableName:e.tableName,fieldName:e.fieldName,previousPath:e.previousPath,path:[...e.previousPath.slice(0,-1),n]};d.push(t),f.add(nestedMemberKey({...t,path:t.previousPath})),f.add(nestedMemberKey(t))}}}return a.length===0&&c.length===0&&d.length===0?{diff:n,unresolved:_}:{diff:compareSnapshots(e,t,{fieldRenames:a,typeRenames:c,nestedMemberRenames:d}),unresolved:_}}async function generateDiffFromSnapshot(e,t,n,r,i,a=[]){if(!hasChanges(t)){M.info(`No schema differences detected.`);return}M.newline(),M.log(formatMigrationDiff(t)),M.newline(),M.info(`Summary: ${formatDiffSummary(t)}`);let o=new Set(a.map(e=>fieldKey(e.tableName,e.fieldName))),s=t.breakingChanges.filter(e=>e.unsupported&&!(e.fieldName&&o.has(fieldKey(e.tableName,e.fieldName))));if(s.length>0){for(let e of s)M.newline(),M.error(`Unsupported change: ${e.tableName}.${e.fieldName}`),M.error(` ${e.reason}`);let t=new Set;for(let{tableName:n,fieldName:r}of s)r!==void 0&&canConvertField({previous:e,current:i,tableName:n,fieldName:r})&&t.add(fieldKey(n,r));if(t.size>0){M.newline(),M.info(`Convert these fields through a temporary field with:`);for(let e of t)M.info(` --expand-contract "${e}"`)}if(s.some(e=>e.showThreeStepHint)){M.newline();for(let e of getUnsupportedMigrationHintLines())M.info(e)}let n=s.map(e=>` - ${e.tableName}.${e.fieldName}: ${e.reason}`).join(`
|
|
570
|
-
`);throw R({code:`MIGRATION_UNSUPPORTED_SCHEMA_CHANGE`,message:`Unsupported schema changes detected:\n${n}`})}if(t.hasBreakingChanges&&(M.newline(),M.warn(formatBreakingChanges(t.breakingChanges)),!r.yes)){if(!await X.confirm({message:`Continue generating migration?`,default:!0})){M.info(`Migration generation cancelled.`);return}M.newline()}if(t.hasWarnings&&(M.newline(),M.warn(formatWarnings(t.warnings))),a.length>0){await generateExpandContractMigrations({previousSnapshot:e,currentSnapshot:i,resolvedDiff:t,plans:a,migrationsDir:n,description:r.name});return}let c=await generateDiffFiles(t,n,getNextMigrationNumber(n),e,r.name);M.success(`Generated migration ${j.bold(formatMigrationNumber(c.migrationNumber))}`),M.info(` Diff file: ${c.diffFilePath}`),c.migrateFilePath?(M.info(` Migration script: ${c.migrateFilePath}`),c.dbTypesFilePath&&(M.info(` DB types: ${c.dbTypesFilePath}`),logPgliteSchemaResult(c)),M.newline(),M.log(`A migration script was generated for breaking changes.`),M.log(`Please review and edit the script before running 'tailor deploy'.`),await openMigrationScriptInEditor(c.migrateFilePath)):t.hasWarnings&&await acknowledgeWarnings({namespace:t.namespace,migrationsDir:n,migrationNumber:c.migrationNumber,skipPrompt:r.yes,configPath:r.configPath})}async function generateExpandContractMigrations(e){let{previousSnapshot:t,currentSnapshot:n,resolvedDiff:r,plans:i,migrationsDir:a,description:o}=e,s=buildIntermediateSnapshot(t,i),c=buildExpandDiff(t,s,i),l=r.changes.filter(e=>e.kind===`field_renamed`).map(({tableName:e,previousFieldName:t,fieldName:n})=>({tableName:e,previousFieldName:t,fieldName:n})),u=r.changes.filter(e=>e.kind===`table_renamed`).map(({previousTableName:e,tableName:t})=>({previousTableName:e,tableName:t})),d=compareSnapshots(s,n,{nestedMemberRenames:r.changes.flatMap(e=>e.kind===`field_modified`?(e.memberRenames??[]).map(t=>({tableName:e.tableName,fieldName:e.fieldName,...t})):[]),fieldRenames:[...l,...i.map(e=>({tableName:e.tableName,previousFieldName:e.tempFieldName,fieldName:e.fieldName}))],typeRenames:u}),f=getNextMigrationNumber(a);if(f+1>9999)throw R({code:`MIGRATION_NUMBER_EXHAUSTED`,message:`Converting a field type needs two migration numbers, and ${formatMigrationNumber(9999)} is the last one available.`,suggestion:`Re-baseline the migration history first.`});let p=await generateDiffFiles(c,a,f,t,o,i),m=await generateDiffFiles(d,a,f+1,s,o),h=i.map(e=>`${e.tableName}.${e.fieldName}`).join(`, `);M.success(`Generated migrations ${j.bold(formatMigrationNumber(p.migrationNumber))} and ${j.bold(formatMigrationNumber(m.migrationNumber))} to convert ${h}`),M.info(` Diff files: ${p.diffFilePath}, ${m.diffFilePath}`),p.migrateFilePath&&M.info(` Conversion script: ${p.migrateFilePath}`),m.migrateFilePath&&M.info(` Copy script: ${m.migrateFilePath}`),M.newline(),M.info(`Edit the conversion in ${formatMigrationNumber(p.migrationNumber)} before deploying. The copy script in ${formatMigrationNumber(m.migrationNumber)} is complete, though that migration also carries any other change in this run.`,{mode:`plain`}),M.info(`Both migrations are applied by 'tailor deploy'.`,{mode:`plain`})}async function acknowledgeWarnings(e){let{namespace:t,migrationsDir:n,migrationNumber:r,skipPrompt:i,configPath:a}=e,o=formatMigrationNumber(r);if(M.newline(),M.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.`})});M.success(`Recorded that migration ${j.bold(o)} intentionally has no migration script`),M.info(` Reason: ${e.reason}`);return}let s={migrationNumber:r,namespace:t,configPath:a};M.log(`To add a custom migrate.ts, run:`),M.log(` ${j.bold(formatMigrationScriptCommand(s))}`),M.log(`To record that this migration intentionally has no script, run:`),M.log(` ${j.bold(formatMigrationScriptCommand({...s,noScript:!0}))}`)}const
|
|
570
|
+
`);throw R({code:`MIGRATION_UNSUPPORTED_SCHEMA_CHANGE`,message:`Unsupported schema changes detected:\n${n}`})}if(t.hasBreakingChanges&&(M.newline(),M.warn(formatBreakingChanges(t.breakingChanges)),!r.yes)){if(!await X.confirm({message:`Continue generating migration?`,default:!0})){M.info(`Migration generation cancelled.`);return}M.newline()}if(t.hasWarnings&&(M.newline(),M.warn(formatWarnings(t.warnings))),a.length>0){await generateExpandContractMigrations({previousSnapshot:e,currentSnapshot:i,resolvedDiff:t,plans:a,migrationsDir:n,description:r.name});return}let c=await generateDiffFiles(t,n,getNextMigrationNumber(n),e,r.name);M.success(`Generated migration ${j.bold(formatMigrationNumber(c.migrationNumber))}`),M.info(` Diff file: ${c.diffFilePath}`),c.migrateFilePath?(M.info(` Migration script: ${c.migrateFilePath}`),c.dbTypesFilePath&&(M.info(` DB types: ${c.dbTypesFilePath}`),logPgliteSchemaResult(c)),M.newline(),M.log(`A migration script was generated for breaking changes.`),M.log(`Please review and edit the script before running 'tailor deploy'.`),await openMigrationScriptInEditor(c.migrateFilePath)):t.hasWarnings&&await acknowledgeWarnings({namespace:t.namespace,migrationsDir:n,migrationNumber:c.migrationNumber,skipPrompt:r.yes,configPath:r.configPath})}async function generateExpandContractMigrations(e){let{previousSnapshot:t,currentSnapshot:n,resolvedDiff:r,plans:i,migrationsDir:a,description:o}=e,s=buildIntermediateSnapshot(t,i),c=buildExpandDiff(t,s,i),l=r.changes.filter(e=>e.kind===`field_renamed`).map(({tableName:e,previousFieldName:t,fieldName:n})=>({tableName:e,previousFieldName:t,fieldName:n})),u=r.changes.filter(e=>e.kind===`table_renamed`).map(({previousTableName:e,tableName:t})=>({previousTableName:e,tableName:t})),d=compareSnapshots(s,n,{nestedMemberRenames:r.changes.flatMap(e=>e.kind===`field_modified`?(e.memberRenames??[]).map(t=>({tableName:e.tableName,fieldName:e.fieldName,...t})):[]),fieldRenames:[...l,...i.map(e=>({tableName:e.tableName,previousFieldName:e.tempFieldName,fieldName:e.fieldName}))],typeRenames:u}),f=getNextMigrationNumber(a);if(f+1>9999)throw R({code:`MIGRATION_NUMBER_EXHAUSTED`,message:`Converting a field type needs two migration numbers, and ${formatMigrationNumber(9999)} is the last one available.`,suggestion:`Re-baseline the migration history first.`});let p=await generateDiffFiles(c,a,f,t,o,i),m=await generateDiffFiles(d,a,f+1,s,o),h=i.map(e=>`${e.tableName}.${e.fieldName}`).join(`, `);M.success(`Generated migrations ${j.bold(formatMigrationNumber(p.migrationNumber))} and ${j.bold(formatMigrationNumber(m.migrationNumber))} to convert ${h}`),M.info(` Diff files: ${p.diffFilePath}, ${m.diffFilePath}`),p.migrateFilePath&&M.info(` Conversion script: ${p.migrateFilePath}`),m.migrateFilePath&&M.info(` Copy script: ${m.migrateFilePath}`),M.newline(),M.info(`Edit the conversion in ${formatMigrationNumber(p.migrationNumber)} before deploying. The copy script in ${formatMigrationNumber(m.migrationNumber)} is complete, though that migration also carries any other change in this run.`,{mode:`plain`}),M.info(`Both migrations are applied by 'tailor deploy'.`,{mode:`plain`})}async function acknowledgeWarnings(e){let{namespace:t,migrationsDir:n,migrationNumber:r,skipPrompt:i,configPath:a}=e,o=formatMigrationNumber(r);if(M.newline(),M.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.`})});M.success(`Recorded that migration ${j.bold(o)} intentionally has no migration script`),M.info(` Reason: ${e.reason}`);return}let s={migrationNumber:r,namespace:t,configPath:a};M.log(`To add a custom migrate.ts, run:`),M.log(` ${j.bold(formatMigrationScriptCommand(s))}`),M.log(`To record that this migration intentionally has no script, run:`),M.log(` ${j.bold(formatMigrationScriptCommand({...s,noScript:!0}))}`)}const vc=Y({name:`generate`,description:`Generate migration files by detecting schema differences between current local tables and the previous migration snapshot.`,args:H.strictObject({...oi,...ri,name:B(H.string().optional(),{alias:`n`,description:`Optional description for the migration`}),init:B(H.boolean().default(!1),{description:`Delete existing migrations and start fresh`}),"data-only":B(H.boolean().default(!1),{description:`Create a migration with no schema changes whose migration script runs a standalone data transformation`}),namespace:B(H.string().optional(),{description:`Target TailorDB namespace for --data-only (required if multiple namespaces exist)`}),rename:B(H.array(H.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:B(H.array(H.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":B(H.array(H.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=>{await generate({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`]})}});function generateSeedScriptContent(e){return I`
|
|
571
571
|
import { Kysely, TailordbDialect } from "@tailor-platform/sdk/kysely";
|
|
572
572
|
|
|
573
573
|
type SeedInput = {
|
|
@@ -848,7 +848,7 @@ This is the baseline schema. Future changes will be tracked as diffs.`)}function
|
|
|
848
848
|
return { success: false, rows: [], cursor: null, errors: [message] };
|
|
849
849
|
}
|
|
850
850
|
}
|
|
851
|
-
`}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=V.resolve($t(),`seed`);U.mkdirSync(i,{recursive:!0});let a=V.join(i,t);U.writeFileSync(a,n);let o;try{o=await Wn(r)}catch{o=void 0}let s=bt({tsconfig:o}),c=await Sr.build({plugins:[Tt(a,r),Wt(),Ut],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}function chunkSeedData(e){let{data:t,order:n,codeByteSize:r,maxMessageSize:i=3670016}=e,a=i-r-1024;if(a<=0)throw Error(`Code size (${r} bytes) exceeds the message size limit (${i} bytes). No space left for seed data.`);let o=n.filter(e=>(t[e]?.length??0)>0);if(o.length===0)return[];if(byteSize(JSON.stringify({data:t,order:n}))<=a)return[{data:t,order:n,index:0,total:1}];let s=[],c={},l=[];for(let e of o){let n=k(t[e],`seed data missing for type: ${e}`);if(l.length>0){let t={...c,[e]:n},r=[...l,e];byteSize(JSON.stringify({data:t,order:r}))>a&&(s.push({data:c,order:l,index:s.length}),c={},l=[])}if(byteSize(JSON.stringify({data:{[e]:n},order:[e]}))<=a){c[e]=n,l.push(e);continue}l.length>0&&(s.push({data:c,order:l,index:s.length}),c={},l=[]);let r=[];for(let t of n){if(byteSize(JSON.stringify({data:{[e]:[t]},order:[e]}))>a){let n=byteSize(JSON.stringify(t));throw Error(`A single record in table "${e}" (${n} bytes) exceeds the message size budget (${a} bytes). Consider increasing maxMessageSize or reducing the record size.`)}let n=[...r,t],i={...c,[e]:n},o=l.includes(e)?l:[...l,e];byteSize(JSON.stringify({data:i,order:o}))>a&&r.length>0?(c[e]=r,l.includes(e)||l.push(e),s.push({data:c,order:l,index:s.length}),c={},l=[],r=[t]):r=n}r.length>0&&(c[e]=r,l.includes(e)||l.push(e))}l.length>0&&s.push({data:c,order:l,index:s.length});let u=s.length;return s.map(e=>({...e,total:u}))}function byteSize(e){return new TextEncoder().encode(e).length}function processSeedTypeInfo(e,t){let n=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))}return{name:e.name,namespace:t,dependencies:Array.from(n),selfRefFields:r,selfRefKeys:i,dataFile:`data/${e.name}.jsonl`}}function collectRelationTargetKeys(e){let t=new Map;for(let n of e)for(let e of Object.values(n.tables))for(let n of Object.values(e.fields)){let e=n.relation?.targetType??n.config.foreignKeyType,r=n.relation?.key??n.config.foreignKeyField;if(!e||!r)continue;let i=t.get(e)??new Set;i.add(r),t.set(e,i)}return t}function buildSeedNamespaceConfigs(e){let t=collectRelationTargetKeys(e);return e.map(e=>{let n=[],r={},i=[],a={},o={},s={},c={};for(let[l,u]of Object.entries(e.tables)){let d=processSeedTypeInfo(u,e.namespace);n.push(d.name),r[d.name]=d.dependencies,a[d.name]=d.selfRefFields,o[d.name]=d.selfRefKeys,d.selfRefFields.length>0&&i.push(d.name);let f=k(e.sourceInfo.get(l),`source info missing for table: ${l}`),p=Nn(u,f),m=t.get(d.name);c[d.name]=m?p.omitFields.filter(e=>!m.has(e)):p.omitFields,s[d.name]=Object.entries(u.fields).filter(([e,t])=>t.config.required!==!1&&!p.optionalFields.includes(e)&&!p.omitFields.includes(e)).map(([e])=>e)}return{namespace:e.namespace,types:n,dependencies:r,selfRefTypes:i,selfRefFields:a,selfRefKeys:o,requiredFields:s,omitFields:c}})}async function loadSeedContext(e={}){let{config:t,plugins:n,application:r,namespaces:i}=await loadApplicationNamespaces({configPath:e.configPath});sn({tailorDBServices:r.tailorDBServices});let a=resolvePluginConfig(n,Fn);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?Pn(o):void 0,c=s?{idpNamespace:s.idpNamespace,seedScriptCode:An(s.idpNamespace),listScriptCode:jn(s.idpNamespace),truncateScriptCode:Mn(s.idpNamespace)}:null;return{config:t,distPath:V.resolve(a.distPath),machineUserName:a.machineUserName,namespaces:buildSeedNamespaceConfigs(i),idpUser:c}}async function resolveTableNamespaces(e){let t=new Map;for(let n of e.tableNames){let e=n.toLowerCase(),r=t.get(e);if(r){r.push(n);continue}t.set(e,[n])}let n=new Set(e.tableNames),r=new Map;for(let i of e.namespaces){if(n.size===0)break;try{let{tailordbTypes:a}=await e.client.listTailorDBTypes({workspaceId:e.workspaceId,namespaceName:i});for(let e of a){let a=t.get(e.name.toLowerCase());if(a)for(let e of a)r.has(e)||(r.set(e,i),n.delete(e))}}catch{continue}}return r}async function truncateSingleType(e,t){await t.truncateTailorDBType({workspaceId:e.workspaceId,namespaceName:e.namespaceName,tailordbTypeName:e.tableName}),M.success(`Truncated table "${e.tableName}" in namespace "${e.namespaceName}"`)}async function truncateNamespace(e,t,n){await n.truncateTailorDBTypes({workspaceId:e,namespaceName:t}),M.success(`Truncated all tables in namespace "${t}"`)}async function truncate(e){return 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,a=!!e.all,o=[a,i,r].filter(Boolean).length;if(o===0)throw R({code:`TRUNCATE_TARGET_REQUIRED`,message:`Please specify one of: --all, --namespace <name>, or table names`,command:`tailordb truncate`});if(o>1)throw R({code:`TRUNCATE_OPTIONS_CONFLICT`,message:`Options --all, --namespace, and table names are mutually exclusive. Please specify only one.`,command:`tailordb truncate`});let{config:s}=await loadConfig(e.configPath),c=extractOwnedNamespaces(s);if(a){if(c.length===0){M.warn(`No namespaces found in config file.`);return}if(!e.yes){let e=c.join(`, `);if(!await X.confirm({message:`This will truncate ALL tables in the following owned namespaces (external namespaces are excluded): ${e}. Continue?`,default:!1})){M.info(`Truncate cancelled.`);return}}for(let e of c)await truncateNamespace(n,e,t);M.success(`Truncated all tables in all owned namespaces`);return}if(i){let r=k(e.namespace,`namespace option missing`);if(!c.includes(r)){let e=s.db?.[r];throw e&&`external`in e?R({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.`}):R({code:`TAILORDB_NAMESPACE_NOT_FOUND`,message:`Namespace "${r}" not found in config. Available owned namespaces (external namespaces are excluded): ${c.join(`, `)}`})}if(!e.yes&&!await X.confirm({message:`This will truncate ALL tables in namespace "${r}". Continue?`,default:!1})){M.info(`Truncate cancelled.`);return}await truncateNamespace(n,r,t);return}if(r){let r=k(e.tables,`tables option missing`),i=await resolveTableNamespaces({workspaceId:n,namespaces:c,tableNames:r,client:t}),a=r.filter(e=>!i.has(e));if(a.length>0)throw R({code:`TAILORDB_TABLE_NOT_FOUND`,message:`The following tables were not found in any namespace: ${a.join(`, `)}`});if(!e.yes){let e=r.join(`, `);if(!await X.confirm({message:`This will truncate the following tables: ${e}. Continue?`,default:!1})){M.info(`Truncate cancelled.`);return}}for(let e of r){let r=i.get(e);r&&await truncateSingleType({workspaceId:n,namespaceName:r,tableName:e},t)}}}const fc=Y({name:`truncate`,description:`Truncate (delete all records from) TailorDB tables.`,args:H.strictObject({...$r,...ei,tables:B(H.string().array().optional(),{positional:!0,description:`Table names to truncate`}),all:B(H.boolean().default(!1),{alias:`a`,description:`Truncate all tables in all owned namespaces (excludes external namespaces)`}),namespace:B(H.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;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=toPageDirection(e?.order);return(await jt(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 pc=Y({name:`list`,description:`List all workflows in the workspace.`,args:H.strictObject({...J,...paginationArgs()}),run:async e=>{let t=M.jsonMode,n=await listWorkflows({workspaceId:e[`workspace-id`],profile:e.profile,order:e.order,limit:e.limit});n.length===0&&(M.info(`No workflows found.`),!t)||M.out(n)}});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 K){if(t.code===G.NotFound)throw R({code:`WORKFLOW_EXECUTION_NOT_FOUND`,message:`Execution '${e.executionId}' not found.`,cause:t});if(t.code===G.FailedPrecondition)throw R({code:`WORKFLOW_EXECUTION_NOT_RESUMABLE`,message:`Execution '${e.executionId}' is not in a resumable state.`,cause:t})}throw t}}const mc=Y({name:`resume`,description:`Resume a failed or pending workflow execution.`,args:H.strictObject({...J,"execution-id":B(H.string(),{positional:!0,description:`Failed execution ID`}),...xs}),run:async e=>{let t=M.jsonMode||e.json,{executionId:n,wait:r}=await resumeWorkflow({executionId:e.executionId,workspaceId:e[`workspace-id`],profile:e.profile,interval:parseDuration(e.interval)});if(t||M.info(`Execution ID: ${n}`,{mode:`stream`}),e.wait){let i=await r({showProgress:!t,timeout:parseDuration(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});M.out({...i,jobDetails:t.jobDetails})}else M.out(i);let a=getWorkflowWaitFailure(i,e.until);if(a)throw a}else M.out({executionId:n})}});async function waitWorkflowExecution(e){return await waitForWorkflowExecutionById({...e,showProgress:e.showProgress??!M.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 hc=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:H.strictObject({...J,"execution-id":B(H.string(),{positional:!0,description:`Execution ID`}),...bs}),run:async e=>{let t=M.jsonMode||e.json,n=await waitWorkflowExecution({executionId:e.executionId,workspaceId:e[`workspace-id`],profile:e.profile,interval:parseDuration(e.interval),timeout:parseDuration(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}):M.out(r);let i=getWorkflowWaitFailure(n,e.until);if(i)throw i}}),statusToString=e=>{switch(e){case d.OK:return`ok`;case d.COMPOSITION_ERROR:return`composition_error`;default:return`unknown`}},attemptStatusToString=e=>{switch(e){case m.SUCCEEDED:return`success`;case m.FAILED:return`failure`;default:return`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??``}},gc=H.object({workspaceId:H.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:H.string().optional(),name:H.string().min(1,{message:`name is required`})});async function loadOptions$9(e){let t=parseOptions(gc,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 _c=Y({name:`health`,description:`Check application schema health`,args:H.strictObject({...J,name:B(H.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)};M.out(n)}}),vc=H.object({workspaceId:H.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:H.string().optional(),order:Jr.optional(),limit:H.coerce.number().int().nonnegative().optional()});async function loadOptions$8(e){let t=parseOptions(vc,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=toPageDirection(r);return(await jt(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 yc=Y({name:`list`,description:`List applications in a workspace`,args:H.strictObject({...J,...paginationArgs()}),run:async e=>{let t=M.jsonMode,n=await listApps({workspaceId:e[`workspace-id`],profile:e.profile,order:e.order,limit:e.limit}),r=t?n:n.map(({updatedAt:e,createdAt:t,...n})=>({...n,createdAt:humanizeRelativeTime(t)}));M.out(r)}});async function removeProfilesForWorkspaces(e){let t=await readPlatformConfig(),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 writePlatformConfig(t),n}const bc=H.object({workspaceId:H.uuid({message:`workspace-id must be a valid UUID`})});async function loadOptions$7(e){let t=parseOptions(bc,e),n=await loadAccessToken();return{client:await P(n),workspaceId:t.workspaceId}}async function deleteWorkspace(e){let{client:t,workspaceId:n}=await loadOptions$7(e);await t.deleteWorkspace({workspaceId:n})}const xc=Y({name:`delete`,description:`Delete a Tailor Platform workspace.`,args:H.strictObject({"workspace-id":B(H.string(),{alias:`w`,description:`Workspace ID`}),...ei}),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 K&&e.code===G.NotFound?R({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}):`});if(e!==a&&e!==o){M.info(`Workspace deletion cancelled.`);return}}try{await t.deleteWorkspace({workspaceId:n})}catch(e){throw await removeProfilesForWorkspaces(new Set([n])),e}let s=await removeProfilesForWorkspaces(new Set([n]));s.length>0?M.success(`Workspace "${o}" and ${s.length} associated profile(s) deleted successfully.`):M.success(`Workspace "${o}" deleted successfully.`)}}),Sc=H.object({workspaceId:H.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:H.string().optional()});async function loadOptions$6(e){let t=parseOptions(Sc,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 R({code:`WORKSPACE_NOT_FOUND`,message:`Workspace "${n}" not found.`});let[i,a]=await Promise.all([workspaceDetailsWithFolderName(t,r.workspace),fetchWorkspaceExpiry(t,n,new Date)]);return{...i,expiresAt:reportedExpiry(a)}}const Cc=Y({name:`get`,description:`Show detailed information about a workspace`,args:H.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)};M.out(n,{display:{name:us,folderName:null}})}}),wc=H.object({workspaceId:H.uuid({message:`workspace-id must be a valid UUID`})});async function loadOptions$5(e){let t=parseOptions(wc,e),n=await loadAccessToken();return{client:await P(n),workspaceId:t.workspaceId}}async function restoreWorkspace(e){let{client:t,workspaceId:n}=await loadOptions$5(e);await t.restoreWorkspace({workspaceId:n})}const Tc=Y({name:`restore`,description:`Restore a deleted workspace`,args:H.strictObject({"workspace-id":B(H.string(),{alias:`w`,description:`Workspace ID`}),...ei}),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):`})!==`yes`){M.info(`Workspace restoration cancelled.`);return}await t.restoreWorkspace({workspaceId:n}),M.success(`Workspace "${n}" restored successfully.`)}}),roleToString=e=>{switch(e){case Xe.ADMIN:return`admin`;case Xe.EDITOR:return`editor`;case Xe.VIEWER:return`viewer`;default:return`unknown`}},stringToRole=e=>{switch(e.toLowerCase()){case`admin`:return Xe.ADMIN;case`editor`:return Xe.EDITOR;case`viewer`:return Xe.VIEWER;default:throw R({code:`WORKSPACE_ROLE_INVALID`,message:`Invalid role: ${e}. Valid roles: admin, editor, viewer`})}},userInfo=e=>({userId:e.platformUser?.userId??``,email:e.platformUser?.email??``,role:roleToString(e.role)}),Ec=[`admin`,`editor`,`viewer`],Dc=H.object({workspaceId:H.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:H.string().optional(),email:H.email({message:`email must be a valid email address`}),role:H.enum(Ec,{message:`role must be one of: ${Ec.join(`, `)}`})});async function loadOptions$4(e){let t=parseOptions(Dc,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){let{client:t,workspaceId:n,email:r,role:i}=await loadOptions$4(e);await t.inviteWorkspacePlatformUser({workspaceId:n,email:r,role:i})}const Oc=Y({name:`invite`,description:`Invite a user to a workspace`,args:H.strictObject({...J,email:B(H.email(),{description:`Email address of the user to invite`}),role:B(H.enum(Ec),{description:`Role to assign (${Ec.join(`, `)})`,alias:`r`})}),run:async e=>{await assertWritable({profile:e.profile}),await inviteUser({workspaceId:e[`workspace-id`],profile:e.profile,email:e.email,role:e.role}),M.success(`User "${e.email}" invited successfully with role "${e.role}".`)}}),kc=H.object({workspaceId:H.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:H.string().optional(),order:Jr.optional(),limit:H.coerce.number().int().nonnegative().optional()});async function loadOptions$3(e){let t=parseOptions(kc,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=toPageDirection(r);return(await jt(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 Ac=Y({name:`list`,description:`List users in a workspace`,args:H.strictObject({...J,...paginationArgs()}),run:async e=>{let t=await listUsers({workspaceId:e[`workspace-id`],profile:e.profile,order:e.order,limit:e.limit});M.out(t)}}),jc=H.object({workspaceId:H.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:H.string().optional(),email:H.email({message:`email must be a valid email address`})});async function loadOptions$2(e){let t=parseOptions(jc,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){let{client:t,workspaceId:n,email:r}=await loadOptions$2(e);await t.removeWorkspacePlatformUser({workspaceId:n,email:r})}const Mc=Y({name:`remove`,description:`Remove a user from a workspace`,args:H.strictObject({...J,email:B(H.email(),{description:`Email address of the user to remove`}),...ei}),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):`})!==`yes`){M.info(`User removal cancelled.`);return}await removeUser({workspaceId:e[`workspace-id`],profile:e.profile,email:e.email}),M.success(`User "${e.email}" removed from workspace.`)}}),Nc=H.object({workspaceId:H.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:H.string().optional(),email:H.email({message:`email must be a valid email address`}),role:H.enum(Ec,{message:`role must be one of: ${Ec.join(`, `)}`})});async function loadOptions$1(e){let t=parseOptions(Nc,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){let{client:t,workspaceId:n,email:r,role:i}=await loadOptions$1(e);await t.updateWorkspacePlatformUser({workspaceId:n,email:r,role:i})}const Pc=Y({name:`update`,description:`Update a user's role in a workspace`,args:H.strictObject({...J,email:B(H.email(),{description:`Email address of the user to update`}),role:B(H.enum(Ec),{description:`New role to assign (${Ec.join(`, `)})`,alias:`r`})}),run:async e=>{await assertWritable({profile:e.profile}),await updateUser({workspaceId:e[`workspace-id`],profile:e.profile,email:e.email,role:e.role}),M.success(`User "${e.email}" updated to role "${e.role}".`)}});function createSqlEntry(){return I`
|
|
851
|
+
`}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=V.resolve($t(),`seed`);U.mkdirSync(i,{recursive:!0});let a=V.join(i,t);U.writeFileSync(a,n);let o;try{o=await Yn(r)}catch{o=void 0}let s=wt({tsconfig:o}),c=await Or.build({plugins:[ht(a,r),Ut(),Et],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}function chunkSeedData(e){let{data:t,order:n,codeByteSize:r,maxMessageSize:i=3670016}=e,a=i-r-1024;if(a<=0)throw Error(`Code size (${r} bytes) exceeds the message size limit (${i} bytes). No space left for seed data.`);let o=n.filter(e=>(t[e]?.length??0)>0);if(o.length===0)return[];if(byteSize(JSON.stringify({data:t,order:n}))<=a)return[{data:t,order:n,index:0,total:1}];let s=[],c={},l=[];for(let e of o){let n=k(t[e],`seed data missing for type: ${e}`);if(l.length>0){let t={...c,[e]:n},r=[...l,e];byteSize(JSON.stringify({data:t,order:r}))>a&&(s.push({data:c,order:l,index:s.length}),c={},l=[])}if(byteSize(JSON.stringify({data:{[e]:n},order:[e]}))<=a){c[e]=n,l.push(e);continue}l.length>0&&(s.push({data:c,order:l,index:s.length}),c={},l=[]);let r=[];for(let t of n){if(byteSize(JSON.stringify({data:{[e]:[t]},order:[e]}))>a){let n=byteSize(JSON.stringify(t));throw Error(`A single record in table "${e}" (${n} bytes) exceeds the message size budget (${a} bytes). Consider increasing maxMessageSize or reducing the record size.`)}let n=[...r,t],i={...c,[e]:n},o=l.includes(e)?l:[...l,e];byteSize(JSON.stringify({data:i,order:o}))>a&&r.length>0?(c[e]=r,l.includes(e)||l.push(e),s.push({data:c,order:l,index:s.length}),c={},l=[],r=[t]):r=n}r.length>0&&(c[e]=r,l.includes(e)||l.push(e))}l.length>0&&s.push({data:c,order:l,index:s.length});let u=s.length;return s.map(e=>({...e,total:u}))}function byteSize(e){return new TextEncoder().encode(e).length}function processSeedTypeInfo(e,t){let n=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))}return{name:e.name,namespace:t,dependencies:Array.from(n),selfRefFields:r,selfRefKeys:i,dataFile:`data/${e.name}.jsonl`}}function collectRelationTargetKeys(e){let t=new Map;for(let n of e)for(let e of Object.values(n.tables))for(let n of Object.values(e.fields)){let e=n.relation?.targetType??n.config.foreignKeyType,r=n.relation?.key??n.config.foreignKeyField;if(!e||!r)continue;let i=t.get(e)??new Set;i.add(r),t.set(e,i)}return t}function buildSeedNamespaceConfigs(e){let t=collectRelationTargetKeys(e);return e.map(e=>{let n=[],r={},i=[],a={},o={},s={},c={};for(let[l,u]of Object.entries(e.tables)){let d=processSeedTypeInfo(u,e.namespace);n.push(d.name),r[d.name]=d.dependencies,a[d.name]=d.selfRefFields,o[d.name]=d.selfRefKeys,d.selfRefFields.length>0&&i.push(d.name);let f=k(e.sourceInfo.get(l),`source info missing for table: ${l}`),p=Fn(u,f),m=t.get(d.name);c[d.name]=m?p.omitFields.filter(e=>!m.has(e)):p.omitFields,s[d.name]=Object.entries(u.fields).filter(([e,t])=>t.config.required!==!1&&!p.optionalFields.includes(e)&&!p.omitFields.includes(e)).map(([e])=>e)}return{namespace:e.namespace,types:n,dependencies:r,selfRefTypes:i,selfRefFields:a,selfRefKeys:o,requiredFields:s,omitFields:c}})}async function loadSeedContext(e={}){let{config:t,plugins:n,application:r,namespaces:i}=await loadApplicationNamespaces({configPath:e.configPath});cn({tailorDBServices:r.tailorDBServices});let a=resolvePluginConfig(n,Ln);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?In(o):void 0,c=s?{idpNamespace:s.idpNamespace,seedScriptCode:Mn(s.idpNamespace),listScriptCode:Nn(s.idpNamespace),truncateScriptCode:Pn(s.idpNamespace)}:null;return{config:t,distPath:V.resolve(a.distPath),machineUserName:a.machineUserName,namespaces:buildSeedNamespaceConfigs(i),idpUser:c}}async function resolveTableNamespaces(e){let t=new Map;for(let n of e.tableNames){let e=n.toLowerCase(),r=t.get(e);if(r){r.push(n);continue}t.set(e,[n])}let n=new Set(e.tableNames),r=new Map;for(let i of e.namespaces){if(n.size===0)break;try{let{tailordbTypes:a}=await e.client.listTailorDBTypes({workspaceId:e.workspaceId,namespaceName:i});for(let e of a){let a=t.get(e.name.toLowerCase());if(a)for(let e of a)r.has(e)||(r.set(e,i),n.delete(e))}}catch{continue}}return r}async function truncateSingleType(e,t){await t.truncateTailorDBType({workspaceId:e.workspaceId,namespaceName:e.namespaceName,tailordbTypeName:e.tableName}),M.success(`Truncated table "${e.tableName}" in namespace "${e.namespaceName}"`)}async function truncateNamespace(e,t,n){await n.truncateTailorDBTypes({workspaceId:e,namespaceName:t}),M.success(`Truncated all tables in namespace "${t}"`)}async function truncate(e){return 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,a=!!e.all,o=[a,i,r].filter(Boolean).length;if(o===0)throw R({code:`TRUNCATE_TARGET_REQUIRED`,message:`Please specify one of: --all, --namespace <name>, or table names`,command:`tailordb truncate`});if(o>1)throw R({code:`TRUNCATE_OPTIONS_CONFLICT`,message:`Options --all, --namespace, and table names are mutually exclusive. Please specify only one.`,command:`tailordb truncate`});let{config:s}=await loadConfig(e.configPath),c=extractOwnedNamespaces(s);if(a){if(c.length===0){M.warn(`No namespaces found in config file.`);return}if(!e.yes){let e=c.join(`, `);if(!await X.confirm({message:`This will truncate ALL tables in the following owned namespaces (external namespaces are excluded): ${e}. Continue?`,default:!1})){M.info(`Truncate cancelled.`);return}}for(let e of c)await truncateNamespace(n,e,t);M.success(`Truncated all tables in all owned namespaces`);return}if(i){let r=k(e.namespace,`namespace option missing`);if(!c.includes(r)){let e=s.db?.[r];throw e&&`external`in e?R({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.`}):R({code:`TAILORDB_NAMESPACE_NOT_FOUND`,message:`Namespace "${r}" not found in config. Available owned namespaces (external namespaces are excluded): ${c.join(`, `)}`})}if(!e.yes&&!await X.confirm({message:`This will truncate ALL tables in namespace "${r}". Continue?`,default:!1})){M.info(`Truncate cancelled.`);return}await truncateNamespace(n,r,t);return}if(r){let r=k(e.tables,`tables option missing`),i=await resolveTableNamespaces({workspaceId:n,namespaces:c,tableNames:r,client:t}),a=r.filter(e=>!i.has(e));if(a.length>0)throw R({code:`TAILORDB_TABLE_NOT_FOUND`,message:`The following tables were not found in any namespace: ${a.join(`, `)}`});if(!e.yes){let e=r.join(`, `);if(!await X.confirm({message:`This will truncate the following tables: ${e}. Continue?`,default:!1})){M.info(`Truncate cancelled.`);return}}for(let e of r){let r=i.get(e);r&&await truncateSingleType({workspaceId:n,namespaceName:r,tableName:e},t)}}}const yc=Y({name:`truncate`,description:`Truncate (delete all records from) TailorDB tables.`,args:H.strictObject({...ai,...oi,tables:B(H.string().array().optional(),{positional:!0,description:`Table names to truncate`}),all:B(H.boolean().default(!1),{alias:`a`,description:`Truncate all tables in all owned namespaces (excludes external namespaces)`}),namespace:B(H.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;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=toPageDirection(e?.order);return(await Ct(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 bc=Y({name:`list`,description:`List all workflows in the workspace.`,args:H.strictObject({...J,...paginationArgs()}),run:async e=>{let t=M.jsonMode,n=await listWorkflows({workspaceId:e[`workspace-id`],profile:e.profile,order:e.order,limit:e.limit});n.length===0&&(M.info(`No workflows found.`),!t)||M.out(n)}});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 K){if(t.code===G.NotFound)throw R({code:`WORKFLOW_EXECUTION_NOT_FOUND`,message:`Execution '${e.executionId}' not found.`,cause:t});if(t.code===G.FailedPrecondition)throw R({code:`WORKFLOW_EXECUTION_NOT_RESUMABLE`,message:`Execution '${e.executionId}' is not in a resumable state.`,cause:t})}throw t}}const xc=Y({name:`resume`,description:`Resume a failed or pending workflow execution.`,args:H.strictObject({...J,"execution-id":B(H.string(),{positional:!0,description:`Failed execution ID`}),...Os}),run:async e=>{let t=M.jsonMode||e.json,{executionId:n,wait:r}=await resumeWorkflow({executionId:e.executionId,workspaceId:e[`workspace-id`],profile:e.profile,interval:parseDuration(e.interval)});if(t||M.info(`Execution ID: ${n}`,{mode:`stream`}),e.wait){let i=await r({showProgress:!t,timeout:parseDuration(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});M.out({...i,jobDetails:t.jobDetails})}else M.out(i);let a=getWorkflowWaitFailure(i,e.until);if(a)throw a}else M.out({executionId:n})}});async function waitWorkflowExecution(e){return await waitForWorkflowExecutionById({...e,showProgress:e.showProgress??!M.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 Sc=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:H.strictObject({...J,"execution-id":B(H.string(),{positional:!0,description:`Execution ID`}),...Ds}),run:async e=>{let t=M.jsonMode||e.json,n=await waitWorkflowExecution({executionId:e.executionId,workspaceId:e[`workspace-id`],profile:e.profile,interval:parseDuration(e.interval),timeout:parseDuration(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}):M.out(r);let i=getWorkflowWaitFailure(n,e.until);if(i)throw i}}),statusToString=e=>{switch(e){case d.OK:return`ok`;case d.COMPOSITION_ERROR:return`composition_error`;default:return`unknown`}},attemptStatusToString=e=>{switch(e){case m.SUCCEEDED:return`success`;case m.FAILED:return`failure`;default:return`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??``}},Cc=H.object({workspaceId:H.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:H.string().optional(),name:H.string().min(1,{message:`name is required`})});async function loadOptions$9(e){let t=parseOptions(Cc,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 wc=Y({name:`health`,description:`Check application schema health`,args:H.strictObject({...J,name:B(H.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)};M.out(n)}}),Tc=H.object({workspaceId:H.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:H.string().optional(),order:ei.optional(),limit:H.coerce.number().int().nonnegative().optional()});async function loadOptions$8(e){let t=parseOptions(Tc,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=toPageDirection(r);return(await Ct(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 Ec=Y({name:`list`,description:`List applications in a workspace`,args:H.strictObject({...J,...paginationArgs()}),run:async e=>{let t=M.jsonMode,n=await listApps({workspaceId:e[`workspace-id`],profile:e.profile,order:e.order,limit:e.limit}),r=t?n:n.map(({updatedAt:e,createdAt:t,...n})=>({...n,createdAt:humanizeRelativeTime(t)}));M.out(r)}});async function removeProfilesForWorkspaces(e){let t=await readPlatformConfig(),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 writePlatformConfig(t),n}const Dc=H.object({workspaceId:H.uuid({message:`workspace-id must be a valid UUID`})});async function loadOptions$7(e){let t=parseOptions(Dc,e),n=await loadAccessToken();return{client:await F(n),workspaceId:t.workspaceId}}async function deleteWorkspace(e){let{client:t,workspaceId:n}=await loadOptions$7(e);await t.deleteWorkspace({workspaceId:n})}const Oc=Y({name:`delete`,description:`Delete a Tailor Platform workspace.`,args:H.strictObject({"workspace-id":B(H.string(),{alias:`w`,description:`Workspace ID`}),...oi}),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 K&&e.code===G.NotFound?R({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}):`});if(e!==a&&e!==o){M.info(`Workspace deletion cancelled.`);return}}try{await t.deleteWorkspace({workspaceId:n})}catch(e){throw await removeProfilesForWorkspaces(new Set([n])),e}let s=await removeProfilesForWorkspaces(new Set([n]));s.length>0?M.success(`Workspace "${o}" and ${s.length} associated profile(s) deleted successfully.`):M.success(`Workspace "${o}" deleted successfully.`)}}),kc=H.object({workspaceId:H.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:H.string().optional()});async function loadOptions$6(e){let t=parseOptions(kc,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 R({code:`WORKSPACE_NOT_FOUND`,message:`Workspace "${n}" not found.`});let[i,a]=await Promise.all([workspaceDetailsWithFolderName(t,r.workspace),fetchWorkspaceExpiry(t,n,new Date)]);return{...i,expiresAt:reportedExpiry(a)}}const Ac=Y({name:`get`,description:`Show detailed information about a workspace`,args:H.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)};M.out(n,{display:{name:_s,folderName:null}})}}),jc=H.object({workspaceId:H.uuid({message:`workspace-id must be a valid UUID`})});async function loadOptions$5(e){let t=parseOptions(jc,e),n=await loadAccessToken();return{client:await F(n),workspaceId:t.workspaceId}}async function restoreWorkspace(e){let{client:t,workspaceId:n}=await loadOptions$5(e);await t.restoreWorkspace({workspaceId:n})}const Mc=Y({name:`restore`,description:`Restore a deleted workspace`,args:H.strictObject({"workspace-id":B(H.string(),{alias:`w`,description:`Workspace ID`}),...oi}),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):`})!==`yes`){M.info(`Workspace restoration cancelled.`);return}await t.restoreWorkspace({workspaceId:n}),M.success(`Workspace "${n}" restored successfully.`)}}),roleToString=e=>{switch(e){case Xe.ADMIN:return`admin`;case Xe.EDITOR:return`editor`;case Xe.VIEWER:return`viewer`;default:return`unknown`}},stringToRole=e=>{switch(e.toLowerCase()){case`admin`:return Xe.ADMIN;case`editor`:return Xe.EDITOR;case`viewer`:return Xe.VIEWER;default:throw R({code:`WORKSPACE_ROLE_INVALID`,message:`Invalid role: ${e}. Valid roles: admin, editor, viewer`})}},userInfo=e=>({userId:e.platformUser?.userId??``,email:e.platformUser?.email??``,role:roleToString(e.role)}),Nc=[`admin`,`editor`,`viewer`],Pc=H.object({workspaceId:H.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:H.string().optional(),email:H.email({message:`email must be a valid email address`}),role:H.enum(Nc,{message:`role must be one of: ${Nc.join(`, `)}`})});async function loadOptions$4(e){let t=parseOptions(Pc,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){let{client:t,workspaceId:n,email:r,role:i}=await loadOptions$4(e);await t.inviteWorkspacePlatformUser({workspaceId:n,email:r,role:i})}const Fc=Y({name:`invite`,description:`Invite a user to a workspace`,args:H.strictObject({...J,email:B(H.email(),{description:`Email address of the user to invite`}),role:B(H.enum(Nc),{description:`Role to assign (${Nc.join(`, `)})`,alias:`r`})}),run:async e=>{await assertWritable({profile:e.profile}),await inviteUser({workspaceId:e[`workspace-id`],profile:e.profile,email:e.email,role:e.role}),M.success(`User "${e.email}" invited successfully with role "${e.role}".`)}}),Ic=H.object({workspaceId:H.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:H.string().optional(),order:ei.optional(),limit:H.coerce.number().int().nonnegative().optional()});async function loadOptions$3(e){let t=parseOptions(Ic,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=toPageDirection(r);return(await Ct(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 Lc=Y({name:`list`,description:`List users in a workspace`,args:H.strictObject({...J,...paginationArgs()}),run:async e=>{let t=await listUsers({workspaceId:e[`workspace-id`],profile:e.profile,order:e.order,limit:e.limit});M.out(t)}}),Rc=H.object({workspaceId:H.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:H.string().optional(),email:H.email({message:`email must be a valid email address`})});async function loadOptions$2(e){let t=parseOptions(Rc,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){let{client:t,workspaceId:n,email:r}=await loadOptions$2(e);await t.removeWorkspacePlatformUser({workspaceId:n,email:r})}const zc=Y({name:`remove`,description:`Remove a user from a workspace`,args:H.strictObject({...J,email:B(H.email(),{description:`Email address of the user to remove`}),...oi}),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):`})!==`yes`){M.info(`User removal cancelled.`);return}await removeUser({workspaceId:e[`workspace-id`],profile:e.profile,email:e.email}),M.success(`User "${e.email}" removed from workspace.`)}}),Bc=H.object({workspaceId:H.uuid({message:`workspace-id must be a valid UUID`}).optional(),profile:H.string().optional(),email:H.email({message:`email must be a valid email address`}),role:H.enum(Nc,{message:`role must be one of: ${Nc.join(`, `)}`})});async function loadOptions$1(e){let t=parseOptions(Bc,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){let{client:t,workspaceId:n,email:r,role:i}=await loadOptions$1(e);await t.updateWorkspacePlatformUser({workspaceId:n,email:r,role:i})}const Vc=Y({name:`update`,description:`Update a user's role in a workspace`,args:H.strictObject({...J,email:B(H.email(),{description:`Email address of the user to update`}),role:B(H.enum(Nc),{description:`New role to assign (${Nc.join(`, `)})`,alias:`r`})}),run:async e=>{await assertWritable({profile:e.profile}),await updateUser({workspaceId:e[`workspace-id`],profile:e.profile,email:e.email,role:e.role}),M.success(`User "${e.email}" updated to role "${e.role}".`)}});function createSqlEntry(){return I`
|
|
852
852
|
import { Kysely, sql, TailordbDialect } from "@tailor-platform/sdk/kysely";
|
|
853
853
|
|
|
854
854
|
type QueryInput = {
|
|
@@ -910,8 +910,8 @@ This is the baseline schema. Future changes will be tracked as diffs.`)}function
|
|
|
910
910
|
const json = await response.json();
|
|
911
911
|
return json;
|
|
912
912
|
}
|
|
913
|
-
`}async function bundleQueryScript(e,t){let n=V.resolve($t(),`query`);U.mkdirSync(n,{recursive:!0});let r=V.join(n,`query_${e}.entry.ts`),i=e===`sql`?createSqlEntry():createGqlEntry();U.writeFileSync(r,i);let a=await
|
|
914
|
-
`).at(0)?.trim();return R({code:`invalid_sql`,message:`SQL parse error.`,suggestion:e??`The SQL query contains unsupported syntax.`})}return e.error instanceof Error?e.error:Error(t)}function isGraphQLInputComplete(e){if(e.trim().length===0)return!1;try{return
|
|
915
|
-
`&&(r=!1);continue}if(i>0){if(c===`/`&&l===`*`){i+=1,s+=1;continue}c===`*`&&l===`/`&&(--i,s+=1);continue}if(a!=null){e.startsWith(a,s)&&(s+=a.length-1,a=null);continue}if(t){if(c===`'`&&l===`'`){s+=1;continue}c===`'`&&(t=!1);continue}if(n){if(c===`"`&&l===`"`){s+=1;continue}c===`"`&&(n=!1);continue}if(c===`-`&&l===`-`){r=!0,s+=1;continue}if(c===`/`&&l===`*`){i=1,s+=1;continue}if(c===`'`){o=!1,t=!0;continue}if(c===`"`){o=!1,n=!0;continue}if(c===`$`){let t=e.slice(s),n=t.match(/^\$[A-Za-z_][A-Za-z0-9_]*\$/)??t.match(/^\$\$/);if(n!=null){o=!1,a=n[0],s+=n[0].length-1;continue}}if(c===`;`){o=!0;continue}/\s/.test(c)||(o=!1)}return o&&!t&&!n&&i===0&&a==null}function extractTableNamesFromSql(e){let t;try{t=Vr(e)}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`SQL parse error: ${t}\nIf your table name is a reserved keyword (e.g. User), wrap it in double quotes: SELECT * FROM "User"`,{cause:e})}let n=new Set,r=Br(e=>({tableRef:t=>(n.add(t.name),e.super().tableRef(t),t)}));for(let e of t)r.statement(e);return[...n]}function collectAliasMap(e){let t=new Map;for(let n of e)if(n.type===`table`){let e=n.name.name,r=n.name.alias??e;t.set(r,e)}return t}function extractColumnTemplate(e){try{let t=Vr(e);for(let e of t){if(e.type!==`select`||!e.columns)continue;let t=collectAliasMap(e.from??[]),n=[],r=!1;for(let i of e.columns)if(i.expr.type===`ref`&&i.expr.name===`*`){if(r=!0,i.expr.table){let e=t.get(i.expr.table.name);n.push({type:`wildcard`,tableNames:e?[e]:[]})}else n.push({type:`wildcard`,tableNames:[...new Set(t.values())]})}else{let e=i.alias?.name??(i.expr.type===`ref`?i.expr.name:null);e&&n.push({type:`explicit`,name:e})}return r?n:null}return null}catch{return null}}async function loadTypeFieldOrder(e,t){let n=new Map,r=e.db?.[t];if(!r||!(`files`in r)||r.files.length===0)return n;let i=V.dirname(e.path),a=dn(r,i);return await Promise.all(a.map(async e=>{try{let t=await import(or(e).href);for(let e of Object.values(t)){let t=un.safeParse(fn(e));t.success&&n.set(t.data.name,Object.keys(t.data.fields))}}catch{}})),n}const Fc=H.enum([`sql`,`gql`]),Ic=H.object({workspaceId:H.string().optional(),profile:H.string().optional(),configPath:H.string().optional(),engine:Fc,machineUser:H.string().optional(),machineUserSource:H.enum([`option`,`env`]).optional()}),Lc=Ic.extend({query:H.string()});async function getNamespaceFromSqlQuery(e,t,n,r){if(r.length===0)throw Error(`No namespaces found in configuration.`);if(r.length===1)return k(r[0],`namespace missing`);let i=extractTableNamesFromSql(t);if(i.length===0)throw Error(`Could not infer namespace from query. Detected namespaces: ${r.join(`, `)}.`);let a=await resolveTableNamespaces({workspaceId:e,namespaces:r,tableNames:i,client:n}),o=i.filter(e=>!a.has(e));if(o.length>0)throw Error(`Could not find namespace for tables in query: ${o.join(`, `)}.`);let s=new Set(a.values());if(s.size===1)return k([...s][0],`namespace from types missing`);throw Error(`Query references tables from multiple namespaces: ${[...s].join(`, `)}.`)}async function loadOptions(e){let t=parseOptions(Ic,e),n=await loadMachineUserName({machineUser:t.machineUser,machineUserSource:t.machineUserSource,profile:t.profile});if(!n)throw Error(`Machine user is required. Specify --machine-user, set TAILOR_PLATFORM_MACHINE_USER_NAME, or set a profile default with 'tailor profile update <profile> --machine-user <name>'.`);let r=await loadAccessToken({profile:t.profile}),i=await P(r),a=await loadWorkspaceId({workspaceId:t.workspaceId,profile:t.profile}),{config:o}=await loadConfig(e.configPath),s=extractAllNamespaces(o),{application:c}=await i.getApplication({workspaceId:a,applicationName:o.name});if(!c?.authNamespace)throw Error(`Application ${o.name} does not have an auth configuration.`);let{machineUser:l}=await i.getAuthMachineUser({workspaceId:a,authNamespace:c.authNamespace,name:n});if(!l)throw Error(`Machine user ${n} not found.`);return{engine:t.engine,client:i,workspaceId:a,config:o,application:c,machineUserResource:l,namespaces:s}}async function sqlQuery(e,t,n){let r=splitSqlStatements(n.query),i=await executeScript({client:e,workspaceId:n.workspaceId,name:`query-sql-${n.namespace}.js`,code:n.bundledCode,arg:{namespace:n.namespace,queries:r},invoker:t});if(!i.success)throw Error(i.error);return{engine:`sql`,namespace:n.namespace,query:n.query,result:parseExecutionResult(i.result)}}async function gqlQuery(e,t,n,r,i){let{access_token:a}=await kt(n.url,r.clientId,r.clientSecret),o=await executeScript({client:e,workspaceId:i.workspaceId,name:`query-gql.js`,code:i.bundledCode,arg:{endpoint:`${n.url}/query`,accessToken:a,query:i.query},invoker:t});if(!o.success)throw Error(o.error);return{engine:`gql`,query:i.query,result:parseExecutionResult(o.result)}}function parseExecutionResult(e){if(!e)return null;try{return JSON.parse(e)}catch{return e}}async function resolveQueryCommandInput(e){return e.query==null?e.file==null?e.edit?await resolveEditedQueryInput(e.engine):{mode:`repl`}:{mode:`query`,query:await q.readFile(e.file,`utf-8`)}:{mode:`query`,query:e.query}}async function resolveEditedQueryInput(e){if(!process.stdin.isTTY||!process.stdout.isTTY)throw Error(`Non-interactive terminals are not supported. Pass -q/--query or -f/--file to run a query.`);let t=getEditorCommand(),n=await q.mkdtemp(V.join(Tr(),`tailor-query-`)),r=e===`sql`?`sql`:`graphql`,i=V.join(n,`query.${r}`);try{await q.writeFile(i,``,`utf-8`);try{await openInEditor(i,t)}catch(e){throw Error(`Failed to open query editor "${t}": ${e instanceof Error?e.message:String(e)}`,{cause:e})}let e=await q.readFile(i,`utf-8`);return e.trim().length===0||e===``?{mode:`abort`}:{mode:`query`,query:e}}finally{await q.rm(n,{recursive:!0,force:!0})}}async function query(e){let t=parseOptions(Lc,e);return await(await prepareQueryExecutor(t))(t.query)}async function prepareQueryExecutor(e){let{client:t,workspaceId:n,config:r,application:i,machineUserResource:a,engine:o,namespaces:s}=await loadOptions(e),c=await bundleQueryScript(o,V.dirname(r.path)),l=Gn(Ie,{namespace:i.authNamespace,machineUserName:a.name});return async e=>{let u;try{switch(o){case`sql`:return u=await getNamespaceFromSqlQuery(n,e,t,s),reorderSqlColumns(await sqlQuery(t,l,{workspaceId:n,namespace:u,bundledCode:c,query:e}),r,u,e);case`gql`:return await gqlQuery(t,l,i,a,{workspaceId:n,bundledCode:c,query:e});default:throw Error(`Unsupported query engine: ${o}`)}}catch(e){throw mapQueryExecutionError({error:e,engine:o,namespace:u,machineUser:a.name})}}}function resolveReplCommand(e){let t=e.trim();return t.startsWith(`\\`)?t===`\\q`||t===`\\quit`?`quit`:t===`\\help`||t===`\\h`||t===`\\?`?`help`:t===`\\clear`||t===`\\c`?`clear`:`unknown`:null}function clearReplScreen(){process.stdout.write(`\x1Bc`)}function sanitizeHistoryScope(e){return e.replace(/[^a-zA-Z0-9._-]/g,`_`)}function getReplHistoryPath(e,t,n){if(!dr)return;let r=[t,n].filter(e=>!!e).map(sanitizeHistoryScope).join(`-`),i=e===`sql`?`sql`:`gql`,a=r?`-${r}`:``;return V.join(dr,`tailor-platform`,`query-history-${i}${a}.json`)}function createReplValidator(e){return t=>{let n=t.trim();if(n!==``&&resolveReplCommand(n)===null)return e===`sql`?isSqlInputComplete(t)?void 0:`SQL statement is incomplete (missing ';').`:isGraphQLInputComplete(t)?void 0:`GraphQL document is incomplete.`}}async function runRepl(e){if(!process.stdin.isTTY||!process.stdout.isTTY)throw Error(`Non-interactive terminals are not supported. Pass -q/--query or -f/--file to run a query.`);let t=await prepareQueryExecutor(e),n=getReplHistoryPath(e.engine,e.profile,e.workspaceId),r=createReplValidator(e.engine),{highlightSqlLine:i,highlightGraphqlLine:a,replTransform:o}=await import(`./repl-editor-BG1aDOfH.mjs`),s=e.engine===`sql`?i:a,c=zr({prefix:``,preferNewlineOnEnter:e.newlineOnEnter,validate:r,highlight:s,transform:o,theme:{submitRender:`preserve`},history:n?{filePath:n,maxEntries:100}:[],helpFooter:{items:[`submit`,`newline`],maxLines:1}});for(M.info(`Entering ${e.engine.toUpperCase()} REPL mode.`),M.info(`Type \\help for usage, \\q to quit.`);;){let[n,r]=await c(`${e.engine}> `);if(r?.kind===`cancel`){if(n.length===0)return;continue}if(r?.kind===`eof`)return;let i=n.trim();if(i===``)continue;let a=resolveReplCommand(i);if(a===`quit`)return;if(a===`help`){printReplHelp(e.engine);continue}if(a===`clear`){clearReplScreen();continue}if(a===`unknown`){M.warn(`Unknown command: ${i}`);continue}try{let n=await t(i);n.engine===`sql`?printSqlResult(n,{json:e.json}):printGqlResult(n,{json:e.json})}catch(e){if(xn(e)){M.log(e.format());continue}if(e instanceof Error){M.error(e.message);continue}M.error(String(e))}}}function printReplHelp(e){M.log(`REPL commands:`),M.log(` \\help, \\h, \\? Show this help`),M.log(` \\q, \\quit Exit REPL`),M.log(` \\clear, \\c Clear the screen`),M.log(``),M.log(`Key bindings (see footer for terminal-specific submit/newline keys):`),M.log(` Ctrl+J Insert newline (always available)`),M.log(` Ctrl+C Cancel current input`),M.log(` Ctrl+D Exit REPL (on empty input)`),M.log(` Ctrl+Z / Ctrl+Y Undo / Redo`),M.log(` Up/Down (first/last line) Navigate history`),M.log(``),M.log(`Editing aids:`),M.log(` Syntax highlighting Enabled for the current engine`),M.log(` ( [ { Auto-inserts the matching closing bracket`),M.log(` Enter after open bracket Adds one indent level and closes the block`),M.log(``),M.log(e===`sql`?`Input must end with ';' to submit.`:`Input must be a complete GraphQL document to submit.`)}async function querySql(e){let t=await query({...e,engine:`sql`});if(t.engine!==`sql`)throw Error(`Expected sql engine result but got: ${t.engine}`);return t}async function queryGql(e){let t=await query({...e,engine:`gql`});if(t.engine!==`gql`)throw Error(`Expected gql engine result but got: ${t.engine}`);return t}async function reorderSqlColumns(e,t,n,r){if(!isSQLExecutionResult(e.result)||e.result.rows.length===0)return e;let i=extractColumnTemplate(r);if(!i)return e;try{let r=buildExpectedColumnOrder(i,await loadTypeFieldOrder(t,n));if(r.length===0)return e;let a=e.result.rows.map(e=>reorderRowByTemplate(e,r));return{...e,result:{...e.result,rows:a}}}catch{return e}}const Rc=[`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(...Rc),n.push(...t.get(e)??[]);return n}function reorderRowByTemplate(e,t){let n={},r=new Set(Object.keys(e)),i=new Map;for(let e of r)i.set(e.toLowerCase(),e);for(let a of t){let t=i.get(a.toLowerCase());t!=null&&r.has(t)&&(n[t]=e[t],r.delete(t),i.delete(a.toLowerCase()))}for(let t of r)n[t]=e[t];return n}const zc=Y({name:`query`,description:`Run SQL/GraphQL query.`,args:H.strictObject({...$r,engine:B(Fc,{description:`Query engine (sql or gql)`}),query:B(H.string().optional(),{alias:`q`,description:`Query string to execute directly; omit to start REPL mode`}),file:B(H.string().optional(),{alias:`f`,description:`Read query string from file; omit to start REPL mode`}),edit:B(H.boolean().default(!1),{description:`Open a temporary file in your editor; omit to start REPL mode`}),"machine-user":B(H.string().optional(),{alias:`m`,description:`Machine user name for query execution. Falls back to the active profile's default machine user.`,env:`TAILOR_PLATFORM_MACHINE_USER_NAME`}),"newline-on-enter":B(H.boolean().optional(),{description:`REPL: when true, Enter inserts a newline and Shift+Enter submits. Use --no-newline-on-enter to swap.`})}).superRefine((e,t)=>{e.query!=null&&e.file!=null&&t.addIssue({code:`custom`,path:[`file`],message:`Pass either -q/--query or -f/--file, not both.`}),e.edit&&e.query!=null&&t.addIssue({code:`custom`,path:[`edit`],message:`Pass only one of --edit, -q/--query, or -f/--file.`}),e.edit&&e.file!=null&&t.addIssue({code:`custom`,path:[`edit`],message:`Pass only one of --edit, -q/--query, or -f/--file.`})}),run:async e=>{let t=await resolveQueryCommandInput({query:e.query,file:e.file,edit:e.edit,engine:e.engine}),n={workspaceId:e[`workspace-id`],profile:e.profile,configPath:e.config,engine:e.engine,machineUser:e[`machine-user`],machineUserSource:resolveMachineUserInputSource(e[`machine-user`])};if(t.mode===`abort`){M.info(`Editor closed without a query. Nothing was executed.`);return}if(t.mode===`repl`){let t=e[`newline-on-enter`]??ut(process.env.TAILOR_QUERY_NEWLINE_ON_ENTER)??!0;await runRepl({...n,json:e.json,newlineOnEnter:t});return}let r=t.query;if(e.engine===`sql`){printSqlResult(await querySql({...n,query:r}),{json:e.json});return}printGqlResult(await queryGql({...n,query:r}),{json:e.json})}});function isSQLExecutionResult(e){if(!e||typeof e!=`object`)return!1;let t=e;return Array.isArray(t.rows)&&typeof t.rowCount==`number`}function printSingleSqlResult(e,t={}){if(e.rows.length===0){if(t.json){M.out({results:[],rowCount:0});return}M.info(`No rows returned.`);return}if(t.json){M.out({results:e.rows,rowCount:e.rowCount});return}M.out(e.rows,{showNull:!0}),M.out(`rows: ${e.rowCount}`)}function splitSqlStatements(e){let t=Vr(e,{locationTracking:!0});return t.map((n,r)=>{let i=k(n._location,`SQL statement location missing`).start,a=t[r+1],o=a===void 0?e.length:k(a._location,`SQL statement location missing`).start;return e.substring(i,o)})}function isSQLExecutionResultArray(e){return Array.isArray(e)&&e.length>0&&e.every(isSQLExecutionResult)}function printSqlResult(e,t={}){if(isSQLExecutionResultArray(e.result)){if(t.json){M.out(e.result.map(e=>({results:e.rows,rowCount:e.rowCount})));return}let n=splitSqlStatements(e.query);for(let r=0;r<e.result.length;r++)r>0&&M.log(``),M.info(n[r]??`Statement ${r+1}`),printSingleSqlResult(k(e.result[r],`SQL result at index ${r} missing`),t);return}if(isSQLExecutionResult(e.result)){printSingleSqlResult(e.result,t);return}M.out({engine:e.engine,query:e.query,result:e.result})}function printGqlResult(e,t={}){if(t.json){M.out({result:e.result});return}M.out(JSON.stringify(e.result,null,2))}function escapeData(e){return e.replaceAll(`%`,`%25`).replaceAll(`\r`,`%0D`).replaceAll(`
|
|
916
|
-
`,`%0A`)}function escapeProperty(e){return escapeData(e).replaceAll(`:`,`%3A`).replaceAll(`,`,`%2C`)}function jsonRequestedInArgv(){let e=process.argv.slice(2),t=e.indexOf(`--`);return(t===-1?e:e.slice(0,t)).some(e=>{let t=e.indexOf(`=`),n=t===-1?e:e.slice(0,t);return n!==`--json`&&n!==`-j`?!1:t===-1||ut(e.slice(t+1))!==!1})}function annotationsEnabled(e){return e||jsonRequestedInArgv()||process.env.GITHUB_ACTIONS!==`true`?!1:ut(process.env.TAILOR_GITHUB_ACTIONS_ANNOTATIONS)!==!1}function formatAnnotation(e,t,n={}){let r=[];return n.title!==void 0&&r.push(`title=${escapeProperty(
|
|
917
|
-
//# sourceMappingURL=register-ts-hook-
|
|
913
|
+
`}async function bundleQueryScript(e,t){let n=V.resolve($t(),`query`);U.mkdirSync(n,{recursive:!0});let r=V.join(n,`query_${e}.entry.ts`),i=e===`sql`?createSqlEntry():createGqlEntry();U.writeFileSync(r,i);let a=await Tt(t),o=wt({tsconfig:a}),s=await Or.build({plugins:[ht(r,t),Ut(),Et],input:r,write:!1,output:{format:`esm`,sourcemap:!1,minify:!1,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 R({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 R({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(`
|
|
914
|
+
`).at(0)?.trim();return R({code:`invalid_sql`,message:`SQL parse error.`,suggestion:e??`The SQL query contains unsupported syntax.`})}return e.error instanceof Error?e.error:Error(t)}function isGraphQLInputComplete(e){if(e.trim().length===0)return!1;try{return Jr(e),!0}catch{return!1}}function isSqlInputComplete(e){let t=!1,n=!1,r=!1,i=0,a=null,o=!1;for(let s=0;s<e.length;s+=1){let c=k(e[s],`character at index ${s} missing`),l=e[s+1];if(r){c===`
|
|
915
|
+
`&&(r=!1);continue}if(i>0){if(c===`/`&&l===`*`){i+=1,s+=1;continue}c===`*`&&l===`/`&&(--i,s+=1);continue}if(a!=null){e.startsWith(a,s)&&(s+=a.length-1,a=null);continue}if(t){if(c===`'`&&l===`'`){s+=1;continue}c===`'`&&(t=!1);continue}if(n){if(c===`"`&&l===`"`){s+=1;continue}c===`"`&&(n=!1);continue}if(c===`-`&&l===`-`){r=!0,s+=1;continue}if(c===`/`&&l===`*`){i=1,s+=1;continue}if(c===`'`){o=!1,t=!0;continue}if(c===`"`){o=!1,n=!0;continue}if(c===`$`){let t=e.slice(s),n=t.match(/^\$[A-Za-z_][A-Za-z0-9_]*\$/)??t.match(/^\$\$/);if(n!=null){o=!1,a=n[0],s+=n[0].length-1;continue}}if(c===`;`){o=!0;continue}/\s/.test(c)||(o=!1)}return o&&!t&&!n&&i===0&&a==null}function extractTableNamesFromSql(e){let t;try{t=qr(e)}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`SQL parse error: ${t}\nIf your table name is a reserved keyword (e.g. User), wrap it in double quotes: SELECT * FROM "User"`,{cause:e})}let n=new Set,r=Kr(e=>({tableRef:t=>(n.add(t.name),e.super().tableRef(t),t)}));for(let e of t)r.statement(e);return[...n]}function collectAliasMap(e){let t=new Map;for(let n of e)if(n.type===`table`){let e=n.name.name,r=n.name.alias??e;t.set(r,e)}return t}function extractColumnTemplate(e){try{let t=qr(e);for(let e of t){if(e.type!==`select`||!e.columns)continue;let t=collectAliasMap(e.from??[]),n=[],r=!1;for(let i of e.columns)if(i.expr.type===`ref`&&i.expr.name===`*`){if(r=!0,i.expr.table){let e=t.get(i.expr.table.name);n.push({type:`wildcard`,tableNames:e?[e]:[]})}else n.push({type:`wildcard`,tableNames:[...new Set(t.values())]})}else{let e=i.alias?.name??(i.expr.type===`ref`?i.expr.name:null);e&&n.push({type:`explicit`,name:e})}return r?n:null}return null}catch{return null}}async function loadTypeFieldOrder(e,t){let n=new Map,r=e.db?.[t];if(!r||!(`files`in r)||r.files.length===0)return n;let i=V.dirname(e.path),a=pn(r,i);return await Promise.all(a.map(async e=>{try{let t=await import(fr(e).href);for(let e of Object.values(t)){let t=fn.safeParse(mn(e));t.success&&n.set(t.data.name,Object.keys(t.data.fields))}}catch{}})),n}const Hc=H.enum([`sql`,`gql`]),Uc=H.object({workspaceId:H.string().optional(),profile:H.string().optional(),configPath:H.string().optional(),engine:Hc,machineUser:H.string().optional(),machineUserSource:H.enum([`option`,`env`]).optional()}),Wc=Uc.extend({query:H.string()});async function getNamespaceFromSqlQuery(e,t,n,r){if(r.length===0)throw Error(`No namespaces found in configuration.`);if(r.length===1)return k(r[0],`namespace missing`);let i=extractTableNamesFromSql(t);if(i.length===0)throw Error(`Could not infer namespace from query. Detected namespaces: ${r.join(`, `)}.`);let a=await resolveTableNamespaces({workspaceId:e,namespaces:r,tableNames:i,client:n}),o=i.filter(e=>!a.has(e));if(o.length>0)throw Error(`Could not find namespace for tables in query: ${o.join(`, `)}.`);let s=new Set(a.values());if(s.size===1)return k([...s][0],`namespace from types missing`);throw Error(`Query references tables from multiple namespaces: ${[...s].join(`, `)}.`)}async function loadOptions(e){let t=parseOptions(Uc,e),n=await loadMachineUserName({machineUser:t.machineUser,machineUserSource:t.machineUserSource,profile:t.profile});if(!n)throw Error(`Machine user is required. Specify --machine-user, set TAILOR_PLATFORM_MACHINE_USER_NAME, or set a profile default with 'tailor profile update <profile> --machine-user <name>'.`);let r=await loadAccessToken({profile:t.profile}),i=await F(r),a=await loadWorkspaceId({workspaceId:t.workspaceId,profile:t.profile}),{config:o}=await loadConfig(e.configPath),s=extractAllNamespaces(o),{application:c}=await i.getApplication({workspaceId:a,applicationName:o.name});if(!c?.authNamespace)throw Error(`Application ${o.name} does not have an auth configuration.`);let{machineUser:l}=await i.getAuthMachineUser({workspaceId:a,authNamespace:c.authNamespace,name:n});if(!l)throw Error(`Machine user ${n} not found.`);return{engine:t.engine,client:i,workspaceId:a,config:o,application:c,machineUserResource:l,namespaces:s}}async function sqlQuery(e,t,n){let r=splitSqlStatements(n.query),i=await executeScript({client:e,workspaceId:n.workspaceId,name:`query-sql-${n.namespace}.js`,code:n.bundledCode,arg:{namespace:n.namespace,queries:r},invoker:t});if(!i.success)throw Error(i.error);return{engine:`sql`,namespace:n.namespace,query:n.query,result:parseExecutionResult(i.result)}}async function gqlQuery(e,t,n,r,i){let{access_token:a}=await bt(n.url,r.clientId,r.clientSecret),o=await executeScript({client:e,workspaceId:i.workspaceId,name:`query-gql.js`,code:i.bundledCode,arg:{endpoint:`${n.url}/query`,accessToken:a,query:i.query},invoker:t});if(!o.success)throw Error(o.error);return{engine:`gql`,query:i.query,result:parseExecutionResult(o.result)}}function parseExecutionResult(e){if(!e)return null;try{return JSON.parse(e)}catch{return e}}async function resolveQueryCommandInput(e){return e.query==null?e.file==null?e.edit?await resolveEditedQueryInput(e.engine):{mode:`repl`}:{mode:`query`,query:await q.readFile(e.file,`utf-8`)}:{mode:`query`,query:e.query}}async function resolveEditedQueryInput(e){if(!process.stdin.isTTY||!process.stdout.isTTY)throw Error(`Non-interactive terminals are not supported. Pass -q/--query or -f/--file to run a query.`);let t=getEditorCommand(),n=await q.mkdtemp(V.join(jr(),`tailor-query-`)),r=e===`sql`?`sql`:`graphql`,i=V.join(n,`query.${r}`);try{await q.writeFile(i,``,`utf-8`);try{await openInEditor(i,t)}catch(e){throw Error(`Failed to open query editor "${t}": ${e instanceof Error?e.message:String(e)}`,{cause:e})}let e=await q.readFile(i,`utf-8`);return e.trim().length===0||e===``?{mode:`abort`}:{mode:`query`,query:e}}finally{await q.rm(n,{recursive:!0,force:!0})}}async function query(e){let t=parseOptions(Wc,e);return await(await prepareQueryExecutor(t))(t.query)}async function prepareQueryExecutor(e){let{client:t,workspaceId:n,config:r,application:i,machineUserResource:a,engine:o,namespaces:s}=await loadOptions(e),c=await bundleQueryScript(o,V.dirname(r.path)),l=Xn(Ie,{namespace:i.authNamespace,machineUserName:a.name});return async e=>{let u;try{switch(o){case`sql`:return u=await getNamespaceFromSqlQuery(n,e,t,s),reorderSqlColumns(await sqlQuery(t,l,{workspaceId:n,namespace:u,bundledCode:c,query:e}),r,u,e);case`gql`:return await gqlQuery(t,l,i,a,{workspaceId:n,bundledCode:c,query:e});default:throw Error(`Unsupported query engine: ${o}`)}}catch(e){throw mapQueryExecutionError({error:e,engine:o,namespace:u,machineUser:a.name})}}}function resolveReplCommand(e){let t=e.trim();return t.startsWith(`\\`)?t===`\\q`||t===`\\quit`?`quit`:t===`\\help`||t===`\\h`||t===`\\?`?`help`:t===`\\clear`||t===`\\c`?`clear`:`unknown`:null}function clearReplScreen(){process.stdout.write(`\x1Bc`)}function sanitizeHistoryScope(e){return e.replace(/[^a-zA-Z0-9._-]/g,`_`)}function getReplHistoryPath(e,t,n){if(!_r)return;let r=[t,n].filter(e=>!!e).map(sanitizeHistoryScope).join(`-`),i=e===`sql`?`sql`:`gql`,a=r?`-${r}`:``;return V.join(_r,`tailor-platform`,`query-history-${i}${a}.json`)}function createReplValidator(e){return t=>{let n=t.trim();if(n!==``&&resolveReplCommand(n)===null)return e===`sql`?isSqlInputComplete(t)?void 0:`SQL statement is incomplete (missing ';').`:isGraphQLInputComplete(t)?void 0:`GraphQL document is incomplete.`}}async function runRepl(e){if(!process.stdin.isTTY||!process.stdout.isTTY)throw Error(`Non-interactive terminals are not supported. Pass -q/--query or -f/--file to run a query.`);let t=await prepareQueryExecutor(e),n=getReplHistoryPath(e.engine,e.profile,e.workspaceId),r=createReplValidator(e.engine),{highlightSqlLine:i,highlightGraphqlLine:a,replTransform:o}=await import(`./repl-editor-BG1aDOfH.mjs`),s=e.engine===`sql`?i:a,c=Gr({prefix:``,preferNewlineOnEnter:e.newlineOnEnter,validate:r,highlight:s,transform:o,theme:{submitRender:`preserve`},history:n?{filePath:n,maxEntries:100}:[],helpFooter:{items:[`submit`,`newline`],maxLines:1}});for(M.info(`Entering ${e.engine.toUpperCase()} REPL mode.`),M.info(`Type \\help for usage, \\q to quit.`);;){let[n,r]=await c(`${e.engine}> `);if(r?.kind===`cancel`){if(n.length===0)return;continue}if(r?.kind===`eof`)return;let i=n.trim();if(i===``)continue;let a=resolveReplCommand(i);if(a===`quit`)return;if(a===`help`){printReplHelp(e.engine);continue}if(a===`clear`){clearReplScreen();continue}if(a===`unknown`){M.warn(`Unknown command: ${i}`);continue}try{let n=await t(i);n.engine===`sql`?printSqlResult(n,{json:e.json}):printGqlResult(n,{json:e.json})}catch(e){if(Cn(e)){M.log(e.format());continue}if(e instanceof Error){M.error(e.message);continue}M.error(String(e))}}}function printReplHelp(e){M.log(`REPL commands:`),M.log(` \\help, \\h, \\? Show this help`),M.log(` \\q, \\quit Exit REPL`),M.log(` \\clear, \\c Clear the screen`),M.log(``),M.log(`Key bindings (see footer for terminal-specific submit/newline keys):`),M.log(` Ctrl+J Insert newline (always available)`),M.log(` Ctrl+C Cancel current input`),M.log(` Ctrl+D Exit REPL (on empty input)`),M.log(` Ctrl+Z / Ctrl+Y Undo / Redo`),M.log(` Up/Down (first/last line) Navigate history`),M.log(``),M.log(`Editing aids:`),M.log(` Syntax highlighting Enabled for the current engine`),M.log(` ( [ { Auto-inserts the matching closing bracket`),M.log(` Enter after open bracket Adds one indent level and closes the block`),M.log(``),M.log(e===`sql`?`Input must end with ';' to submit.`:`Input must be a complete GraphQL document to submit.`)}async function querySql(e){let t=await query({...e,engine:`sql`});if(t.engine!==`sql`)throw Error(`Expected sql engine result but got: ${t.engine}`);return t}async function queryGql(e){let t=await query({...e,engine:`gql`});if(t.engine!==`gql`)throw Error(`Expected gql engine result but got: ${t.engine}`);return t}async function reorderSqlColumns(e,t,n,r){if(!isSQLExecutionResult(e.result)||e.result.rows.length===0)return e;let i=extractColumnTemplate(r);if(!i)return e;try{let r=buildExpectedColumnOrder(i,await loadTypeFieldOrder(t,n));if(r.length===0)return e;let a=e.result.rows.map(e=>reorderRowByTemplate(e,r));return{...e,result:{...e.result,rows:a}}}catch{return e}}const Gc=[`id`];function buildExpectedColumnOrder(e,t){let n=[];for(let r of e)if(r.type===`explicit`)n.push(r.name);else for(let e of r.tableNames)n.push(...Gc),n.push(...t.get(e)??[]);return n}function reorderRowByTemplate(e,t){let n={},r=new Set(Object.keys(e)),i=new Map;for(let e of r)i.set(e.toLowerCase(),e);for(let a of t){let t=i.get(a.toLowerCase());t!=null&&r.has(t)&&(n[t]=e[t],r.delete(t),i.delete(a.toLowerCase()))}for(let t of r)n[t]=e[t];return n}const Kc=Y({name:`query`,description:`Run SQL/GraphQL query.`,args:H.strictObject({...ai,engine:B(Hc,{description:`Query engine (sql or gql)`}),query:B(H.string().optional(),{alias:`q`,description:`Query string to execute directly; omit to start REPL mode`}),file:B(H.string().optional(),{alias:`f`,description:`Read query string from file; omit to start REPL mode`}),edit:B(H.boolean().default(!1),{description:`Open a temporary file in your editor; omit to start REPL mode`}),"machine-user":B(H.string().optional(),{alias:`m`,description:`Machine user name for query execution. Falls back to the active profile's default machine user.`,env:`TAILOR_PLATFORM_MACHINE_USER_NAME`}),"newline-on-enter":B(H.boolean().optional(),{description:`REPL: when true, Enter inserts a newline and Shift+Enter submits. Use --no-newline-on-enter to swap.`})}).superRefine((e,t)=>{e.query!=null&&e.file!=null&&t.addIssue({code:`custom`,path:[`file`],message:`Pass either -q/--query or -f/--file, not both.`}),e.edit&&e.query!=null&&t.addIssue({code:`custom`,path:[`edit`],message:`Pass only one of --edit, -q/--query, or -f/--file.`}),e.edit&&e.file!=null&&t.addIssue({code:`custom`,path:[`edit`],message:`Pass only one of --edit, -q/--query, or -f/--file.`})}),run:async e=>{let t=await resolveQueryCommandInput({query:e.query,file:e.file,edit:e.edit,engine:e.engine}),n={workspaceId:e[`workspace-id`],profile:e.profile,configPath:e.config,engine:e.engine,machineUser:e[`machine-user`],machineUserSource:resolveMachineUserInputSource(e[`machine-user`])};if(t.mode===`abort`){M.info(`Editor closed without a query. Nothing was executed.`);return}if(t.mode===`repl`){let t=e[`newline-on-enter`]??ut(process.env.TAILOR_QUERY_NEWLINE_ON_ENTER)??!0;await runRepl({...n,json:e.json,newlineOnEnter:t});return}let r=t.query;if(e.engine===`sql`){printSqlResult(await querySql({...n,query:r}),{json:e.json});return}printGqlResult(await queryGql({...n,query:r}),{json:e.json})}});function isSQLExecutionResult(e){if(!e||typeof e!=`object`)return!1;let t=e;return Array.isArray(t.rows)&&typeof t.rowCount==`number`}function printSingleSqlResult(e,t={}){if(e.rows.length===0){if(t.json){M.out({results:[],rowCount:0});return}M.info(`No rows returned.`);return}if(t.json){M.out({results:e.rows,rowCount:e.rowCount});return}M.out(e.rows,{showNull:!0}),M.out(`rows: ${e.rowCount}`)}function splitSqlStatements(e){let t=qr(e,{locationTracking:!0});return t.map((n,r)=>{let i=k(n._location,`SQL statement location missing`).start,a=t[r+1],o=a===void 0?e.length:k(a._location,`SQL statement location missing`).start;return e.substring(i,o)})}function isSQLExecutionResultArray(e){return Array.isArray(e)&&e.length>0&&e.every(isSQLExecutionResult)}function printSqlResult(e,t={}){if(isSQLExecutionResultArray(e.result)){if(t.json){M.out(e.result.map(e=>({results:e.rows,rowCount:e.rowCount})));return}let n=splitSqlStatements(e.query);for(let r=0;r<e.result.length;r++)r>0&&M.log(``),M.info(n[r]??`Statement ${r+1}`),printSingleSqlResult(k(e.result[r],`SQL result at index ${r} missing`),t);return}if(isSQLExecutionResult(e.result)){printSingleSqlResult(e.result,t);return}M.out({engine:e.engine,query:e.query,result:e.result})}function printGqlResult(e,t={}){if(t.json){M.out({result:e.result});return}M.out(JSON.stringify(e.result,null,2))}function escapeData(e){return e.replaceAll(`%`,`%25`).replaceAll(`\r`,`%0D`).replaceAll(`
|
|
916
|
+
`,`%0A`)}function escapeProperty(e){return escapeData(e).replaceAll(`:`,`%3A`).replaceAll(`,`,`%2C`)}function jsonRequestedInArgv(){let e=process.argv.slice(2),t=e.indexOf(`--`);return(t===-1?e:e.slice(0,t)).some(e=>{let t=e.indexOf(`=`),n=t===-1?e:e.slice(0,t);return n!==`--json`&&n!==`-j`?!1:t===-1||ut(e.slice(t+1))!==!1})}function annotationsEnabled(e){return e||jsonRequestedInArgv()||process.env.GITHUB_ACTIONS!==`true`?!1:ut(process.env.TAILOR_GITHUB_ACTIONS_ANNOTATIONS)!==!1}function realPath(e){try{return nr(qn(e))}catch{return qn(e)}}function workspaceRelativePath(e){let t=process.env.GITHUB_WORKSPACE;if(!t||!Wn(e))return;let n=Kn(realPath(t),realPath(e));if(n===``||Wn(n))return;let r=n.split(Jn);if(r[0]!==`..`)return r.join(`/`)}function formatAnnotation(e,t,n={}){let r=[];return n.title!==void 0&&r.push(`title=${escapeProperty(lr(n.title))}`),n.file!==void 0&&r.push(`file=${escapeProperty(n.file)}`),n.line!==void 0&&r.push(`line=${n.line}`),`::${e}${r.length>0?` ${r.join(`,`)}`:``}::${escapeData(lr(t))}\n`}function formattedMessage(e){let t=e.format;if(typeof t!=`function`)return;let n=t.call(e);return typeof n==`string`?n:void 0}function describeTerminalError(e,t){if(Cn(e))return{message:e.format(),title:e.code||`CLI_ERROR`};if(e instanceof Error){let n=Yt(e).code??(e.name||`Error`),r=formattedMessage(e);if(r!==void 0)return{message:r,title:n};let i=t?`\nSuggestion: ${t}`:``;return{message:`${e.message}${i}`,title:n}}return{message:`Unknown error: ${String(e)}`,title:`UNKNOWN_ERROR`}}function withSourceLocation(e,t){return en(e,{location:t})}function annotateTerminalError(e,t){if(!annotationsEnabled(t.jsonMode))return;let{message:n,title:r}=describeTerminalError(e,t.suggestion);process.stderr.write(formatAnnotation(`error`,n,{title:r,...sourceLocation(e)}))}function sourceLocation(e){if(!(e instanceof Error))return{};let t=Yt(e).location;if(!t)return{};let n=workspaceRelativePath(t.file);return n===void 0?{}:t.line===void 0?{file:n}:{file:n,line:t.line}}function isNativeTypeScriptRuntime(){return isBun()||isDeno()}function isBun(){return`Bun`in globalThis}function isDeno(){return`Deno`in globalThis}async function registerTsHook(e){if(isNativeTypeScriptRuntime())return;let{resolveSync:t,loadSync:n}=await import(e.href);Rn.registerHooks({resolve:t,load:n})}export{ac as $,protoGqlPermission as $n,apiCall as $r,formatWaitError as $t,listWorkflows as A,Zr as Ai,us as An,loadSnapshot as Ar,waitForExecution as At,hc as B,checkMigrationDiffs as Bn,formatMigrationNumber as Br,listExecutors as Bt,getAppHealth as C,runDefaultSubCommand as Ci,humanizeRelativeTime as Cn,assertMigrationNumberExists as Cr,serializeError as Ct,xc as D,oi as Di,ms as Dn,getMigrationFiles as Dr,extractAllNamespaces as Dt,waitWorkflowExecution as E,ri as Ei,writeWorkspaceExpiry as En,getMigrationFilePath as Er,loadTailorDBNamespaces as Et,bundleSeedDumpScript as F,parseDuration as Fi,parseAppIds as Fn,sanitizeMigrationLabel as Fr,listWebhookExecutors as Ft,show as G,toTailorDBDeployInput as Gn,subscribesToEvents as Gr,watchExecutorJob as Gt,logBetaWarning as H,formatRemoteVerificationResults as Hn,formatDiffSummary as Hr,getExecutorWaitFailureMessage as Ht,bundleSeedScript as I,recoveryContextArgs as Ii,planAppIds as In,compareLocalTypesWithSnapshot as Ir,Rs as It,lc as J,updateMigrationLabel as Jn,zi as Jr,As as Jt,dc as K,verifyRemoteSchema as Kn,resourceTrn as Kr,js as Kt,generate as L,resolveMachineUserInputSource as Li,removeAdoptedConfigIds as Ln,compareSnapshots as Lr,Is as Lt,yc as M,ii as Mi,Q as Mn,ya as Mr,listFunctionRegistries as Mt,loadSeedContext as N,ci as Ni,os as Nn,createMigrationHistoryId as Nr,Bs as Nt,resumeWorkflow as O,createCommonArgs as Oi,parseAge as On,getNextMigrationNumber as Or,extractOwnedNamespaces as Ot,chunkSeedData as P,paginationArgs as Pi,findAppIdLock as Pn,handleOptionalToRequiredError as Pr,getFunctionRegistry as Pt,oc as Q,generateAllTypeManifestsFromSnapshot as Qn,loadOperatorWorkspaceContext as Qr,listWorkflowExecutions as Qt,vc as R,toPageDirection as Ri,ensureConfigId as Rn,ia as Rr,triggerExecutor as Rt,Ec as S,Y as Si,formatTimestamp as Sn,xo as Sr,errorToJson as St,Sc as T,ti as Ti,fetchWorkspaceExpiry as Tn,getMigrationDirPath as Tr,loadApplicationNamespaces as Tt,pc as U,logMissingCheckpointGuidance as Un,formatMigrationDiff as Ur,Ms as Ut,generateSchemaFile as V,fetchRemoteSchemaSnapshot as Vn,parseMigrationNumberArg as Vr,getExecutorJob as Vt,deployStaticWebsite as W,logRemoteDriftGuidance as Wn,hasChanges as Wr,listExecutorJobs as Wt,updateOrganization as X,bundleMigrationScript as Xn,writeMetadataLabels as Xr,ks as Xt,cc as Y,formatMigrationScriptCommand as Yn,Bi as Yr,getWorkflow as Yt,organizationTree as Z,compareSnapshotWithRemote as Zn,X as Zr,getWorkflowExecution as Zt,getWorkspace as _,removeLegacyUserAlias as _i,createWorkspace$1 as _n,Co as _r,getMachineUserToken as _t,Kc as a,hasUserTokenEntry as ai,isFunctionExecutionTerminalStatus as an,captureFileState as ar,ec as at,removeProfilesForWorkspaces as b,saveUserTokens as bi,_s as bn,ko as br,listMachineUsers as bt,zc as c,loadConfigPath as ci,getExecutor as cn,formatSchemaDrifts as cr,getFolder as ct,listUsers as d,loadPlatformClientConfig as di,deployMigrationTestBaseline as dn,assertValidMigrationFiles as dr,Js as dt,assertWritable as ei,isRetryableWaitError as en,fetchRemoteMigrationNumber as er,listOrganizations as et,Fc as f,loadStoredUserTokens as fi,deployMigrationTestTarget as fn,reconstructSnapshotFromMigrations as fr,createFolder as ft,Ac as g,registerTokenSecrets as gi,createValidatedWorkspaceWithClient as gn,bo as gr,getOAuth2Client as gt,restoreWorkspace as h,readPlatformConfig as hi,ys as hn,So as hr,Gs as ht,query as i,hasAnyUserTokenEntry as ii,functionExecutionStatusToString as in,selectTargetNamespace as ir,updateFolder as it,truncate as j,loadEnvFiles as ji,parseOptions as jn,ba as jr,Hs as jt,bc as k,ai as ki,ds as kn,loadDiff as kr,executeScript as kt,removeUser as l,loadConsoleBaseUrl as li,deploy as ln,createSnapshotFromLocalTypes as lr,Xs as lt,Mc as m,platformConfigFromProfile as mi,listWorkspaces as mn,To as mr,listOAuth2Clients as mt,annotateTerminalError as n,deleteUserTokens as ni,formatFunctionLogEntry as nn,getNamespacesWithMigrations as nr,getOrganization as nt,Vc as o,loadAccessToken as oi,toFunctionLogEntryInfo as on,captureMigrationFileState as or,listFolders as ot,inviteUser as p,loadWorkspaceId as pi,bs as pn,Eo as pr,Ks as pt,remove as q,getMigrationMachineUser as qn,Vi as qr,startWorkflow as qt,withSourceLocation as r,fetchLatestToken as ri,formatFunctionLogLines as rn,migrationConfigNotFoundError as rr,nc as rt,updateUser as s,loadAuthStatus as si,ws as sn,createRemoteComparableSnapshot as sr,Qs as st,registerTsHook as t,loadConfig as ti,colorizeFunctionExecutionStatus as tn,fetchRemoteMigrationState as tr,ic as tt,Lc as u,loadMachineUserName as ui,deployFromCLI as un,createSnapshotType as ur,deleteFolder as ut,Oc as v,resolveConfigUser as vi,workspaceDisplayName as vn,Do as vr,Ws as vt,wc as w,ni as wi,clearWorkspaceExpiry as wn,getLatestMigrationNumber as wr,resolvePluginConfig as wt,listApps as x,writePlatformConfig as xi,formatKeyValueTable as xn,Oo as xr,generate$1 as xt,deleteWorkspace as y,resolveUserTokenKey as yi,workspaceInfosWithFolderNames as yn,wo as yr,Us as yt,_c as z,J as zi,generateUserTypes as zn,normalizeSchemaSnapshot as zr,Ns as zt};
|
|
917
|
+
//# sourceMappingURL=register-ts-hook-Djjnj5R8.mjs.map
|