shop-cli 0.1.0 → 0.1.2
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/cli/approvalRequired.d.ts +30 -0
- package/dist/cli/approvalRequired.js +87 -0
- package/dist/cli/errors.d.ts +4 -1
- package/dist/cli/errors.js +3 -1
- package/dist/cli/gid.d.ts +1 -1
- package/dist/cli/help/registry.js +1013 -221
- package/dist/cli/help/render.d.ts +1 -0
- package/dist/cli/help/render.js +47 -0
- package/dist/cli/parse-command.d.ts +18 -0
- package/dist/cli/parse-command.js +109 -0
- package/dist/cli/router.js +3 -0
- package/dist/cli/suggest.d.ts +5 -0
- package/dist/cli/suggest.js +88 -0
- package/dist/cli/verbs/_shared.d.ts +1 -1
- package/dist/cli/verbs/_shared.js +4 -3
- package/dist/cli/verbs/catalogs.js +1 -1
- package/dist/cli/verbs/checkout-branding.js +2 -2
- package/dist/cli/verbs/collections.js +147 -12
- package/dist/cli/verbs/companies.js +2 -2
- package/dist/cli/verbs/company-contacts.js +8 -4
- package/dist/cli/verbs/company-locations.js +1 -1
- package/dist/cli/verbs/customers.js +156 -19
- package/dist/cli/verbs/discounts-automatic.js +36 -10
- package/dist/cli/verbs/discounts-code.js +27 -10
- package/dist/cli/verbs/draft-orders.js +49 -3
- package/dist/cli/verbs/files.js +171 -55
- package/dist/cli/verbs/fulfillment-orders.js +19 -4
- package/dist/cli/verbs/fulfillments.js +8 -2
- package/dist/cli/verbs/graphql.js +2 -0
- package/dist/cli/verbs/inventory.js +7 -1
- package/dist/cli/verbs/marketing-activities.js +1 -1
- package/dist/cli/verbs/markets.js +37 -4
- package/dist/cli/verbs/metaobjects.js +10 -1
- package/dist/cli/verbs/orders.js +80 -8
- package/dist/cli/verbs/product-variants.js +67 -16
- package/dist/cli/verbs/products.js +1263 -211
- package/dist/cli/verbs/selling-plan-groups.js +32 -10
- package/dist/cli/verbs/subscription-contracts.js +1 -0
- package/dist/cli/verbs/themes.js +18 -0
- package/dist/cli/verbs/url-redirects.js +64 -6
- package/dist/cli/workflows/files/stagedUploads.d.ts +3 -3
- package/dist/cli/workflows/files/stagedUploads.js +71 -19
- package/dist/cli/workflows/files/stdinFile.d.ts +7 -0
- package/dist/cli/workflows/files/stdinFile.js +65 -0
- package/dist/cli/workflows/files/urlDownloads.d.ts +14 -0
- package/dist/cli/workflows/files/urlDownloads.js +114 -0
- package/dist/cli/workflows/files/waitForReady.d.ts +20 -0
- package/dist/cli/workflows/files/waitForReady.js +114 -0
- package/dist/cli.js +115 -29
- package/package.json +3 -2
|
@@ -181,22 +181,44 @@ const runSellingPlanGroups = async ({
|
|
|
181
181
|
});
|
|
182
182
|
const id = (0, import_shared.requireId)(args.id, "SellingPlanGroup");
|
|
183
183
|
const variantIds = (0, import_shared.parseIds)(args["variant-ids"], "ProductVariant");
|
|
184
|
-
|
|
185
|
-
|
|
184
|
+
if (verb === "add-variants") {
|
|
185
|
+
const result2 = await (0, import_router.runMutation)(ctx, {
|
|
186
|
+
sellingPlanGroupAddProductVariants: {
|
|
187
|
+
__args: { id, productVariantIds: variantIds },
|
|
188
|
+
sellingPlanGroup: sellingPlanGroupSummarySelection,
|
|
189
|
+
userErrors: { field: true, message: true }
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
if (result2 === void 0) return;
|
|
193
|
+
const payload2 = result2.sellingPlanGroupAddProductVariants;
|
|
194
|
+
(0, import_userErrors.maybeFailOnUserErrors)({ payload: payload2, failOnUserErrors: ctx.failOnUserErrors });
|
|
195
|
+
if (ctx.quiet) return console.log(payload2?.sellingPlanGroup?.id ?? "");
|
|
196
|
+
(0, import_output.printJson)(payload2, ctx.format !== "raw");
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
186
199
|
const result = await (0, import_router.runMutation)(ctx, {
|
|
187
|
-
|
|
200
|
+
sellingPlanGroupRemoveProductVariants: {
|
|
188
201
|
__args: { id, productVariantIds: variantIds },
|
|
189
|
-
|
|
202
|
+
removedProductVariantIds: true,
|
|
203
|
+
userErrors: { field: true, message: true }
|
|
190
204
|
}
|
|
191
205
|
});
|
|
192
206
|
if (result === void 0) return;
|
|
193
|
-
const payload = result
|
|
207
|
+
const payload = result.sellingPlanGroupRemoveProductVariants;
|
|
194
208
|
(0, import_userErrors.maybeFailOnUserErrors)({ payload, failOnUserErrors: ctx.failOnUserErrors });
|
|
195
|
-
if (ctx.quiet)
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}
|
|
199
|
-
|
|
209
|
+
if (ctx.quiet) return console.log(id ?? "");
|
|
210
|
+
const groupResult = await (0, import_router.runQuery)(ctx, {
|
|
211
|
+
sellingPlanGroup: { __args: { id }, ...sellingPlanGroupSummarySelection }
|
|
212
|
+
});
|
|
213
|
+
if (groupResult === void 0) return;
|
|
214
|
+
(0, import_output.printJson)(
|
|
215
|
+
{
|
|
216
|
+
sellingPlanGroup: groupResult.sellingPlanGroup ?? null,
|
|
217
|
+
removedProductVariantIds: payload?.removedProductVariantIds ?? [],
|
|
218
|
+
userErrors: payload?.userErrors ?? []
|
|
219
|
+
},
|
|
220
|
+
ctx.format !== "raw"
|
|
221
|
+
);
|
|
200
222
|
return;
|
|
201
223
|
}
|
|
202
224
|
throw new import_errors.CliError(`Unknown verb for selling-plan-groups: ${verb}`, 2);
|
package/dist/cli/verbs/themes.js
CHANGED
|
@@ -269,6 +269,15 @@ const runThemes = async ({
|
|
|
269
269
|
});
|
|
270
270
|
if (result === void 0) return;
|
|
271
271
|
(0, import_userErrors.maybeFailOnUserErrors)({ payload: result.themeFilesDelete, failOnUserErrors: ctx.failOnUserErrors });
|
|
272
|
+
if (ctx.quiet) {
|
|
273
|
+
const deleted = result.themeFilesDelete?.deletedThemeFiles ?? [];
|
|
274
|
+
for (const f of deleted) {
|
|
275
|
+
const name = typeof f?.filename === "string" ? f.filename : "";
|
|
276
|
+
if (name) process.stdout.write(`${name}
|
|
277
|
+
`);
|
|
278
|
+
}
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
272
281
|
(0, import_output.printJson)(result.themeFilesDelete, ctx.format !== "raw");
|
|
273
282
|
return;
|
|
274
283
|
}
|
|
@@ -285,6 +294,15 @@ const runThemes = async ({
|
|
|
285
294
|
});
|
|
286
295
|
if (result === void 0) return;
|
|
287
296
|
(0, import_userErrors.maybeFailOnUserErrors)({ payload: result.themeFilesCopy, failOnUserErrors: ctx.failOnUserErrors });
|
|
297
|
+
if (ctx.quiet) {
|
|
298
|
+
const copied = result.themeFilesCopy?.copiedThemeFiles ?? [];
|
|
299
|
+
for (const f of copied) {
|
|
300
|
+
const name = typeof f?.filename === "string" ? f.filename : "";
|
|
301
|
+
if (name) process.stdout.write(`${name}
|
|
302
|
+
`);
|
|
303
|
+
}
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
288
306
|
(0, import_output.printJson)(result.themeFilesCopy, ctx.format !== "raw");
|
|
289
307
|
return;
|
|
290
308
|
}
|
|
@@ -193,8 +193,26 @@ const runUrlRedirects = async ({
|
|
|
193
193
|
});
|
|
194
194
|
if (result === void 0) return;
|
|
195
195
|
(0, import_userErrors.maybeFailOnUserErrors)({ payload: result.urlRedirectImportSubmit, failOnUserErrors: ctx.failOnUserErrors });
|
|
196
|
-
if (ctx.quiet) return console.log(
|
|
197
|
-
(0,
|
|
196
|
+
if (ctx.quiet) return console.log(id ?? "");
|
|
197
|
+
const selection = (0, import_select.resolveSelection)({
|
|
198
|
+
typeName: "UrlRedirectImport",
|
|
199
|
+
view: ctx.view,
|
|
200
|
+
baseSelection: getUrlRedirectImportSelection(ctx.view),
|
|
201
|
+
select: args.select,
|
|
202
|
+
selection: args.selection,
|
|
203
|
+
include: args.include,
|
|
204
|
+
ensureId: true
|
|
205
|
+
});
|
|
206
|
+
const importResult = await (0, import_router.runQuery)(ctx, { urlRedirectImport: { __args: { id }, ...selection } });
|
|
207
|
+
if (importResult === void 0) return;
|
|
208
|
+
(0, import_output.printJson)(
|
|
209
|
+
{
|
|
210
|
+
urlRedirectImport: importResult.urlRedirectImport ?? null,
|
|
211
|
+
job: result.urlRedirectImportSubmit?.job ?? null,
|
|
212
|
+
userErrors: result.urlRedirectImportSubmit?.userErrors ?? []
|
|
213
|
+
},
|
|
214
|
+
ctx.format !== "raw"
|
|
215
|
+
);
|
|
198
216
|
return;
|
|
199
217
|
}
|
|
200
218
|
if (verb === "import-get") {
|
|
@@ -224,6 +242,9 @@ const runUrlRedirects = async ({
|
|
|
224
242
|
});
|
|
225
243
|
if (!args.yes) throw new import_errors.CliError("Refusing to delete without --yes", 2);
|
|
226
244
|
if (verb === "bulk-delete-all") {
|
|
245
|
+
const countResult2 = await (0, import_router.runQuery)(ctx, {
|
|
246
|
+
urlRedirectsCount: { count: true, precision: true }
|
|
247
|
+
});
|
|
227
248
|
const result2 = await (0, import_router.runMutation)(ctx, {
|
|
228
249
|
urlRedirectBulkDeleteAll: {
|
|
229
250
|
job: { id: true, done: true },
|
|
@@ -233,7 +254,14 @@ const runUrlRedirects = async ({
|
|
|
233
254
|
if (result2 === void 0) return;
|
|
234
255
|
(0, import_userErrors.maybeFailOnUserErrors)({ payload: result2.urlRedirectBulkDeleteAll, failOnUserErrors: ctx.failOnUserErrors });
|
|
235
256
|
if (ctx.quiet) return console.log(result2.urlRedirectBulkDeleteAll?.job?.id ?? "");
|
|
236
|
-
(0, import_output.printJson)(
|
|
257
|
+
(0, import_output.printJson)(
|
|
258
|
+
{
|
|
259
|
+
job: result2.urlRedirectBulkDeleteAll?.job ?? null,
|
|
260
|
+
count: countResult2?.urlRedirectsCount ?? null,
|
|
261
|
+
userErrors: result2.urlRedirectBulkDeleteAll?.userErrors ?? []
|
|
262
|
+
},
|
|
263
|
+
ctx.format !== "raw"
|
|
264
|
+
);
|
|
237
265
|
return;
|
|
238
266
|
}
|
|
239
267
|
if (verb === "bulk-delete-ids") {
|
|
@@ -248,13 +276,24 @@ const runUrlRedirects = async ({
|
|
|
248
276
|
if (result2 === void 0) return;
|
|
249
277
|
(0, import_userErrors.maybeFailOnUserErrors)({ payload: result2.urlRedirectBulkDeleteByIds, failOnUserErrors: ctx.failOnUserErrors });
|
|
250
278
|
if (ctx.quiet) return console.log(result2.urlRedirectBulkDeleteByIds?.job?.id ?? "");
|
|
251
|
-
(0, import_output.printJson)(
|
|
279
|
+
(0, import_output.printJson)(
|
|
280
|
+
{
|
|
281
|
+
job: result2.urlRedirectBulkDeleteByIds?.job ?? null,
|
|
282
|
+
requestedIds: ids,
|
|
283
|
+
requestedCount: ids.length,
|
|
284
|
+
userErrors: result2.urlRedirectBulkDeleteByIds?.userErrors ?? []
|
|
285
|
+
},
|
|
286
|
+
ctx.format !== "raw"
|
|
287
|
+
);
|
|
252
288
|
return;
|
|
253
289
|
}
|
|
254
290
|
if (verb === "bulk-delete-saved-search") {
|
|
255
291
|
const raw = args["saved-search-id"];
|
|
256
292
|
if (!raw) throw new import_errors.CliError("Missing --saved-search-id", 2);
|
|
257
293
|
const savedSearchId = (0, import_gid.coerceGid)(raw, "SavedSearch");
|
|
294
|
+
const countResult2 = await (0, import_router.runQuery)(ctx, {
|
|
295
|
+
urlRedirectsCount: { __args: { savedSearchId }, count: true, precision: true }
|
|
296
|
+
});
|
|
258
297
|
const result2 = await (0, import_router.runMutation)(ctx, {
|
|
259
298
|
urlRedirectBulkDeleteBySavedSearch: {
|
|
260
299
|
__args: { savedSearchId },
|
|
@@ -268,11 +307,22 @@ const runUrlRedirects = async ({
|
|
|
268
307
|
failOnUserErrors: ctx.failOnUserErrors
|
|
269
308
|
});
|
|
270
309
|
if (ctx.quiet) return console.log(result2.urlRedirectBulkDeleteBySavedSearch?.job?.id ?? "");
|
|
271
|
-
(0, import_output.printJson)(
|
|
310
|
+
(0, import_output.printJson)(
|
|
311
|
+
{
|
|
312
|
+
job: result2.urlRedirectBulkDeleteBySavedSearch?.job ?? null,
|
|
313
|
+
count: countResult2?.urlRedirectsCount ?? null,
|
|
314
|
+
savedSearchId,
|
|
315
|
+
userErrors: result2.urlRedirectBulkDeleteBySavedSearch?.userErrors ?? []
|
|
316
|
+
},
|
|
317
|
+
ctx.format !== "raw"
|
|
318
|
+
);
|
|
272
319
|
return;
|
|
273
320
|
}
|
|
274
321
|
const search = args.search;
|
|
275
322
|
if (!search) throw new import_errors.CliError("Missing --search", 2);
|
|
323
|
+
const countResult = await (0, import_router.runQuery)(ctx, {
|
|
324
|
+
urlRedirectsCount: { __args: { query: search }, count: true, precision: true }
|
|
325
|
+
});
|
|
276
326
|
const result = await (0, import_router.runMutation)(ctx, {
|
|
277
327
|
urlRedirectBulkDeleteBySearch: {
|
|
278
328
|
__args: { search },
|
|
@@ -286,7 +336,15 @@ const runUrlRedirects = async ({
|
|
|
286
336
|
failOnUserErrors: ctx.failOnUserErrors
|
|
287
337
|
});
|
|
288
338
|
if (ctx.quiet) return console.log(result.urlRedirectBulkDeleteBySearch?.job?.id ?? "");
|
|
289
|
-
(0, import_output.printJson)(
|
|
339
|
+
(0, import_output.printJson)(
|
|
340
|
+
{
|
|
341
|
+
job: result.urlRedirectBulkDeleteBySearch?.job ?? null,
|
|
342
|
+
count: countResult?.urlRedirectsCount ?? null,
|
|
343
|
+
search,
|
|
344
|
+
userErrors: result.urlRedirectBulkDeleteBySearch?.userErrors ?? []
|
|
345
|
+
},
|
|
346
|
+
ctx.format !== "raw"
|
|
347
|
+
);
|
|
290
348
|
return;
|
|
291
349
|
}
|
|
292
350
|
if (verb === "get") {
|
|
@@ -15,11 +15,11 @@ export type StagedUploadTarget = {
|
|
|
15
15
|
value: string;
|
|
16
16
|
}>;
|
|
17
17
|
};
|
|
18
|
-
export declare const buildLocalFilesForStagedUpload: ({ filePaths,
|
|
18
|
+
export declare const buildLocalFilesForStagedUpload: ({ filePaths, mimeType, resource, }: {
|
|
19
19
|
filePaths: string[];
|
|
20
|
-
|
|
20
|
+
mimeType?: string;
|
|
21
21
|
resource?: StagedUploadResource;
|
|
22
|
-
}) => LocalFileForStagedUpload[]
|
|
22
|
+
}) => Promise<LocalFileForStagedUpload[]>;
|
|
23
23
|
export declare const stagedUploadsCreate: (ctx: CommandContext, localFiles: LocalFileForStagedUpload[]) => Promise<StagedUploadTarget[] | undefined>;
|
|
24
24
|
export declare const uploadToStagedTarget: ({ target, localFile, }: {
|
|
25
25
|
target: StagedUploadTarget;
|
|
@@ -36,14 +36,15 @@ __export(stagedUploads_exports, {
|
|
|
36
36
|
module.exports = __toCommonJS(stagedUploads_exports);
|
|
37
37
|
var import_node_fs = require("node:fs");
|
|
38
38
|
var import_node_path = __toESM(require("node:path"));
|
|
39
|
+
var import_node_child_process = require("node:child_process");
|
|
39
40
|
var import_mime_types = require("mime-types");
|
|
40
41
|
var import_errors = require("../../errors");
|
|
41
42
|
var import_router = require("../../router");
|
|
42
43
|
var import_userErrors = require("../../userErrors");
|
|
43
|
-
const
|
|
44
|
+
const mimeTypeFromFilename = (filename) => {
|
|
44
45
|
const mimeType = (0, import_mime_types.lookup)(filename);
|
|
45
46
|
if (typeof mimeType === "string") return mimeType;
|
|
46
|
-
return
|
|
47
|
+
return void 0;
|
|
47
48
|
};
|
|
48
49
|
const inferStagedUploadResource = ({
|
|
49
50
|
filename,
|
|
@@ -57,26 +58,51 @@ const inferStagedUploadResource = ({
|
|
|
57
58
|
}
|
|
58
59
|
return "FILE";
|
|
59
60
|
};
|
|
60
|
-
const
|
|
61
|
+
const sniffMimeTypeFromFile = async (filePath) => {
|
|
62
|
+
try {
|
|
63
|
+
const mod = await import("file-type");
|
|
64
|
+
const result = await mod.fileTypeFromFile(filePath);
|
|
65
|
+
return result?.mime;
|
|
66
|
+
} catch {
|
|
67
|
+
return void 0;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
const resolveMimeType = async ({
|
|
71
|
+
filePath,
|
|
72
|
+
filename,
|
|
73
|
+
forcedMimeType
|
|
74
|
+
}) => {
|
|
75
|
+
const forced = typeof forcedMimeType === "string" ? forcedMimeType.trim() : "";
|
|
76
|
+
if (forced) return forced;
|
|
77
|
+
const sniffed = await sniffMimeTypeFromFile(filePath);
|
|
78
|
+
if (sniffed) return sniffed;
|
|
79
|
+
const byExt = mimeTypeFromFilename(filename);
|
|
80
|
+
if (byExt) return byExt;
|
|
81
|
+
throw new import_errors.CliError(
|
|
82
|
+
`Unable to determine MIME type for ${filename}. Pass --mime-type <mime>.`,
|
|
83
|
+
2
|
|
84
|
+
);
|
|
85
|
+
};
|
|
86
|
+
const buildLocalFilesForStagedUpload = async ({
|
|
61
87
|
filePaths,
|
|
62
|
-
|
|
88
|
+
mimeType,
|
|
63
89
|
resource
|
|
64
90
|
}) => {
|
|
65
91
|
if (filePaths.length === 0) return [];
|
|
66
|
-
return filePaths.map((filePath) => {
|
|
92
|
+
return Promise.all(filePaths.map(async (filePath) => {
|
|
67
93
|
const stats = (0, import_node_fs.statSync)(filePath);
|
|
68
94
|
if (!stats.isFile()) throw new import_errors.CliError(`Not a file: ${filePath}`, 2);
|
|
69
95
|
const filename = import_node_path.default.basename(filePath);
|
|
70
|
-
const
|
|
71
|
-
const inferredResource = inferStagedUploadResource({ filename, mimeType });
|
|
96
|
+
const resolvedMimeType = await resolveMimeType({ filePath, filename, forcedMimeType: mimeType });
|
|
97
|
+
const inferredResource = inferStagedUploadResource({ filename, mimeType: resolvedMimeType });
|
|
72
98
|
return {
|
|
73
99
|
filePath,
|
|
74
100
|
filename,
|
|
75
|
-
mimeType,
|
|
101
|
+
mimeType: resolvedMimeType,
|
|
76
102
|
resource: resource ?? inferredResource,
|
|
77
103
|
fileSize: stats.size
|
|
78
104
|
};
|
|
79
|
-
});
|
|
105
|
+
}));
|
|
80
106
|
};
|
|
81
107
|
const stagedUploadsCreate = async (ctx, localFiles) => {
|
|
82
108
|
const input = localFiles.map((f) => ({
|
|
@@ -137,19 +163,45 @@ const uploadToStagedTarget = async ({
|
|
|
137
163
|
target,
|
|
138
164
|
localFile
|
|
139
165
|
}) => {
|
|
140
|
-
const
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
166
|
+
const args = ["--fail-with-body", "--silent", "--show-error", "-X", "POST"];
|
|
167
|
+
for (const p of target.parameters) {
|
|
168
|
+
args.push("--form-string", `${p.name}=${p.value}`);
|
|
169
|
+
}
|
|
170
|
+
args.push(
|
|
171
|
+
"--form",
|
|
172
|
+
`file=@${localFile.filePath};type=${localFile.mimeType};filename=${localFile.filename}`,
|
|
173
|
+
target.url
|
|
174
|
+
);
|
|
175
|
+
let child;
|
|
147
176
|
try {
|
|
148
|
-
|
|
149
|
-
} catch {
|
|
177
|
+
child = (0, import_node_child_process.spawn)("curl", args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
178
|
+
} catch (err) {
|
|
179
|
+
throw err;
|
|
150
180
|
}
|
|
181
|
+
let stdout = "";
|
|
182
|
+
let stderr = "";
|
|
183
|
+
child.stdout?.on("data", (chunk) => {
|
|
184
|
+
stdout += typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
|
|
185
|
+
});
|
|
186
|
+
child.stderr?.on("data", (chunk) => {
|
|
187
|
+
stderr += typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
|
|
188
|
+
});
|
|
189
|
+
const code = await new Promise((resolve, reject) => {
|
|
190
|
+
child.on("error", (err) => {
|
|
191
|
+
if (err && err.code === "ENOENT") {
|
|
192
|
+
reject(new import_errors.CliError("curl is required for streaming staged uploads (curl not found on PATH)", 2));
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
reject(err);
|
|
196
|
+
});
|
|
197
|
+
child.on("close", (c) => resolve(c ?? 1));
|
|
198
|
+
});
|
|
199
|
+
if (code === 0) return;
|
|
200
|
+
const trimmedErr = stderr.trim();
|
|
201
|
+
const trimmedOut = stdout.trim();
|
|
202
|
+
const details = trimmedErr || trimmedOut;
|
|
151
203
|
throw new import_errors.CliError(
|
|
152
|
-
`Staged upload failed for ${localFile.filename}:
|
|
204
|
+
`Staged upload failed for ${localFile.filename}: curl exited with code ${code}${details ? `
|
|
153
205
|
${details}` : ""}`,
|
|
154
206
|
2
|
|
155
207
|
);
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var stdinFile_exports = {};
|
|
30
|
+
__export(stdinFile_exports, {
|
|
31
|
+
writeStdinToTempFile: () => writeStdinToTempFile
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(stdinFile_exports);
|
|
34
|
+
var import_node_fs = require("node:fs");
|
|
35
|
+
var import_promises = require("node:fs/promises");
|
|
36
|
+
var import_node_os = __toESM(require("node:os"));
|
|
37
|
+
var import_node_path = __toESM(require("node:path"));
|
|
38
|
+
var import_promises2 = require("node:stream/promises");
|
|
39
|
+
var import_errors = require("../../errors");
|
|
40
|
+
const safeBasename = (name) => name.replace(/[\\/]/g, "_");
|
|
41
|
+
const writeStdinToTempFile = async ({
|
|
42
|
+
filename,
|
|
43
|
+
stdin = process.stdin
|
|
44
|
+
}) => {
|
|
45
|
+
const raw = typeof filename === "string" ? filename.trim() : "";
|
|
46
|
+
if (!raw) throw new import_errors.CliError("Missing --filename (required with --file -)", 2);
|
|
47
|
+
const tempDir = await (0, import_promises.mkdtemp)(import_node_path.default.join(import_node_os.default.tmpdir(), "shop-cli-stdin-"));
|
|
48
|
+
const cleanup = async () => {
|
|
49
|
+
await (0, import_promises.rm)(tempDir, { recursive: true, force: true });
|
|
50
|
+
};
|
|
51
|
+
try {
|
|
52
|
+
const filePath = import_node_path.default.join(tempDir, safeBasename(raw) || "stdin");
|
|
53
|
+
const out = (0, import_node_fs.createWriteStream)(filePath);
|
|
54
|
+
await (0, import_promises2.pipeline)(stdin, out);
|
|
55
|
+
return { filePath, cleanup };
|
|
56
|
+
} catch (err) {
|
|
57
|
+
await cleanup();
|
|
58
|
+
throw err;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
62
|
+
0 && (module.exports = {
|
|
63
|
+
writeStdinToTempFile
|
|
64
|
+
});
|
|
65
|
+
//# sourceMappingURL=stdinFile.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const inferFilenameFromUrl: (rawUrl: string) => string;
|
|
2
|
+
export type DownloadedUrlFile = {
|
|
3
|
+
url: string;
|
|
4
|
+
filePath: string;
|
|
5
|
+
filename: string;
|
|
6
|
+
};
|
|
7
|
+
export declare const downloadUrlsToTempDir: ({ urls, filenameOverride, }: {
|
|
8
|
+
urls: string[];
|
|
9
|
+
filenameOverride?: string;
|
|
10
|
+
}) => Promise<{
|
|
11
|
+
tempDir: string;
|
|
12
|
+
files: DownloadedUrlFile[];
|
|
13
|
+
cleanup: () => Promise<void>;
|
|
14
|
+
}>;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var urlDownloads_exports = {};
|
|
30
|
+
__export(urlDownloads_exports, {
|
|
31
|
+
downloadUrlsToTempDir: () => downloadUrlsToTempDir,
|
|
32
|
+
inferFilenameFromUrl: () => inferFilenameFromUrl
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(urlDownloads_exports);
|
|
35
|
+
var import_node_fs = require("node:fs");
|
|
36
|
+
var import_promises = require("node:fs/promises");
|
|
37
|
+
var import_promises2 = require("node:stream/promises");
|
|
38
|
+
var import_node_stream = require("node:stream");
|
|
39
|
+
var import_node_os = __toESM(require("node:os"));
|
|
40
|
+
var import_node_path = __toESM(require("node:path"));
|
|
41
|
+
var import_errors = require("../../errors");
|
|
42
|
+
const safeBasename = (name) => name.replace(/[\\/]/g, "_");
|
|
43
|
+
const inferFilenameFromUrl = (rawUrl) => {
|
|
44
|
+
let u;
|
|
45
|
+
try {
|
|
46
|
+
u = new URL(rawUrl);
|
|
47
|
+
} catch {
|
|
48
|
+
throw new import_errors.CliError(`Invalid URL: ${rawUrl}`, 2);
|
|
49
|
+
}
|
|
50
|
+
const base = import_node_path.default.posix.basename(u.pathname || "");
|
|
51
|
+
if (base && base !== "/" && base !== ".") {
|
|
52
|
+
try {
|
|
53
|
+
const decoded = decodeURIComponent(base);
|
|
54
|
+
return safeBasename(decoded) || "download";
|
|
55
|
+
} catch {
|
|
56
|
+
return safeBasename(base) || "download";
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return "download";
|
|
60
|
+
};
|
|
61
|
+
const uniqueFilename = (requested, used) => {
|
|
62
|
+
const base = safeBasename(requested) || "download";
|
|
63
|
+
const count = used.get(base) ?? 0;
|
|
64
|
+
used.set(base, count + 1);
|
|
65
|
+
if (count === 0) return base;
|
|
66
|
+
const ext = import_node_path.default.extname(base);
|
|
67
|
+
const stem = ext ? base.slice(0, -ext.length) : base;
|
|
68
|
+
return `${stem}-${count + 1}${ext}`;
|
|
69
|
+
};
|
|
70
|
+
const downloadUrlsToTempDir = async ({
|
|
71
|
+
urls,
|
|
72
|
+
filenameOverride
|
|
73
|
+
}) => {
|
|
74
|
+
if (urls.length === 0) throw new import_errors.CliError("Missing --url (repeatable)", 2);
|
|
75
|
+
if (filenameOverride && urls.length !== 1) {
|
|
76
|
+
throw new import_errors.CliError("--filename is only valid when exactly 1 --url is provided", 2);
|
|
77
|
+
}
|
|
78
|
+
const tempDir = await (0, import_promises.mkdtemp)(import_node_path.default.join(import_node_os.default.tmpdir(), "shop-cli-files-upload-"));
|
|
79
|
+
const cleanup = async () => {
|
|
80
|
+
await (0, import_promises.rm)(tempDir, { recursive: true, force: true });
|
|
81
|
+
};
|
|
82
|
+
try {
|
|
83
|
+
await (0, import_promises.mkdir)(tempDir, { recursive: true });
|
|
84
|
+
const used = /* @__PURE__ */ new Map();
|
|
85
|
+
const files = [];
|
|
86
|
+
for (let i = 0; i < urls.length; i++) {
|
|
87
|
+
const url = urls[i];
|
|
88
|
+
const inferred = filenameOverride ?? inferFilenameFromUrl(url);
|
|
89
|
+
const filename = uniqueFilename(inferred, used);
|
|
90
|
+
const filePath = import_node_path.default.join(tempDir, filename);
|
|
91
|
+
const res = await fetch(url, { redirect: "follow" });
|
|
92
|
+
if (!res.ok) {
|
|
93
|
+
throw new import_errors.CliError(`Failed to download ${url}: ${res.status} ${res.statusText}`, 2);
|
|
94
|
+
}
|
|
95
|
+
if (!res.body) {
|
|
96
|
+
throw new import_errors.CliError(`Failed to download ${url}: empty response body`, 2);
|
|
97
|
+
}
|
|
98
|
+
const nodeStream = import_node_stream.Readable.fromWeb(res.body);
|
|
99
|
+
const out = (0, import_node_fs.createWriteStream)(filePath);
|
|
100
|
+
await (0, import_promises2.pipeline)(nodeStream, out);
|
|
101
|
+
files.push({ url, filePath, filename });
|
|
102
|
+
}
|
|
103
|
+
return { tempDir, files, cleanup };
|
|
104
|
+
} catch (err) {
|
|
105
|
+
await cleanup();
|
|
106
|
+
throw err;
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
110
|
+
0 && (module.exports = {
|
|
111
|
+
downloadUrlsToTempDir,
|
|
112
|
+
inferFilenameFromUrl
|
|
113
|
+
});
|
|
114
|
+
//# sourceMappingURL=urlDownloads.js.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type CommandContext } from '../../router';
|
|
2
|
+
export type WaitForFilesResult = {
|
|
3
|
+
nodes: any[];
|
|
4
|
+
readyIds: string[];
|
|
5
|
+
failedIds: string[];
|
|
6
|
+
};
|
|
7
|
+
export declare const pollFilesReadyOrFailed: ({ ids, pollIntervalMs, timeoutMs, fetchNodes, now, sleep, }: {
|
|
8
|
+
ids: string[];
|
|
9
|
+
pollIntervalMs: number;
|
|
10
|
+
timeoutMs: number;
|
|
11
|
+
fetchNodes: (ids: string[]) => Promise<any[]>;
|
|
12
|
+
now?: () => number;
|
|
13
|
+
sleep?: (ms: number) => Promise<void>;
|
|
14
|
+
}) => Promise<WaitForFilesResult>;
|
|
15
|
+
export declare const waitForFilesReadyOrFailed: ({ ctx, ids, pollIntervalMs, timeoutMs, }: {
|
|
16
|
+
ctx: CommandContext;
|
|
17
|
+
ids: string[];
|
|
18
|
+
pollIntervalMs: number;
|
|
19
|
+
timeoutMs: number;
|
|
20
|
+
}) => Promise<WaitForFilesResult>;
|