veryfront 0.1.1066 → 0.1.1068
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/esm/cli/commands/deploy/command.d.ts +12 -1
- package/esm/cli/commands/deploy/command.d.ts.map +1 -1
- package/esm/cli/commands/deploy/command.js +28 -1
- package/esm/cli/commands/deploy/index.d.ts +2 -2
- package/esm/cli/commands/deploy/index.d.ts.map +1 -1
- package/esm/cli/commands/deploy/index.js +1 -1
- package/esm/cli/commands/pull/command.d.ts +1 -0
- package/esm/cli/commands/pull/command.d.ts.map +1 -1
- package/esm/cli/commands/pull/command.js +19 -37
- package/esm/deno.js +1 -1
- package/esm/src/discovery/import-rewriter.d.ts +1 -1
- package/esm/src/discovery/import-rewriter.d.ts.map +1 -1
- package/esm/src/discovery/import-rewriter.js +1 -0
- package/esm/src/discovery/transpiler.d.ts.map +1 -1
- package/esm/src/discovery/transpiler.js +2 -0
- package/esm/src/proxy/handler.d.ts +19 -0
- package/esm/src/proxy/handler.d.ts.map +1 -1
- package/esm/src/proxy/handler.js +160 -13
- package/esm/src/proxy/main.js +45 -6
- package/esm/src/proxy/routing-invalidation-redis.d.ts +33 -0
- package/esm/src/proxy/routing-invalidation-redis.d.ts.map +1 -0
- package/esm/src/proxy/routing-invalidation-redis.js +394 -0
- package/esm/src/proxy/routing-invalidation.d.ts +32 -0
- package/esm/src/proxy/routing-invalidation.d.ts.map +1 -0
- package/esm/src/proxy/routing-invalidation.js +135 -0
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +5 -5
|
@@ -82,10 +82,20 @@ interface Release {
|
|
|
82
82
|
build_status: string;
|
|
83
83
|
deploy_status: string;
|
|
84
84
|
}
|
|
85
|
-
|
|
85
|
+
export type DeploymentRoutingConvergence = {
|
|
86
|
+
status: "converged";
|
|
87
|
+
acknowledged: number;
|
|
88
|
+
recipients: number;
|
|
89
|
+
} | {
|
|
90
|
+
status: "pending";
|
|
91
|
+
} | {
|
|
92
|
+
status: "skipped";
|
|
93
|
+
};
|
|
94
|
+
export interface Deployment {
|
|
86
95
|
id: string;
|
|
87
96
|
release_id: string;
|
|
88
97
|
environment_id: string;
|
|
98
|
+
routing_convergence?: DeploymentRoutingConvergence;
|
|
89
99
|
}
|
|
90
100
|
export interface DeploymentVerification {
|
|
91
101
|
projectId: string;
|
|
@@ -128,6 +138,7 @@ interface DeploymentVerificationOptions {
|
|
|
128
138
|
delayMs?: number;
|
|
129
139
|
verifiedRelease?: ReleaseSourceVerification;
|
|
130
140
|
}
|
|
141
|
+
export declare function getDeploymentRoutingConvergenceWarning(deployment: Deployment): string | null;
|
|
131
142
|
export declare function assertProjectOwnership(resourceType: "Environment" | "Release", resource: {
|
|
132
143
|
id: string;
|
|
133
144
|
project_id?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/deploy/command.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AAE3E,OAAO,EAAE,KAAK,SAAS,EAA0C,MAAM,wBAAwB,CAAC;AAchG;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;;;IAO5B,oDAAoD;;GAGvD,CAAC;AAEF,eAAO,MAAM,gBAAgB;;;;;;IALzB,oDAAoD;;GAKO,CAAC;AAEhE;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,WAAW,CAAC,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC;AAEhF;;GAEG;AACH,eAAO,MAAM,eAAe;;;;;;IAfxB,oDAAoD;;GAsBtD,CAAC;AAEH;;GAEG;AACH,UAAU,qBAAqB;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE;QACP,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;KACrB,GAAG,IAAI,CAAC;CACV;AAED,UAAU,WAAW;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,GAAG;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;CAC3C;AAED;;GAEG;AACH,UAAU,OAAO;IACf,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,GAAG;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB;
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/deploy/command.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,7 +10,7 @@ import { defineSchema, lazySchema } from "../../../src/schemas/index.js";
|
|
|
10
10
|
import { cwd } from "../../../src/platform/index.js";
|
|
11
11
|
import { createApiClient, resolveConfigWithAuth } from "../../shared/config.js";
|
|
12
12
|
import { CommonArgs, createArgParser } from "../../shared/args.js";
|
|
13
|
-
import { confirmPrompt, logInfo, logSuccess } from "../../utils/index.js";
|
|
13
|
+
import { confirmPrompt, logInfo, logSuccess, logWarning } from "../../utils/index.js";
|
|
14
14
|
import { createNoopSpinner, createSpinner, muted } from "../../ui/index.js";
|
|
15
15
|
import { isJsonMode, streamJsonLine } from "../../shared/json-output.js";
|
|
16
16
|
import { computeSourceDigest, getProjectTarget, normalizeControlPlane, readPushReceipt, resolveGitSource, validatePushReceipt, } from "../../shared/deployment-provenance.js";
|
|
@@ -60,8 +60,20 @@ function normalizeDeployment(deployment) {
|
|
|
60
60
|
id: deployment.id,
|
|
61
61
|
release_id: releaseId,
|
|
62
62
|
environment_id: environmentId,
|
|
63
|
+
routing_convergence: deployment.routing_convergence,
|
|
63
64
|
};
|
|
64
65
|
}
|
|
66
|
+
export function getDeploymentRoutingConvergenceWarning(deployment) {
|
|
67
|
+
const convergence = deployment.routing_convergence;
|
|
68
|
+
if (!convergence)
|
|
69
|
+
return null;
|
|
70
|
+
if (convergence.status === "converged" &&
|
|
71
|
+
convergence.recipients > 0 &&
|
|
72
|
+
convergence.acknowledged >= convergence.recipients) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
return `Deployment ${deployment.id} committed, but data-plane routing convergence was not confirmed; bounded cache expiry remains the recovery path`;
|
|
76
|
+
}
|
|
65
77
|
export function assertProjectOwnership(resourceType, resource, projectId) {
|
|
66
78
|
if (resource.project_id && resource.project_id !== projectId) {
|
|
67
79
|
throw new Error(`${resourceType} ${resource.id} does not belong to resolved project ${projectId}`);
|
|
@@ -348,6 +360,12 @@ export async function deployCommand(options) {
|
|
|
348
360
|
logInfo(` Environment: ${env} (${verification.environmentId})`);
|
|
349
361
|
logInfo(` Release: ${release.name} (${verification.releaseVersion}, ${verification.releaseId})`);
|
|
350
362
|
logInfo(` Deployment: ${verification.deploymentId}`);
|
|
363
|
+
if (deployment.routing_convergence?.status === "converged") {
|
|
364
|
+
logInfo(` Data plane: ${deployment.routing_convergence.acknowledged}/${deployment.routing_convergence.recipients} proxy replicas converged`);
|
|
365
|
+
}
|
|
366
|
+
const routingConvergenceWarning = getDeploymentRoutingConvergenceWarning(deployment);
|
|
367
|
+
if (routingConvergenceWarning)
|
|
368
|
+
logWarning(routingConvergenceWarning);
|
|
351
369
|
logInfo(` Commit: ${verification.commitSha}`);
|
|
352
370
|
logInfo(` Source digest: ${verification.sourceDigest}`);
|
|
353
371
|
logInfo(` Control plane: ${normalizeControlPlane(config.apiUrl)}`);
|
|
@@ -448,6 +466,14 @@ async function deployCommandJson(options) {
|
|
|
448
466
|
sourceDigest: source.sourceDigest,
|
|
449
467
|
}, { verifiedRelease });
|
|
450
468
|
streamJsonLine({ type: "step", name: "verify-deployment", status: "completed" });
|
|
469
|
+
const routingConvergenceWarning = getDeploymentRoutingConvergenceWarning(deployment);
|
|
470
|
+
if (routingConvergenceWarning) {
|
|
471
|
+
streamJsonLine({
|
|
472
|
+
type: "warning",
|
|
473
|
+
code: "routing-convergence-unconfirmed",
|
|
474
|
+
message: routingConvergenceWarning,
|
|
475
|
+
});
|
|
476
|
+
}
|
|
451
477
|
streamJsonLine({
|
|
452
478
|
type: "result",
|
|
453
479
|
success: true,
|
|
@@ -462,6 +488,7 @@ async function deployCommandJson(options) {
|
|
|
462
488
|
environment: env,
|
|
463
489
|
environmentId: verification.environmentId,
|
|
464
490
|
deploymentId: verification.deploymentId,
|
|
491
|
+
routingConvergence: deployment.routing_convergence ?? null,
|
|
465
492
|
commitSha: verification.commitSha,
|
|
466
493
|
sourceDigest: verification.sourceDigest,
|
|
467
494
|
controlPlane: normalizeControlPlane(config.apiUrl),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Deploy command - Create and deploy releases
|
|
3
3
|
*/
|
|
4
|
-
export { assertProjectOwnership, createDeployment, createRelease, DeployArgsSchema, deployCommand, getDeployment, getEnvironmentByName, getProject, getRelease, getReleaseSourceDigest, parseDeployArgs, resolvePushedSource, verifyDeployment, verifyReleaseSource, } from "./command.js";
|
|
5
|
-
export type { DeploymentVerification, DeployOptions, ReleaseSourceVerification, } from "./command.js";
|
|
4
|
+
export { assertProjectOwnership, createDeployment, createRelease, DeployArgsSchema, deployCommand, getDeployment, getDeploymentRoutingConvergenceWarning, getEnvironmentByName, getProject, getRelease, getReleaseSourceDigest, parseDeployArgs, resolvePushedSource, verifyDeployment, verifyReleaseSource, } from "./command.js";
|
|
5
|
+
export type { Deployment, DeploymentRoutingConvergence, DeploymentVerification, DeployOptions, ReleaseSourceVerification, } from "./command.js";
|
|
6
6
|
export { handleDeployCommand } from "./handler.js";
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/deploy/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,oBAAoB,EACpB,UAAU,EACV,UAAU,EACV,sBAAsB,EACtB,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,sBAAsB,EACtB,aAAa,EACb,yBAAyB,GAC1B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/deploy/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,sCAAsC,EACtC,oBAAoB,EACpB,UAAU,EACV,UAAU,EACV,sBAAsB,EACtB,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,UAAU,EACV,4BAA4B,EAC5B,sBAAsB,EACtB,aAAa,EACb,yBAAyB,GAC1B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Deploy command - Create and deploy releases
|
|
3
3
|
*/
|
|
4
|
-
export { assertProjectOwnership, createDeployment, createRelease, DeployArgsSchema, deployCommand, getDeployment, getEnvironmentByName, getProject, getRelease, getReleaseSourceDigest, parseDeployArgs, resolvePushedSource, verifyDeployment, verifyReleaseSource, } from "./command.js";
|
|
4
|
+
export { assertProjectOwnership, createDeployment, createRelease, DeployArgsSchema, deployCommand, getDeployment, getDeploymentRoutingConvergenceWarning, getEnvironmentByName, getProject, getRelease, getReleaseSourceDigest, parseDeployArgs, resolvePushedSource, verifyDeployment, verifyReleaseSource, } from "./command.js";
|
|
5
5
|
export { handleDeployCommand } from "./handler.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/pull/command.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AAM3E,OAAO,EACL,eAAe,EAIhB,MAAM,wBAAwB,CAAC;AAiBhC;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;GAa7B,CAAC;AAEF,eAAO,MAAM,cAAc;;;;;;;;;;;GAAgC,CAAC;AAE5D,MAAM,MAAM,QAAQ,GAAG,WAAW,CAAC,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC,CAAC;AAEzE;;GAEG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;;GAWxB,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,gCAAgC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,0EAA0E;IAC1E,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,oDAAoD;IACpD,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,UAAU,CAKlE;AAED,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/pull/command.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AAM3E,OAAO,EACL,eAAe,EAIhB,MAAM,wBAAwB,CAAC;AAiBhC;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;GAa7B,CAAC;AAEF,eAAO,MAAM,cAAc;;;;;;;;;;;GAAgC,CAAC;AAE5D,MAAM,MAAM,QAAQ,GAAG,WAAW,CAAC,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC,CAAC;AAEzE;;GAEG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;;GAWxB,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,gCAAgC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,0EAA0E;IAC1E,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,oDAAoD;IACpD,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,UAAU,CAKlE;AAED,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAsCD,sEAAsE;AACtE,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAmB/D;AAkDD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM,CAWjF;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,EAC1C,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,WAAW,EAAE,CAAC,CAoBxB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM,CAmBjG;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,EAC1C,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,MAAM,CAAC,CAKjB;AA8aD;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoKpE"}
|
|
@@ -181,18 +181,9 @@ export async function getFileContent(client, projectSlug, path, source) {
|
|
|
181
181
|
const response = await client.get(url);
|
|
182
182
|
return response.content;
|
|
183
183
|
}
|
|
184
|
-
/** Concurrency limit for parallel file
|
|
184
|
+
/** Concurrency limit for parallel file writes. */
|
|
185
185
|
const CONCURRENCY = 20;
|
|
186
|
-
async function
|
|
187
|
-
try {
|
|
188
|
-
const content = await getFileContent(client, projectSlug, op.relativePath, source);
|
|
189
|
-
return { success: true, op: { ...op, content } };
|
|
190
|
-
}
|
|
191
|
-
catch (error) {
|
|
192
|
-
return { success: false, path: op.relativePath, error: error };
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
async function writePreparedFile(op, fs) {
|
|
186
|
+
async function writeFile(op, fs) {
|
|
196
187
|
try {
|
|
197
188
|
await fs.mkdir(dirname(op.path), { recursive: true });
|
|
198
189
|
await fs.writeTextFile(op.path, op.content);
|
|
@@ -202,33 +193,18 @@ async function writePreparedFile(op, fs) {
|
|
|
202
193
|
return { success: false, path: op.relativePath, error: error };
|
|
203
194
|
}
|
|
204
195
|
}
|
|
205
|
-
async function writeFiles(ops,
|
|
196
|
+
async function writeFiles(ops, dryRun) {
|
|
206
197
|
if (dryRun) {
|
|
207
198
|
for (const op of ops)
|
|
208
199
|
cliLogger.info(` Would write: ${op.relativePath}`);
|
|
209
200
|
return { written: ops.length, failed: 0 };
|
|
210
201
|
}
|
|
211
202
|
const fs = createFileSystem();
|
|
212
|
-
const prepared = [];
|
|
213
203
|
let failed = 0;
|
|
204
|
+
let written = 0;
|
|
214
205
|
for (let i = 0; i < ops.length; i += CONCURRENCY) {
|
|
215
206
|
const batch = ops.slice(i, i + CONCURRENCY);
|
|
216
|
-
const results = await Promise.all(batch.map((op) =>
|
|
217
|
-
for (const result of results) {
|
|
218
|
-
if (result.success) {
|
|
219
|
-
prepared.push(result.op);
|
|
220
|
-
continue;
|
|
221
|
-
}
|
|
222
|
-
cliLogger.error(`Failed to fetch ${result.path}:`, result.error);
|
|
223
|
-
failed++;
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
if (failed > 0)
|
|
227
|
-
return { written: 0, failed };
|
|
228
|
-
let written = 0;
|
|
229
|
-
for (let i = 0; i < prepared.length; i += CONCURRENCY) {
|
|
230
|
-
const batch = prepared.slice(i, i + CONCURRENCY);
|
|
231
|
-
const results = await Promise.all(batch.map((op) => writePreparedFile(op, fs)));
|
|
207
|
+
const results = await Promise.all(batch.map((op) => writeFile(op, fs)));
|
|
232
208
|
for (const result of results) {
|
|
233
209
|
if (result.success) {
|
|
234
210
|
written++;
|
|
@@ -452,18 +428,13 @@ async function pullSingleProject(projectSlug, projectDir, source, force, dryRun,
|
|
|
452
428
|
const writeOps = [];
|
|
453
429
|
const remotePaths = new Set();
|
|
454
430
|
for (const file of files) {
|
|
431
|
+
let op;
|
|
455
432
|
try {
|
|
456
|
-
|
|
433
|
+
op = await validateFilePath(file.path, projectDir);
|
|
457
434
|
if (remotePaths.has(op.relativePath)) {
|
|
458
435
|
throw new Error(`Duplicate remote file path: "${op.relativePath}"`);
|
|
459
436
|
}
|
|
460
437
|
remotePaths.add(op.relativePath);
|
|
461
|
-
if (pruneIgnoreChecker &&
|
|
462
|
-
(pruneIgnoreChecker.isIgnored(op.relativePath) ||
|
|
463
|
-
!pruneIgnoreChecker.isSupportedExtension(op.relativePath))) {
|
|
464
|
-
continue;
|
|
465
|
-
}
|
|
466
|
-
writeOps.push(op);
|
|
467
438
|
}
|
|
468
439
|
catch (error) {
|
|
469
440
|
throw INVALID_ARGUMENT.create({
|
|
@@ -471,6 +442,17 @@ async function pullSingleProject(projectSlug, projectDir, source, force, dryRun,
|
|
|
471
442
|
cause: error,
|
|
472
443
|
});
|
|
473
444
|
}
|
|
445
|
+
if (pruneIgnoreChecker &&
|
|
446
|
+
(pruneIgnoreChecker.isIgnored(op.relativePath) ||
|
|
447
|
+
!pruneIgnoreChecker.isSupportedExtension(op.relativePath))) {
|
|
448
|
+
continue;
|
|
449
|
+
}
|
|
450
|
+
if (typeof file.content !== "string") {
|
|
451
|
+
throw INVALID_ARGUMENT.create({
|
|
452
|
+
detail: `Veryfront returned invalid content for file "${file.path}". No local files were changed.`,
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
writeOps.push({ ...op, content: file.content });
|
|
474
456
|
}
|
|
475
457
|
let deleteOps = [];
|
|
476
458
|
if (pruneIgnoreChecker) {
|
|
@@ -495,7 +477,7 @@ async function pullSingleProject(projectSlug, projectDir, source, force, dryRun,
|
|
|
495
477
|
}
|
|
496
478
|
}
|
|
497
479
|
spinner = quiet ? createNoopSpinner() : createSpinner(`Writing files to ${projectDir}...`);
|
|
498
|
-
const writeResult = await writeFiles(writeOps,
|
|
480
|
+
const writeResult = await writeFiles(writeOps, dryRun);
|
|
499
481
|
if (writeResult.failed > 0) {
|
|
500
482
|
spinner.stop();
|
|
501
483
|
throw new Error(`Failed to pull ${writeResult.failed} file${writeResult.failed === 1 ? "" : "s"}. No local files were pruned. Review git status and restore a clean worktree before retrying if any files were written.`);
|
package/esm/deno.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* (Deno, Node.js) and handles veryfront package resolution.
|
|
6
6
|
*/
|
|
7
7
|
import { createFileSystem } from "../platform/compat/fs.js";
|
|
8
|
-
export declare const DISCOVERY_GLOBAL_VERYFRONT_MODULES: readonly ["veryfront/agent", "veryfront/tool", "veryfront/platform", "veryfront/prompt", "veryfront/resource", "veryfront/embedding", "veryfront/knowledge", "veryfront/workflow", "veryfront/eval", "veryfront/metrics", "veryfront/schemas", "veryfront/chat/uploads"];
|
|
8
|
+
export declare const DISCOVERY_GLOBAL_VERYFRONT_MODULES: readonly ["veryfront/agent", "veryfront/tool", "veryfront/platform", "veryfront/prompt", "veryfront/resource", "veryfront/embedding", "veryfront/knowledge", "veryfront/workflow", "veryfront/eval", "veryfront/metrics", "veryfront/schemas", "veryfront/integrations", "veryfront/chat/uploads"];
|
|
9
9
|
interface DenoRewriteOptions {
|
|
10
10
|
compiled?: boolean;
|
|
11
11
|
resolveSpecifier?: (specifier: string) => string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"import-rewriter.d.ts","sourceRoot":"","sources":["../../../src/src/discovery/import-rewriter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAI5D,eAAO,MAAM,kCAAkC,
|
|
1
|
+
{"version":3,"file":"import-rewriter.d.ts","sourceRoot":"","sources":["../../../src/src/discovery/import-rewriter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAI5D,eAAO,MAAM,kCAAkC,oSAerC,CAAC;AAEX,UAAU,kBAAkB;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;CAClD;AAkHD;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,kBAAuB,GAC/B,MAAM,CA2BR;AAqFD;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,EACvC,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC,CA2PjB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transpiler.d.ts","sourceRoot":"","sources":["../../../src/src/discovery/transpiler.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"transpiler.d.ts","sourceRoot":"","sources":["../../../src/src/discovery/transpiler.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AA4MvD;;GAEG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,OAAO,CAAC,CAgIlB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C"}
|
|
@@ -25,6 +25,7 @@ import * as workflowMod from "../workflow/index.js";
|
|
|
25
25
|
import * as evalMod from "../eval/index.js";
|
|
26
26
|
import * as metricsMod from "../metrics/index.js";
|
|
27
27
|
import * as schemasMod from "../schemas/index.js";
|
|
28
|
+
import * as integrationsMod from "../integrations/index.js";
|
|
28
29
|
import * as chatUploadsMod from "../chat/upload-handler.js";
|
|
29
30
|
// Keyed by entry file + entry source hash; each entry additionally records the
|
|
30
31
|
// bundled dependency contents it was built from and is only served while those
|
|
@@ -90,6 +91,7 @@ async function ensureVeryfrontGlobals() {
|
|
|
90
91
|
"veryfront/eval": evalMod,
|
|
91
92
|
"veryfront/metrics": metricsMod,
|
|
92
93
|
"veryfront/schemas": schemasMod,
|
|
94
|
+
"veryfront/integrations": integrationsMod,
|
|
93
95
|
"veryfront/chat/uploads": chatUploadsMod,
|
|
94
96
|
};
|
|
95
97
|
dntShim.dntGlobalThis.__VERYFRONT_MODULES__ = modules;
|
|
@@ -48,6 +48,20 @@ export interface ProxyRequestOptions {
|
|
|
48
48
|
url?: URL;
|
|
49
49
|
timing?: ProxyServerTiming;
|
|
50
50
|
}
|
|
51
|
+
export interface ProxyRoutingInvalidation {
|
|
52
|
+
projectId: string;
|
|
53
|
+
projectSlug?: string;
|
|
54
|
+
deploymentId?: string;
|
|
55
|
+
environmentId?: string;
|
|
56
|
+
environmentName?: string;
|
|
57
|
+
releaseId?: string;
|
|
58
|
+
}
|
|
59
|
+
export interface ConfirmedProxyRoutingInvalidation extends ProxyRoutingInvalidation {
|
|
60
|
+
projectSlug: string;
|
|
61
|
+
environmentId: string;
|
|
62
|
+
environmentName: string;
|
|
63
|
+
releaseId: string;
|
|
64
|
+
}
|
|
51
65
|
export declare function createProxyHandler(options: ProxyHandlerOptions): {
|
|
52
66
|
processRequest: (req: Request, options?: ProxyRequestOptions) => Promise<ProxyContext>;
|
|
53
67
|
getTokenForApi: (req: Request, options?: ProxyRequestOptions) => Promise<string | undefined>;
|
|
@@ -59,6 +73,11 @@ export declare function createProxyHandler(options: ProxyHandlerOptions): {
|
|
|
59
73
|
}>;
|
|
60
74
|
close: () => Promise<void>;
|
|
61
75
|
validateConfig: () => string[];
|
|
76
|
+
invalidateRoutingLookup: (input: ProxyRoutingInvalidation) => {
|
|
77
|
+
evictedEntries: number;
|
|
78
|
+
generation: number;
|
|
79
|
+
};
|
|
80
|
+
invalidateAndConfirmRoutingLookup: (input: ConfirmedProxyRoutingInvalidation) => Promise<void>;
|
|
62
81
|
localProjects: Record<string, string>;
|
|
63
82
|
};
|
|
64
83
|
export type ProxyHandler = ReturnType<typeof createProxyHandler>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/src/proxy/handler.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,YAAY,EAAsB,MAAM,kCAAkC,CAAC;AACzF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAenD,OAAO,EAAiC,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAG3F,OAAO,EAAE,iCAAiC,EAAE,MAAM,2BAA2B,CAAC;AAE9E,eAAO,MAAM,sBAAsB,0MAYzB,CAAC;
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/src/proxy/handler.ts"],"names":[],"mappings":"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"}
|
package/esm/src/proxy/handler.js
CHANGED
|
@@ -26,6 +26,7 @@ export const INTERNAL_PROXY_HEADERS = [
|
|
|
26
26
|
];
|
|
27
27
|
const DEFAULT_PROXY_ROUTING_CACHE_TTL_MS = 60_000;
|
|
28
28
|
const DEFAULT_PROXY_ROUTING_CACHE_MAX_ENTRIES = 1_000;
|
|
29
|
+
const MAX_ROUTING_LOOKUP_INVALIDATION_RETRIES = 2;
|
|
29
30
|
function readNonNegativeIntegerEnv(name, fallback) {
|
|
30
31
|
const raw = getEnv(name);
|
|
31
32
|
if (!raw)
|
|
@@ -46,6 +47,12 @@ class ProxyLookupAuthError extends Error {
|
|
|
46
47
|
this.name = "ProxyLookupAuthError";
|
|
47
48
|
}
|
|
48
49
|
}
|
|
50
|
+
class ProxyRoutingInvalidationRaceError extends Error {
|
|
51
|
+
constructor() {
|
|
52
|
+
super("Project routing changed during request; retry");
|
|
53
|
+
this.name = "ProxyRoutingInvalidationRaceError";
|
|
54
|
+
}
|
|
55
|
+
}
|
|
49
56
|
function isProxyLookupAuthError(error) {
|
|
50
57
|
return error instanceof ProxyLookupAuthError;
|
|
51
58
|
}
|
|
@@ -225,6 +232,11 @@ export function createProxyHandler(options) {
|
|
|
225
232
|
const routingCacheMaxEntries = readNonNegativeIntegerEnv("VERYFRONT_PROXY_ROUTING_CACHE_MAX_ENTRIES", DEFAULT_PROXY_ROUTING_CACHE_MAX_ENTRIES);
|
|
226
233
|
const routingLookupCache = new Map();
|
|
227
234
|
const routingLookupInflight = new Map();
|
|
235
|
+
const projectInvalidationGenerations = new Map();
|
|
236
|
+
const lookupKeyInvalidationGenerations = new Map();
|
|
237
|
+
const activeRoutingLookupGenerations = new Map();
|
|
238
|
+
const maxTrackedInvalidationGenerations = Math.max(routingCacheMaxEntries, DEFAULT_PROXY_ROUTING_CACHE_MAX_ENTRIES);
|
|
239
|
+
let routingLookupGeneration = 0;
|
|
228
240
|
async function resolveProjectLookup(lookupKey, token, timing) {
|
|
229
241
|
return await profileProxyServerTimingPhase(timing ?? { enabled: false, startedAt: 0, phases: new Map() }, "proxy.project_lookup", () => lookupProjectByDomain(lookupKey, config.apiBaseUrl, token, logger));
|
|
230
242
|
}
|
|
@@ -261,6 +273,71 @@ export function createProxyHandler(options) {
|
|
|
261
273
|
expiresAt: Date.now() + routingCacheTtlMs,
|
|
262
274
|
});
|
|
263
275
|
}
|
|
276
|
+
function pruneInvalidationGenerations(generations) {
|
|
277
|
+
const oldestActiveGeneration = activeRoutingLookupGenerations.size > 0
|
|
278
|
+
? Math.min(...activeRoutingLookupGenerations.keys())
|
|
279
|
+
: Number.POSITIVE_INFINITY;
|
|
280
|
+
while (generations.size > maxTrackedInvalidationGenerations) {
|
|
281
|
+
const oldestEntry = generations.entries().next().value;
|
|
282
|
+
if (!oldestEntry || oldestEntry[1] > oldestActiveGeneration)
|
|
283
|
+
break;
|
|
284
|
+
generations.delete(oldestEntry[0]);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
function rememberInvalidationGeneration(generations, key, generation) {
|
|
288
|
+
generations.delete(key);
|
|
289
|
+
generations.set(key, generation);
|
|
290
|
+
pruneInvalidationGenerations(generations);
|
|
291
|
+
}
|
|
292
|
+
function beginRoutingLookup(generation) {
|
|
293
|
+
activeRoutingLookupGenerations.set(generation, (activeRoutingLookupGenerations.get(generation) ?? 0) + 1);
|
|
294
|
+
}
|
|
295
|
+
function endRoutingLookup(generation) {
|
|
296
|
+
const activeCount = activeRoutingLookupGenerations.get(generation) ?? 0;
|
|
297
|
+
if (activeCount <= 1)
|
|
298
|
+
activeRoutingLookupGenerations.delete(generation);
|
|
299
|
+
else
|
|
300
|
+
activeRoutingLookupGenerations.set(generation, activeCount - 1);
|
|
301
|
+
pruneInvalidationGenerations(projectInvalidationGenerations);
|
|
302
|
+
pruneInvalidationGenerations(lookupKeyInvalidationGenerations);
|
|
303
|
+
}
|
|
304
|
+
function wasRoutingLookupInvalidated(cacheKey, result, startedAtGeneration) {
|
|
305
|
+
const keyGeneration = lookupKeyInvalidationGenerations.get(cacheKey) ?? 0;
|
|
306
|
+
if (keyGeneration > startedAtGeneration)
|
|
307
|
+
return true;
|
|
308
|
+
if (!result)
|
|
309
|
+
return false;
|
|
310
|
+
return (projectInvalidationGenerations.get(result.id) ?? 0) > startedAtGeneration;
|
|
311
|
+
}
|
|
312
|
+
function invalidateRoutingLookup(input) {
|
|
313
|
+
const generation = ++routingLookupGeneration;
|
|
314
|
+
rememberInvalidationGeneration(projectInvalidationGenerations, input.projectId, generation);
|
|
315
|
+
const normalizedProjectSlug = input.projectSlug
|
|
316
|
+
? normalizeProjectLookupKey(input.projectSlug)
|
|
317
|
+
: undefined;
|
|
318
|
+
if (normalizedProjectSlug) {
|
|
319
|
+
rememberInvalidationGeneration(lookupKeyInvalidationGenerations, normalizedProjectSlug, generation);
|
|
320
|
+
}
|
|
321
|
+
let evictedEntries = 0;
|
|
322
|
+
for (const [cacheKey, entry] of routingLookupCache) {
|
|
323
|
+
if (entry.value.id !== input.projectId && cacheKey !== normalizedProjectSlug)
|
|
324
|
+
continue;
|
|
325
|
+
routingLookupCache.delete(cacheKey);
|
|
326
|
+
rememberInvalidationGeneration(lookupKeyInvalidationGenerations, cacheKey, generation);
|
|
327
|
+
evictedEntries++;
|
|
328
|
+
}
|
|
329
|
+
logger?.info("Proxy routing metadata invalidated after deployment activation", {
|
|
330
|
+
projectId: input.projectId,
|
|
331
|
+
projectSlug: input.projectSlug,
|
|
332
|
+
deploymentId: input.deploymentId,
|
|
333
|
+
environmentId: input.environmentId,
|
|
334
|
+
environmentName: input.environmentName,
|
|
335
|
+
releaseId: input.releaseId,
|
|
336
|
+
generation,
|
|
337
|
+
evictedEntries,
|
|
338
|
+
});
|
|
339
|
+
return { evictedEntries, generation };
|
|
340
|
+
}
|
|
264
341
|
async function resolveProjectRoutingLookup(lookupKey, token, timing) {
|
|
265
342
|
const cacheKey = normalizeProjectLookupKey(lookupKey);
|
|
266
343
|
return await profileProxyServerTimingPhase(timing ?? { enabled: false, startedAt: 0, phases: new Map() }, "proxy.routing_lookup", async () => {
|
|
@@ -270,27 +347,89 @@ export function createProxyHandler(options) {
|
|
|
270
347
|
return cached;
|
|
271
348
|
}
|
|
272
349
|
const existingLookup = routingLookupInflight.get(cacheKey);
|
|
273
|
-
if (existingLookup) {
|
|
350
|
+
if (existingLookup?.generation === routingLookupGeneration) {
|
|
274
351
|
logger?.debug("Proxy routing metadata lookup joined in-flight request", { lookupKey });
|
|
275
|
-
return await existingLookup;
|
|
352
|
+
return await existingLookup.promise;
|
|
276
353
|
}
|
|
277
|
-
const lookupPromise =
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
354
|
+
const lookupPromise = (async () => {
|
|
355
|
+
for (let attempt = 0; attempt <= MAX_ROUTING_LOOKUP_INVALIDATION_RETRIES; attempt++) {
|
|
356
|
+
const startedAtGeneration = routingLookupGeneration;
|
|
357
|
+
beginRoutingLookup(startedAtGeneration);
|
|
358
|
+
try {
|
|
359
|
+
const result = await lookupProjectRoutingMetadata(lookupKey, config.apiBaseUrl, token, logger);
|
|
360
|
+
if (!wasRoutingLookupInvalidated(cacheKey, result, startedAtGeneration)) {
|
|
361
|
+
if (result)
|
|
362
|
+
setCachedRoutingLookup(cacheKey, result);
|
|
363
|
+
return result;
|
|
364
|
+
}
|
|
365
|
+
logger?.info("Retrying proxy routing metadata lookup after invalidation race", {
|
|
366
|
+
lookupKey,
|
|
367
|
+
attempt: attempt + 1,
|
|
368
|
+
generation: routingLookupGeneration,
|
|
369
|
+
});
|
|
370
|
+
if (attempt === MAX_ROUTING_LOOKUP_INVALIDATION_RETRIES) {
|
|
371
|
+
logger?.warn("Proxy routing metadata changed repeatedly during lookup; failing request closed", {
|
|
372
|
+
lookupKey,
|
|
373
|
+
attempts: attempt + 1,
|
|
374
|
+
});
|
|
375
|
+
throw new ProxyRoutingInvalidationRaceError();
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
finally {
|
|
379
|
+
endRoutingLookup(startedAtGeneration);
|
|
380
|
+
}
|
|
281
381
|
}
|
|
282
|
-
return
|
|
283
|
-
})
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
382
|
+
return null;
|
|
383
|
+
})();
|
|
384
|
+
const inflightEntry = {
|
|
385
|
+
generation: routingLookupGeneration,
|
|
386
|
+
promise: lookupPromise,
|
|
387
|
+
};
|
|
388
|
+
routingLookupInflight.set(cacheKey, inflightEntry);
|
|
389
|
+
try {
|
|
390
|
+
return await lookupPromise;
|
|
391
|
+
}
|
|
392
|
+
finally {
|
|
393
|
+
if (routingLookupInflight.get(cacheKey) === inflightEntry) {
|
|
394
|
+
routingLookupInflight.delete(cacheKey);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
289
397
|
});
|
|
290
398
|
}
|
|
291
399
|
async function resolveProjectAccessLookup(lookupKey, token, includeUsers, timing) {
|
|
292
400
|
return await profileProxyServerTimingPhase(timing ?? { enabled: false, startedAt: 0, phases: new Map() }, "proxy.access_lookup", () => lookupProjectAccessMetadata(lookupKey, config.apiBaseUrl, token, includeUsers, logger));
|
|
293
401
|
}
|
|
402
|
+
async function invalidateAndConfirmRoutingLookup(input) {
|
|
403
|
+
invalidateRoutingLookup(input);
|
|
404
|
+
const scope = getScope(input.environmentName.toLowerCase());
|
|
405
|
+
const resolveWithToken = async (token) => {
|
|
406
|
+
const result = await resolveProjectRoutingLookup(input.projectSlug, token);
|
|
407
|
+
const environment = result?.environments?.find((candidate) => candidate.id === input.environmentId);
|
|
408
|
+
if (result?.id !== input.projectId ||
|
|
409
|
+
environment?.active_release_id !== input.releaseId) {
|
|
410
|
+
throw new Error(`Proxy routing metadata did not converge for project ${input.projectId} environment ${input.environmentId}`);
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
let token = await tokenManager.getToken(scope, input.projectSlug);
|
|
414
|
+
try {
|
|
415
|
+
await resolveWithToken(token);
|
|
416
|
+
}
|
|
417
|
+
catch (error) {
|
|
418
|
+
if (!isProxyLookupAuthError(error))
|
|
419
|
+
throw error;
|
|
420
|
+
await tokenManager.invalidateToken(scope, input.projectSlug);
|
|
421
|
+
token = await tokenManager.getToken(scope, input.projectSlug);
|
|
422
|
+
await resolveWithToken(token);
|
|
423
|
+
}
|
|
424
|
+
logger?.info("Proxy routing metadata converged after deployment activation", {
|
|
425
|
+
projectId: input.projectId,
|
|
426
|
+
projectSlug: input.projectSlug,
|
|
427
|
+
deploymentId: input.deploymentId,
|
|
428
|
+
environmentId: input.environmentId,
|
|
429
|
+
environmentName: input.environmentName,
|
|
430
|
+
releaseId: input.releaseId,
|
|
431
|
+
});
|
|
432
|
+
}
|
|
294
433
|
function validateConfig() {
|
|
295
434
|
const missing = [];
|
|
296
435
|
if (!config.apiClientId)
|
|
@@ -410,6 +549,9 @@ export function createProxyHandler(options) {
|
|
|
410
549
|
return await resolveWithCurrentToken();
|
|
411
550
|
}
|
|
412
551
|
catch (error) {
|
|
552
|
+
if (error instanceof ProxyRoutingInvalidationRaceError) {
|
|
553
|
+
return { error: { status: 503, message: error.message } };
|
|
554
|
+
}
|
|
413
555
|
if (!isProxyLookupAuthError(error))
|
|
414
556
|
throw error;
|
|
415
557
|
const projectKey = tokenIdentity.projectSlug ?? tokenIdentity.customDomain;
|
|
@@ -444,6 +586,9 @@ export function createProxyHandler(options) {
|
|
|
444
586
|
return await resolveWithCurrentToken();
|
|
445
587
|
}
|
|
446
588
|
catch (retryError) {
|
|
589
|
+
if (retryError instanceof ProxyRoutingInvalidationRaceError) {
|
|
590
|
+
return { error: { status: 503, message: retryError.message } };
|
|
591
|
+
}
|
|
447
592
|
if (!isProxyLookupAuthError(retryError))
|
|
448
593
|
throw retryError;
|
|
449
594
|
logger?.error("Proxy API token rejected after refresh", retryError, {
|
|
@@ -689,6 +834,8 @@ export function createProxyHandler(options) {
|
|
|
689
834
|
getStats,
|
|
690
835
|
close,
|
|
691
836
|
validateConfig,
|
|
837
|
+
invalidateRoutingLookup,
|
|
838
|
+
invalidateAndConfirmRoutingLookup,
|
|
692
839
|
localProjects,
|
|
693
840
|
};
|
|
694
841
|
}
|