vector-framework 1.2.2 → 1.2.3
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/README.md +18 -6
- package/dist/auth/protected.d.ts +4 -4
- package/dist/auth/protected.d.ts.map +1 -1
- package/dist/auth/protected.js +10 -7
- package/dist/auth/protected.js.map +1 -1
- package/dist/cache/manager.d.ts +2 -0
- package/dist/cache/manager.d.ts.map +1 -1
- package/dist/cache/manager.js +21 -4
- package/dist/cache/manager.js.map +1 -1
- package/dist/checkpoint/artifacts/compressor.d.ts +5 -0
- package/dist/checkpoint/artifacts/compressor.d.ts.map +1 -0
- package/dist/checkpoint/artifacts/compressor.js +24 -0
- package/dist/checkpoint/artifacts/compressor.js.map +1 -0
- package/dist/checkpoint/artifacts/decompress-worker.d.ts +2 -0
- package/dist/checkpoint/artifacts/decompress-worker.d.ts.map +1 -0
- package/dist/checkpoint/artifacts/decompress-worker.js +31 -0
- package/dist/checkpoint/artifacts/decompress-worker.js.map +1 -0
- package/dist/checkpoint/artifacts/hasher.d.ts +2 -0
- package/dist/checkpoint/artifacts/hasher.d.ts.map +1 -0
- package/dist/checkpoint/artifacts/hasher.js +7 -0
- package/dist/checkpoint/artifacts/hasher.js.map +1 -0
- package/dist/checkpoint/artifacts/manifest.d.ts +6 -0
- package/dist/checkpoint/artifacts/manifest.d.ts.map +1 -0
- package/dist/checkpoint/artifacts/manifest.js +55 -0
- package/dist/checkpoint/artifacts/manifest.js.map +1 -0
- package/dist/checkpoint/artifacts/materializer.d.ts +16 -0
- package/dist/checkpoint/artifacts/materializer.d.ts.map +1 -0
- package/dist/checkpoint/artifacts/materializer.js +168 -0
- package/dist/checkpoint/artifacts/materializer.js.map +1 -0
- package/dist/checkpoint/artifacts/packager.d.ts +12 -0
- package/dist/checkpoint/artifacts/packager.d.ts.map +1 -0
- package/dist/checkpoint/artifacts/packager.js +82 -0
- package/dist/checkpoint/artifacts/packager.js.map +1 -0
- package/dist/checkpoint/artifacts/repository.d.ts +11 -0
- package/dist/checkpoint/artifacts/repository.d.ts.map +1 -0
- package/dist/checkpoint/artifacts/repository.js +29 -0
- package/dist/checkpoint/artifacts/repository.js.map +1 -0
- package/dist/checkpoint/artifacts/store.d.ts +13 -0
- package/dist/checkpoint/artifacts/store.d.ts.map +1 -0
- package/dist/checkpoint/artifacts/store.js +85 -0
- package/dist/checkpoint/artifacts/store.js.map +1 -0
- package/dist/checkpoint/artifacts/types.d.ts +21 -0
- package/dist/checkpoint/artifacts/types.d.ts.map +1 -0
- package/dist/checkpoint/artifacts/types.js +2 -0
- package/dist/checkpoint/artifacts/types.js.map +1 -0
- package/dist/checkpoint/artifacts/worker-decompressor.d.ts +17 -0
- package/dist/checkpoint/artifacts/worker-decompressor.d.ts.map +1 -0
- package/dist/checkpoint/artifacts/worker-decompressor.js +148 -0
- package/dist/checkpoint/artifacts/worker-decompressor.js.map +1 -0
- package/dist/checkpoint/asset-store.d.ts +10 -0
- package/dist/checkpoint/asset-store.d.ts.map +1 -0
- package/dist/checkpoint/asset-store.js +46 -0
- package/dist/checkpoint/asset-store.js.map +1 -0
- package/dist/checkpoint/bundler.d.ts +15 -0
- package/dist/checkpoint/bundler.d.ts.map +1 -0
- package/dist/checkpoint/bundler.js +45 -0
- package/dist/checkpoint/bundler.js.map +1 -0
- package/dist/checkpoint/cli.d.ts +2 -0
- package/dist/checkpoint/cli.d.ts.map +1 -0
- package/dist/checkpoint/cli.js +157 -0
- package/dist/checkpoint/cli.js.map +1 -0
- package/dist/checkpoint/entrypoint-generator.d.ts +17 -0
- package/dist/checkpoint/entrypoint-generator.d.ts.map +1 -0
- package/dist/checkpoint/entrypoint-generator.js +251 -0
- package/dist/checkpoint/entrypoint-generator.js.map +1 -0
- package/dist/checkpoint/forwarder.d.ts +6 -0
- package/dist/checkpoint/forwarder.d.ts.map +1 -0
- package/dist/checkpoint/forwarder.js +74 -0
- package/dist/checkpoint/forwarder.js.map +1 -0
- package/dist/checkpoint/gateway.d.ts +11 -0
- package/dist/checkpoint/gateway.d.ts.map +1 -0
- package/dist/checkpoint/gateway.js +30 -0
- package/dist/checkpoint/gateway.js.map +1 -0
- package/dist/checkpoint/ipc.d.ts +12 -0
- package/dist/checkpoint/ipc.d.ts.map +1 -0
- package/dist/checkpoint/ipc.js +96 -0
- package/dist/checkpoint/ipc.js.map +1 -0
- package/dist/checkpoint/manager.d.ts +20 -0
- package/dist/checkpoint/manager.d.ts.map +1 -0
- package/dist/checkpoint/manager.js +214 -0
- package/dist/checkpoint/manager.js.map +1 -0
- package/dist/checkpoint/process-manager.d.ts +35 -0
- package/dist/checkpoint/process-manager.d.ts.map +1 -0
- package/dist/checkpoint/process-manager.js +203 -0
- package/dist/checkpoint/process-manager.js.map +1 -0
- package/dist/checkpoint/resolver.d.ts +25 -0
- package/dist/checkpoint/resolver.d.ts.map +1 -0
- package/dist/checkpoint/resolver.js +95 -0
- package/dist/checkpoint/resolver.js.map +1 -0
- package/dist/checkpoint/socket-path.d.ts +2 -0
- package/dist/checkpoint/socket-path.d.ts.map +1 -0
- package/dist/checkpoint/socket-path.js +51 -0
- package/dist/checkpoint/socket-path.js.map +1 -0
- package/dist/checkpoint/types.d.ts +54 -0
- package/dist/checkpoint/types.d.ts.map +1 -0
- package/dist/checkpoint/types.js +2 -0
- package/dist/checkpoint/types.js.map +1 -0
- package/dist/cli/index.js +10 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/option-resolution.d.ts +1 -1
- package/dist/cli/option-resolution.d.ts.map +1 -1
- package/dist/cli/option-resolution.js.map +1 -1
- package/dist/cli.js +3709 -328
- package/dist/core/config-loader.d.ts +1 -0
- package/dist/core/config-loader.d.ts.map +1 -1
- package/dist/core/config-loader.js +10 -2
- package/dist/core/config-loader.js.map +1 -1
- package/dist/core/router.d.ts +24 -3
- package/dist/core/router.d.ts.map +1 -1
- package/dist/core/router.js +398 -249
- package/dist/core/router.js.map +1 -1
- package/dist/core/server.d.ts +2 -0
- package/dist/core/server.d.ts.map +1 -1
- package/dist/core/server.js +22 -8
- package/dist/core/server.js.map +1 -1
- package/dist/core/vector.d.ts +3 -0
- package/dist/core/vector.d.ts.map +1 -1
- package/dist/core/vector.js +51 -1
- package/dist/core/vector.js.map +1 -1
- package/dist/dev/route-scanner.d.ts.map +1 -1
- package/dist/dev/route-scanner.js +2 -1
- package/dist/dev/route-scanner.js.map +1 -1
- package/dist/http.d.ts +32 -7
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +144 -13
- package/dist/http.js.map +1 -1
- package/dist/index.cjs +1297 -74
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1296 -73
- package/dist/middleware/manager.d.ts +3 -3
- package/dist/middleware/manager.d.ts.map +1 -1
- package/dist/middleware/manager.js +9 -8
- package/dist/middleware/manager.js.map +1 -1
- package/dist/openapi/docs-ui.d.ts.map +1 -1
- package/dist/openapi/docs-ui.js +1097 -61
- package/dist/openapi/docs-ui.js.map +1 -1
- package/dist/openapi/generator.d.ts +2 -1
- package/dist/openapi/generator.d.ts.map +1 -1
- package/dist/openapi/generator.js +240 -7
- package/dist/openapi/generator.js.map +1 -1
- package/dist/types/index.d.ts +71 -28
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +24 -1
- package/dist/types/index.js.map +1 -1
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +3 -2
- package/dist/utils/validation.js.map +1 -1
- package/package.json +2 -1
- package/src/auth/protected.ts +11 -8
- package/src/cache/manager.ts +23 -4
- package/src/checkpoint/artifacts/compressor.ts +30 -0
- package/src/checkpoint/artifacts/decompress-worker.ts +49 -0
- package/src/checkpoint/artifacts/hasher.ts +6 -0
- package/src/checkpoint/artifacts/manifest.ts +72 -0
- package/src/checkpoint/artifacts/materializer.ts +211 -0
- package/src/checkpoint/artifacts/packager.ts +100 -0
- package/src/checkpoint/artifacts/repository.ts +36 -0
- package/src/checkpoint/artifacts/store.ts +102 -0
- package/src/checkpoint/artifacts/types.ts +24 -0
- package/src/checkpoint/artifacts/worker-decompressor.ts +192 -0
- package/src/checkpoint/asset-store.ts +61 -0
- package/src/checkpoint/bundler.ts +64 -0
- package/src/checkpoint/cli.ts +177 -0
- package/src/checkpoint/entrypoint-generator.ts +275 -0
- package/src/checkpoint/forwarder.ts +84 -0
- package/src/checkpoint/gateway.ts +40 -0
- package/src/checkpoint/ipc.ts +107 -0
- package/src/checkpoint/manager.ts +254 -0
- package/src/checkpoint/process-manager.ts +250 -0
- package/src/checkpoint/resolver.ts +124 -0
- package/src/checkpoint/socket-path.ts +61 -0
- package/src/checkpoint/types.ts +63 -0
- package/src/cli/index.ts +11 -2
- package/src/cli/option-resolution.ts +5 -1
- package/src/core/config-loader.ts +11 -2
- package/src/core/router.ts +505 -264
- package/src/core/server.ts +36 -9
- package/src/core/vector.ts +60 -1
- package/src/dev/route-scanner.ts +2 -1
- package/src/http.ts +219 -19
- package/src/index.ts +3 -2
- package/src/middleware/manager.ts +10 -10
- package/src/openapi/docs-ui.ts +1097 -61
- package/src/openapi/generator.ts +265 -6
- package/src/types/index.ts +83 -30
- package/src/utils/validation.ts +5 -3
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { parseArgs } from 'node:util';
|
|
2
|
+
import { CheckpointManager } from './manager';
|
|
3
|
+
export async function runCheckpointCli(argv) {
|
|
4
|
+
const subcommand = argv[0];
|
|
5
|
+
switch (subcommand) {
|
|
6
|
+
case 'publish':
|
|
7
|
+
return await cliPublish(argv.slice(1));
|
|
8
|
+
case 'list':
|
|
9
|
+
return await cliList(argv.slice(1));
|
|
10
|
+
case 'rollback':
|
|
11
|
+
return await cliRollback(argv.slice(1));
|
|
12
|
+
case 'remove':
|
|
13
|
+
return await cliRemove(argv.slice(1));
|
|
14
|
+
default:
|
|
15
|
+
printCheckpointHelp();
|
|
16
|
+
if (subcommand) {
|
|
17
|
+
console.error(`\nUnknown checkpoint command: ${subcommand}`);
|
|
18
|
+
}
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
async function cliPublish(args) {
|
|
23
|
+
const { values } = parseArgs({
|
|
24
|
+
args,
|
|
25
|
+
options: {
|
|
26
|
+
version: { type: 'string', short: 'v' },
|
|
27
|
+
routes: { type: 'string', short: 'r', default: './routes' },
|
|
28
|
+
storage: { type: 'string', short: 's' },
|
|
29
|
+
},
|
|
30
|
+
strict: true,
|
|
31
|
+
});
|
|
32
|
+
if (!values.version) {
|
|
33
|
+
console.error('Error: --version is required for publish');
|
|
34
|
+
console.error('Usage: vector checkpoint publish --version <ver> [--routes <dir>]');
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
const manager = new CheckpointManager(values.storage ? { storageDir: values.storage } : undefined);
|
|
38
|
+
try {
|
|
39
|
+
console.log(`Publishing checkpoint ${values.version}...`);
|
|
40
|
+
const manifest = await manager.publish({
|
|
41
|
+
version: values.version,
|
|
42
|
+
routesDir: values.routes,
|
|
43
|
+
});
|
|
44
|
+
console.log(`Checkpoint ${manifest.version} published successfully.`);
|
|
45
|
+
console.log(` Bundle hash: ${manifest.bundleHash.slice(0, 12)}...`);
|
|
46
|
+
console.log(` Bundle size: ${formatBytes(manifest.bundleSize)}`);
|
|
47
|
+
console.log(` Routes: ${manifest.routes.length}`);
|
|
48
|
+
console.log(` Assets: ${manifest.assets.length}`);
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
console.error(`Failed to publish checkpoint: ${err.message}`);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async function cliList(args) {
|
|
56
|
+
const { values } = parseArgs({
|
|
57
|
+
args,
|
|
58
|
+
options: {
|
|
59
|
+
storage: { type: 'string', short: 's' },
|
|
60
|
+
},
|
|
61
|
+
strict: true,
|
|
62
|
+
});
|
|
63
|
+
const manager = new CheckpointManager(values.storage ? { storageDir: values.storage } : undefined);
|
|
64
|
+
const manifests = await manager.listVersions();
|
|
65
|
+
const active = await manager.getActive();
|
|
66
|
+
if (manifests.length === 0) {
|
|
67
|
+
console.log('No checkpoints found.');
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
console.log('');
|
|
71
|
+
console.log(' Version Created Bundle Hash Size Status');
|
|
72
|
+
console.log(' ─────────────────────────────────────────────────────────────────────────');
|
|
73
|
+
for (const m of manifests) {
|
|
74
|
+
const isActive = active?.version === m.version;
|
|
75
|
+
const status = isActive ? '● active' : ' ';
|
|
76
|
+
const hash = m.bundleHash.slice(0, 12);
|
|
77
|
+
const size = formatBytes(m.bundleSize).padEnd(10);
|
|
78
|
+
const created = new Date(m.createdAt).toISOString().replace('T', ' ').slice(0, 19);
|
|
79
|
+
console.log(` ${m.version.padEnd(12)} ${created} ${hash}... ${size} ${status}`);
|
|
80
|
+
}
|
|
81
|
+
console.log('');
|
|
82
|
+
}
|
|
83
|
+
async function cliRollback(args) {
|
|
84
|
+
const { positionals, values } = parseArgs({
|
|
85
|
+
args,
|
|
86
|
+
options: {
|
|
87
|
+
storage: { type: 'string', short: 's' },
|
|
88
|
+
},
|
|
89
|
+
strict: true,
|
|
90
|
+
allowPositionals: true,
|
|
91
|
+
});
|
|
92
|
+
const version = positionals[0];
|
|
93
|
+
if (!version) {
|
|
94
|
+
console.error('Error: version argument is required');
|
|
95
|
+
console.error('Usage: vector checkpoint rollback <version>');
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
const manager = new CheckpointManager(values.storage ? { storageDir: values.storage } : undefined);
|
|
99
|
+
try {
|
|
100
|
+
await manager.setActive(version);
|
|
101
|
+
console.log(`Active checkpoint set to ${version}.`);
|
|
102
|
+
console.log('Note: Restart the server for the change to take effect.');
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
console.error(`Failed to rollback: ${err.message}`);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
async function cliRemove(args) {
|
|
110
|
+
const { positionals, values } = parseArgs({
|
|
111
|
+
args,
|
|
112
|
+
options: {
|
|
113
|
+
storage: { type: 'string', short: 's' },
|
|
114
|
+
},
|
|
115
|
+
strict: true,
|
|
116
|
+
allowPositionals: true,
|
|
117
|
+
});
|
|
118
|
+
const version = positionals[0];
|
|
119
|
+
if (!version) {
|
|
120
|
+
console.error('Error: version argument is required');
|
|
121
|
+
console.error('Usage: vector checkpoint remove <version>');
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
const manager = new CheckpointManager(values.storage ? { storageDir: values.storage } : undefined);
|
|
125
|
+
try {
|
|
126
|
+
await manager.remove(version);
|
|
127
|
+
console.log(`Checkpoint ${version} removed.`);
|
|
128
|
+
}
|
|
129
|
+
catch (err) {
|
|
130
|
+
console.error(`Failed to remove checkpoint: ${err.message}`);
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
function printCheckpointHelp() {
|
|
135
|
+
console.log(`
|
|
136
|
+
Usage: vector checkpoint <command>
|
|
137
|
+
|
|
138
|
+
Commands:
|
|
139
|
+
publish --version <ver> [--routes <dir>] Build and store a checkpoint
|
|
140
|
+
list List all stored checkpoints
|
|
141
|
+
rollback <version> Activate a specific checkpoint
|
|
142
|
+
remove <version> Delete a checkpoint
|
|
143
|
+
|
|
144
|
+
Options:
|
|
145
|
+
-v, --version Semver version string (e.g. 1.2.0)
|
|
146
|
+
-r, --routes Routes directory (default: ./routes)
|
|
147
|
+
-s, --storage Checkpoint storage dir (default: .vector/checkpoints)
|
|
148
|
+
`);
|
|
149
|
+
}
|
|
150
|
+
function formatBytes(bytes) {
|
|
151
|
+
if (bytes < 1024)
|
|
152
|
+
return `${bytes} B`;
|
|
153
|
+
if (bytes < 1024 * 1024)
|
|
154
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
155
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/checkpoint/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { CheckpointRouteRecord } from './types';
|
|
2
|
+
export interface EntrypointGeneratorOptions {
|
|
3
|
+
version: string;
|
|
4
|
+
outputDir: string;
|
|
5
|
+
routesDir: string;
|
|
6
|
+
socketPath: string;
|
|
7
|
+
}
|
|
8
|
+
export declare class CheckpointEntrypointGenerator {
|
|
9
|
+
private discoveredRoutes;
|
|
10
|
+
generate(options: EntrypointGeneratorOptions): Promise<string>;
|
|
11
|
+
getDiscoveredRoutes(): CheckpointRouteRecord[];
|
|
12
|
+
private scanRouteFiles;
|
|
13
|
+
private walkDir;
|
|
14
|
+
private buildSource;
|
|
15
|
+
private toImportSpecifier;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=entrypoint-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entrypoint-generator.d.ts","sourceRoot":"","sources":["../../src/checkpoint/entrypoint-generator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAErD,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,6BAA6B;IACxC,OAAO,CAAC,gBAAgB,CAA+B;IAEjD,QAAQ,CAAC,OAAO,EAAE,0BAA0B,GAAG,OAAO,CAAC,MAAM,CAAC;IASpE,mBAAmB,IAAI,qBAAqB,EAAE;YAIhC,cAAc;YAUd,OAAO;IAsBrB,OAAO,CAAC,WAAW;IAgNnB,OAAO,CAAC,iBAAiB;CAO1B"}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import { existsSync, promises as fs } from 'node:fs';
|
|
2
|
+
import { join, relative, sep } from 'node:path';
|
|
3
|
+
export class CheckpointEntrypointGenerator {
|
|
4
|
+
discoveredRoutes = [];
|
|
5
|
+
async generate(options) {
|
|
6
|
+
const routeFiles = await this.scanRouteFiles(options.routesDir);
|
|
7
|
+
const source = this.buildSource(routeFiles, options);
|
|
8
|
+
const outputPath = join(options.outputDir, 'entrypoint.ts');
|
|
9
|
+
await fs.writeFile(outputPath, source, 'utf-8');
|
|
10
|
+
return outputPath;
|
|
11
|
+
}
|
|
12
|
+
getDiscoveredRoutes() {
|
|
13
|
+
return this.discoveredRoutes;
|
|
14
|
+
}
|
|
15
|
+
async scanRouteFiles(routesDir) {
|
|
16
|
+
if (!existsSync(routesDir)) {
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
19
|
+
const files = [];
|
|
20
|
+
await this.walkDir(routesDir, files);
|
|
21
|
+
return files;
|
|
22
|
+
}
|
|
23
|
+
async walkDir(dir, files) {
|
|
24
|
+
const entries = await fs.readdir(dir);
|
|
25
|
+
for (const entry of entries) {
|
|
26
|
+
const fullPath = join(dir, entry);
|
|
27
|
+
const stats = await fs.stat(fullPath);
|
|
28
|
+
if (stats.isDirectory()) {
|
|
29
|
+
await this.walkDir(fullPath, files);
|
|
30
|
+
}
|
|
31
|
+
else if ((entry.endsWith('.ts') || entry.endsWith('.js')) &&
|
|
32
|
+
!entry.endsWith('.test.ts') &&
|
|
33
|
+
!entry.endsWith('.test.js') &&
|
|
34
|
+
!entry.endsWith('.spec.ts') &&
|
|
35
|
+
!entry.endsWith('.spec.js') &&
|
|
36
|
+
!entry.endsWith('.d.ts')) {
|
|
37
|
+
files.push(fullPath);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
buildSource(routeFiles, options) {
|
|
42
|
+
this.discoveredRoutes = [];
|
|
43
|
+
const imports = [];
|
|
44
|
+
const registrations = [];
|
|
45
|
+
for (const [i, file] of routeFiles.entries()) {
|
|
46
|
+
const varName = `routeModule_${i}`;
|
|
47
|
+
const importSpecifier = this.toImportSpecifier(file, options.outputDir);
|
|
48
|
+
imports.push(`import * as ${varName} from ${JSON.stringify(importSpecifier)};`);
|
|
49
|
+
registrations.push(` registerModule(${varName});`);
|
|
50
|
+
// Record discovered route for manifest
|
|
51
|
+
const routePath = relative(options.routesDir, file)
|
|
52
|
+
.replace(/\.(ts|js)$/, '')
|
|
53
|
+
.split(sep)
|
|
54
|
+
.join('/');
|
|
55
|
+
this.discoveredRoutes.push({
|
|
56
|
+
method: '*',
|
|
57
|
+
path: `/${routePath}`,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return `// Checkpoint entrypoint — auto-generated for version ${options.version}
|
|
61
|
+
// DO NOT EDIT: This file is generated by Vector checkpoint publish.
|
|
62
|
+
|
|
63
|
+
${imports.join('\n')}
|
|
64
|
+
|
|
65
|
+
const socketPath = process.env.VECTOR_CHECKPOINT_SOCKET ?? '${options.socketPath}';
|
|
66
|
+
const checkpointContextHeader = 'x-vector-checkpoint-context';
|
|
67
|
+
|
|
68
|
+
// Route registration helper
|
|
69
|
+
type RouteDefinition = {
|
|
70
|
+
entry: { method: string; path: string };
|
|
71
|
+
options: { method: string; path: string; [key: string]: any };
|
|
72
|
+
handler: (ctx: any) => any;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
function isRouteDefinition(value: unknown): value is RouteDefinition {
|
|
76
|
+
return (
|
|
77
|
+
value !== null &&
|
|
78
|
+
typeof value === 'object' &&
|
|
79
|
+
'entry' in value &&
|
|
80
|
+
'options' in value &&
|
|
81
|
+
'handler' in value &&
|
|
82
|
+
typeof (value as any).handler === 'function'
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const routeTable: Record<string, Record<string, (req: Request) => Response | Promise<Response>>> = {};
|
|
87
|
+
|
|
88
|
+
function parseCheckpointContext(req: Request): Record<string, unknown> {
|
|
89
|
+
const encoded = req.headers.get(checkpointContextHeader);
|
|
90
|
+
if (!encoded) {
|
|
91
|
+
return {};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
const json = Buffer.from(encoded, 'base64url').toString('utf-8');
|
|
96
|
+
const parsed = JSON.parse(json);
|
|
97
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
98
|
+
return {};
|
|
99
|
+
}
|
|
100
|
+
return parsed as Record<string, unknown>;
|
|
101
|
+
} catch {
|
|
102
|
+
return {};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function parseQuery(url: URL): Record<string, string | string[]> {
|
|
107
|
+
const query: Record<string, string | string[]> = {};
|
|
108
|
+
for (const [key, value] of url.searchParams) {
|
|
109
|
+
if (key in query) {
|
|
110
|
+
const existing = query[key];
|
|
111
|
+
if (Array.isArray(existing)) {
|
|
112
|
+
existing.push(value);
|
|
113
|
+
} else {
|
|
114
|
+
query[key] = [existing as string, value];
|
|
115
|
+
}
|
|
116
|
+
} else {
|
|
117
|
+
query[key] = value;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return query;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function parseCookies(cookieHeader: string | null): Record<string, string> {
|
|
124
|
+
const cookies: Record<string, string> = {};
|
|
125
|
+
if (!cookieHeader) {
|
|
126
|
+
return cookies;
|
|
127
|
+
}
|
|
128
|
+
for (const pair of cookieHeader.split(';')) {
|
|
129
|
+
const idx = pair.indexOf('=');
|
|
130
|
+
if (idx > 0) {
|
|
131
|
+
cookies[pair.slice(0, idx).trim()] = pair.slice(idx + 1).trim();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return cookies;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function extractRouteParams(req: Request): Record<string, string> {
|
|
138
|
+
const nativeParams = (req as Request & { params?: Record<string, string> }).params;
|
|
139
|
+
if (nativeParams && typeof nativeParams === 'object' && !Array.isArray(nativeParams)) {
|
|
140
|
+
return nativeParams;
|
|
141
|
+
}
|
|
142
|
+
return {};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function createContext(req: Request): Record<string, unknown> {
|
|
146
|
+
const ctx: Record<string, unknown> = Object.create(null);
|
|
147
|
+
setContextField(ctx, 'request', req);
|
|
148
|
+
|
|
149
|
+
// Initialize always-present VectorContext fields with defaults derived from the request
|
|
150
|
+
setContextField(ctx, 'params', extractRouteParams(req));
|
|
151
|
+
|
|
152
|
+
try {
|
|
153
|
+
setContextField(ctx, 'query', parseQuery(new URL(req.url)));
|
|
154
|
+
} catch {
|
|
155
|
+
setContextField(ctx, 'query', {});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
setContextField(ctx, 'cookies', parseCookies(req.headers.get('cookie')));
|
|
159
|
+
setContextField(ctx, 'metadata', {});
|
|
160
|
+
|
|
161
|
+
const checkpointContext = parseCheckpointContext(req);
|
|
162
|
+
const allowedCheckpointKeys = ['metadata', 'content', 'validatedInput', 'authUser'] as const;
|
|
163
|
+
for (const key of allowedCheckpointKeys) {
|
|
164
|
+
if (!Object.prototype.hasOwnProperty.call(checkpointContext, key)) {
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
const value = checkpointContext[key];
|
|
168
|
+
setContextField(ctx, key, value);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return ctx;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function setContextField(target: Record<string, unknown>, key: string, value: unknown) {
|
|
175
|
+
const ownDescriptor = Object.getOwnPropertyDescriptor(target as object, key);
|
|
176
|
+
if (ownDescriptor && ownDescriptor.writable === false && typeof ownDescriptor.set !== 'function') {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
try {
|
|
181
|
+
target[key] = value;
|
|
182
|
+
return;
|
|
183
|
+
} catch {
|
|
184
|
+
// Fall back to own-property define when inherited Request field is readonly.
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
try {
|
|
188
|
+
Object.defineProperty(target, key, {
|
|
189
|
+
value,
|
|
190
|
+
writable: true,
|
|
191
|
+
configurable: true,
|
|
192
|
+
enumerable: true,
|
|
193
|
+
});
|
|
194
|
+
} catch {
|
|
195
|
+
// Ignore non-extensible context edge cases.
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function addToRouteTable(method: string, path: string, handler: (ctx: any) => any) {
|
|
200
|
+
if (!routeTable[path]) {
|
|
201
|
+
routeTable[path] = Object.create(null);
|
|
202
|
+
}
|
|
203
|
+
routeTable[path][method.toUpperCase()] = async (req: Request) => {
|
|
204
|
+
const ctx = createContext(req);
|
|
205
|
+
const result = await handler(ctx);
|
|
206
|
+
if (result instanceof Response) return result;
|
|
207
|
+
return Response.json(result);
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function registerModule(mod: Record<string, unknown>) {
|
|
212
|
+
for (const [name, value] of Object.entries(mod)) {
|
|
213
|
+
if (isRouteDefinition(value)) {
|
|
214
|
+
addToRouteTable(value.options.method, value.options.path, value.handler);
|
|
215
|
+
} else if (name === 'default' && typeof value === 'function') {
|
|
216
|
+
// Default export functions need path context — skip for now
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
${registrations.join('\n')}
|
|
222
|
+
|
|
223
|
+
// Health check endpoint for parent process
|
|
224
|
+
routeTable['/_vector/health'] = {
|
|
225
|
+
GET: () => Response.json({ status: 'ok', version: '${options.version}' }),
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
const server = Bun.serve({
|
|
229
|
+
unix: socketPath,
|
|
230
|
+
routes: routeTable,
|
|
231
|
+
fetch(req: Request) {
|
|
232
|
+
return Response.json(
|
|
233
|
+
{ error: true, message: 'Not Found', statusCode: 404 },
|
|
234
|
+
{ status: 404 }
|
|
235
|
+
);
|
|
236
|
+
},
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
// Signal readiness to parent process
|
|
240
|
+
process.stdout.write('READY\\n');
|
|
241
|
+
`;
|
|
242
|
+
}
|
|
243
|
+
toImportSpecifier(filePath, outputDir) {
|
|
244
|
+
const normalized = relative(outputDir, filePath).split(sep).join('/');
|
|
245
|
+
if (normalized.startsWith('.') || normalized.startsWith('/')) {
|
|
246
|
+
return normalized;
|
|
247
|
+
}
|
|
248
|
+
return `./${normalized}`;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
//# sourceMappingURL=entrypoint-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entrypoint-generator.js","sourceRoot":"","sources":["../../src/checkpoint/entrypoint-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const CHECKPOINT_CONTEXT_HEADER = "x-vector-checkpoint-context";
|
|
2
|
+
export type CheckpointContextPayload = Record<string, unknown>;
|
|
3
|
+
export declare class CheckpointForwarder {
|
|
4
|
+
forward(request: Request, socketPath: string, contextPayload?: CheckpointContextPayload): Promise<Response>;
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=forwarder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forwarder.d.ts","sourceRoot":"","sources":["../../src/checkpoint/forwarder.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,yBAAyB,gCAAgC,CAAC;AAEvE,MAAM,MAAM,wBAAwB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE/D,qBAAa,mBAAmB;IACxB,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,wBAAwB,GAAG,OAAO,CAAC,QAAQ,CAAC;CA6BlH"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
export const CHECKPOINT_CONTEXT_HEADER = 'x-vector-checkpoint-context';
|
|
2
|
+
export class CheckpointForwarder {
|
|
3
|
+
async forward(request, socketPath, contextPayload) {
|
|
4
|
+
try {
|
|
5
|
+
const encodedContext = encodeCheckpointContext(contextPayload);
|
|
6
|
+
const headers = buildForwardHeaders(request.headers, encodedContext);
|
|
7
|
+
const response = await fetch(request.url, {
|
|
8
|
+
method: request.method,
|
|
9
|
+
headers,
|
|
10
|
+
body: request.body,
|
|
11
|
+
unix: socketPath,
|
|
12
|
+
// @ts-ignore - duplex required for streaming body
|
|
13
|
+
duplex: request.body ? 'half' : undefined,
|
|
14
|
+
});
|
|
15
|
+
// Clone the response so headers are mutable (fetch returns immutable headers).
|
|
16
|
+
// This is required because the parent server applies CORS headers after forwarding.
|
|
17
|
+
return new Response(response.body, {
|
|
18
|
+
status: response.status,
|
|
19
|
+
statusText: response.statusText,
|
|
20
|
+
headers: new Headers(response.headers),
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
console.error('[CheckpointForwarder] Forward failed:', error);
|
|
25
|
+
return new Response(JSON.stringify({ error: true, message: 'Checkpoint unavailable', statusCode: 503 }), {
|
|
26
|
+
status: 503,
|
|
27
|
+
headers: { 'content-type': 'application/json' },
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function buildForwardHeaders(source, encodedContext) {
|
|
33
|
+
const headers = new Headers(source);
|
|
34
|
+
stripHopByHopHeaders(headers);
|
|
35
|
+
if (encodedContext) {
|
|
36
|
+
headers.set(CHECKPOINT_CONTEXT_HEADER, encodedContext);
|
|
37
|
+
}
|
|
38
|
+
return headers;
|
|
39
|
+
}
|
|
40
|
+
function stripHopByHopHeaders(headers) {
|
|
41
|
+
const connectionValue = headers.get('connection');
|
|
42
|
+
if (connectionValue) {
|
|
43
|
+
for (const token of connectionValue.split(',')) {
|
|
44
|
+
const normalized = token.trim().toLowerCase();
|
|
45
|
+
if (normalized) {
|
|
46
|
+
headers.delete(normalized);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
headers.delete('connection');
|
|
51
|
+
headers.delete('keep-alive');
|
|
52
|
+
headers.delete('proxy-authenticate');
|
|
53
|
+
headers.delete('proxy-authorization');
|
|
54
|
+
headers.delete('te');
|
|
55
|
+
headers.delete('trailer');
|
|
56
|
+
headers.delete('transfer-encoding');
|
|
57
|
+
headers.delete('upgrade');
|
|
58
|
+
}
|
|
59
|
+
function encodeCheckpointContext(contextPayload) {
|
|
60
|
+
if (!contextPayload) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
const keys = Object.keys(contextPayload);
|
|
64
|
+
if (keys.length === 0) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
try {
|
|
68
|
+
return Buffer.from(JSON.stringify(contextPayload), 'utf-8').toString('base64url');
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=forwarder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forwarder.js","sourceRoot":"","sources":["../../src/checkpoint/forwarder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CheckpointResolver } from './resolver';
|
|
2
|
+
import type { CheckpointContextPayload, CheckpointForwarder } from './forwarder';
|
|
3
|
+
export declare class CheckpointGateway {
|
|
4
|
+
private resolver;
|
|
5
|
+
private forwarder;
|
|
6
|
+
constructor(resolver: CheckpointResolver, forwarder: CheckpointForwarder);
|
|
7
|
+
getRequestedVersion(request: Request): string | null;
|
|
8
|
+
getCacheKeyOverrideValue(request: Request): string | null;
|
|
9
|
+
handle(request: Request, contextPayload?: CheckpointContextPayload): Promise<Response | null>;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=gateway.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../../src/checkpoint/gateway.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,KAAK,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEjF,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAqB;IACrC,OAAO,CAAC,SAAS,CAAsB;gBAE3B,QAAQ,EAAE,kBAAkB,EAAE,SAAS,EAAE,mBAAmB;IAKxE,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI;IAIpD,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI;IAInD,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,CAAC,EAAE,wBAAwB,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;CAmBpG"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export class CheckpointGateway {
|
|
2
|
+
resolver;
|
|
3
|
+
forwarder;
|
|
4
|
+
constructor(resolver, forwarder) {
|
|
5
|
+
this.resolver = resolver;
|
|
6
|
+
this.forwarder = forwarder;
|
|
7
|
+
}
|
|
8
|
+
getRequestedVersion(request) {
|
|
9
|
+
return this.resolver.getRequestedVersion(request);
|
|
10
|
+
}
|
|
11
|
+
getCacheKeyOverrideValue(request) {
|
|
12
|
+
return this.resolver.getCacheKeyOverrideValue(request);
|
|
13
|
+
}
|
|
14
|
+
async handle(request, contextPayload) {
|
|
15
|
+
const requestedVersion = this.getRequestedVersion(request);
|
|
16
|
+
const socketPath = await this.resolver.resolve(request);
|
|
17
|
+
if (!socketPath) {
|
|
18
|
+
if (requestedVersion) {
|
|
19
|
+
return new Response(JSON.stringify({
|
|
20
|
+
error: true,
|
|
21
|
+
message: `Requested checkpoint version "${requestedVersion}" is unavailable`,
|
|
22
|
+
statusCode: 503,
|
|
23
|
+
}), { status: 503, headers: { 'content-type': 'application/json' } });
|
|
24
|
+
}
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
return await this.forwarder.forward(request, socketPath, contextPayload);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=gateway.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gateway.js","sourceRoot":"","sources":["../../src/checkpoint/gateway.ts"],"names":[],"mappings":"AAGA,MAAM,OAAO,iBAAiB;IACpB,QAAQ,CAAqB;IAC7B,SAAS,CAAsB;IAEvC,YAAY,QAA4B,EAAE,SAA8B;QACtE,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IAED,mBAAmB,CAAC,OAAgB;QAClC,OAAO,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACpD,CAAC;IAED,wBAAwB,CAAC,OAAgB;QACvC,OAAO,IAAI,CAAC,QAAQ,CAAC,wBAAwB,CAAC,OAAO,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,OAAgB,EAAE,cAAyC;QACtE,MAAM,gBAAgB,GAAG,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;QAC3D,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACxD,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,IAAI,gBAAgB,EAAE,CAAC;gBACrB,OAAO,IAAI,QAAQ,CACjB,IAAI,CAAC,SAAS,CAAC;oBACb,KAAK,EAAE,IAAI;oBACX,OAAO,EAAE,iCAAiC,gBAAgB,kBAAkB;oBAC5E,UAAU,EAAE,GAAG;iBAChB,CAAC,EACF,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,EAAE,CACjE,CAAC;YACJ,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,UAAU,EAAE,cAAc,CAAC,CAAC;IAC3E,CAAC;CACF"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type CheckpointIpcMessage = {
|
|
2
|
+
type: 'ready';
|
|
3
|
+
} | {
|
|
4
|
+
type: 'error';
|
|
5
|
+
message: string;
|
|
6
|
+
} | {
|
|
7
|
+
type: 'health';
|
|
8
|
+
status: 'ok' | 'degraded';
|
|
9
|
+
};
|
|
10
|
+
export declare function parseIpcLine(line: string): CheckpointIpcMessage | null;
|
|
11
|
+
export declare function waitForReady(stdout: ReadableStream<Uint8Array>, timeoutMs?: number): Promise<void>;
|
|
12
|
+
//# sourceMappingURL=ipc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ipc.d.ts","sourceRoot":"","sources":["../../src/checkpoint/ipc.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,oBAAoB,GAC5B;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,IAAI,GAAG,UAAU,CAAA;CAAE,CAAC;AAIlD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI,CAUtE;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,EAAE,SAAS,GAAE,MAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAuFhH"}
|