@drawcall/market 0.1.95 → 0.1.96
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/dist/commands/upload.d.ts.map +1 -1
- package/dist/commands/upload.js +68 -9
- package/dist/commands/upload.js.map +1 -1
- package/dist/template-deployment.d.ts +20 -0
- package/dist/template-deployment.d.ts.map +1 -0
- package/dist/template-deployment.js +117 -0
- package/dist/template-deployment.js.map +1 -0
- package/package.json +1 -1
- package/src/commands/upload.ts +77 -6
- package/src/template-deployment.ts +160 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../src/commands/upload.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../src/commands/upload.ts"],"names":[],"mappings":"AAUA,OAAO,EAKL,KAAK,WAAW,EAChB,KAAK,SAAS,EACf,MAAM,eAAe,CAAA;AAEtB,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,SAAS,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,mEAAmE;IACnE,GAAG,CAAC,EAAE,MAAM,EAAE,CAAA;IACd,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,iFAAiF;IACjF,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB;AAED,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC,IAAI,CAAC,CAiIf;AAuBD,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAQlE"}
|
package/dist/commands/upload.js
CHANGED
|
@@ -3,6 +3,7 @@ import semver from 'semver';
|
|
|
3
3
|
import { getCliClient } from '../cli-client.js';
|
|
4
4
|
import { packAsset, packPolicyFromInstallMetadata, parsePackDependencies } from '../pack.js';
|
|
5
5
|
import { unchangedUploadResult, uploadResult } from '../output.js';
|
|
6
|
+
import { buildTemplateDeployment, getTemplateDeploymentStatus, uploadTemplateDeployment, } from '../template-deployment.js';
|
|
6
7
|
import { assetDescriptionSchema, assetNameSchema, semverSchema, MAX_ASSET_DESCRIPTION_LENGTH, } from '../schemas.js';
|
|
7
8
|
export async function uploadCommand(name, zipFilter, description, opts) {
|
|
8
9
|
const spinner = ora({
|
|
@@ -22,7 +23,12 @@ export async function uploadCommand(name, zipFilter, description, opts) {
|
|
|
22
23
|
});
|
|
23
24
|
const cwd = opts.cwd ?? process.cwd();
|
|
24
25
|
const type = opts.type;
|
|
25
|
-
const { client } = await getCliClient({
|
|
26
|
+
const { client, baseUrl, authToken } = await getCliClient({
|
|
27
|
+
baseUrl: opts.baseUrl,
|
|
28
|
+
requireAuth: true,
|
|
29
|
+
});
|
|
30
|
+
if (!authToken)
|
|
31
|
+
throw new Error('Not logged in. Run `market login` first.');
|
|
26
32
|
const installMetadata = await client.asset.installMetadata();
|
|
27
33
|
const packed = await packAsset(zipFilter, {
|
|
28
34
|
cwd,
|
|
@@ -43,23 +49,53 @@ export async function uploadCommand(name, zipFilter, description, opts) {
|
|
|
43
49
|
if (existing && existing.ownerId !== profile.id) {
|
|
44
50
|
throw new Error(`Asset "${parsedName}" already exists and is owned by another user`);
|
|
45
51
|
}
|
|
52
|
+
let unchanged = false;
|
|
46
53
|
if (existing) {
|
|
47
54
|
const latestZip = await client.asset.downloadZip({
|
|
48
55
|
name: parsedName,
|
|
49
56
|
version: existing.latestVersion,
|
|
50
57
|
});
|
|
51
58
|
const latestBytes = new Uint8Array(await latestZip.arrayBuffer());
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
unchanged =
|
|
60
|
+
existing.description === parsedDescription &&
|
|
61
|
+
depsEqual(existing.npmDependencies, npmDependencies) &&
|
|
62
|
+
depsEqual(existing.assetDependencies, assetDependencies) &&
|
|
63
|
+
depsEqual(existing.skillDependencies, skillDependencies) &&
|
|
64
|
+
bytesEqual(latestBytes, zip);
|
|
65
|
+
}
|
|
66
|
+
if (unchanged && existing) {
|
|
67
|
+
if (type === 'template') {
|
|
68
|
+
const status = await getTemplateDeploymentStatus({
|
|
69
|
+
baseUrl,
|
|
70
|
+
authToken,
|
|
71
|
+
name: parsedName,
|
|
72
|
+
version: existing.latestVersion,
|
|
73
|
+
});
|
|
74
|
+
if (!status.ready) {
|
|
75
|
+
spinner.stop();
|
|
76
|
+
const root = await buildTemplateDeployment(zipFilter, cwd);
|
|
77
|
+
spinner.start(`Uploading deployment for ${parsedName}@${existing.latestVersion}`);
|
|
78
|
+
await uploadDeployment({
|
|
79
|
+
baseUrl,
|
|
80
|
+
authToken,
|
|
81
|
+
name: parsedName,
|
|
82
|
+
version: existing.latestVersion,
|
|
83
|
+
root,
|
|
84
|
+
spinner,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
60
87
|
}
|
|
88
|
+
spinner.stop();
|
|
89
|
+
console.log(unchangedUploadResult(parsedName, existing.latestVersion));
|
|
90
|
+
return;
|
|
61
91
|
}
|
|
62
92
|
const version = parsedVersion ?? nextVersion(existing?.latestVersion);
|
|
93
|
+
let deploymentRoot = null;
|
|
94
|
+
if (type === 'template') {
|
|
95
|
+
spinner.stop();
|
|
96
|
+
deploymentRoot = await buildTemplateDeployment(zipFilter, cwd);
|
|
97
|
+
spinner.start(`Uploading ${parsedName}@${version}`);
|
|
98
|
+
}
|
|
63
99
|
spinner.text = `Uploading ${parsedName}@${version}`;
|
|
64
100
|
const uploaded = await client.asset.uploadZip({
|
|
65
101
|
name: parsedName,
|
|
@@ -75,6 +111,16 @@ export async function uploadCommand(name, zipFilter, description, opts) {
|
|
|
75
111
|
type: 'application/zip',
|
|
76
112
|
}),
|
|
77
113
|
});
|
|
114
|
+
if (deploymentRoot) {
|
|
115
|
+
await uploadDeployment({
|
|
116
|
+
baseUrl,
|
|
117
|
+
authToken,
|
|
118
|
+
name: parsedName,
|
|
119
|
+
version: uploaded.version,
|
|
120
|
+
root: deploymentRoot,
|
|
121
|
+
spinner,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
78
124
|
spinner.stop();
|
|
79
125
|
console.log(uploadResult(parsedName, uploaded.version));
|
|
80
126
|
}
|
|
@@ -83,6 +129,19 @@ export async function uploadCommand(name, zipFilter, description, opts) {
|
|
|
83
129
|
throw err;
|
|
84
130
|
}
|
|
85
131
|
}
|
|
132
|
+
async function uploadDeployment(input) {
|
|
133
|
+
input.spinner.text = `Uploading deployment for ${input.name}@${input.version}`;
|
|
134
|
+
await uploadTemplateDeployment({
|
|
135
|
+
baseUrl: input.baseUrl,
|
|
136
|
+
authToken: input.authToken,
|
|
137
|
+
name: input.name,
|
|
138
|
+
version: input.version,
|
|
139
|
+
root: input.root,
|
|
140
|
+
onProgress(uploaded, total) {
|
|
141
|
+
input.spinner.text = `Uploading deployment for ${input.name}@${input.version} (${uploaded}/${total})`;
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
}
|
|
86
145
|
export function parseUploadDescription(description) {
|
|
87
146
|
try {
|
|
88
147
|
return assetDescriptionSchema.parse(description);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload.js","sourceRoot":"","sources":["../../src/commands/upload.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAA;AACrB,OAAO,MAAM,MAAM,QAAQ,CAAA;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,SAAS,EAAE,6BAA6B,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAC5F,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAClE,OAAO,EACL,sBAAsB,EACtB,eAAe,EACf,YAAY,EACZ,4BAA4B,GAG7B,MAAM,eAAe,CAAA;AAiBtB,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,IAAY,EACZ,SAAiB,EACjB,WAAmB,EACnB,IAA0B;IAE1B,MAAM,OAAO,GAAG,GAAG,CAAC;QAClB,IAAI,EAAE,kBAAkB;QACxB,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;QACxC,QAAQ,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK;KAChC,CAAC,CAAC,KAAK,EAAE,CAAA;IAEV,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAC9C,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;QACjF,MAAM,iBAAiB,GAAG,sBAAsB,CAAC,WAAW,CAAC,CAAA;QAC7D,0EAA0E;QAC1E,MAAM,YAAY,GAAG,qBAAqB,CAAC;YACzC,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,KAAK,EAAE,IAAI,CAAC,KAAK;SAClB,CAAC,CAAA;QACF,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAA;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAA;QACtB,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,YAAY,CAAC,
|
|
1
|
+
{"version":3,"file":"upload.js","sourceRoot":"","sources":["../../src/commands/upload.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface TemplateDeploymentStatus {
|
|
2
|
+
ready: boolean;
|
|
3
|
+
url: string | null;
|
|
4
|
+
}
|
|
5
|
+
export interface UploadTemplateDeploymentInput {
|
|
6
|
+
baseUrl: string;
|
|
7
|
+
authToken: string;
|
|
8
|
+
name: string;
|
|
9
|
+
version: string;
|
|
10
|
+
root: string;
|
|
11
|
+
onProgress?(uploaded: number, total: number): void;
|
|
12
|
+
}
|
|
13
|
+
export declare function buildTemplateDeployment(zipFilter: string, cwd: string): Promise<string>;
|
|
14
|
+
export declare function getTemplateDeploymentStatus(input: Omit<UploadTemplateDeploymentInput, 'root' | 'onProgress'>): Promise<TemplateDeploymentStatus>;
|
|
15
|
+
export declare function uploadTemplateDeployment(input: UploadTemplateDeploymentInput): Promise<string>;
|
|
16
|
+
export declare function deploymentFiles(root: string): Promise<Array<{
|
|
17
|
+
absolutePath: string;
|
|
18
|
+
path: string;
|
|
19
|
+
}>>;
|
|
20
|
+
//# sourceMappingURL=template-deployment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-deployment.d.ts","sourceRoot":"","sources":["../src/template-deployment.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,OAAO,CAAA;IACd,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CACnB;AAED,MAAM,WAAW,6BAA6B;IAC5C,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACnD;AAED,wBAAsB,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAa7F;AAED,wBAAsB,2BAA2B,CAC/C,KAAK,EAAE,IAAI,CAAC,6BAA6B,EAAE,MAAM,GAAG,YAAY,CAAC,GAChE,OAAO,CAAC,wBAAwB,CAAC,CAOnC;AAED,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,6BAA6B,GACnC,OAAO,CAAC,MAAM,CAAC,CAwCjB;AAED,wBAAsB,eAAe,CACnC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,KAAK,CAAC;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAuBxD"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import * as fs from 'node:fs/promises';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import { detectPackageManager, runScript } from 'nypm';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
const deploymentStatusSchema = z.object({
|
|
6
|
+
ready: z.boolean(),
|
|
7
|
+
url: z.string().url().nullable(),
|
|
8
|
+
});
|
|
9
|
+
const deploymentCompleteSchema = z.object({
|
|
10
|
+
url: z.string().url(),
|
|
11
|
+
});
|
|
12
|
+
export async function buildTemplateDeployment(zipFilter, cwd) {
|
|
13
|
+
const sourceRoot = path.resolve(cwd, zipFilter);
|
|
14
|
+
const stat = await fs.stat(sourceRoot).catch(() => null);
|
|
15
|
+
if (!stat?.isDirectory()) {
|
|
16
|
+
throw new Error('Template uploads require a project directory so Market can run its build');
|
|
17
|
+
}
|
|
18
|
+
const packageManager = (await detectPackageManager(sourceRoot)) ?? 'npm';
|
|
19
|
+
await runScript('build', { cwd: sourceRoot, packageManager });
|
|
20
|
+
const deploymentRoot = path.join(sourceRoot, 'dist');
|
|
21
|
+
await requireFile(path.join(deploymentRoot, 'index.html'), 'dist/index.html');
|
|
22
|
+
await requireFile(path.join(deploymentRoot, 'schema.json'), 'dist/schema.json');
|
|
23
|
+
return deploymentRoot;
|
|
24
|
+
}
|
|
25
|
+
export async function getTemplateDeploymentStatus(input) {
|
|
26
|
+
const response = await fetch(deploymentEndpoint(input), {
|
|
27
|
+
headers: authHeaders(input.authToken),
|
|
28
|
+
});
|
|
29
|
+
const body = await responseBody(response);
|
|
30
|
+
if (!response.ok)
|
|
31
|
+
throw httpError('read template deployment', response, body);
|
|
32
|
+
return deploymentStatusSchema.parse(body);
|
|
33
|
+
}
|
|
34
|
+
export async function uploadTemplateDeployment(input) {
|
|
35
|
+
const files = await deploymentFiles(input.root);
|
|
36
|
+
if (files.length === 0)
|
|
37
|
+
throw new Error('Template deployment is empty');
|
|
38
|
+
await checkedFetch(new URL(`${deploymentEndpoint(input).pathname}/prepare`, input.baseUrl), { method: 'POST', headers: authHeaders(input.authToken) }, 'prepare template deployment');
|
|
39
|
+
let uploaded = 0;
|
|
40
|
+
for (let start = 0; start < files.length; start += 6) {
|
|
41
|
+
await Promise.all(files.slice(start, start + 6).map(async (file) => {
|
|
42
|
+
const url = deploymentEndpoint(input);
|
|
43
|
+
url.searchParams.set('path', file.path);
|
|
44
|
+
const bytes = await fs.readFile(file.absolutePath);
|
|
45
|
+
await checkedFetch(url, {
|
|
46
|
+
method: 'PUT',
|
|
47
|
+
headers: authHeaders(input.authToken),
|
|
48
|
+
body: new Blob([bytes]),
|
|
49
|
+
}, `upload ${file.path}`);
|
|
50
|
+
uploaded += 1;
|
|
51
|
+
input.onProgress?.(uploaded, files.length);
|
|
52
|
+
}));
|
|
53
|
+
}
|
|
54
|
+
const completeUrl = new URL(`${deploymentEndpoint(input).pathname}/complete`, input.baseUrl);
|
|
55
|
+
const response = await fetch(completeUrl, {
|
|
56
|
+
method: 'POST',
|
|
57
|
+
headers: authHeaders(input.authToken),
|
|
58
|
+
});
|
|
59
|
+
const body = await responseBody(response);
|
|
60
|
+
if (!response.ok)
|
|
61
|
+
throw httpError('publish template deployment', response, body);
|
|
62
|
+
return deploymentCompleteSchema.parse(body).url;
|
|
63
|
+
}
|
|
64
|
+
export async function deploymentFiles(root) {
|
|
65
|
+
const files = [];
|
|
66
|
+
async function visit(directory) {
|
|
67
|
+
const entries = await fs.readdir(directory, { withFileTypes: true });
|
|
68
|
+
for (const entry of entries) {
|
|
69
|
+
const absolutePath = path.join(directory, entry.name);
|
|
70
|
+
if (entry.isDirectory()) {
|
|
71
|
+
await visit(absolutePath);
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
if (!entry.isFile()) {
|
|
75
|
+
throw new Error(`Template deployment contains an unsupported entry: ${absolutePath}`);
|
|
76
|
+
}
|
|
77
|
+
files.push({
|
|
78
|
+
absolutePath,
|
|
79
|
+
path: path.relative(root, absolutePath).split(path.sep).join('/'),
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
await visit(root);
|
|
84
|
+
return files.sort((a, b) => a.path.localeCompare(b.path));
|
|
85
|
+
}
|
|
86
|
+
function deploymentEndpoint(input) {
|
|
87
|
+
return new URL(`/api/templates/${encodeURIComponent(input.name)}/${encodeURIComponent(input.version)}/deployment`, input.baseUrl);
|
|
88
|
+
}
|
|
89
|
+
function authHeaders(token) {
|
|
90
|
+
return new Headers({ authorization: `Bearer ${token}` });
|
|
91
|
+
}
|
|
92
|
+
async function checkedFetch(url, init, action) {
|
|
93
|
+
const response = await fetch(url, init);
|
|
94
|
+
if (response.ok)
|
|
95
|
+
return;
|
|
96
|
+
throw httpError(action, response, await responseBody(response));
|
|
97
|
+
}
|
|
98
|
+
async function responseBody(response) {
|
|
99
|
+
const text = await response.text();
|
|
100
|
+
if (!text)
|
|
101
|
+
return {};
|
|
102
|
+
try {
|
|
103
|
+
return JSON.parse(text);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return { raw: text };
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function httpError(action, response, body) {
|
|
110
|
+
return new Error(`${action} failed (${response.status}): ${JSON.stringify(body)}`);
|
|
111
|
+
}
|
|
112
|
+
async function requireFile(file, label) {
|
|
113
|
+
const stat = await fs.stat(file).catch(() => null);
|
|
114
|
+
if (!stat?.isFile())
|
|
115
|
+
throw new Error(`Template build did not produce ${label}`);
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=template-deployment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-deployment.js","sourceRoot":"","sources":["../src/template-deployment.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/commands/upload.ts
CHANGED
|
@@ -3,6 +3,11 @@ import semver from 'semver'
|
|
|
3
3
|
import { getCliClient } from '../cli-client.js'
|
|
4
4
|
import { packAsset, packPolicyFromInstallMetadata, parsePackDependencies } from '../pack.js'
|
|
5
5
|
import { unchangedUploadResult, uploadResult } from '../output.js'
|
|
6
|
+
import {
|
|
7
|
+
buildTemplateDeployment,
|
|
8
|
+
getTemplateDeploymentStatus,
|
|
9
|
+
uploadTemplateDeployment,
|
|
10
|
+
} from '../template-deployment.js'
|
|
6
11
|
import {
|
|
7
12
|
assetDescriptionSchema,
|
|
8
13
|
assetNameSchema,
|
|
@@ -51,7 +56,11 @@ export async function uploadCommand(
|
|
|
51
56
|
})
|
|
52
57
|
const cwd = opts.cwd ?? process.cwd()
|
|
53
58
|
const type = opts.type
|
|
54
|
-
const { client } = await getCliClient({
|
|
59
|
+
const { client, baseUrl, authToken } = await getCliClient({
|
|
60
|
+
baseUrl: opts.baseUrl,
|
|
61
|
+
requireAuth: true,
|
|
62
|
+
})
|
|
63
|
+
if (!authToken) throw new Error('Not logged in. Run `market login` first.')
|
|
55
64
|
const installMetadata = await client.asset.installMetadata()
|
|
56
65
|
const packed = await packAsset(zipFilter, {
|
|
57
66
|
cwd,
|
|
@@ -74,26 +83,56 @@ export async function uploadCommand(
|
|
|
74
83
|
throw new Error(`Asset "${parsedName}" already exists and is owned by another user`)
|
|
75
84
|
}
|
|
76
85
|
|
|
86
|
+
let unchanged = false
|
|
77
87
|
if (existing) {
|
|
78
88
|
const latestZip = await client.asset.downloadZip({
|
|
79
89
|
name: parsedName,
|
|
80
90
|
version: existing.latestVersion,
|
|
81
91
|
})
|
|
82
92
|
const latestBytes = new Uint8Array(await latestZip.arrayBuffer())
|
|
83
|
-
|
|
93
|
+
unchanged =
|
|
84
94
|
existing.description === parsedDescription &&
|
|
85
95
|
depsEqual(existing.npmDependencies, npmDependencies) &&
|
|
86
96
|
depsEqual(existing.assetDependencies, assetDependencies) &&
|
|
87
97
|
depsEqual(existing.skillDependencies, skillDependencies) &&
|
|
88
98
|
bytesEqual(latestBytes, zip)
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (unchanged && existing) {
|
|
102
|
+
if (type === 'template') {
|
|
103
|
+
const status = await getTemplateDeploymentStatus({
|
|
104
|
+
baseUrl,
|
|
105
|
+
authToken,
|
|
106
|
+
name: parsedName,
|
|
107
|
+
version: existing.latestVersion,
|
|
108
|
+
})
|
|
109
|
+
if (!status.ready) {
|
|
110
|
+
spinner.stop()
|
|
111
|
+
const root = await buildTemplateDeployment(zipFilter, cwd)
|
|
112
|
+
spinner.start(`Uploading deployment for ${parsedName}@${existing.latestVersion}`)
|
|
113
|
+
await uploadDeployment({
|
|
114
|
+
baseUrl,
|
|
115
|
+
authToken,
|
|
116
|
+
name: parsedName,
|
|
117
|
+
version: existing.latestVersion,
|
|
118
|
+
root,
|
|
119
|
+
spinner,
|
|
120
|
+
})
|
|
121
|
+
}
|
|
93
122
|
}
|
|
123
|
+
spinner.stop()
|
|
124
|
+
console.log(unchangedUploadResult(parsedName, existing.latestVersion))
|
|
125
|
+
return
|
|
94
126
|
}
|
|
95
127
|
|
|
96
128
|
const version = parsedVersion ?? nextVersion(existing?.latestVersion)
|
|
129
|
+
let deploymentRoot: string | null = null
|
|
130
|
+
if (type === 'template') {
|
|
131
|
+
spinner.stop()
|
|
132
|
+
deploymentRoot = await buildTemplateDeployment(zipFilter, cwd)
|
|
133
|
+
spinner.start(`Uploading ${parsedName}@${version}`)
|
|
134
|
+
}
|
|
135
|
+
|
|
97
136
|
spinner.text = `Uploading ${parsedName}@${version}`
|
|
98
137
|
const uploaded = await client.asset.uploadZip({
|
|
99
138
|
name: parsedName,
|
|
@@ -110,6 +149,17 @@ export async function uploadCommand(
|
|
|
110
149
|
}),
|
|
111
150
|
})
|
|
112
151
|
|
|
152
|
+
if (deploymentRoot) {
|
|
153
|
+
await uploadDeployment({
|
|
154
|
+
baseUrl,
|
|
155
|
+
authToken,
|
|
156
|
+
name: parsedName,
|
|
157
|
+
version: uploaded.version,
|
|
158
|
+
root: deploymentRoot,
|
|
159
|
+
spinner,
|
|
160
|
+
})
|
|
161
|
+
}
|
|
162
|
+
|
|
113
163
|
spinner.stop()
|
|
114
164
|
console.log(uploadResult(parsedName, uploaded.version))
|
|
115
165
|
} catch (err) {
|
|
@@ -118,6 +168,27 @@ export async function uploadCommand(
|
|
|
118
168
|
}
|
|
119
169
|
}
|
|
120
170
|
|
|
171
|
+
async function uploadDeployment(input: {
|
|
172
|
+
baseUrl: string
|
|
173
|
+
authToken: string
|
|
174
|
+
name: string
|
|
175
|
+
version: string
|
|
176
|
+
root: string
|
|
177
|
+
spinner: ReturnType<typeof ora>
|
|
178
|
+
}): Promise<void> {
|
|
179
|
+
input.spinner.text = `Uploading deployment for ${input.name}@${input.version}`
|
|
180
|
+
await uploadTemplateDeployment({
|
|
181
|
+
baseUrl: input.baseUrl,
|
|
182
|
+
authToken: input.authToken,
|
|
183
|
+
name: input.name,
|
|
184
|
+
version: input.version,
|
|
185
|
+
root: input.root,
|
|
186
|
+
onProgress(uploaded, total) {
|
|
187
|
+
input.spinner.text = `Uploading deployment for ${input.name}@${input.version} (${uploaded}/${total})`
|
|
188
|
+
},
|
|
189
|
+
})
|
|
190
|
+
}
|
|
191
|
+
|
|
121
192
|
export function parseUploadDescription(description: string): string {
|
|
122
193
|
try {
|
|
123
194
|
return assetDescriptionSchema.parse(description)
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import * as fs from 'node:fs/promises'
|
|
2
|
+
import * as path from 'node:path'
|
|
3
|
+
import { detectPackageManager, runScript } from 'nypm'
|
|
4
|
+
import { z } from 'zod'
|
|
5
|
+
|
|
6
|
+
const deploymentStatusSchema = z.object({
|
|
7
|
+
ready: z.boolean(),
|
|
8
|
+
url: z.string().url().nullable(),
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
const deploymentCompleteSchema = z.object({
|
|
12
|
+
url: z.string().url(),
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
export interface TemplateDeploymentStatus {
|
|
16
|
+
ready: boolean
|
|
17
|
+
url: string | null
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface UploadTemplateDeploymentInput {
|
|
21
|
+
baseUrl: string
|
|
22
|
+
authToken: string
|
|
23
|
+
name: string
|
|
24
|
+
version: string
|
|
25
|
+
root: string
|
|
26
|
+
onProgress?(uploaded: number, total: number): void
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export async function buildTemplateDeployment(zipFilter: string, cwd: string): Promise<string> {
|
|
30
|
+
const sourceRoot = path.resolve(cwd, zipFilter)
|
|
31
|
+
const stat = await fs.stat(sourceRoot).catch(() => null)
|
|
32
|
+
if (!stat?.isDirectory()) {
|
|
33
|
+
throw new Error('Template uploads require a project directory so Market can run its build')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const packageManager = (await detectPackageManager(sourceRoot)) ?? 'npm'
|
|
37
|
+
await runScript('build', { cwd: sourceRoot, packageManager })
|
|
38
|
+
const deploymentRoot = path.join(sourceRoot, 'dist')
|
|
39
|
+
await requireFile(path.join(deploymentRoot, 'index.html'), 'dist/index.html')
|
|
40
|
+
await requireFile(path.join(deploymentRoot, 'schema.json'), 'dist/schema.json')
|
|
41
|
+
return deploymentRoot
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export async function getTemplateDeploymentStatus(
|
|
45
|
+
input: Omit<UploadTemplateDeploymentInput, 'root' | 'onProgress'>,
|
|
46
|
+
): Promise<TemplateDeploymentStatus> {
|
|
47
|
+
const response = await fetch(deploymentEndpoint(input), {
|
|
48
|
+
headers: authHeaders(input.authToken),
|
|
49
|
+
})
|
|
50
|
+
const body = await responseBody(response)
|
|
51
|
+
if (!response.ok) throw httpError('read template deployment', response, body)
|
|
52
|
+
return deploymentStatusSchema.parse(body)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export async function uploadTemplateDeployment(
|
|
56
|
+
input: UploadTemplateDeploymentInput,
|
|
57
|
+
): Promise<string> {
|
|
58
|
+
const files = await deploymentFiles(input.root)
|
|
59
|
+
if (files.length === 0) throw new Error('Template deployment is empty')
|
|
60
|
+
|
|
61
|
+
await checkedFetch(
|
|
62
|
+
new URL(`${deploymentEndpoint(input).pathname}/prepare`, input.baseUrl),
|
|
63
|
+
{ method: 'POST', headers: authHeaders(input.authToken) },
|
|
64
|
+
'prepare template deployment',
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
let uploaded = 0
|
|
68
|
+
for (let start = 0; start < files.length; start += 6) {
|
|
69
|
+
await Promise.all(
|
|
70
|
+
files.slice(start, start + 6).map(async (file) => {
|
|
71
|
+
const url = deploymentEndpoint(input)
|
|
72
|
+
url.searchParams.set('path', file.path)
|
|
73
|
+
const bytes = await fs.readFile(file.absolutePath)
|
|
74
|
+
await checkedFetch(
|
|
75
|
+
url,
|
|
76
|
+
{
|
|
77
|
+
method: 'PUT',
|
|
78
|
+
headers: authHeaders(input.authToken),
|
|
79
|
+
body: new Blob([bytes]),
|
|
80
|
+
},
|
|
81
|
+
`upload ${file.path}`,
|
|
82
|
+
)
|
|
83
|
+
uploaded += 1
|
|
84
|
+
input.onProgress?.(uploaded, files.length)
|
|
85
|
+
}),
|
|
86
|
+
)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const completeUrl = new URL(`${deploymentEndpoint(input).pathname}/complete`, input.baseUrl)
|
|
90
|
+
const response = await fetch(completeUrl, {
|
|
91
|
+
method: 'POST',
|
|
92
|
+
headers: authHeaders(input.authToken),
|
|
93
|
+
})
|
|
94
|
+
const body = await responseBody(response)
|
|
95
|
+
if (!response.ok) throw httpError('publish template deployment', response, body)
|
|
96
|
+
return deploymentCompleteSchema.parse(body).url
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export async function deploymentFiles(
|
|
100
|
+
root: string,
|
|
101
|
+
): Promise<Array<{ absolutePath: string; path: string }>> {
|
|
102
|
+
const files: Array<{ absolutePath: string; path: string }> = []
|
|
103
|
+
|
|
104
|
+
async function visit(directory: string): Promise<void> {
|
|
105
|
+
const entries = await fs.readdir(directory, { withFileTypes: true })
|
|
106
|
+
for (const entry of entries) {
|
|
107
|
+
const absolutePath = path.join(directory, entry.name)
|
|
108
|
+
if (entry.isDirectory()) {
|
|
109
|
+
await visit(absolutePath)
|
|
110
|
+
continue
|
|
111
|
+
}
|
|
112
|
+
if (!entry.isFile()) {
|
|
113
|
+
throw new Error(`Template deployment contains an unsupported entry: ${absolutePath}`)
|
|
114
|
+
}
|
|
115
|
+
files.push({
|
|
116
|
+
absolutePath,
|
|
117
|
+
path: path.relative(root, absolutePath).split(path.sep).join('/'),
|
|
118
|
+
})
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
await visit(root)
|
|
123
|
+
return files.sort((a, b) => a.path.localeCompare(b.path))
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function deploymentEndpoint(input: { baseUrl: string; name: string; version: string }): URL {
|
|
127
|
+
return new URL(
|
|
128
|
+
`/api/templates/${encodeURIComponent(input.name)}/${encodeURIComponent(input.version)}/deployment`,
|
|
129
|
+
input.baseUrl,
|
|
130
|
+
)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function authHeaders(token: string): Headers {
|
|
134
|
+
return new Headers({ authorization: `Bearer ${token}` })
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
async function checkedFetch(url: URL, init: RequestInit, action: string): Promise<void> {
|
|
138
|
+
const response = await fetch(url, init)
|
|
139
|
+
if (response.ok) return
|
|
140
|
+
throw httpError(action, response, await responseBody(response))
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async function responseBody(response: Response): Promise<unknown> {
|
|
144
|
+
const text = await response.text()
|
|
145
|
+
if (!text) return {}
|
|
146
|
+
try {
|
|
147
|
+
return JSON.parse(text)
|
|
148
|
+
} catch {
|
|
149
|
+
return { raw: text }
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function httpError(action: string, response: Response, body: unknown): Error {
|
|
154
|
+
return new Error(`${action} failed (${response.status}): ${JSON.stringify(body)}`)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
async function requireFile(file: string, label: string): Promise<void> {
|
|
158
|
+
const stat = await fs.stat(file).catch(() => null)
|
|
159
|
+
if (!stat?.isFile()) throw new Error(`Template build did not produce ${label}`)
|
|
160
|
+
}
|