@tailor-platform/sdk 1.79.0 → 1.80.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 +28 -0
- package/dist/{application-fjqb-Gh8.mjs → application-C1d52JP9.mjs} +241 -222
- package/dist/application-C1d52JP9.mjs.map +1 -0
- package/dist/application-Nlh9BHQf.mjs +3 -0
- package/dist/cli/commands/tailordb/migrate/bundler.d.mts +3 -2
- package/dist/cli/index.mjs +17 -21
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli/lib.mjs +3 -6
- package/dist/cli/lib.mjs.map +1 -1
- package/dist/cli/tsconfig-paths-hook.d.mts +1 -0
- package/dist/cli/tsconfig-paths-hook.mjs +153 -0
- package/dist/completion/zsh-worker.zsh +1 -1
- package/dist/configure/config/types.d.mts +5 -1
- package/dist/configure/services/auth/types.d.mts +18 -23
- package/dist/{runtime-CjMeYuPA.mjs → register-typescript-runtime-Bd4bcLbW.mjs} +398 -123
- package/dist/register-typescript-runtime-Bd4bcLbW.mjs.map +1 -0
- package/dist/{service-D12iQGcS.mjs → service-CDPatibu.mjs} +31 -17
- package/dist/service-CDPatibu.mjs.map +1 -0
- package/dist/service-Cg7Qibit.mjs +3 -0
- package/docs/cli/application.md +6 -0
- package/docs/cli-reference.md +21 -21
- package/docs/configuration.md +2 -0
- package/docs/services/auth.md +2 -2
- package/package.json +7 -6
- package/dist/application-BB6BlUfk.mjs +0 -3
- package/dist/application-fjqb-Gh8.mjs.map +0 -1
- package/dist/runtime-CjMeYuPA.mjs.map +0 -1
- package/dist/service-CghpdV-9.mjs +0 -3
- package/dist/service-D12iQGcS.mjs.map +0 -1
|
@@ -2,8 +2,8 @@ import { t as db } from "./schema-CYrle8JZ.mjs";
|
|
|
2
2
|
import { $ as CreateAuthIDPConfigRequestSchema, A as CreatePipelineResolverRequestSchema, At as TenantProviderConfig_TenantProviderType, B as IdPPermissionOperator, Bt as CreateAIGatewayRequestSchema, C as UpdateStaticWebsiteRequestSchema, Ct as AuthOAuth2Client_ClientType, D as CreateSecretManagerVaultRequestSchema, Dt as AuthSCIMAttribute_Uniqueness, E as CreateSecretManagerSecretRequestSchema, Et as AuthSCIMAttribute_Type, F as PipelineResolver_OperationType, Ft as GetApplicationSchemaHealthResponse_ApplicationSchemaHealthStatus, G as CreateExecutorExecutorRequestSchema, Gt as ConditionSchema, H as FunctionExecution_Status, I as CreateIdPServiceRequestSchema, It as UpdateApplicationRequestSchema, J as ExecutorJobStatus, Jt as PageDirection, K as UpdateExecutorExecutorRequestSchema, Kt as Condition_Operator, L as UpdateIdPServiceRequestSchema, M as UpdatePipelineResolverRequestSchema, N as UpdatePipelineServiceRequestSchema, O as UpdateSecretManagerSecretRequestSchema, Ot as AuthSCIMConfig_AuthorizationType, Pt as CreateApplicationRequestSchema, Q as CreateAuthHookRequestSchema, Rt as ApplicationSchemaUpdateAttemptStatus, S as CreateStaticWebsiteRequestSchema, St as AuthInvokerSchema, Tt as AuthSCIMAttribute_Mutability, V as IdPPermissionPermit, Vt as UpdateAIGatewayRequestSchema, X as ExecutorTriggerType, Y as ExecutorTargetType, Z as CreateAuthConnectionRequestSchema, _ as TailorDBGQLPermission_Permit, a as CreateWorkflowRequestSchema, at as CreateTenantConfigRequestSchema, b as TailorDBType_PermitAction, bt as AuthHookPoint, ct as UpdateAuthHookRequestSchema, d as CreateTailorDBServiceRequestSchema, dt as UpdateAuthOAuth2ClientRequestSchema, et as CreateAuthMachineUserRequestSchema, f as CreateTailorDBTypeRequestSchema, ft as UpdateAuthSCIMConfigRequestSchema, g as TailorDBGQLPermission_Operator, gt as UpdateUserProfileConfigRequestSchema, h as TailorDBGQLPermission_Action, ht as UpdateTenantConfigRequestSchema, i as CreateWorkflowJobFunctionRequestSchema, it as CreateAuthServiceRequestSchema, j as CreatePipelineServiceRequestSchema, jt as UserProfileProviderConfig_UserProfileProviderType, l as WorkflowExecution_Status, lt as UpdateAuthIDPConfigRequestSchema, mt as UpdateAuthServiceRequestSchema, nt as CreateAuthSCIMConfigRequestSchema, o as UpdateWorkflowJobFunctionExecutionPolicyRequestSchema, ot as CreateUserProfileConfigRequestSchema, p as UpdateTailorDBTypeRequestSchema, pt as UpdateAuthSCIMResourceRequestSchema, qt as FilterSchema, r as CreateWorkflowJobFunctionExecutionPolicyRequestSchema, rt as CreateAuthSCIMResourceRequestSchema, s as UpdateWorkflowRequestSchema, st as UpdateAuthConnectionRequestSchema, t as WorkspacePlatformUserRole, tt as CreateAuthOAuth2ClientRequestSchema, u as WorkflowJobExecution_Status, ut as UpdateAuthMachineUserRequestSchema, v as TailorDBType_Permission_Operator, vt as AuthConnection_Status, wt as AuthOAuth2Client_GrantType, x as AddCustomDomainRequestSchema, xt as AuthIDPConfig_AuthType, y as TailorDBType_Permission_Permit, yt as AuthConnection_Type, z as IdPLang, zt as Subgraph_ServiceType } from "./workspace_resource_pb-Db3fv68L.mjs";
|
|
3
3
|
import { t as assertDefined } from "./assert-DBxo8jPo.mjs";
|
|
4
4
|
import { a as parseBoolean, i as symbols, n as logger, r as styles, t as CIPromptError } from "./logger-BwS4ppwO.mjs";
|
|
5
|
-
import { A as
|
|
6
|
-
import { o as loadFilesWithIgnores, s as functionSchema, t as createExecutorService } from "./service-
|
|
5
|
+
import { A as fetchAll, B as initOAuth2Client, C as hasGenerationHooks, D as hashFile, E as hashContent, G as resolveStaticWebsiteUrls, H as isDefaultPlatform, I as getConsoleBaseUrl, J as LOG_LEVELS, K as byName, L as getOAuth2ClientId, M as fetchMachineUserToken, N as fetchPaged, R as getOrNull, S as getPluginGenerationDependencies, T as getDistDir, U as normalizeBaseUrl, V as initOperatorClient, W as rememberPlatformConfigForToken, _ as resolveTSConfigWithFallback, d as buildExecutorArgsExpr, f as buildResolverOperationHookExpr, g as stringifyFunction, h as TailorDBTypeSchema, i as resolverBundleKey, j as fetchAllTolerant, k as defaultPlatformBaseUrl, l as HTTP_METHODS, m as assertUniqueTailorDBTypeNamesWithExternal, n as generatePluginFilesIfNeeded, o as WorkflowJobFunctionExecutionPolicySchema, p as assertUniqueLocalTailorDBTypeNames, q as createApplyLimiter, r as loadApplication, t as defineApplication, v as platformBundleDefinePlugin, w as createBundleCache, z as getPlatformBaseUrl } from "./application-C1d52JP9.mjs";
|
|
6
|
+
import { o as loadFilesWithIgnores, s as functionSchema, t as createExecutorService } from "./service-CDPatibu.mjs";
|
|
7
7
|
import { n as enumConstantsPlugin, t as EnumConstantsGeneratorID } from "./enum-constants-j9QBF0cB.mjs";
|
|
8
8
|
import { t as multiline } from "./multiline-sfHpTZZK.mjs";
|
|
9
9
|
import { n as fileUtilsPlugin, t as FileUtilsGeneratorID } from "./file-utils-DcyIPFQh.mjs";
|
|
@@ -14,11 +14,12 @@ import { t as userAgent } from "./user-agent-DX2Jnw0-.mjs";
|
|
|
14
14
|
import { r as isCLIError, t as createCLIError } from "./errors-DVFS0AZk.mjs";
|
|
15
15
|
import { n as tightenSecretFilePermissions, r as writeSecretFile } from "./secret-file-DBqZhjFQ.mjs";
|
|
16
16
|
import { r as withSpan } from "./telemetry-CdqJEzkj.mjs";
|
|
17
|
+
import * as mod from "node:module";
|
|
17
18
|
import { arg, createDefineCommand, defineCommand, runCommand } from "politty";
|
|
18
19
|
import { z } from "zod";
|
|
19
20
|
import { create, fromJson, toJson } from "@bufbuild/protobuf";
|
|
20
21
|
import * as fs$1 from "node:fs";
|
|
21
|
-
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
22
|
+
import { mkdirSync, readFileSync, renameSync, rmSync, statSync, utimesSync, writeFileSync } from "node:fs";
|
|
22
23
|
import { parseEnv } from "node:util";
|
|
23
24
|
import { ValueSchema, timestampDate } from "@bufbuild/protobuf/wkt";
|
|
24
25
|
import * as path from "pathe";
|
|
@@ -34,17 +35,16 @@ import { lt } from "semver";
|
|
|
34
35
|
import { xdgConfig } from "xdg-basedir";
|
|
35
36
|
import { Code, ConnectError } from "@connectrpc/connect";
|
|
36
37
|
import pLimit from "p-limit";
|
|
37
|
-
import { resolveTSConfig } from "pkg-types";
|
|
38
38
|
import * as crypto$1 from "node:crypto";
|
|
39
39
|
import { createHash, randomUUID } from "node:crypto";
|
|
40
40
|
import { ExitPromptError } from "@inquirer/core";
|
|
41
41
|
import { confirm, input, password, select } from "@inquirer/prompts";
|
|
42
42
|
import { isCI } from "std-env";
|
|
43
43
|
import * as rolldown from "rolldown";
|
|
44
|
-
import * as fs from "node:fs/promises";
|
|
45
|
-
import { glob, mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
46
44
|
import { parseSync } from "oxc-parser";
|
|
47
45
|
import * as inflection from "inflection";
|
|
46
|
+
import * as fs from "node:fs/promises";
|
|
47
|
+
import { glob, mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
48
48
|
import { pathToString } from "@bufbuild/protobuf/reflect";
|
|
49
49
|
import { createValidator } from "@bufbuild/protovalidate";
|
|
50
50
|
import { setTimeout as setTimeout$1 } from "timers/promises";
|
|
@@ -1444,6 +1444,54 @@ function createCacheManager(options) {
|
|
|
1444
1444
|
};
|
|
1445
1445
|
}
|
|
1446
1446
|
|
|
1447
|
+
//#endregion
|
|
1448
|
+
//#region src/cli/services/stale-cleanup.ts
|
|
1449
|
+
const legacyBundleDirectories = [
|
|
1450
|
+
{
|
|
1451
|
+
name: "resolvers",
|
|
1452
|
+
suffixes: [".entry.js"]
|
|
1453
|
+
},
|
|
1454
|
+
{
|
|
1455
|
+
name: "executors",
|
|
1456
|
+
suffixes: [".entry.js"]
|
|
1457
|
+
},
|
|
1458
|
+
{
|
|
1459
|
+
name: "workflow-jobs",
|
|
1460
|
+
suffixes: [".js", ".js.map"]
|
|
1461
|
+
},
|
|
1462
|
+
{
|
|
1463
|
+
name: "auth-hooks",
|
|
1464
|
+
suffixes: [".entry.js"]
|
|
1465
|
+
},
|
|
1466
|
+
{
|
|
1467
|
+
name: "http-adapters",
|
|
1468
|
+
suffixes: [".entry.js"]
|
|
1469
|
+
}
|
|
1470
|
+
];
|
|
1471
|
+
/**
|
|
1472
|
+
* Remove bundle artifacts created by SDK versions that used disk-backed entries.
|
|
1473
|
+
*
|
|
1474
|
+
* Concurrent callers are safe because current bundlers no longer create files
|
|
1475
|
+
* in these directories and each removal uses `force: true`.
|
|
1476
|
+
* @param outputRoot - SDK output directory
|
|
1477
|
+
*/
|
|
1478
|
+
async function removeLegacyBundleFiles(outputRoot) {
|
|
1479
|
+
await Promise.all([...legacyBundleDirectories.map(({ name, suffixes }) => removeMatchingFiles(path.join(outputRoot, name), suffixes)), fs.rm(path.join(outputRoot, "hooks-validate-scripts"), {
|
|
1480
|
+
recursive: true,
|
|
1481
|
+
force: true
|
|
1482
|
+
})]);
|
|
1483
|
+
}
|
|
1484
|
+
async function removeMatchingFiles(outputDir, suffixes) {
|
|
1485
|
+
let files;
|
|
1486
|
+
try {
|
|
1487
|
+
files = await fs.readdir(outputDir);
|
|
1488
|
+
} catch (error) {
|
|
1489
|
+
if (error.code === "ENOENT") return;
|
|
1490
|
+
throw error;
|
|
1491
|
+
}
|
|
1492
|
+
for (const file of files) if (suffixes.some((suffix) => file.endsWith(suffix))) await fs.rm(path.join(outputDir, file), { force: true });
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1447
1495
|
//#endregion
|
|
1448
1496
|
//#region src/cli/shared/type-generator.ts
|
|
1449
1497
|
/**
|
|
@@ -1467,7 +1515,7 @@ function extractAttributesFromConfig(config) {
|
|
|
1467
1515
|
* @returns Generated type definition source
|
|
1468
1516
|
*/
|
|
1469
1517
|
function generateTypeDefinition(attributeMap, attributeList, env, machineUserNames, idpNames, connectionNames, aiGatewayNames) {
|
|
1470
|
-
const mapFields = attributeMap ? Object.entries(attributeMap).map(([key,
|
|
1518
|
+
const mapFields = attributeMap ? Object.entries(attributeMap).map(([key, { type, optional }]) => ` ${key}${optional ? "?" : ""}: ${type};`).join("\n") : "";
|
|
1471
1519
|
const mapBody = !attributeMap || Object.keys(attributeMap).length === 0 ? "{}" : `{
|
|
1472
1520
|
${mapFields}
|
|
1473
1521
|
}`;
|
|
@@ -1530,12 +1578,15 @@ function collectAttributesFromConfig(config) {
|
|
|
1530
1578
|
const inferAttributeType = (field) => {
|
|
1531
1579
|
const type = field?.type;
|
|
1532
1580
|
const metadata = field?.metadata;
|
|
1533
|
-
if (!metadata) return "string";
|
|
1581
|
+
if (!metadata) return { type: "string" };
|
|
1534
1582
|
let typeStr = "string";
|
|
1535
1583
|
if (type === "boolean") typeStr = "boolean";
|
|
1536
1584
|
else if (type === "enum" && metadata.allowedValues) typeStr = metadata.allowedValues.map((v) => `"${v.value}"`).join(" | ");
|
|
1537
1585
|
if (metadata.array) typeStr += "[]";
|
|
1538
|
-
return
|
|
1586
|
+
return {
|
|
1587
|
+
type: typeStr,
|
|
1588
|
+
optional: metadata.required === false
|
|
1589
|
+
};
|
|
1539
1590
|
};
|
|
1540
1591
|
if ("userProfile" in auth) {
|
|
1541
1592
|
const userProfile = auth.userProfile;
|
|
@@ -2850,12 +2901,16 @@ function protoSubgraph(subgraph) {
|
|
|
2850
2901
|
|
|
2851
2902
|
//#endregion
|
|
2852
2903
|
//#region src/cli/commands/deploy/secrets-state.ts
|
|
2904
|
+
const SecretsStateEntrySchema = z.object({
|
|
2905
|
+
hash: z.string(),
|
|
2906
|
+
updateTime: z.string().optional()
|
|
2907
|
+
});
|
|
2853
2908
|
const SecretsStateSchema = z.object({
|
|
2854
|
-
vaults: z.record(z.string(), z.record(z.string(),
|
|
2909
|
+
vaults: z.record(z.string(), z.record(z.string(), SecretsStateEntrySchema)),
|
|
2855
2910
|
connections: z.record(z.string(), z.string()).optional()
|
|
2856
2911
|
});
|
|
2857
2912
|
const PersistedSecretsStateSchema = z.object({
|
|
2858
|
-
version: z.literal(
|
|
2913
|
+
version: z.literal(2),
|
|
2859
2914
|
workspaceId: z.string(),
|
|
2860
2915
|
applicationKey: z.string(),
|
|
2861
2916
|
state: SecretsStateSchema
|
|
@@ -2901,12 +2956,14 @@ function saveSecretsState(scope, state) {
|
|
|
2901
2956
|
if (!scope.applicationId) return;
|
|
2902
2957
|
const filePath = getSecretsStatePath(scope);
|
|
2903
2958
|
mkdirSync(path.dirname(filePath), { recursive: true });
|
|
2904
|
-
|
|
2905
|
-
|
|
2959
|
+
const tempPath = `${filePath}.tmp-${randomUUID()}`;
|
|
2960
|
+
writeFileSync(tempPath, JSON.stringify({
|
|
2961
|
+
version: 2,
|
|
2906
2962
|
workspaceId: scope.workspaceId,
|
|
2907
2963
|
applicationKey: applicationStateKey(scope),
|
|
2908
2964
|
state
|
|
2909
2965
|
}, null, 2), "utf-8");
|
|
2966
|
+
renameSync(tempPath, filePath);
|
|
2910
2967
|
}
|
|
2911
2968
|
/**
|
|
2912
2969
|
* Compute SHA-256 hex digest of a value.
|
|
@@ -2916,6 +2973,133 @@ function saveSecretsState(scope, state) {
|
|
|
2916
2973
|
function hashValue(value) {
|
|
2917
2974
|
return createHash("sha256").update(value).digest("hex");
|
|
2918
2975
|
}
|
|
2976
|
+
/**
|
|
2977
|
+
* Serialize a platform timestamp into the string stored as update evidence.
|
|
2978
|
+
* @param updateTime - Timestamp from a Secret Manager list or mutation response
|
|
2979
|
+
* @returns Serialized timestamp, or undefined when the platform sent none
|
|
2980
|
+
*/
|
|
2981
|
+
function serializeUpdateTime(updateTime) {
|
|
2982
|
+
return updateTime === void 0 ? void 0 : `${updateTime.seconds}.${updateTime.nanos}`;
|
|
2983
|
+
}
|
|
2984
|
+
const LOCK_POLL_INTERVAL_MS = 100;
|
|
2985
|
+
const LOCK_ACQUIRE_TIMEOUT_MS = 300 * 1e3;
|
|
2986
|
+
const LOCK_HEARTBEAT_INTERVAL_MS = 10 * 1e3;
|
|
2987
|
+
const LOCK_LEASE_MS = 60 * 1e3;
|
|
2988
|
+
const lockQueues = /* @__PURE__ */ new Map();
|
|
2989
|
+
/**
|
|
2990
|
+
* Run a remote-update/state-save sequence exclusively for one target's secrets state.
|
|
2991
|
+
*
|
|
2992
|
+
* Serializes concurrent deploys to the same workspace and application (across
|
|
2993
|
+
* processes sharing the same output directory) so the persisted hash state
|
|
2994
|
+
* always reflects the last remote write.
|
|
2995
|
+
* @param scope - Workspace and application identity for the deployment
|
|
2996
|
+
* @param fn - Critical section performing remote updates and the state save
|
|
2997
|
+
* @returns The value returned by fn
|
|
2998
|
+
*/
|
|
2999
|
+
async function withSecretsStateLock(scope, fn) {
|
|
3000
|
+
if (!scope.applicationId) return fn();
|
|
3001
|
+
const lockPath = `${getSecretsStatePath(scope)}.lock`;
|
|
3002
|
+
let queue = lockQueues.get(lockPath);
|
|
3003
|
+
if (!queue) {
|
|
3004
|
+
queue = pLimit(1);
|
|
3005
|
+
lockQueues.set(lockPath, queue);
|
|
3006
|
+
}
|
|
3007
|
+
return queue(async () => {
|
|
3008
|
+
const token = await acquireFileLock(lockPath);
|
|
3009
|
+
const heartbeat = setInterval(() => refreshLock(lockPath, token), LOCK_HEARTBEAT_INTERVAL_MS);
|
|
3010
|
+
heartbeat.unref();
|
|
3011
|
+
try {
|
|
3012
|
+
return await fn();
|
|
3013
|
+
} finally {
|
|
3014
|
+
clearInterval(heartbeat);
|
|
3015
|
+
releaseFileLock(lockPath, token);
|
|
3016
|
+
}
|
|
3017
|
+
});
|
|
3018
|
+
}
|
|
3019
|
+
async function acquireFileLock(lockPath) {
|
|
3020
|
+
mkdirSync(path.dirname(lockPath), { recursive: true });
|
|
3021
|
+
const token = randomUUID();
|
|
3022
|
+
const deadline = Date.now() + LOCK_ACQUIRE_TIMEOUT_MS;
|
|
3023
|
+
for (;;) {
|
|
3024
|
+
let created = true;
|
|
3025
|
+
try {
|
|
3026
|
+
mkdirSync(lockPath);
|
|
3027
|
+
} catch (error) {
|
|
3028
|
+
if (error.code !== "EEXIST") throw error;
|
|
3029
|
+
created = false;
|
|
3030
|
+
}
|
|
3031
|
+
if (created) {
|
|
3032
|
+
try {
|
|
3033
|
+
writeFileSync(path.join(lockPath, "owner.json"), JSON.stringify({
|
|
3034
|
+
pid: process.pid,
|
|
3035
|
+
token
|
|
3036
|
+
}));
|
|
3037
|
+
} catch (error) {
|
|
3038
|
+
rmSync(lockPath, {
|
|
3039
|
+
recursive: true,
|
|
3040
|
+
force: true
|
|
3041
|
+
});
|
|
3042
|
+
throw error;
|
|
3043
|
+
}
|
|
3044
|
+
return token;
|
|
3045
|
+
}
|
|
3046
|
+
if (isLockExpired(lockPath) && stealLock(lockPath)) continue;
|
|
3047
|
+
if (Date.now() >= deadline) throw new Error("Timed out waiting for another deploy to the same workspace and application to finish. Wait for it to complete and retry; an interrupted deploy recovers automatically within a minute.");
|
|
3048
|
+
await new Promise((resolve) => setTimeout(resolve, LOCK_POLL_INTERVAL_MS));
|
|
3049
|
+
}
|
|
3050
|
+
}
|
|
3051
|
+
function isLockExpired(lockPath) {
|
|
3052
|
+
try {
|
|
3053
|
+
return Date.now() - statSync(lockPath).mtimeMs > LOCK_LEASE_MS;
|
|
3054
|
+
} catch {
|
|
3055
|
+
return false;
|
|
3056
|
+
}
|
|
3057
|
+
}
|
|
3058
|
+
function readLockToken(lockPath) {
|
|
3059
|
+
try {
|
|
3060
|
+
return JSON.parse(readFileSync(path.join(lockPath, "owner.json"), "utf-8")).token;
|
|
3061
|
+
} catch {
|
|
3062
|
+
return;
|
|
3063
|
+
}
|
|
3064
|
+
}
|
|
3065
|
+
function refreshLock(lockPath, token) {
|
|
3066
|
+
if (readLockToken(lockPath) !== token) return;
|
|
3067
|
+
const now = /* @__PURE__ */ new Date();
|
|
3068
|
+
try {
|
|
3069
|
+
utimesSync(lockPath, now, now);
|
|
3070
|
+
} catch {}
|
|
3071
|
+
}
|
|
3072
|
+
function releaseFileLock(lockPath, token) {
|
|
3073
|
+
if (readLockToken(lockPath) !== token) return;
|
|
3074
|
+
rmSync(lockPath, {
|
|
3075
|
+
recursive: true,
|
|
3076
|
+
force: true
|
|
3077
|
+
});
|
|
3078
|
+
}
|
|
3079
|
+
function stealLock(lockPath) {
|
|
3080
|
+
const trash = `${lockPath}.stale-${process.pid}-${Date.now()}`;
|
|
3081
|
+
try {
|
|
3082
|
+
renameSync(lockPath, trash);
|
|
3083
|
+
} catch {
|
|
3084
|
+
return false;
|
|
3085
|
+
}
|
|
3086
|
+
if (isLockExpired(trash)) {
|
|
3087
|
+
rmSync(trash, {
|
|
3088
|
+
recursive: true,
|
|
3089
|
+
force: true
|
|
3090
|
+
});
|
|
3091
|
+
return true;
|
|
3092
|
+
}
|
|
3093
|
+
try {
|
|
3094
|
+
renameSync(trash, lockPath);
|
|
3095
|
+
} catch {
|
|
3096
|
+
rmSync(trash, {
|
|
3097
|
+
recursive: true,
|
|
3098
|
+
force: true
|
|
3099
|
+
});
|
|
3100
|
+
}
|
|
3101
|
+
return false;
|
|
3102
|
+
}
|
|
2919
3103
|
|
|
2920
3104
|
//#endregion
|
|
2921
3105
|
//#region src/cli/commands/deploy/auth-connection.ts
|
|
@@ -3074,44 +3258,44 @@ async function planAuthConnections(client, workspaceId, appName, appId, auths) {
|
|
|
3074
3258
|
async function applyAuthConnections(client, result, phase) {
|
|
3075
3259
|
const { changeSet, stateScope } = result;
|
|
3076
3260
|
if (phase === "create-update") {
|
|
3077
|
-
|
|
3078
|
-
await
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3261
|
+
if (changeSet.creates.length > 0 || changeSet.replaces.length > 0) await withSecretsStateLock(stateScope, async () => {
|
|
3262
|
+
await Promise.all(changeSet.creates.map(async (create) => {
|
|
3263
|
+
await client.createAuthConnection(create.request);
|
|
3264
|
+
await client.setMetadata(create.metaRequest);
|
|
3265
|
+
logger.info(`Connection "${create.name}" was created. Authorize it with:\n tailor-sdk authconnection authorize --name ${create.name}\nOr via the Console: tailor-sdk authconnection open`);
|
|
3266
|
+
}));
|
|
3267
|
+
for (const replace of changeSet.replaces) {
|
|
3268
|
+
if ((await client.updateAuthConnection(replace.updateRequest)).connection?.status === AuthConnection_Status.UNAUTHORIZED) logger.warn(`Connection "${replace.name}" requires re-authorization. Authorize with:\n tailor-sdk authconnection authorize --name ${replace.name}\nOr via the Console: tailor-sdk authconnection open`);
|
|
3269
|
+
await client.setMetadata(replace.metaRequest);
|
|
3270
|
+
}
|
|
3271
|
+
const secretReplaces = changeSet.replaces.filter((replace) => replace.updateRequest.updateMask?.paths?.includes("oauth2.client_secret"));
|
|
3272
|
+
if (changeSet.creates.length > 0 || secretReplaces.length > 0) {
|
|
3273
|
+
const state = loadSecretsState(stateScope);
|
|
3274
|
+
if (!state.connections) state.connections = {};
|
|
3275
|
+
for (const create of changeSet.creates) {
|
|
3276
|
+
const conn = create.request.connection;
|
|
3277
|
+
if (conn?.config?.case === "oauth2") state.connections[create.name] = hashValue(conn.config.value.clientSecret ?? "");
|
|
3278
|
+
}
|
|
3279
|
+
for (const replace of secretReplaces) {
|
|
3280
|
+
const conn = replace.updateRequest.connection;
|
|
3281
|
+
if (conn?.config?.case === "oauth2") state.connections[replace.name] = hashValue(conn.config.value.clientSecret ?? "");
|
|
3282
|
+
}
|
|
3283
|
+
saveSecretsState(stateScope, state);
|
|
3284
|
+
}
|
|
3285
|
+
});
|
|
3086
3286
|
await Promise.all(changeSet.updates.map(async (update) => {
|
|
3087
3287
|
await client.setMetadata(update.metaRequest);
|
|
3088
3288
|
}));
|
|
3089
|
-
|
|
3090
|
-
if (changeSet.creates.length > 0 || secretReplaces.length > 0) {
|
|
3091
|
-
const state = loadSecretsState(stateScope);
|
|
3092
|
-
if (!state.connections) state.connections = {};
|
|
3093
|
-
for (const create of changeSet.creates) {
|
|
3094
|
-
const conn = create.request.connection;
|
|
3095
|
-
if (conn?.config?.case === "oauth2") state.connections[create.name] = hashValue(conn.config.value.clientSecret ?? "");
|
|
3096
|
-
}
|
|
3097
|
-
for (const replace of secretReplaces) {
|
|
3098
|
-
const conn = replace.updateRequest.connection;
|
|
3099
|
-
if (conn?.config?.case === "oauth2") state.connections[replace.name] = hashValue(conn.config.value.clientSecret ?? "");
|
|
3100
|
-
}
|
|
3101
|
-
saveSecretsState(stateScope, state);
|
|
3102
|
-
}
|
|
3103
|
-
} else {
|
|
3289
|
+
} else if (changeSet.deletes.length > 0) await withSecretsStateLock(stateScope, async () => {
|
|
3104
3290
|
await Promise.all(changeSet.deletes.map(async (del) => {
|
|
3105
3291
|
await client.deleteAuthConnection(del.request);
|
|
3106
3292
|
}));
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
saveSecretsState(stateScope, state);
|
|
3112
|
-
}
|
|
3293
|
+
const state = loadSecretsState(stateScope);
|
|
3294
|
+
if (state.connections) {
|
|
3295
|
+
for (const del of changeSet.deletes) delete state.connections[del.name];
|
|
3296
|
+
saveSecretsState(stateScope, state);
|
|
3113
3297
|
}
|
|
3114
|
-
}
|
|
3298
|
+
});
|
|
3115
3299
|
}
|
|
3116
3300
|
|
|
3117
3301
|
//#endregion
|
|
@@ -3424,14 +3608,14 @@ async function uploadFunctionScript(client, workspaceId, entry, isCreate) {
|
|
|
3424
3608
|
async function applyFunctionRegistry(client, workspaceId, result, phase = "create-update") {
|
|
3425
3609
|
const { changeSet } = result;
|
|
3426
3610
|
if (phase === "create-update") {
|
|
3427
|
-
|
|
3611
|
+
const limitFunction = createApplyLimiter();
|
|
3612
|
+
await Promise.all([...changeSet.creates.map((create) => limitFunction(async () => {
|
|
3428
3613
|
await uploadFunctionScript(client, workspaceId, create.entry, true);
|
|
3429
3614
|
await client.setMetadata(create.metaRequest);
|
|
3430
|
-
}
|
|
3431
|
-
for (const update of changeSet.updates) {
|
|
3615
|
+
})), ...changeSet.updates.map((update) => limitFunction(async () => {
|
|
3432
3616
|
await uploadFunctionScript(client, workspaceId, update.entry, false);
|
|
3433
3617
|
await client.setMetadata(update.metaRequest);
|
|
3434
|
-
}
|
|
3618
|
+
}))]);
|
|
3435
3619
|
} else await Promise.all(changeSet.deletes.map((del) => client.deleteFunctionRegistry({
|
|
3436
3620
|
workspaceId: del.workspaceId,
|
|
3437
3621
|
name: del.name
|
|
@@ -6276,17 +6460,20 @@ async function planSecretManager(context) {
|
|
|
6276
6460
|
name: vaultName,
|
|
6277
6461
|
workspaceId
|
|
6278
6462
|
});
|
|
6279
|
-
|
|
6280
|
-
if (existing)
|
|
6281
|
-
const
|
|
6282
|
-
|
|
6283
|
-
|
|
6284
|
-
|
|
6285
|
-
|
|
6463
|
+
const existingSecretTimes = /* @__PURE__ */ new Map();
|
|
6464
|
+
if (existing) {
|
|
6465
|
+
const secrets = await fetchAllTolerant(async (pageToken, maxPageSize) => {
|
|
6466
|
+
const { secrets, nextPageToken } = await client.listSecretManagerSecrets({
|
|
6467
|
+
workspaceId,
|
|
6468
|
+
secretmanagerVaultName: vaultName,
|
|
6469
|
+
pageToken,
|
|
6470
|
+
pageSize: maxPageSize
|
|
6471
|
+
});
|
|
6472
|
+
return [secrets, nextPageToken];
|
|
6286
6473
|
});
|
|
6287
|
-
|
|
6288
|
-
}
|
|
6289
|
-
const existingSet = new Set(
|
|
6474
|
+
for (const secret of secrets) existingSecretTimes.set(secret.name, serializeUpdateTime(secret.updateTime));
|
|
6475
|
+
}
|
|
6476
|
+
const existingSet = new Set(existingSecretTimes.keys());
|
|
6290
6477
|
for (const secret of vault.secrets) {
|
|
6291
6478
|
if (secret.value == null) {
|
|
6292
6479
|
existingSet.delete(secret.name);
|
|
@@ -6294,9 +6481,10 @@ async function planSecretManager(context) {
|
|
|
6294
6481
|
continue;
|
|
6295
6482
|
}
|
|
6296
6483
|
if (existingSet.has(secret.name)) {
|
|
6297
|
-
const
|
|
6298
|
-
const
|
|
6299
|
-
|
|
6484
|
+
const stored = state.vaults[vaultName]?.[secret.name];
|
|
6485
|
+
const remoteUpdateTime = existingSecretTimes.get(secret.name);
|
|
6486
|
+
const unchanged = stored !== void 0 && stored.hash === hashValue(secret.value) && stored.updateTime !== void 0 && stored.updateTime === remoteUpdateTime;
|
|
6487
|
+
if (forceApplyAll || !unchanged) secretChangeSet.updates.push({
|
|
6300
6488
|
name: `${vaultName}/${secret.name}`,
|
|
6301
6489
|
secretName: secret.name,
|
|
6302
6490
|
workspaceId,
|
|
@@ -6389,18 +6577,31 @@ async function applySecretManager(client, result, phase = "create-update", appli
|
|
|
6389
6577
|
});
|
|
6390
6578
|
await client.setMetadata(metaRequest);
|
|
6391
6579
|
}));
|
|
6392
|
-
await Promise.all(secretChangeSet.creates.map((create) => client.createSecretManagerSecret(secretCreateRequest(create))));
|
|
6393
|
-
await Promise.all(secretChangeSet.updates.map((update) => client.updateSecretManagerSecret(secretUpdateRequest(update))));
|
|
6394
6580
|
const secretHashUpdates = [...secretChangeSet.creates, ...secretChangeSet.updates];
|
|
6395
|
-
if (
|
|
6396
|
-
const
|
|
6397
|
-
|
|
6398
|
-
|
|
6399
|
-
|
|
6581
|
+
if (secretHashUpdates.length > 0) await withSecretsStateLock(stateScope, async () => {
|
|
6582
|
+
const appliedUpdateTimes = /* @__PURE__ */ new Map();
|
|
6583
|
+
await Promise.all(secretChangeSet.creates.map(async (create) => {
|
|
6584
|
+
const response = await client.createSecretManagerSecret(secretCreateRequest(create));
|
|
6585
|
+
appliedUpdateTimes.set(create.name, serializeUpdateTime(response.secret?.updateTime));
|
|
6586
|
+
}));
|
|
6587
|
+
await Promise.all(secretChangeSet.updates.map(async (update) => {
|
|
6588
|
+
const response = await client.updateSecretManagerSecret(secretUpdateRequest(update));
|
|
6589
|
+
appliedUpdateTimes.set(update.name, serializeUpdateTime(response.secret?.updateTime));
|
|
6590
|
+
}));
|
|
6591
|
+
if (application) {
|
|
6592
|
+
const state = loadSecretsState(stateScope);
|
|
6593
|
+
for (const secret of secretHashUpdates) {
|
|
6594
|
+
if (!Object.hasOwn(state.vaults, secret.vaultName)) state.vaults[secret.vaultName] = {};
|
|
6595
|
+
const updateTime = appliedUpdateTimes.get(secret.name);
|
|
6596
|
+
assertDefined(state.vaults[secret.vaultName], "vault state entry missing")[secret.secretName] = {
|
|
6597
|
+
hash: hashValue(secret.value),
|
|
6598
|
+
...updateTime === void 0 ? {} : { updateTime }
|
|
6599
|
+
};
|
|
6600
|
+
}
|
|
6601
|
+
saveSecretsState(stateScope, state);
|
|
6400
6602
|
}
|
|
6401
|
-
|
|
6402
|
-
|
|
6403
|
-
} else {
|
|
6603
|
+
});
|
|
6604
|
+
} else if (secretChangeSet.deletes.length > 0 || vaultChangeSet.deletes.length > 0) await withSecretsStateLock(stateScope, async () => {
|
|
6404
6605
|
await Promise.all(secretChangeSet.deletes.map((del) => client.deleteSecretManagerSecret({
|
|
6405
6606
|
workspaceId: del.workspaceId,
|
|
6406
6607
|
secretmanagerVaultName: del.vaultName,
|
|
@@ -6410,16 +6611,14 @@ async function applySecretManager(client, result, phase = "create-update", appli
|
|
|
6410
6611
|
workspaceId: del.workspaceId,
|
|
6411
6612
|
secretmanagerVaultName: del.name
|
|
6412
6613
|
})));
|
|
6413
|
-
|
|
6414
|
-
|
|
6415
|
-
|
|
6416
|
-
|
|
6417
|
-
if (Object.keys(assertDefined(state.vaults[del.vaultName], "vault state entry missing")).length === 0) delete state.vaults[del.vaultName];
|
|
6418
|
-
}
|
|
6419
|
-
for (const del of vaultChangeSet.deletes) delete state.vaults[del.name];
|
|
6420
|
-
saveSecretsState(stateScope, state);
|
|
6614
|
+
const state = loadSecretsState(stateScope);
|
|
6615
|
+
for (const del of secretChangeSet.deletes) if (Object.hasOwn(state.vaults, del.vaultName)) {
|
|
6616
|
+
delete assertDefined(state.vaults[del.vaultName], "vault state entry missing")[del.secretName];
|
|
6617
|
+
if (Object.keys(assertDefined(state.vaults[del.vaultName], "vault state entry missing")).length === 0) delete state.vaults[del.vaultName];
|
|
6421
6618
|
}
|
|
6422
|
-
|
|
6619
|
+
for (const del of vaultChangeSet.deletes) delete state.vaults[del.name];
|
|
6620
|
+
saveSecretsState(stateScope, state);
|
|
6621
|
+
});
|
|
6423
6622
|
}
|
|
6424
6623
|
|
|
6425
6624
|
//#endregion
|
|
@@ -9248,19 +9447,21 @@ function handleOptionalToRequiredError(error, messages) {
|
|
|
9248
9447
|
* 1. Imports the migration script's main function
|
|
9249
9448
|
* 2. Defines getDB() function inline
|
|
9250
9449
|
* 3. Wraps migration in a transaction using getDB()
|
|
9251
|
-
* 4. Exports as main() for
|
|
9450
|
+
* 4. Exports as main() for server-side execution
|
|
9252
9451
|
* @param {string} sourceFile - Path to the migration script file
|
|
9253
9452
|
* @param {string} namespace - TailorDB namespace
|
|
9254
9453
|
* @param {number} migrationNumber - Migration number
|
|
9255
9454
|
* @param {Record<string, string | number | boolean>} env - Environment variables to inject into the migration context
|
|
9455
|
+
* @param {string} [baseDir] - Directory to resolve the bundler's tsconfig against; defaults to the migration script's directory
|
|
9256
9456
|
* @returns {Promise<MigrationBundleResult>} Bundled migration result
|
|
9257
9457
|
*/
|
|
9258
|
-
async function bundleMigrationScript(sourceFile, namespace, migrationNumber, env = {}) {
|
|
9458
|
+
async function bundleMigrationScript(sourceFile, namespace, migrationNumber, env = {}, baseDir) {
|
|
9259
9459
|
const outputDir = path.resolve(getDistDir(), "migrations");
|
|
9260
9460
|
fs$1.mkdirSync(outputDir, { recursive: true });
|
|
9261
9461
|
const entryPath = path.join(outputDir, `migration_${namespace}_${migrationNumber}.entry.js`);
|
|
9462
|
+
const absoluteSourcePath = path.resolve(sourceFile).replace(/\\/g, "/");
|
|
9262
9463
|
const entryContent = multiline`
|
|
9263
|
-
import { main as _migrationMain } from "${
|
|
9464
|
+
import { main as _migrationMain } from "${absoluteSourcePath}";
|
|
9264
9465
|
import { Kysely, TailordbDialect } from "@tailor-platform/sdk/kysely";
|
|
9265
9466
|
|
|
9266
9467
|
function getDB(namespace) {
|
|
@@ -9280,12 +9481,7 @@ async function bundleMigrationScript(sourceFile, namespace, migrationNumber, env
|
|
|
9280
9481
|
}
|
|
9281
9482
|
`;
|
|
9282
9483
|
fs$1.writeFileSync(entryPath, entryContent);
|
|
9283
|
-
|
|
9284
|
-
try {
|
|
9285
|
-
tsconfig = await resolveTSConfig();
|
|
9286
|
-
} catch {
|
|
9287
|
-
tsconfig = void 0;
|
|
9288
|
-
}
|
|
9484
|
+
const tsconfig = await resolveTSConfigWithFallback(baseDir ?? path.dirname(absoluteSourcePath));
|
|
9289
9485
|
return {
|
|
9290
9486
|
namespace,
|
|
9291
9487
|
migrationNumber,
|
|
@@ -9621,12 +9817,12 @@ async function detectPendingMigrations(client, workspaceId, namespacesWithMigrat
|
|
|
9621
9817
|
* @returns {Promise<ExecutionResult>} Execution result
|
|
9622
9818
|
*/
|
|
9623
9819
|
async function executeSingleMigration(options, migration) {
|
|
9624
|
-
const { client, workspaceId, authInvoker, env } = options;
|
|
9820
|
+
const { client, workspaceId, authInvoker, env, configDir } = options;
|
|
9625
9821
|
const result = await executeScript({
|
|
9626
9822
|
client,
|
|
9627
9823
|
workspaceId,
|
|
9628
9824
|
name: `migration-${migration.namespace}-${formatMigrationNumber(migration.number)}.js`,
|
|
9629
|
-
code: (await bundleMigrationScript(migration.scriptPath, migration.namespace, migration.number, env)).bundledCode,
|
|
9825
|
+
code: (await bundleMigrationScript(migration.scriptPath, migration.namespace, migration.number, env, configDir)).bundledCode,
|
|
9630
9826
|
invoker: authInvoker
|
|
9631
9827
|
});
|
|
9632
9828
|
return {
|
|
@@ -9680,7 +9876,8 @@ async function executeMigrations(context, migrations) {
|
|
|
9680
9876
|
client: context.client,
|
|
9681
9877
|
workspaceId: context.workspaceId,
|
|
9682
9878
|
authInvoker,
|
|
9683
|
-
env: context.env
|
|
9879
|
+
env: context.env,
|
|
9880
|
+
configDir: context.configDir
|
|
9684
9881
|
};
|
|
9685
9882
|
logger.info(`Using machine user: ${styles.bold(machineUserName)} for namespace '${namespace}'`);
|
|
9686
9883
|
for (const migration of namespaceMigrations) {
|
|
@@ -9993,7 +10190,8 @@ function buildMigrationContextForScripts(client, migrationContext, migrationsReq
|
|
|
9993
10190
|
authNamespace: authService.config.name,
|
|
9994
10191
|
machineUsers: authService.config.machineUsers ? Object.keys(authService.config.machineUsers) : void 0,
|
|
9995
10192
|
dbConfig: dbConfigMap,
|
|
9996
|
-
env: migrationContext.config.env ?? {}
|
|
10193
|
+
env: migrationContext.config.env ?? {},
|
|
10194
|
+
configDir: path.dirname(migrationContext.config.path)
|
|
9997
10195
|
};
|
|
9998
10196
|
}
|
|
9999
10197
|
/**
|
|
@@ -12907,6 +13105,15 @@ function collectVisibleResolverNamespaces(application, applications) {
|
|
|
12907
13105
|
addResource: addPossiblyAmbiguousNamespace
|
|
12908
13106
|
});
|
|
12909
13107
|
}
|
|
13108
|
+
/**
|
|
13109
|
+
* Detect whether any resource owned by this application was last applied by a
|
|
13110
|
+
* different SDK version, in which case every resource is re-applied.
|
|
13111
|
+
* @param client - Operator client instance
|
|
13112
|
+
* @param workspaceId - Workspace ID
|
|
13113
|
+
* @param application - Application being deployed
|
|
13114
|
+
* @param functionEntries - Function registry entries of the application
|
|
13115
|
+
* @returns True when an owned resource carries a different sdk-version label
|
|
13116
|
+
*/
|
|
12910
13117
|
async function shouldForceApplyAll(client, workspaceId, application, functionEntries) {
|
|
12911
13118
|
const desiredLabels = (await buildMetaRequest({
|
|
12912
13119
|
trn: resourceTrn(workspaceId, "application", application.name),
|
|
@@ -12943,14 +13150,13 @@ async function shouldForceApplyAll(client, workspaceId, application, functionEnt
|
|
|
12943
13150
|
functionEntries.forEach((entry) => {
|
|
12944
13151
|
candidateTrns.add(resourceTrn(workspaceId, "function_registry", entry.name));
|
|
12945
13152
|
});
|
|
12946
|
-
|
|
12947
|
-
const metadata = await
|
|
12948
|
-
|
|
12949
|
-
|
|
12950
|
-
|
|
12951
|
-
|
|
12952
|
-
|
|
12953
|
-
}
|
|
13153
|
+
const results = await Promise.allSettled([...candidateTrns].map((trn) => getOrNull(async () => {
|
|
13154
|
+
const { metadata } = await client.getMetadata({ trn });
|
|
13155
|
+
return metadata;
|
|
13156
|
+
})));
|
|
13157
|
+
if (results.some((result) => result.status === "fulfilled" && result.value?.labels["sdk-name"] === application.name && !hasMatchingSdkVersion(result.value.labels, desiredLabels))) return true;
|
|
13158
|
+
const failure = results.find((result) => result.status === "rejected");
|
|
13159
|
+
if (failure) throw failure.reason;
|
|
12954
13160
|
return false;
|
|
12955
13161
|
}
|
|
12956
13162
|
/**
|
|
@@ -13282,6 +13488,7 @@ async function loadDeployConfig(params) {
|
|
|
13282
13488
|
}
|
|
13283
13489
|
async function buildDeploymentTargets(params) {
|
|
13284
13490
|
const { configPaths, loadedConfigs, buildTarget = buildDeploymentTarget, ...targetParams } = params;
|
|
13491
|
+
await removeLegacyBundleFiles(path.resolve(getDistDir()));
|
|
13285
13492
|
return Promise.all(configPaths.map((configPath, index) => buildTarget({
|
|
13286
13493
|
...targetParams,
|
|
13287
13494
|
configPath,
|
|
@@ -16223,6 +16430,7 @@ function hasDependency(generator, dependency) {
|
|
|
16223
16430
|
|
|
16224
16431
|
//#endregion
|
|
16225
16432
|
//#region src/cli/commands/generate/watch/index.ts
|
|
16433
|
+
const warnedFallbacks = /* @__PURE__ */ new Set();
|
|
16226
16434
|
/**
|
|
16227
16435
|
* Error codes.
|
|
16228
16436
|
*/
|
|
@@ -16377,6 +16585,22 @@ function createDependencyGraphManager(options = {}) {
|
|
|
16377
16585
|
};
|
|
16378
16586
|
}
|
|
16379
16587
|
/**
|
|
16588
|
+
* Resolve a watch group's glob patterns against baseDir into absolute file paths.
|
|
16589
|
+
* @param groupId - Watch group identifier, used only for the progress log line
|
|
16590
|
+
* @param patterns - Glob patterns to resolve
|
|
16591
|
+
* @param baseDir - Directory relative patterns are resolved against
|
|
16592
|
+
* @returns Absolute paths of every matched file
|
|
16593
|
+
*/
|
|
16594
|
+
async function globPatterns(groupId, patterns, baseDir) {
|
|
16595
|
+
const files = /* @__PURE__ */ new Set();
|
|
16596
|
+
for (const pattern of patterns) {
|
|
16597
|
+
const absolutePattern = path.resolve(baseDir, pattern);
|
|
16598
|
+
logger.log(`${styles.dim(`Watch pattern for`)} ${styles.dim(groupId + ":")} ${path.relative(process.cwd(), absolutePattern)}`);
|
|
16599
|
+
for await (const file of glob(absolutePattern)) files.add(path.resolve(file));
|
|
16600
|
+
}
|
|
16601
|
+
return files;
|
|
16602
|
+
}
|
|
16603
|
+
/**
|
|
16380
16604
|
* Creates a dependency watcher.
|
|
16381
16605
|
* @param options - Watcher options
|
|
16382
16606
|
* @returns DependencyWatcher instance
|
|
@@ -16544,13 +16768,17 @@ function createDependencyWatcher(options = {}) {
|
|
|
16544
16768
|
}
|
|
16545
16769
|
return {
|
|
16546
16770
|
initialize,
|
|
16547
|
-
async addWatchGroup(groupId, patterns) {
|
|
16771
|
+
async addWatchGroup(groupId, patterns, baseDir) {
|
|
16548
16772
|
validateWatchGroup(groupId, patterns);
|
|
16549
16773
|
if (!isInitialized) await initialize();
|
|
16550
|
-
|
|
16551
|
-
|
|
16552
|
-
|
|
16553
|
-
|
|
16774
|
+
let files = await globPatterns(groupId, patterns, baseDir);
|
|
16775
|
+
if (files.size === 0 && baseDir !== process.cwd()) {
|
|
16776
|
+
const fallbackKey = `${baseDir}\0${groupId}`;
|
|
16777
|
+
if (!warnedFallbacks.has(fallbackKey)) {
|
|
16778
|
+
warnedFallbacks.add(fallbackKey);
|
|
16779
|
+
logger.warn(`No files matched watch patterns for "${groupId}" relative to "${baseDir}"; falling back to process.cwd(). Update this config's file patterns to be relative to its own directory before v2, when this fallback will be removed.`);
|
|
16780
|
+
}
|
|
16781
|
+
files = await globPatterns(groupId, patterns, process.cwd());
|
|
16554
16782
|
}
|
|
16555
16783
|
const watchGroup = {
|
|
16556
16784
|
id: groupId,
|
|
@@ -16567,7 +16795,7 @@ function createDependencyWatcher(options = {}) {
|
|
|
16567
16795
|
async removeWatchGroup(groupId) {
|
|
16568
16796
|
const watchGroup = watchGroups.get(groupId);
|
|
16569
16797
|
if (!watchGroup) return;
|
|
16570
|
-
if (chokidarWatcher) chokidarWatcher.unwatch(watchGroup.
|
|
16798
|
+
if (chokidarWatcher) chokidarWatcher.unwatch(Array.from(watchGroup.files));
|
|
16571
16799
|
for (const filePath of watchGroup.files) dependencyGraphManager.removeNode(filePath);
|
|
16572
16800
|
watchGroups.delete(groupId);
|
|
16573
16801
|
dependencyCache.clear();
|
|
@@ -16967,7 +17195,10 @@ function createGenerationManager(params) {
|
|
|
16967
17195
|
const pluginExecutorFiles = generatePluginFilesIfNeeded(pluginManager, app.tailorDBServices, config.path);
|
|
16968
17196
|
return {
|
|
16969
17197
|
pluginExecutorFiles,
|
|
16970
|
-
executorService: app.executorService ?? (pluginExecutorFiles.length > 0 ? createExecutorService({
|
|
17198
|
+
executorService: app.executorService ?? (pluginExecutorFiles.length > 0 ? createExecutorService({
|
|
17199
|
+
config: { files: [] },
|
|
17200
|
+
baseDir: path.dirname(config.path)
|
|
17201
|
+
}) : void 0)
|
|
16971
17202
|
};
|
|
16972
17203
|
});
|
|
16973
17204
|
if (app.authService) {
|
|
@@ -17034,15 +17265,16 @@ function createGenerationManager(params) {
|
|
|
17034
17265
|
watcher.setRestartCallback(() => {
|
|
17035
17266
|
restartWatchProcess();
|
|
17036
17267
|
});
|
|
17037
|
-
|
|
17268
|
+
const configDir = path.dirname(config.path);
|
|
17269
|
+
await watcher.addWatchGroup("Config", [config.path], configDir);
|
|
17038
17270
|
const app = application;
|
|
17039
17271
|
for (const db of app.tailorDBServices) {
|
|
17040
17272
|
const dbNamespace = db.namespace;
|
|
17041
|
-
await watcher.addWatchGroup(`TailorDB/${dbNamespace}`, db.config.files);
|
|
17273
|
+
await watcher.addWatchGroup(`TailorDB/${dbNamespace}`, db.config.files, configDir);
|
|
17042
17274
|
}
|
|
17043
17275
|
for (const resolverService of app.resolverServices) {
|
|
17044
17276
|
const resolverNamespace = resolverService.namespace;
|
|
17045
|
-
await watcher.addWatchGroup(`Resolver/${resolverNamespace}`, resolverService["config"].files);
|
|
17277
|
+
await watcher.addWatchGroup(`Resolver/${resolverNamespace}`, resolverService["config"].files, configDir);
|
|
17046
17278
|
}
|
|
17047
17279
|
await new Promise(() => {});
|
|
17048
17280
|
}
|
|
@@ -18690,7 +18922,7 @@ async function generate(options) {
|
|
|
18690
18922
|
if (options.init) await handleInitOption(namespacesWithMigrations, options.yes);
|
|
18691
18923
|
let pluginManager;
|
|
18692
18924
|
if (plugins.length > 0) pluginManager = new PluginManager(plugins);
|
|
18693
|
-
const { defineApplication } = await import("./application-
|
|
18925
|
+
const { defineApplication } = await import("./application-Nlh9BHQf.mjs");
|
|
18694
18926
|
const application = defineApplication({
|
|
18695
18927
|
config,
|
|
18696
18928
|
pluginManager
|
|
@@ -19894,20 +20126,16 @@ function createGqlEntry() {
|
|
|
19894
20126
|
/**
|
|
19895
20127
|
* Bundle a query executor script for TestExecScript.
|
|
19896
20128
|
* @param engine - Query engine type
|
|
20129
|
+
* @param baseDir - Directory to resolve the bundler's tsconfig against
|
|
19897
20130
|
* @returns Bundled code
|
|
19898
20131
|
*/
|
|
19899
|
-
async function bundleQueryScript(engine) {
|
|
20132
|
+
async function bundleQueryScript(engine, baseDir) {
|
|
19900
20133
|
const outputDir = path.resolve(getDistDir(), "query");
|
|
19901
20134
|
fs$1.mkdirSync(outputDir, { recursive: true });
|
|
19902
20135
|
const entryPath = path.join(outputDir, `query_${engine}.entry.ts`);
|
|
19903
20136
|
const entryContent = engine === "sql" ? createSqlEntry() : createGqlEntry();
|
|
19904
20137
|
fs$1.writeFileSync(entryPath, entryContent);
|
|
19905
|
-
|
|
19906
|
-
try {
|
|
19907
|
-
tsconfig = await resolveTSConfig();
|
|
19908
|
-
} catch {
|
|
19909
|
-
tsconfig = void 0;
|
|
19910
|
-
}
|
|
20138
|
+
const tsconfig = await resolveTSConfigWithFallback(baseDir);
|
|
19911
20139
|
return (await rolldown.build({
|
|
19912
20140
|
plugins: [platformBundleDefinePlugin],
|
|
19913
20141
|
input: entryPath,
|
|
@@ -20169,7 +20397,7 @@ async function loadTypeFieldOrder(config, namespace) {
|
|
|
20169
20397
|
const fieldOrder = /* @__PURE__ */ new Map();
|
|
20170
20398
|
const dbConfig = config.db?.[namespace];
|
|
20171
20399
|
if (!dbConfig || !("files" in dbConfig) || dbConfig.files.length === 0) return fieldOrder;
|
|
20172
|
-
const typeFiles = loadFilesWithIgnores(dbConfig);
|
|
20400
|
+
const typeFiles = loadFilesWithIgnores(dbConfig, path.dirname(config.path));
|
|
20173
20401
|
await Promise.all(typeFiles.map(async (typeFile) => {
|
|
20174
20402
|
try {
|
|
20175
20403
|
const module = await import(pathToFileURL(typeFile).href);
|
|
@@ -20363,7 +20591,7 @@ async function query(options) {
|
|
|
20363
20591
|
}
|
|
20364
20592
|
async function prepareQueryExecutor(options) {
|
|
20365
20593
|
const { client, workspaceId, config, application, machineUserResource, engine, namespaces } = await loadOptions(options);
|
|
20366
|
-
const bundledCode = await bundleQueryScript(engine);
|
|
20594
|
+
const bundledCode = await bundleQueryScript(engine, path.dirname(config.path));
|
|
20367
20595
|
const invoker = create(AuthInvokerSchema, {
|
|
20368
20596
|
namespace: application.authNamespace,
|
|
20369
20597
|
machineUserName: machineUserResource.name
|
|
@@ -20775,5 +21003,52 @@ function isDeno() {
|
|
|
20775
21003
|
}
|
|
20776
21004
|
|
|
20777
21005
|
//#endregion
|
|
20778
|
-
|
|
20779
|
-
|
|
21006
|
+
//#region src/cli/shared/register-tsconfig-paths-hook.ts
|
|
21007
|
+
/**
|
|
21008
|
+
* Register the tsconfig `paths` alias resolve hook alongside tsx.
|
|
21009
|
+
*
|
|
21010
|
+
* tsx's own tsconfig-paths support is scoped to the tsconfig discovered from
|
|
21011
|
+
* where tsx was registered, so a project-local alias in a dynamically
|
|
21012
|
+
* imported user file (resolver, executor, workflow, TailorDB type) can fail
|
|
21013
|
+
* to resolve when the importing file lives outside that directory. This
|
|
21014
|
+
* hook activates only when tsx's own resolution throws (a fallback, not an
|
|
21015
|
+
* override): it then re-derives `paths` from each importing file's own
|
|
21016
|
+
* directory, without touching TypeScript transformation (left to tsx).
|
|
21017
|
+
*
|
|
21018
|
+
* Uses `module.register()` rather than `module.registerHooks()`: chaining
|
|
21019
|
+
* another `register()` loader after tsx's composes correctly regardless of
|
|
21020
|
+
* which of the two internal registration APIs tsx itself picks (it varies
|
|
21021
|
+
* by Node.js version).
|
|
21022
|
+
* @param hookUrl - URL of the tsconfig-paths-hook.mjs module.
|
|
21023
|
+
*/
|
|
21024
|
+
async function registerTsconfigPathsHook(hookUrl) {
|
|
21025
|
+
if (isNativeTypeScriptRuntime()) return;
|
|
21026
|
+
if (typeof mod.register !== "function") return;
|
|
21027
|
+
mod.register(hookUrl);
|
|
21028
|
+
}
|
|
21029
|
+
|
|
21030
|
+
//#endregion
|
|
21031
|
+
//#region src/cli/shared/register-typescript-runtime.ts
|
|
21032
|
+
/**
|
|
21033
|
+
* Register TypeScript loading for the CLI: tsx for transformation, plus the
|
|
21034
|
+
* tsconfig `paths` alias resolve hook tsx's own cwd-scoped resolver misses.
|
|
21035
|
+
*
|
|
21036
|
+
* Shared by both the `tailor` binary entrypoint and the programmatic `./cli`
|
|
21037
|
+
* API entrypoint so the two registration steps can't drift apart.
|
|
21038
|
+
* @param hookUrl - URL of the tsconfig-paths-hook.mjs module, resolved by the
|
|
21039
|
+
* caller via its own `import.meta.url`. Bundling can move this shared module
|
|
21040
|
+
* to a different output location than tsconfig-paths-hook.mjs, so the URL
|
|
21041
|
+
* can't be resolved relative to this file — it must come from an entrypoint
|
|
21042
|
+
* whose bundled output path stays predictable.
|
|
21043
|
+
*/
|
|
21044
|
+
async function registerTypeScriptRuntime(hookUrl) {
|
|
21045
|
+
if (!isNativeTypeScriptRuntime()) {
|
|
21046
|
+
const { register } = await import("tsx/esm/api");
|
|
21047
|
+
register();
|
|
21048
|
+
}
|
|
21049
|
+
await registerTsconfigPathsHook(hookUrl);
|
|
21050
|
+
}
|
|
21051
|
+
|
|
21052
|
+
//#endregion
|
|
21053
|
+
export { listFolders as $, deploymentArgs as $n, handleOptionalToRequiredError as $t, generate as A, generateUserTypes as An, startCommand as At, remove as B, loadConsoleBaseUrl as Bn, deploy as Bt, waitWorkflowExecution as C, formatDiffSummary as Cn, listCommand$8 as Ct, listWorkflows as D, resourceTrn as Dn, jobsCommand as Dt, listCommand$2 as E, getNamespacesWithMigrations as En, getExecutorWaitFailureMessage as Et, openInConfiguredEditor as F, deleteUserTokens as Fn, getWorkflowExecution as Ft, treeCommand as G, readPlatformConfig as Gn, createWorkspace$1 as Gt, updateCommand$1 as H, loadStoredUserTokens as Hn, listCommand$9 as Ht, show as I, fetchLatestToken as In, listWorkflowExecutions as It, getCommand$1 as J, writePlatformConfig as Jn, ensureConfigId as Jt, listCommand$3 as K, resolveUserTokenKey as Kn, formatKeyValueTable as Kt, showCommand as L, hasAnyUserTokenEntry as Ln, functionExecutionStatusToString as Lt, generateMigrationScript as M, apiCall as Mn, getCommand$5 as Mt, writeDbTypesFile as N, assertWritable as Nn, getWorkflow as Nt, truncate as O, sdkNameLabelKey as On, listExecutorJobs as Ot, getConfiguredEditorCommand as P, loadConfig as Pn, executionsCommand as Pt, listCommand$4 as Q, confirmationArgs as Qn, MIGRATION_LABEL_KEY as Qt, extractOwnedNamespaces as R, hasUserTokenEntry as Rn, getCommand$6 as Rt, waitCommand as S, parseMigrationNumberArg as Sn, triggerExecutor as St, resumeWorkflow as T, hasChanges as Tn, getExecutorJob as Tt, updateOrganization as U, loadWorkspaceId as Un, listWorkspaces as Ut, removeCommand$1 as V, loadMachineUserName as Vn, deployFromCLI as Vt, organizationTree as W, platformConfigFromProfile as Wn, createCommand$1 as Wt, updateCommand$2 as X, commonArgs as Xn, waitForExecution as Xt, getOrganization as Y, defineAppCommand as Yn, executeScript as Yt, updateFolder as Z, configArg as Zn, bundleMigrationScript as Zt, deleteWorkspace as _, getNextMigrationNumber as _n, getCommand$4 as _t, updateUser as a, DIFF_FILE_NAME as an, toPageDirection as ar, createFolder as at, getAppHealth as b, reconstructSnapshotFromMigrations as bn, webhookCommand as bt, listCommand as c, SCHEMA_FILE_NAME as cn, getCommand$3 as ct, inviteUser as d, compareSnapshots as dn, tokenCommand as dt, parseMigrationLabelNumber as en, isVerbose as er, getCommand$2 as et, restoreCommand as f, createSnapshotFromLocalTypes as fn, listCommand$6 as ft, deleteCommand as g, getMigrationFiles as gn, listFunctionRegistries as gt, getWorkspace as h, getMigrationFilePath as hn, listCommand$7 as ht, updateCommand as i, DB_TYPES_FILE_NAME as in, resolveMachineUserInputSource as ir, createCommand as it, generateCommand as j, prompt as jn, startWorkflow as jt, truncateCommand as k, PluginManager as kn, watchExecutorJob as kt, listUsers as l, assertValidMigrationFiles as ln, getOAuth2Client as lt, getCommand as m, getMigrationDirPath as mn, generate$1 as mt, query as n, generateAllTypeManifestsFromSnapshot as nn, pagedLogArgs as nr, deleteCommand$1 as nt, removeCommand as o, INITIAL_SCHEMA_NUMBER as on, workspaceArgs as or, listCommand$5 as ot, restoreWorkspace as p, getLatestMigrationNumber as pn, listMachineUsers as pt, listOrganizations as q, saveUserTokens as qn, workspaceNameSchema as qt, queryCommand as r, protoGqlPermission as rn, paginationArgs as rr, deleteFolder as rt, removeUser as s, MIGRATE_FILE_NAME as sn, listOAuth2Clients as st, registerTypeScriptRuntime as t, compareSnapshotWithRemote as tn, multiConfigArg as tr, getFolder as tt, inviteCommand as u, compareLocalTypesWithSnapshot as un, getMachineUserToken as ut, listApps as v, isValidMigrationNumber as vn, getFunctionRegistry as vt, resumeCommand as w, formatMigrationDiff as wn, listExecutors as wt, healthCommand as x, formatMigrationNumber as xn, triggerCommand as xt, listCommand$1 as y, loadDiff as yn, listWebhookExecutors as yt, logBetaWarning as z, loadAccessToken as zn, getExecutor as zt };
|
|
21054
|
+
//# sourceMappingURL=register-typescript-runtime-Bd4bcLbW.mjs.map
|