@scenar/cli 0.2.1 → 0.4.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/example-bundle/embed.js +1 -0
- package/example-bundle/pack-manifest.json +6 -0
- package/package.json +4 -8
- package/src/__tests__/embed-loader.test.ts +29 -0
- package/src/__tests__/embed-snippet.test.ts +48 -1
- package/src/__tests__/install-command.test.ts +97 -0
- package/src/__tests__/local-url.test.ts +17 -0
- package/src/__tests__/run-install.test.ts +222 -0
- package/src/api.d.ts +3 -1
- package/src/api.d.ts.map +1 -1
- package/src/api.js +3 -1
- package/src/api.js.map +1 -1
- package/src/api.ts +10 -1
- package/src/commands/install.d.ts +3 -0
- package/src/commands/install.d.ts.map +1 -0
- package/src/commands/install.js +67 -0
- package/src/commands/install.js.map +1 -0
- package/src/commands/install.ts +89 -0
- package/src/commands/pack.js +2 -2
- package/src/commands/pack.js.map +1 -1
- package/src/commands/pack.ts +2 -2
- package/src/commands/publish.d.ts.map +1 -1
- package/src/commands/publish.js +3 -1
- package/src/commands/publish.js.map +1 -1
- package/src/commands/publish.ts +5 -1
- package/src/commands/serve.d.ts.map +1 -1
- package/src/commands/serve.js +3 -2
- package/src/commands/serve.js.map +1 -1
- package/src/commands/serve.ts +5 -2
- package/src/commands/try.js +1 -1
- package/src/commands/try.ts +1 -1
- package/src/{deploy → embed}/embed-snippet.d.ts +16 -0
- package/src/embed/embed-snippet.d.ts.map +1 -0
- package/src/{deploy → embed}/embed-snippet.js +27 -0
- package/src/embed/embed-snippet.js.map +1 -0
- package/src/{deploy → embed}/embed-snippet.ts +28 -0
- package/src/index.d.ts.map +1 -1
- package/src/index.js +3 -5
- package/src/index.js.map +1 -1
- package/src/index.ts +3 -5
- package/src/install/run-install.d.ts +72 -0
- package/src/install/run-install.d.ts.map +1 -0
- package/src/install/run-install.js +378 -0
- package/src/install/run-install.js.map +1 -0
- package/src/install/run-install.ts +461 -0
- package/src/install/scaffold.d.ts +29 -0
- package/src/install/scaffold.d.ts.map +1 -0
- package/src/install/scaffold.js +233 -0
- package/src/install/scaffold.js.map +1 -0
- package/src/install/scaffold.ts +255 -0
- package/src/pack/embed-loader.d.ts +18 -0
- package/src/pack/embed-loader.d.ts.map +1 -0
- package/src/pack/embed-loader.js +25 -0
- package/src/pack/embed-loader.js.map +1 -0
- package/src/pack/embed-loader.ts +27 -0
- package/src/pack/pack-manifest.d.ts +1 -1
- package/src/pack/pack-manifest.d.ts.map +1 -1
- package/src/pack/pack-manifest.ts +1 -1
- package/src/pack/run-pack.d.ts.map +1 -1
- package/src/pack/run-pack.js +6 -0
- package/src/pack/run-pack.js.map +1 -1
- package/src/pack/run-pack.ts +7 -0
- package/src/publish/publish-flow.d.ts +3 -3
- package/src/publish/publish-flow.js +3 -3
- package/src/publish/publish-flow.ts +3 -3
- package/src/publish/run-publish.d.ts +2 -0
- package/src/publish/run-publish.d.ts.map +1 -1
- package/src/publish/run-publish.js +3 -2
- package/src/publish/run-publish.js.map +1 -1
- package/src/publish/run-publish.ts +5 -2
- package/src/render/detect-render-export.d.ts +2 -2
- package/src/render/detect-render-export.js +2 -2
- package/src/render/detect-render-export.ts +2 -2
- package/src/serve/local-url.d.ts +8 -0
- package/src/serve/local-url.d.ts.map +1 -0
- package/src/serve/local-url.js +21 -0
- package/src/serve/local-url.js.map +1 -0
- package/src/serve/local-url.ts +20 -0
- package/src/serve/run-serve.d.ts +2 -0
- package/src/serve/run-serve.d.ts.map +1 -1
- package/src/serve/run-serve.js +4 -3
- package/src/serve/run-serve.js.map +1 -1
- package/src/serve/run-serve.ts +6 -3
- package/tsconfig.tsbuildinfo +1 -1
- package/src/__tests__/deploy-command.test.ts +0 -45
- package/src/__tests__/deploy-flow.test.ts +0 -125
- package/src/__tests__/deploy-upload.test.ts +0 -39
- package/src/commands/deploy.d.ts +0 -3
- package/src/commands/deploy.d.ts.map +0 -1
- package/src/commands/deploy.js +0 -150
- package/src/commands/deploy.js.map +0 -1
- package/src/commands/deploy.ts +0 -186
- package/src/commands/preview.d.ts +0 -3
- package/src/commands/preview.d.ts.map +0 -1
- package/src/commands/preview.js +0 -93
- package/src/commands/preview.js.map +0 -1
- package/src/commands/preview.ts +0 -138
- package/src/deploy/client.d.ts +0 -20
- package/src/deploy/client.d.ts.map +0 -1
- package/src/deploy/client.js +0 -22
- package/src/deploy/client.js.map +0 -1
- package/src/deploy/client.ts +0 -28
- package/src/deploy/deploy-flow.d.ts +0 -78
- package/src/deploy/deploy-flow.d.ts.map +0 -1
- package/src/deploy/deploy-flow.js +0 -53
- package/src/deploy/deploy-flow.js.map +0 -1
- package/src/deploy/deploy-flow.ts +0 -115
- package/src/deploy/embed-snippet.d.ts.map +0 -1
- package/src/deploy/embed-snippet.js.map +0 -1
- package/src/deploy/upload.d.ts +0 -10
- package/src/deploy/upload.d.ts.map +0 -1
- package/src/deploy/upload.js +0 -23
- package/src/deploy/upload.js.map +0 -1
- package/src/deploy/upload.ts +0 -29
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"preview.js","sourceRoot":"","sources":["../../../src/commands/preview.ts"],"names":[],"mappings":"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"}
|
package/src/commands/preview.ts
DELETED
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import * as path from "path";
|
|
2
|
-
import { Command } from "commander";
|
|
3
|
-
import { scanProject, generate, initMswServiceWorker } from "@scenar/preview";
|
|
4
|
-
|
|
5
|
-
interface PreviewInitOptions {
|
|
6
|
-
source?: string;
|
|
7
|
-
output?: string;
|
|
8
|
-
resetProviders?: boolean;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
interface PreviewSyncOptions {
|
|
12
|
-
source?: string;
|
|
13
|
-
output?: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function registerPreviewCommand(program: Command): void {
|
|
17
|
-
const preview = program
|
|
18
|
-
.command("preview")
|
|
19
|
-
.description("Scan a React project and generate a preview view registry.");
|
|
20
|
-
|
|
21
|
-
preview
|
|
22
|
-
.command("init")
|
|
23
|
-
.description("Scan a project and generate the .scenar/ directory.")
|
|
24
|
-
.option("-s, --source <path>", "project to scan (default: cwd)")
|
|
25
|
-
.option("-o, --output <path>", "output directory for generated files (default: .scenar relative to cwd)")
|
|
26
|
-
.option("--reset-providers", "force-regenerate providers.tsx")
|
|
27
|
-
.action(async (options: PreviewInitOptions) => {
|
|
28
|
-
await runPreviewInit(options);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
preview
|
|
32
|
-
.command("sync")
|
|
33
|
-
.description("Re-scan and update scanner-owned files (preserves user files).")
|
|
34
|
-
.option("-s, --source <path>", "project to scan (default: cwd)")
|
|
35
|
-
.option("-o, --output <path>", "output directory for generated files (default: .scenar relative to cwd)")
|
|
36
|
-
.action(async (options: PreviewSyncOptions) => {
|
|
37
|
-
await runPreviewSync(options);
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async function runPreviewInit(options: PreviewInitOptions): Promise<void> {
|
|
42
|
-
const sourceRoot = path.resolve(options.source ?? process.cwd());
|
|
43
|
-
const outputDir = path.resolve(options.output ?? ".scenar");
|
|
44
|
-
|
|
45
|
-
process.stdout.write(`\x1b[36m●\x1b[0m Scanning project: ${sourceRoot}\n`);
|
|
46
|
-
|
|
47
|
-
const scanResult = scanProject(sourceRoot);
|
|
48
|
-
|
|
49
|
-
process.stdout.write(
|
|
50
|
-
` Found ${scanResult.discovered.length} components, ` +
|
|
51
|
-
`skipped ${scanResult.skipped.length}\n`,
|
|
52
|
-
);
|
|
53
|
-
process.stdout.write(
|
|
54
|
-
` Framework: ${scanResult.framework}, ` +
|
|
55
|
-
`entry: ${scanResult.entryPoint ?? "none detected"}\n`,
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
if (scanResult.detectedProviders.length > 0) {
|
|
59
|
-
process.stdout.write(
|
|
60
|
-
` Providers: ${scanResult.detectedProviders.join(", ")}\n`,
|
|
61
|
-
);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const relOutput = path.relative(process.cwd(), outputDir);
|
|
65
|
-
process.stdout.write(`\n\x1b[36m●\x1b[0m Generating ${relOutput}/\n`);
|
|
66
|
-
|
|
67
|
-
const result = generate(scanResult, {
|
|
68
|
-
sourceRoot,
|
|
69
|
-
outputDir,
|
|
70
|
-
isInit: true,
|
|
71
|
-
resetProviders: options.resetProviders,
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
for (const file of result.written) {
|
|
75
|
-
process.stdout.write(` \x1b[32m✓\x1b[0m ${file}\n`);
|
|
76
|
-
}
|
|
77
|
-
for (const file of result.preserved) {
|
|
78
|
-
process.stdout.write(` \x1b[33m●\x1b[0m ${file} (preserved)\n`);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// --- MSW service worker ---
|
|
82
|
-
const projectRoot = path.resolve(path.dirname(outputDir));
|
|
83
|
-
const mswResult = initMswServiceWorker(projectRoot, scanResult.framework);
|
|
84
|
-
|
|
85
|
-
if (mswResult.status === "created") {
|
|
86
|
-
process.stdout.write(
|
|
87
|
-
`\n\x1b[36m●\x1b[0m MSW service worker\n` +
|
|
88
|
-
` \x1b[32m✓\x1b[0m ${path.relative(process.cwd(), mswResult.path!)}\n`,
|
|
89
|
-
);
|
|
90
|
-
} else if (mswResult.status === "exists") {
|
|
91
|
-
process.stdout.write(
|
|
92
|
-
`\n\x1b[36m●\x1b[0m MSW service worker\n` +
|
|
93
|
-
` \x1b[33m●\x1b[0m ${path.relative(process.cwd(), mswResult.path!)} (exists)\n`,
|
|
94
|
-
);
|
|
95
|
-
} else if (mswResult.status === "error") {
|
|
96
|
-
process.stdout.write(
|
|
97
|
-
`\n\x1b[33m⚠\x1b[0m Could not generate MSW service worker: ${mswResult.error}\n` +
|
|
98
|
-
` Run \`npx msw init public/\` manually.\n`,
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
process.stdout.write(`\n\x1b[32m✓\x1b[0m Preview initialized.\n`);
|
|
103
|
-
process.stdout.write(` Review ${relOutput}/report.md for scan details.\n`);
|
|
104
|
-
process.stdout.write(` Add custom views in ${relOutput}/views.custom.tsx.\n`);
|
|
105
|
-
process.stdout.write(` Customize providers in ${relOutput}/providers.tsx.\n`);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
async function runPreviewSync(options: PreviewSyncOptions): Promise<void> {
|
|
109
|
-
const sourceRoot = path.resolve(options.source ?? process.cwd());
|
|
110
|
-
const outputDir = path.resolve(options.output ?? ".scenar");
|
|
111
|
-
|
|
112
|
-
process.stdout.write(`\x1b[36m●\x1b[0m Re-scanning project: ${sourceRoot}\n`);
|
|
113
|
-
|
|
114
|
-
const scanResult = scanProject(sourceRoot);
|
|
115
|
-
|
|
116
|
-
process.stdout.write(
|
|
117
|
-
` Found ${scanResult.discovered.length} components, ` +
|
|
118
|
-
`skipped ${scanResult.skipped.length}\n`,
|
|
119
|
-
);
|
|
120
|
-
|
|
121
|
-
const relOutput = path.relative(process.cwd(), outputDir);
|
|
122
|
-
process.stdout.write(`\n\x1b[36m●\x1b[0m Updating ${relOutput}/\n`);
|
|
123
|
-
|
|
124
|
-
const result = generate(scanResult, {
|
|
125
|
-
sourceRoot,
|
|
126
|
-
outputDir,
|
|
127
|
-
isInit: false,
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
for (const file of result.written) {
|
|
131
|
-
process.stdout.write(` \x1b[32m✓\x1b[0m ${file} (updated)\n`);
|
|
132
|
-
}
|
|
133
|
-
for (const file of result.preserved) {
|
|
134
|
-
process.stdout.write(` \x1b[33m●\x1b[0m ${file} (preserved)\n`);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
process.stdout.write(`\n\x1b[32m✓\x1b[0m Preview synced.\n`);
|
|
138
|
-
}
|
package/src/deploy/client.d.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { type Client } from "@connectrpc/connect";
|
|
2
|
-
import { DeployCommandController } from "@scenar/stubs/ai/scenar/deploy/v1/command_pb.js";
|
|
3
|
-
import { ScenarioCommandController } from "@scenar/stubs/ai/scenar/scenario/v1/command_pb.js";
|
|
4
|
-
/** The backend controllers `scenar deploy` drives. */
|
|
5
|
-
export interface BackendClients {
|
|
6
|
-
readonly deploy: Client<typeof DeployCommandController>;
|
|
7
|
-
readonly scenario: Client<typeof ScenarioCommandController>;
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Build typed Connect clients over a single gRPC transport, mirroring the
|
|
11
|
-
* canonical CLI pattern (createClient(service, transport)). The transport uses
|
|
12
|
-
* Node's http2 module; an http:// baseUrl speaks gRPC over cleartext HTTP/2
|
|
13
|
-
* (h2c), which is what the local scenar-service expects.
|
|
14
|
-
*
|
|
15
|
-
* Auth: none is sent for local `test` security mode (the backend injects a
|
|
16
|
-
* synthetic authorized caller). A production scoped-API-key path would attach a
|
|
17
|
-
* bearer interceptor here — the clean seam is the transport's interceptors.
|
|
18
|
-
*/
|
|
19
|
-
export declare function createBackendClients(baseUrl: string): BackendClients;
|
|
20
|
-
//# sourceMappingURL=client.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/deploy/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAEhE,OAAO,EAAE,uBAAuB,EAAE,MAAM,iDAAiD,CAAC;AAC1F,OAAO,EAAE,yBAAyB,EAAE,MAAM,mDAAmD,CAAC;AAE9F,sDAAsD;AACtD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,uBAAuB,CAAC,CAAC;IACxD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,OAAO,yBAAyB,CAAC,CAAC;CAC7D;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAMpE"}
|
package/src/deploy/client.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { createClient } from "@connectrpc/connect";
|
|
2
|
-
import { createGrpcTransport } from "@connectrpc/connect-node";
|
|
3
|
-
import { DeployCommandController } from "@scenar/stubs/ai/scenar/deploy/v1/command_pb.js";
|
|
4
|
-
import { ScenarioCommandController } from "@scenar/stubs/ai/scenar/scenario/v1/command_pb.js";
|
|
5
|
-
/**
|
|
6
|
-
* Build typed Connect clients over a single gRPC transport, mirroring the
|
|
7
|
-
* canonical CLI pattern (createClient(service, transport)). The transport uses
|
|
8
|
-
* Node's http2 module; an http:// baseUrl speaks gRPC over cleartext HTTP/2
|
|
9
|
-
* (h2c), which is what the local scenar-service expects.
|
|
10
|
-
*
|
|
11
|
-
* Auth: none is sent for local `test` security mode (the backend injects a
|
|
12
|
-
* synthetic authorized caller). A production scoped-API-key path would attach a
|
|
13
|
-
* bearer interceptor here — the clean seam is the transport's interceptors.
|
|
14
|
-
*/
|
|
15
|
-
export function createBackendClients(baseUrl) {
|
|
16
|
-
const transport = createGrpcTransport({ baseUrl });
|
|
17
|
-
return {
|
|
18
|
-
deploy: createClient(DeployCommandController, transport),
|
|
19
|
-
scenario: createClient(ScenarioCommandController, transport),
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
//# sourceMappingURL=client.js.map
|
package/src/deploy/client.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/deploy/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAe,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,uBAAuB,EAAE,MAAM,iDAAiD,CAAC;AAC1F,OAAO,EAAE,yBAAyB,EAAE,MAAM,mDAAmD,CAAC;AAQ9F;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAe;IAClD,MAAM,SAAS,GAAG,mBAAmB,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IACnD,OAAO;QACL,MAAM,EAAE,YAAY,CAAC,uBAAuB,EAAE,SAAS,CAAC;QACxD,QAAQ,EAAE,YAAY,CAAC,yBAAyB,EAAE,SAAS,CAAC;KAC7D,CAAC;AACJ,CAAC"}
|
package/src/deploy/client.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { createClient, type Client } from "@connectrpc/connect";
|
|
2
|
-
import { createGrpcTransport } from "@connectrpc/connect-node";
|
|
3
|
-
import { DeployCommandController } from "@scenar/stubs/ai/scenar/deploy/v1/command_pb.js";
|
|
4
|
-
import { ScenarioCommandController } from "@scenar/stubs/ai/scenar/scenario/v1/command_pb.js";
|
|
5
|
-
|
|
6
|
-
/** The backend controllers `scenar deploy` drives. */
|
|
7
|
-
export interface BackendClients {
|
|
8
|
-
readonly deploy: Client<typeof DeployCommandController>;
|
|
9
|
-
readonly scenario: Client<typeof ScenarioCommandController>;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Build typed Connect clients over a single gRPC transport, mirroring the
|
|
14
|
-
* canonical CLI pattern (createClient(service, transport)). The transport uses
|
|
15
|
-
* Node's http2 module; an http:// baseUrl speaks gRPC over cleartext HTTP/2
|
|
16
|
-
* (h2c), which is what the local scenar-service expects.
|
|
17
|
-
*
|
|
18
|
-
* Auth: none is sent for local `test` security mode (the backend injects a
|
|
19
|
-
* synthetic authorized caller). A production scoped-API-key path would attach a
|
|
20
|
-
* bearer interceptor here — the clean seam is the transport's interceptors.
|
|
21
|
-
*/
|
|
22
|
-
export function createBackendClients(baseUrl: string): BackendClients {
|
|
23
|
-
const transport = createGrpcTransport({ baseUrl });
|
|
24
|
-
return {
|
|
25
|
-
deploy: createClient(DeployCommandController, transport),
|
|
26
|
-
scenario: createClient(ScenarioCommandController, transport),
|
|
27
|
-
};
|
|
28
|
-
}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import type { PackManifest } from "../pack/pack-manifest.js";
|
|
2
|
-
/**
|
|
3
|
-
* One presigned upload target as the backend returns it. Mirrors the relevant
|
|
4
|
-
* fields of ai.scenar.deploy.v1.FileUploadTarget.
|
|
5
|
-
*/
|
|
6
|
-
export interface UploadTarget {
|
|
7
|
-
readonly relativePath: string;
|
|
8
|
-
readonly presignedPutUrl: string;
|
|
9
|
-
/**
|
|
10
|
-
* Headers that MUST be replayed verbatim on the PUT for the signature to
|
|
11
|
-
* validate (Content-Type + x-amz-checksum-sha256). The backend deliberately
|
|
12
|
-
* omits host/content-length, which the HTTP layer owns.
|
|
13
|
-
*/
|
|
14
|
-
readonly requiredHeaders: Record<string, string>;
|
|
15
|
-
}
|
|
16
|
-
/** A file declared to the upload session — the init shape for DeclaredFile. */
|
|
17
|
-
export interface DeclaredFileInit {
|
|
18
|
-
readonly relativePath: string;
|
|
19
|
-
/** Lowercase-hex SHA-256 (the proto + presign both bind this exact form). */
|
|
20
|
-
readonly sha256: string;
|
|
21
|
-
/** int64 on the wire — carried as bigint to avoid precision loss. */
|
|
22
|
-
readonly sizeBytes: bigint;
|
|
23
|
-
readonly contentType: string;
|
|
24
|
-
}
|
|
25
|
-
/** Identity for the ensure-scenario (apply) step. */
|
|
26
|
-
export interface ScenarioApplyInput {
|
|
27
|
-
readonly org: string;
|
|
28
|
-
readonly slug: string;
|
|
29
|
-
readonly name: string;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* The side-effecting operations the flow depends on, injected so the ordering
|
|
33
|
-
* and payloads can be unit-tested against fakes without a live backend.
|
|
34
|
-
*/
|
|
35
|
-
export interface DeployFlowDeps {
|
|
36
|
-
/** Idempotently ensure the parent scenario exists; returns its metadata.id. */
|
|
37
|
-
applyScenario(input: ScenarioApplyInput): Promise<string>;
|
|
38
|
-
/** Open the upload session; returns the deploy id + per-file targets. */
|
|
39
|
-
createSession(scenarioId: string, files: DeclaredFileInit[]): Promise<{
|
|
40
|
-
deployId: string;
|
|
41
|
-
uploadTargets: UploadTarget[];
|
|
42
|
-
}>;
|
|
43
|
-
/** Read a bundle file's bytes by its relative path. */
|
|
44
|
-
readBundleFile(relativePath: string): Promise<Uint8Array>;
|
|
45
|
-
/** PUT one file's bytes to its presigned target, replaying required headers. */
|
|
46
|
-
uploadFile(target: UploadTarget, bytes: Uint8Array): Promise<void>;
|
|
47
|
-
/** Finalize the session; returns the published deploy's embed_url. */
|
|
48
|
-
completeSession(deployId: string): Promise<string>;
|
|
49
|
-
/** Progress sink (stderr in the command; captured in tests). */
|
|
50
|
-
log(message: string): void;
|
|
51
|
-
}
|
|
52
|
-
/** Map a pack manifest to the deploy session's declared-file inventory. */
|
|
53
|
-
export declare function toDeclaredFiles(manifest: PackManifest): DeclaredFileInit[];
|
|
54
|
-
/**
|
|
55
|
-
* Drive the deploy: ensure the parent scenario, open the upload session, PUT
|
|
56
|
-
* every file to its presigned target (in the order the backend returned them,
|
|
57
|
-
* replaying required headers verbatim), then complete and return the embed URL.
|
|
58
|
-
*
|
|
59
|
-
* The ensure-then-deploy ordering is load-bearing: createDeployUploadSession
|
|
60
|
-
* authorizes against and inherits its org from an existing scenario, so the
|
|
61
|
-
* scenario must exist first.
|
|
62
|
-
*/
|
|
63
|
-
export declare function runDeployFlow(deps: DeployFlowDeps, opts: {
|
|
64
|
-
manifest: PackManifest;
|
|
65
|
-
org: string;
|
|
66
|
-
slug: string;
|
|
67
|
-
name: string;
|
|
68
|
-
}): Promise<{
|
|
69
|
-
deployId: string;
|
|
70
|
-
embedUrl: string;
|
|
71
|
-
}>;
|
|
72
|
-
/**
|
|
73
|
-
* Derive a locally-viewable URL from a deploy's embed_url. The backend always
|
|
74
|
-
* emits https://, but the local edge (wrangler dev) serves over http on
|
|
75
|
-
* *.localhost; for those hosts we downgrade the scheme so the link is clickable.
|
|
76
|
-
*/
|
|
77
|
-
export declare function localViewUrl(embedUrl: string): string;
|
|
78
|
-
//# sourceMappingURL=deploy-flow.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"deploy-flow.d.ts","sourceRoot":"","sources":["../../../src/deploy/deploy-flow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClD;AAED,+EAA+E;AAC/E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,qEAAqE;IACrE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,qDAAqD;AACrD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,+EAA+E;IAC/E,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1D,yEAAyE;IACzE,aAAa,CACX,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,gBAAgB,EAAE,GACxB,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,YAAY,EAAE,CAAA;KAAE,CAAC,CAAC;IAChE,uDAAuD;IACvD,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC1D,gFAAgF;IAChF,UAAU,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,sEAAsE;IACtE,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACnD,gEAAgE;IAChE,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,2EAA2E;AAC3E,wBAAgB,eAAe,CAAC,QAAQ,EAAE,YAAY,GAAG,gBAAgB,EAAE,CAO1E;AAED;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,cAAc,EACpB,IAAI,EAAE;IAAE,QAAQ,EAAE,YAAY,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACxE,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAiBjD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAYrD"}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
/** Map a pack manifest to the deploy session's declared-file inventory. */
|
|
2
|
-
export function toDeclaredFiles(manifest) {
|
|
3
|
-
return manifest.files.map((file) => ({
|
|
4
|
-
relativePath: file.path,
|
|
5
|
-
sha256: file.sha256,
|
|
6
|
-
sizeBytes: BigInt(file.sizeBytes),
|
|
7
|
-
contentType: file.contentType,
|
|
8
|
-
}));
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* Drive the deploy: ensure the parent scenario, open the upload session, PUT
|
|
12
|
-
* every file to its presigned target (in the order the backend returned them,
|
|
13
|
-
* replaying required headers verbatim), then complete and return the embed URL.
|
|
14
|
-
*
|
|
15
|
-
* The ensure-then-deploy ordering is load-bearing: createDeployUploadSession
|
|
16
|
-
* authorizes against and inherits its org from an existing scenario, so the
|
|
17
|
-
* scenario must exist first.
|
|
18
|
-
*/
|
|
19
|
-
export async function runDeployFlow(deps, opts) {
|
|
20
|
-
deps.log(`Ensuring scenario ${opts.org}/${opts.slug}...`);
|
|
21
|
-
const scenarioId = await deps.applyScenario({ org: opts.org, slug: opts.slug, name: opts.name });
|
|
22
|
-
const files = toDeclaredFiles(opts.manifest);
|
|
23
|
-
deps.log(`Creating deploy session (${files.length} files)...`);
|
|
24
|
-
const { deployId, uploadTargets } = await deps.createSession(scenarioId, files);
|
|
25
|
-
for (const target of uploadTargets) {
|
|
26
|
-
const bytes = await deps.readBundleFile(target.relativePath);
|
|
27
|
-
deps.log(`Uploading ${target.relativePath} (${bytes.byteLength} bytes)...`);
|
|
28
|
-
await deps.uploadFile(target, bytes);
|
|
29
|
-
}
|
|
30
|
-
deps.log("Completing deploy...");
|
|
31
|
-
const embedUrl = await deps.completeSession(deployId);
|
|
32
|
-
return { deployId, embedUrl };
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Derive a locally-viewable URL from a deploy's embed_url. The backend always
|
|
36
|
-
* emits https://, but the local edge (wrangler dev) serves over http on
|
|
37
|
-
* *.localhost; for those hosts we downgrade the scheme so the link is clickable.
|
|
38
|
-
*/
|
|
39
|
-
export function localViewUrl(embedUrl) {
|
|
40
|
-
try {
|
|
41
|
-
const url = new URL(embedUrl);
|
|
42
|
-
const isLocal = url.hostname === "localhost" || url.hostname.endsWith(".localhost");
|
|
43
|
-
if (isLocal && url.protocol === "https:") {
|
|
44
|
-
url.protocol = "http:";
|
|
45
|
-
return url.toString();
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
catch {
|
|
49
|
-
// Not a parseable URL — return as-is.
|
|
50
|
-
}
|
|
51
|
-
return embedUrl;
|
|
52
|
-
}
|
|
53
|
-
//# sourceMappingURL=deploy-flow.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"deploy-flow.js","sourceRoot":"","sources":["../../../src/deploy/deploy-flow.ts"],"names":[],"mappings":"AAwDA,2EAA2E;AAC3E,MAAM,UAAU,eAAe,CAAC,QAAsB;IACpD,OAAO,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACnC,YAAY,EAAE,IAAI,CAAC,IAAI;QACvB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;QACjC,WAAW,EAAE,IAAI,CAAC,WAAW;KAC9B,CAAC,CAAC,CAAC;AACN,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,IAAoB,EACpB,IAAyE;IAEzE,IAAI,CAAC,GAAG,CAAC,qBAAqB,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC;IAC1D,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAEjG,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC7C,IAAI,CAAC,GAAG,CAAC,4BAA4B,KAAK,CAAC,MAAM,YAAY,CAAC,CAAC;IAC/D,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IAEhF,KAAK,MAAM,MAAM,IAAI,aAAa,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAC7D,IAAI,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,YAAY,KAAK,KAAK,CAAC,UAAU,YAAY,CAAC,CAAC;QAC5E,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACvC,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IACjC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;IACtD,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;AAChC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC9B,MAAM,OAAO,GAAG,GAAG,CAAC,QAAQ,KAAK,WAAW,IAAI,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QACpF,IAAI,OAAO,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACzC,GAAG,CAAC,QAAQ,GAAG,OAAO,CAAC;YACvB,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;QACxB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,sCAAsC;IACxC,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import type { PackManifest } from "../pack/pack-manifest.js";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* One presigned upload target as the backend returns it. Mirrors the relevant
|
|
5
|
-
* fields of ai.scenar.deploy.v1.FileUploadTarget.
|
|
6
|
-
*/
|
|
7
|
-
export interface UploadTarget {
|
|
8
|
-
readonly relativePath: string;
|
|
9
|
-
readonly presignedPutUrl: string;
|
|
10
|
-
/**
|
|
11
|
-
* Headers that MUST be replayed verbatim on the PUT for the signature to
|
|
12
|
-
* validate (Content-Type + x-amz-checksum-sha256). The backend deliberately
|
|
13
|
-
* omits host/content-length, which the HTTP layer owns.
|
|
14
|
-
*/
|
|
15
|
-
readonly requiredHeaders: Record<string, string>;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/** A file declared to the upload session — the init shape for DeclaredFile. */
|
|
19
|
-
export interface DeclaredFileInit {
|
|
20
|
-
readonly relativePath: string;
|
|
21
|
-
/** Lowercase-hex SHA-256 (the proto + presign both bind this exact form). */
|
|
22
|
-
readonly sha256: string;
|
|
23
|
-
/** int64 on the wire — carried as bigint to avoid precision loss. */
|
|
24
|
-
readonly sizeBytes: bigint;
|
|
25
|
-
readonly contentType: string;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/** Identity for the ensure-scenario (apply) step. */
|
|
29
|
-
export interface ScenarioApplyInput {
|
|
30
|
-
readonly org: string;
|
|
31
|
-
readonly slug: string;
|
|
32
|
-
readonly name: string;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* The side-effecting operations the flow depends on, injected so the ordering
|
|
37
|
-
* and payloads can be unit-tested against fakes without a live backend.
|
|
38
|
-
*/
|
|
39
|
-
export interface DeployFlowDeps {
|
|
40
|
-
/** Idempotently ensure the parent scenario exists; returns its metadata.id. */
|
|
41
|
-
applyScenario(input: ScenarioApplyInput): Promise<string>;
|
|
42
|
-
/** Open the upload session; returns the deploy id + per-file targets. */
|
|
43
|
-
createSession(
|
|
44
|
-
scenarioId: string,
|
|
45
|
-
files: DeclaredFileInit[],
|
|
46
|
-
): Promise<{ deployId: string; uploadTargets: UploadTarget[] }>;
|
|
47
|
-
/** Read a bundle file's bytes by its relative path. */
|
|
48
|
-
readBundleFile(relativePath: string): Promise<Uint8Array>;
|
|
49
|
-
/** PUT one file's bytes to its presigned target, replaying required headers. */
|
|
50
|
-
uploadFile(target: UploadTarget, bytes: Uint8Array): Promise<void>;
|
|
51
|
-
/** Finalize the session; returns the published deploy's embed_url. */
|
|
52
|
-
completeSession(deployId: string): Promise<string>;
|
|
53
|
-
/** Progress sink (stderr in the command; captured in tests). */
|
|
54
|
-
log(message: string): void;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/** Map a pack manifest to the deploy session's declared-file inventory. */
|
|
58
|
-
export function toDeclaredFiles(manifest: PackManifest): DeclaredFileInit[] {
|
|
59
|
-
return manifest.files.map((file) => ({
|
|
60
|
-
relativePath: file.path,
|
|
61
|
-
sha256: file.sha256,
|
|
62
|
-
sizeBytes: BigInt(file.sizeBytes),
|
|
63
|
-
contentType: file.contentType,
|
|
64
|
-
}));
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Drive the deploy: ensure the parent scenario, open the upload session, PUT
|
|
69
|
-
* every file to its presigned target (in the order the backend returned them,
|
|
70
|
-
* replaying required headers verbatim), then complete and return the embed URL.
|
|
71
|
-
*
|
|
72
|
-
* The ensure-then-deploy ordering is load-bearing: createDeployUploadSession
|
|
73
|
-
* authorizes against and inherits its org from an existing scenario, so the
|
|
74
|
-
* scenario must exist first.
|
|
75
|
-
*/
|
|
76
|
-
export async function runDeployFlow(
|
|
77
|
-
deps: DeployFlowDeps,
|
|
78
|
-
opts: { manifest: PackManifest; org: string; slug: string; name: string },
|
|
79
|
-
): Promise<{ deployId: string; embedUrl: string }> {
|
|
80
|
-
deps.log(`Ensuring scenario ${opts.org}/${opts.slug}...`);
|
|
81
|
-
const scenarioId = await deps.applyScenario({ org: opts.org, slug: opts.slug, name: opts.name });
|
|
82
|
-
|
|
83
|
-
const files = toDeclaredFiles(opts.manifest);
|
|
84
|
-
deps.log(`Creating deploy session (${files.length} files)...`);
|
|
85
|
-
const { deployId, uploadTargets } = await deps.createSession(scenarioId, files);
|
|
86
|
-
|
|
87
|
-
for (const target of uploadTargets) {
|
|
88
|
-
const bytes = await deps.readBundleFile(target.relativePath);
|
|
89
|
-
deps.log(`Uploading ${target.relativePath} (${bytes.byteLength} bytes)...`);
|
|
90
|
-
await deps.uploadFile(target, bytes);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
deps.log("Completing deploy...");
|
|
94
|
-
const embedUrl = await deps.completeSession(deployId);
|
|
95
|
-
return { deployId, embedUrl };
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Derive a locally-viewable URL from a deploy's embed_url. The backend always
|
|
100
|
-
* emits https://, but the local edge (wrangler dev) serves over http on
|
|
101
|
-
* *.localhost; for those hosts we downgrade the scheme so the link is clickable.
|
|
102
|
-
*/
|
|
103
|
-
export function localViewUrl(embedUrl: string): string {
|
|
104
|
-
try {
|
|
105
|
-
const url = new URL(embedUrl);
|
|
106
|
-
const isLocal = url.hostname === "localhost" || url.hostname.endsWith(".localhost");
|
|
107
|
-
if (isLocal && url.protocol === "https:") {
|
|
108
|
-
url.protocol = "http:";
|
|
109
|
-
return url.toString();
|
|
110
|
-
}
|
|
111
|
-
} catch {
|
|
112
|
-
// Not a parseable URL — return as-is.
|
|
113
|
-
}
|
|
114
|
-
return embedUrl;
|
|
115
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"embed-snippet.d.ts","sourceRoot":"","sources":["../../../src/deploy/embed-snippet.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpD,4CAA4C;AAC5C,MAAM,WAAW,iBAAiB;IAChC,2EAA2E;IAC3E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,+EAA+E;IAC/E,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,+EAA+E;IAC/E,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAelE"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"embed-snippet.js","sourceRoot":"","sources":["../../../src/deploy/embed-snippet.ts"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAwB;IACxD,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;IACrC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,cAAc,CAAC;IAC5C,OAAO;QACL,sDAAsD,QAAQ,CAAC,KAAK,mBAAmB,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,MAAM,IAAI;QAC5H,WAAW;QACX,YAAY,UAAU,CAAC,QAAQ,CAAC,GAAG;QACnC,cAAc,UAAU,CAAC,KAAK,CAAC,GAAG;QAClC,oBAAoB;QACpB,uEAAuE;QACvE,kCAAkC;QAClC,qBAAqB;QACrB,cAAc;QACd,QAAQ;KACT,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,kFAAkF;AAClF,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,KAAK;SACT,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC3B,CAAC"}
|
package/src/deploy/upload.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Upload one file's bytes to its presigned PUT target.
|
|
3
|
-
*
|
|
4
|
-
* The presign binds the content type and SHA-256 into the signature, so every
|
|
5
|
-
* header the backend returned in `required_headers` is replayed verbatim. The
|
|
6
|
-
* backend intentionally omits host and content-length (the HTTP layer owns
|
|
7
|
-
* them) — fetch sets content-length from the body, matching the declared size.
|
|
8
|
-
*/
|
|
9
|
-
export declare function putFile(presignedPutUrl: string, requiredHeaders: Record<string, string>, bytes: Uint8Array): Promise<void>;
|
|
10
|
-
//# sourceMappingURL=upload.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../../src/deploy/upload.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wBAAsB,OAAO,CAC3B,eAAe,EAAE,MAAM,EACvB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACvC,KAAK,EAAE,UAAU,GAChB,OAAO,CAAC,IAAI,CAAC,CAgBf"}
|
package/src/deploy/upload.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Upload one file's bytes to its presigned PUT target.
|
|
3
|
-
*
|
|
4
|
-
* The presign binds the content type and SHA-256 into the signature, so every
|
|
5
|
-
* header the backend returned in `required_headers` is replayed verbatim. The
|
|
6
|
-
* backend intentionally omits host and content-length (the HTTP layer owns
|
|
7
|
-
* them) — fetch sets content-length from the body, matching the declared size.
|
|
8
|
-
*/
|
|
9
|
-
export async function putFile(presignedPutUrl, requiredHeaders, bytes) {
|
|
10
|
-
const response = await fetch(presignedPutUrl, {
|
|
11
|
-
method: "PUT",
|
|
12
|
-
headers: requiredHeaders,
|
|
13
|
-
// The DOM BodyInit type is overly narrow for Uint8Array under this TS/lib
|
|
14
|
-
// combination; raw bytes are a valid fetch body at runtime.
|
|
15
|
-
body: bytes,
|
|
16
|
-
});
|
|
17
|
-
if (!response.ok) {
|
|
18
|
-
const detail = await response.text().catch(() => "");
|
|
19
|
-
throw new Error(`upload failed (${response.status} ${response.statusText})` +
|
|
20
|
-
(detail ? `: ${detail.slice(0, 300)}` : ""));
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
//# sourceMappingURL=upload.js.map
|
package/src/deploy/upload.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"upload.js","sourceRoot":"","sources":["../../../src/deploy/upload.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,eAAuB,EACvB,eAAuC,EACvC,KAAiB;IAEjB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,eAAe,EAAE;QAC5C,MAAM,EAAE,KAAK;QACb,OAAO,EAAE,eAAe;QACxB,0EAA0E;QAC1E,4DAA4D;QAC5D,IAAI,EAAE,KAA4B;KACnC,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QACrD,MAAM,IAAI,KAAK,CACb,kBAAkB,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,GAAG;YACzD,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAC9C,CAAC;IACJ,CAAC;AACH,CAAC"}
|
package/src/deploy/upload.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Upload one file's bytes to its presigned PUT target.
|
|
3
|
-
*
|
|
4
|
-
* The presign binds the content type and SHA-256 into the signature, so every
|
|
5
|
-
* header the backend returned in `required_headers` is replayed verbatim. The
|
|
6
|
-
* backend intentionally omits host and content-length (the HTTP layer owns
|
|
7
|
-
* them) — fetch sets content-length from the body, matching the declared size.
|
|
8
|
-
*/
|
|
9
|
-
export async function putFile(
|
|
10
|
-
presignedPutUrl: string,
|
|
11
|
-
requiredHeaders: Record<string, string>,
|
|
12
|
-
bytes: Uint8Array,
|
|
13
|
-
): Promise<void> {
|
|
14
|
-
const response = await fetch(presignedPutUrl, {
|
|
15
|
-
method: "PUT",
|
|
16
|
-
headers: requiredHeaders,
|
|
17
|
-
// The DOM BodyInit type is overly narrow for Uint8Array under this TS/lib
|
|
18
|
-
// combination; raw bytes are a valid fetch body at runtime.
|
|
19
|
-
body: bytes as unknown as BodyInit,
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
if (!response.ok) {
|
|
23
|
-
const detail = await response.text().catch(() => "");
|
|
24
|
-
throw new Error(
|
|
25
|
-
`upload failed (${response.status} ${response.statusText})` +
|
|
26
|
-
(detail ? `: ${detail.slice(0, 300)}` : ""),
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
}
|