@01.software/cli 0.17.4 → 0.19.5
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/index.js +1385 -260
- package/dist/index.js.map +1 -1
- package/package.json +7 -4
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import {
|
|
4
|
+
import { realpathSync } from "fs";
|
|
5
|
+
import { createRequire as createRequire2 } from "module";
|
|
6
|
+
import { fileURLToPath } from "url";
|
|
5
7
|
import { Command } from "commander";
|
|
6
8
|
|
|
7
9
|
// src/lib/client.ts
|
|
@@ -11,6 +13,386 @@ import {
|
|
|
11
13
|
TenantIntrospectionApi
|
|
12
14
|
} from "@01.software/sdk/server";
|
|
13
15
|
|
|
16
|
+
// ../../internal/http-contracts/src/index.ts
|
|
17
|
+
var operationBrand = /* @__PURE__ */ Symbol("sdk-http-operation");
|
|
18
|
+
var operation = (collection, method, path2, errorFamily) => Object.freeze({
|
|
19
|
+
[operationBrand]: true,
|
|
20
|
+
collection,
|
|
21
|
+
method,
|
|
22
|
+
path: path2,
|
|
23
|
+
...errorFamily && { errorFamily }
|
|
24
|
+
});
|
|
25
|
+
var strictCommerceOperation = (collection, method, path2) => operation(collection, method, path2, "commerce");
|
|
26
|
+
var selectiveCommerceOperation = (collection, method, path2, typedCommerceErrorReasons) => Object.freeze({
|
|
27
|
+
...operation(collection, method, path2),
|
|
28
|
+
typedCommerceErrorReasons: Object.freeze([...typedCommerceErrorReasons])
|
|
29
|
+
});
|
|
30
|
+
var COMMERCE_ENDPOINT_OPERATIONS = {
|
|
31
|
+
products: {
|
|
32
|
+
detail: operation("products", "get", "/detail"),
|
|
33
|
+
detailCatalog: operation("products", "get", "/detail/catalog"),
|
|
34
|
+
listingGroups: operation("products", "get", "/listing-groups"),
|
|
35
|
+
listingGroupsCatalog: operation(
|
|
36
|
+
"products",
|
|
37
|
+
"get",
|
|
38
|
+
"/listing-groups/catalog"
|
|
39
|
+
),
|
|
40
|
+
listingGroupsQuery: operation("products", "post", "/listing-groups/query"),
|
|
41
|
+
listingGroupsQueryGet: operation(
|
|
42
|
+
"products",
|
|
43
|
+
"get",
|
|
44
|
+
"/listing-groups/query"
|
|
45
|
+
),
|
|
46
|
+
listingGroupsQueryCatalog: operation(
|
|
47
|
+
"products",
|
|
48
|
+
"get",
|
|
49
|
+
"/listing-groups/query/catalog"
|
|
50
|
+
),
|
|
51
|
+
stockCheck: operation("products", "post", "/stock-check"),
|
|
52
|
+
stockSnapshot: operation("products", "get", "/stock"),
|
|
53
|
+
upsert: operation("products", "post", "/upsert")
|
|
54
|
+
},
|
|
55
|
+
orders: {
|
|
56
|
+
create: operation("orders", "post", "/create"),
|
|
57
|
+
update: operation("orders", "post", "/update"),
|
|
58
|
+
confirmPayment: operation("orders", "post", "/confirm-payment"),
|
|
59
|
+
byPayment: operation("orders", "get", "/by-payment"),
|
|
60
|
+
cancel: operation("orders", "post", "/cancel"),
|
|
61
|
+
resolveCancelRefund: selectiveCommerceOperation(
|
|
62
|
+
"orders",
|
|
63
|
+
"post",
|
|
64
|
+
"/resolve-cancel-refund",
|
|
65
|
+
["managed_refund_attestation_forbidden"]
|
|
66
|
+
),
|
|
67
|
+
checkout: strictCommerceOperation("orders", "post", "/checkout"),
|
|
68
|
+
createFulfillment: operation("orders", "post", "/create-fulfillment"),
|
|
69
|
+
updateFulfillment: operation("orders", "post", "/update-fulfillment")
|
|
70
|
+
},
|
|
71
|
+
checkouts: {
|
|
72
|
+
detail: strictCommerceOperation("checkouts", "post", "/detail"),
|
|
73
|
+
query: strictCommerceOperation("checkouts", "post", "/query")
|
|
74
|
+
},
|
|
75
|
+
draftOrders: {
|
|
76
|
+
calculate: operation("draft-orders", "post", "/:id/calculate"),
|
|
77
|
+
complete: operation("draft-orders", "post", "/:id/complete"),
|
|
78
|
+
finalize: operation("draft-orders", "post", "/:id/finalize")
|
|
79
|
+
},
|
|
80
|
+
transactions: {
|
|
81
|
+
update: operation("transactions", "post", "/update")
|
|
82
|
+
},
|
|
83
|
+
returns: {
|
|
84
|
+
create: operation("returns", "post", "/create"),
|
|
85
|
+
update: operation("returns", "post", "/update"),
|
|
86
|
+
returnRefund: operation("returns", "post", "/return-refund")
|
|
87
|
+
},
|
|
88
|
+
fulfillmentOrders: {
|
|
89
|
+
prepare: operation(
|
|
90
|
+
"fulfillment-orders",
|
|
91
|
+
"post",
|
|
92
|
+
"/prepare-fulfillment-order"
|
|
93
|
+
)
|
|
94
|
+
},
|
|
95
|
+
fulfillments: {
|
|
96
|
+
bulkImport: operation("fulfillments", "post", "/bulk-import")
|
|
97
|
+
},
|
|
98
|
+
carts: {
|
|
99
|
+
create: strictCommerceOperation("carts", "post", "/create"),
|
|
100
|
+
retrieve: strictCommerceOperation("carts", "post", "/retrieve"),
|
|
101
|
+
mine: strictCommerceOperation("carts", "post", "/mine"),
|
|
102
|
+
merge: strictCommerceOperation("carts", "post", "/merge"),
|
|
103
|
+
addItem: strictCommerceOperation("carts", "post", "/add-item"),
|
|
104
|
+
updateItem: strictCommerceOperation("carts", "post", "/update-item"),
|
|
105
|
+
removeItem: strictCommerceOperation("carts", "post", "/remove-item"),
|
|
106
|
+
updateDiscountCodes: strictCommerceOperation(
|
|
107
|
+
"carts",
|
|
108
|
+
"post",
|
|
109
|
+
"/update-discount-codes"
|
|
110
|
+
),
|
|
111
|
+
updateAttributes: strictCommerceOperation(
|
|
112
|
+
"carts",
|
|
113
|
+
"post",
|
|
114
|
+
"/update-attributes"
|
|
115
|
+
),
|
|
116
|
+
clear: strictCommerceOperation("carts", "post", "/clear")
|
|
117
|
+
},
|
|
118
|
+
paymentSessions: {
|
|
119
|
+
create: strictCommerceOperation("payment-sessions", "post", "/create"),
|
|
120
|
+
retrieve: strictCommerceOperation("payment-sessions", "post", "/retrieve"),
|
|
121
|
+
cancel: strictCommerceOperation("payment-sessions", "post", "/cancel"),
|
|
122
|
+
server: {
|
|
123
|
+
create: strictCommerceOperation(
|
|
124
|
+
"payment-sessions",
|
|
125
|
+
"post",
|
|
126
|
+
"/server/create"
|
|
127
|
+
),
|
|
128
|
+
retrieve: strictCommerceOperation(
|
|
129
|
+
"payment-sessions",
|
|
130
|
+
"post",
|
|
131
|
+
"/server/retrieve"
|
|
132
|
+
),
|
|
133
|
+
cancel: strictCommerceOperation(
|
|
134
|
+
"payment-sessions",
|
|
135
|
+
"post",
|
|
136
|
+
"/server/cancel"
|
|
137
|
+
),
|
|
138
|
+
confirm: strictCommerceOperation(
|
|
139
|
+
"payment-sessions",
|
|
140
|
+
"post",
|
|
141
|
+
"/server/confirm"
|
|
142
|
+
),
|
|
143
|
+
findPortOne: strictCommerceOperation(
|
|
144
|
+
"payment-sessions",
|
|
145
|
+
"post",
|
|
146
|
+
"/server/portone/find"
|
|
147
|
+
),
|
|
148
|
+
reconcilePortOne: strictCommerceOperation(
|
|
149
|
+
"payment-sessions",
|
|
150
|
+
"post",
|
|
151
|
+
"/server/portone/reconcile"
|
|
152
|
+
)
|
|
153
|
+
},
|
|
154
|
+
custom: {
|
|
155
|
+
create: operation("orders", "post", "/custom-payment-sessions"),
|
|
156
|
+
retrieve: operation(
|
|
157
|
+
"orders",
|
|
158
|
+
"post",
|
|
159
|
+
"/custom-payment-sessions/retrieve"
|
|
160
|
+
),
|
|
161
|
+
confirm: operation("orders", "post", "/custom-payment-sessions/confirm")
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
shippingPolicies: {
|
|
165
|
+
calculate: operation("shipping-policies", "post", "/calculate")
|
|
166
|
+
},
|
|
167
|
+
discounts: {
|
|
168
|
+
validate: operation("discounts", "post", "/validate")
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
var portOneStandardActionCapabilityOperations = /* @__PURE__ */ new Set([
|
|
172
|
+
COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.create,
|
|
173
|
+
COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.retrieve,
|
|
174
|
+
COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.server.create,
|
|
175
|
+
COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.server.retrieve
|
|
176
|
+
]);
|
|
177
|
+
var MEMBERSHIP_ENDPOINT_OPERATIONS = {
|
|
178
|
+
subscribe: operation(null, "post", "/memberships/subscribe"),
|
|
179
|
+
cancel: operation(null, "post", "/memberships/:id/cancel"),
|
|
180
|
+
me: operation(null, "get", "/memberships/me"),
|
|
181
|
+
chargeResult: operation(null, "post", "/memberships/:id/charge-result"),
|
|
182
|
+
refundResult: operation(null, "post", "/memberships/:id/refund-result"),
|
|
183
|
+
revoke: operation(null, "post", "/memberships/:id/revoke")
|
|
184
|
+
};
|
|
185
|
+
var CUSTOMER_GROUP_ENDPOINT_OPERATIONS = {
|
|
186
|
+
members: operation("customer-groups", "get", "/:id/members"),
|
|
187
|
+
grant: operation("customer-groups", "post", "/:id/members/grant"),
|
|
188
|
+
revoke: operation("customer-groups", "post", "/:id/members/revoke")
|
|
189
|
+
};
|
|
190
|
+
var EMBEDDED_ADMIN_ENDPOINT_OPERATIONS = {
|
|
191
|
+
show: operation("tenants", "get", "/embedded-admin-app"),
|
|
192
|
+
configure: operation("tenants", "patch", "/embedded-admin-app"),
|
|
193
|
+
disable: operation("tenants", "delete", "/embedded-admin-app")
|
|
194
|
+
};
|
|
195
|
+
var EVENTS_ENDPOINT_OPERATIONS = {
|
|
196
|
+
events: {
|
|
197
|
+
convertSchedule: operation("events", "post", "/:id/schedule")
|
|
198
|
+
},
|
|
199
|
+
occurrences: {
|
|
200
|
+
range: operation("event-occurrences", "get", "/range"),
|
|
201
|
+
admissionAvailability: operation(
|
|
202
|
+
"event-occurrences",
|
|
203
|
+
"get",
|
|
204
|
+
"/admission-availability"
|
|
205
|
+
)
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
var COMMUNITY_ENDPOINT_OPERATIONS = {
|
|
209
|
+
posts: {
|
|
210
|
+
detail: operation("posts", "get", "/detail")
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
function resolveOperationTemplate(descriptor) {
|
|
214
|
+
return descriptor.collection ? `/api/${descriptor.collection}${descriptor.path}` : `/api${descriptor.path}`;
|
|
215
|
+
}
|
|
216
|
+
function resolveOperationPath(descriptor, options) {
|
|
217
|
+
const path2 = resolveOperationTemplate(descriptor).replace(
|
|
218
|
+
/:([A-Za-z][A-Za-z0-9_]*)/g,
|
|
219
|
+
(_, key) => {
|
|
220
|
+
const value = options?.pathParams?.[key];
|
|
221
|
+
if (value === void 0) {
|
|
222
|
+
throw new TypeError(`Missing path parameter: ${key}`);
|
|
223
|
+
}
|
|
224
|
+
return encodeURIComponent(value);
|
|
225
|
+
}
|
|
226
|
+
);
|
|
227
|
+
const unresolved = path2.match(/:([A-Za-z][A-Za-z0-9_]*)/);
|
|
228
|
+
if (unresolved) {
|
|
229
|
+
throw new TypeError(`Missing path parameter: ${unresolved[1]}`);
|
|
230
|
+
}
|
|
231
|
+
const query = options?.query?.toString().replace(/^\?/, "");
|
|
232
|
+
return query ? `${path2}?${query}` : path2;
|
|
233
|
+
}
|
|
234
|
+
function resolveOperationMethod(descriptor) {
|
|
235
|
+
return descriptor.method.toUpperCase();
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// src/lib/embedded-admin-management.ts
|
|
239
|
+
import {
|
|
240
|
+
normalizeEmbeddedAdminBindingConfiguration
|
|
241
|
+
} from "@01.software/sdk/embedded-admin";
|
|
242
|
+
var REQUEST_TIMEOUT_MS = 3e4;
|
|
243
|
+
var EmbeddedAdminManagementError = class extends Error {
|
|
244
|
+
constructor(message, status, options = {}) {
|
|
245
|
+
super(message);
|
|
246
|
+
this.name = "EmbeddedAdminManagementError";
|
|
247
|
+
this.status = status;
|
|
248
|
+
this.reason = options.reason;
|
|
249
|
+
this.requestId = options.requestId;
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
function resolveApiUrl(explicit) {
|
|
253
|
+
const buildDefault = true ? "https://api.01.software" : "https://api.01.software";
|
|
254
|
+
return (explicit ?? process.env.SOFTWARE_API_URL ?? process.env.NEXT_PUBLIC_SOFTWARE_API_URL ?? buildDefault).replace(/\/$/, "");
|
|
255
|
+
}
|
|
256
|
+
function inferConsoleOrigin(apiUrl) {
|
|
257
|
+
const url = new URL(apiUrl);
|
|
258
|
+
if (url.hostname === "api.01.software") {
|
|
259
|
+
return {
|
|
260
|
+
allowLoopbackConsoleHttp: false,
|
|
261
|
+
consoleOrigin: "https://console.01.software"
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
if (url.hostname === "api.stg.01.software") {
|
|
265
|
+
return {
|
|
266
|
+
allowLoopbackConsoleHttp: false,
|
|
267
|
+
consoleOrigin: "https://console.stg.01.software"
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
const loopback = url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "[::1]";
|
|
271
|
+
return {
|
|
272
|
+
allowLoopbackConsoleHttp: loopback && url.protocol === "http:",
|
|
273
|
+
...loopback ? { consoleOrigin: url.origin } : {}
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
function parseBindingState(value) {
|
|
277
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
278
|
+
throw new Error("Embedded admin binding response is invalid.");
|
|
279
|
+
}
|
|
280
|
+
const input = value;
|
|
281
|
+
if (typeof input.tenantId !== "string" || input.tenantId.length === 0 || typeof input.tenantName !== "string" || input.status !== "unconfigured" && input.status !== "disabled" && input.status !== "enabled" && input.status !== "invalid") {
|
|
282
|
+
throw new Error("Embedded admin binding response is invalid.");
|
|
283
|
+
}
|
|
284
|
+
if (input.status === "unconfigured" || input.status === "invalid") {
|
|
285
|
+
if (input.binding !== null) {
|
|
286
|
+
throw new Error("Embedded admin binding response is invalid.");
|
|
287
|
+
}
|
|
288
|
+
return {
|
|
289
|
+
binding: null,
|
|
290
|
+
status: input.status,
|
|
291
|
+
tenantId: input.tenantId,
|
|
292
|
+
tenantName: input.tenantName
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
const binding = normalizeEmbeddedAdminBindingConfiguration(input.binding);
|
|
296
|
+
if (binding.enabled !== (input.status === "enabled")) {
|
|
297
|
+
throw new Error("Embedded admin binding response is invalid.");
|
|
298
|
+
}
|
|
299
|
+
return {
|
|
300
|
+
binding,
|
|
301
|
+
status: input.status,
|
|
302
|
+
tenantId: input.tenantId,
|
|
303
|
+
tenantName: input.tenantName
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
var EmbeddedAdminManagementClient = class {
|
|
307
|
+
constructor(options) {
|
|
308
|
+
this.apiUrl = resolveApiUrl(options.apiUrl);
|
|
309
|
+
this.fetchImplementation = options.fetch ?? globalThis.fetch;
|
|
310
|
+
this.publishableKey = options.publishableKey;
|
|
311
|
+
this.secretKey = options.secretKey;
|
|
312
|
+
}
|
|
313
|
+
validateConfiguration(input) {
|
|
314
|
+
this.validateManagementAccess();
|
|
315
|
+
const console2 = inferConsoleOrigin(this.apiUrl);
|
|
316
|
+
return normalizeEmbeddedAdminBindingConfiguration(
|
|
317
|
+
{ ...input, enabled: true, path: input.path ?? "/" },
|
|
318
|
+
console2
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
show() {
|
|
322
|
+
this.validateManagementAccess();
|
|
323
|
+
return this.request(EMBEDDED_ADMIN_ENDPOINT_OPERATIONS.show);
|
|
324
|
+
}
|
|
325
|
+
configure(input) {
|
|
326
|
+
const binding = this.validateConfiguration(input);
|
|
327
|
+
return this.request(EMBEDDED_ADMIN_ENDPOINT_OPERATIONS.configure, {
|
|
328
|
+
label: binding.label,
|
|
329
|
+
origin: binding.origin,
|
|
330
|
+
path: binding.path
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
disable() {
|
|
334
|
+
this.validateManagementAccess();
|
|
335
|
+
return this.request(EMBEDDED_ADMIN_ENDPOINT_OPERATIONS.disable);
|
|
336
|
+
}
|
|
337
|
+
validateManagementAccess() {
|
|
338
|
+
if (!this.secretKey.startsWith("pat01_")) {
|
|
339
|
+
const error = new Error(
|
|
340
|
+
"Embedded admin binding management requires a user PAT (pat01_...)."
|
|
341
|
+
);
|
|
342
|
+
error.name = "ConfigError";
|
|
343
|
+
throw error;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
async request(operation2, body) {
|
|
347
|
+
const controller = new AbortController();
|
|
348
|
+
const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
349
|
+
let response;
|
|
350
|
+
try {
|
|
351
|
+
response = await this.fetchImplementation(
|
|
352
|
+
new URL(resolveOperationPath(operation2), `${this.apiUrl}/`),
|
|
353
|
+
{
|
|
354
|
+
method: resolveOperationMethod(operation2),
|
|
355
|
+
headers: {
|
|
356
|
+
Accept: "application/json",
|
|
357
|
+
Authorization: `Bearer ${this.secretKey}`,
|
|
358
|
+
"Content-Type": "application/json",
|
|
359
|
+
"X-Publishable-Key": this.publishableKey
|
|
360
|
+
},
|
|
361
|
+
...body === void 0 ? {} : { body: JSON.stringify(body) },
|
|
362
|
+
signal: controller.signal
|
|
363
|
+
}
|
|
364
|
+
);
|
|
365
|
+
} catch (cause) {
|
|
366
|
+
const error = new Error(
|
|
367
|
+
"Embedded admin binding request failed."
|
|
368
|
+
);
|
|
369
|
+
error.cause = cause;
|
|
370
|
+
error.name = "NetworkError";
|
|
371
|
+
throw error;
|
|
372
|
+
} finally {
|
|
373
|
+
clearTimeout(timer);
|
|
374
|
+
}
|
|
375
|
+
let payload;
|
|
376
|
+
try {
|
|
377
|
+
payload = await response.json();
|
|
378
|
+
} catch {
|
|
379
|
+
payload = null;
|
|
380
|
+
}
|
|
381
|
+
if (!response.ok) {
|
|
382
|
+
const record = payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
|
|
383
|
+
throw new EmbeddedAdminManagementError(
|
|
384
|
+
typeof record.error === "string" ? record.error : `Embedded admin binding request failed (${response.status}).`,
|
|
385
|
+
response.status,
|
|
386
|
+
{
|
|
387
|
+
...typeof record.reason === "string" ? { reason: record.reason } : {},
|
|
388
|
+
...response.headers.get("x-request-id") ? { requestId: response.headers.get("x-request-id") } : {}
|
|
389
|
+
}
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
return parseBindingState(payload);
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
|
|
14
396
|
// src/lib/credentials.ts
|
|
15
397
|
import {
|
|
16
398
|
chmodSync,
|
|
@@ -573,7 +955,10 @@ function adminErrorExitCode(err) {
|
|
|
573
955
|
}
|
|
574
956
|
|
|
575
957
|
// src/lib/i18n.ts
|
|
576
|
-
|
|
958
|
+
function withDoctorActionTranslations(translations) {
|
|
959
|
+
return translations;
|
|
960
|
+
}
|
|
961
|
+
var CLI_I18N_KO = withDoctorActionTranslations({
|
|
577
962
|
// CLI-surface microcopy
|
|
578
963
|
AuthenticationRequired: "\uC778\uC99D\uC774 \uD544\uC694\uD569\uB2C8\uB2E4",
|
|
579
964
|
RunLoginToAuthenticate: "`01 login` \uBA85\uB839\uC73C\uB85C \uBE0C\uB77C\uC6B0\uC800 \uC778\uC99D\uC744 \uC9C4\uD589\uD558\uAC70\uB098,",
|
|
@@ -587,6 +972,26 @@ var CLI_I18N_KO = {
|
|
|
587
972
|
Empty: "(\uC5C6\uC74C)",
|
|
588
973
|
Total: "\uCD1D {{n}}\uAC1C",
|
|
589
974
|
PageOf: "{{page}} / {{total}} \uD398\uC774\uC9C0",
|
|
975
|
+
// Redacted app-integration doctor remediation keys. These are stable
|
|
976
|
+
// machine references; the human CLI renders this locale-specific copy.
|
|
977
|
+
DoctorProjectPackageJsonReady: "package.json\uC744 \uC77D\uC744 \uC218 \uC788\uC2B5\uB2C8\uB2E4.",
|
|
978
|
+
DoctorProjectPackageJsonBlocked: "package.json\uC774 \uC788\uB294 \uC571 \uB514\uB809\uD130\uB9AC\uC5D0\uC11C \uC2E4\uD589\uD558\uC138\uC694.",
|
|
979
|
+
DoctorNodeEngineReady: "\uD604\uC7AC Node.js\uAC00 \uC120\uC5B8\uB41C engine\uC744 \uCDA9\uC871\uD569\uB2C8\uB2E4.",
|
|
980
|
+
DoctorNodeEngineAttention: "package.json\uC758 Node.js engine\uACFC \uD604\uC7AC \uBC84\uC804\uC744 \uD655\uC778\uD558\uC138\uC694.",
|
|
981
|
+
DoctorNodeEngineNotDeclared: "package.json\uC5D0 \uC9C0\uC6D0\uD558\uB294 Node.js engine \uBC94\uC704\uB97C \uC120\uC5B8\uD558\uC138\uC694.",
|
|
982
|
+
DoctorSdkDeclarationReady: "@01.software/sdk\uAC00 package.json\uC5D0 \uC120\uC5B8\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4.",
|
|
983
|
+
DoctorSdkDeclarationBlocked: "package.json\uC5D0 @01.software/sdk\uB97C \uCD94\uAC00\uD558\uC138\uC694.",
|
|
984
|
+
DoctorSdkInstallationReady: "@01.software/sdk\uC758 server export\uB97C \uD655\uC778\uD588\uC2B5\uB2C8\uB2E4.",
|
|
985
|
+
DoctorSdkInstallationAttention: "\uC571\uC744 \uC2E4\uD589\uD558\uAE30 \uC804\uC5D0 \uC120\uC5B8\uB41C \uC758\uC874\uC131\uC744 \uC124\uCE58\uD558\uC138\uC694.",
|
|
986
|
+
DoctorEnvCredentialsReady: "\uC571 \uC790\uACA9\uC99D\uBA85 \uD615\uC2DD\uACFC API \uB300\uC0C1\uC774 \uC62C\uBC14\uB985\uB2C8\uB2E4.",
|
|
987
|
+
DoctorEnvCredentialsBlocked: "\uD558\uB098\uC758 pk01_/sk01_ \uC571 \uC30D\uC744 \uC0AC\uC6A9\uD558\uACE0 \uACF5\uAC1C \uD658\uACBD \uBCC0\uC218\uB098 PAT\uC5D0 secret\uC744 \uB123\uC9C0 \uB9C8\uC138\uC694.",
|
|
988
|
+
DoctorEnvFileInvalid: "\uC77C\uBC18 \uD30C\uC77C\uC778 \uC571 \uD658\uACBD \uD30C\uC77C\uC744 \uC9C0\uC815\uD558\uACE0 symlink\xB7\uD2B9\uC218 \uD30C\uC77C\uC744 \uC81C\uAC70\uD558\uC138\uC694.",
|
|
989
|
+
DoctorOriginInputInvalid: "\uC808\uB300 http(s) origin URL\uC744 \uC9C0\uC815\uD558\uC138\uC694.",
|
|
990
|
+
DoctorTenantContextReady: "\uC571 \uC790\uACA9\uC99D\uBA85\uC73C\uB85C \uD14C\uB10C\uD2B8 \uCEE8\uD14D\uC2A4\uD2B8\uC5D0 \uC5F0\uACB0\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.",
|
|
991
|
+
DoctorTenantContextBlocked: "\uC571 \uC790\uACA9\uC99D\uBA85, \uD14C\uB10C\uD2B8 \uC811\uADFC \uAD8C\uD55C \uBC0F API \uC5F0\uACB0\uC744 \uD655\uC778\uD558\uC138\uC694.",
|
|
992
|
+
DoctorOriginCorsReady: "API CORS \uC815\uCC45\uC5D0\uC11C origin\uC774 \uD5C8\uC6A9\uB429\uB2C8\uB2E4.",
|
|
993
|
+
DoctorOriginCorsBlocked: "\uC774 origin\uC744 \uD14C\uB10C\uD2B8 CORS \uC815\uCC45\uC5D0 \uCD94\uAC00\uD558\uC138\uC694.",
|
|
994
|
+
DoctorOriginCorsAttention: "API URL \uBC0F CORS \uC815\uCC45\uC744 \uD655\uC778\uD558\uC138\uC694.",
|
|
590
995
|
// AdminError code translations (mirrors apps/console admin.ts).
|
|
591
996
|
tenant_mismatch: "\uAD8C\uD55C\uC774 \uC5C6\uB294 \uD14C\uB10C\uD2B8",
|
|
592
997
|
account_suspended: "\uACC4\uC815\uC774 \uC815\uC9C0\uB418\uC5C8\uC2B5\uB2C8\uB2E4",
|
|
@@ -597,7 +1002,7 @@ var CLI_I18N_KO = {
|
|
|
597
1002
|
publishable_key_mismatch: "\uACF5\uAC1C \uD0A4\uAC00 \uC77C\uCE58\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4",
|
|
598
1003
|
scope_denied: "\uBC94\uC704 \uAD8C\uD55C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4",
|
|
599
1004
|
redis_unavailable: "\uCE90\uC2DC\uAC00 \uC77C\uC2DC\uC801\uC73C\uB85C \uC0AC\uC6A9 \uBD88\uAC00\uD569\uB2C8\uB2E4",
|
|
600
|
-
provider_unavailable: "\uC678\uBD80 \uACF5\
|
|
1005
|
+
provider_unavailable: "\uC678\uBD80 \uC81C\uACF5\uC790\uAC00 \uC751\uB2F5\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4",
|
|
601
1006
|
rate_limited: "\uC694\uCCAD\uC774 \uB108\uBB34 \uB9CE\uC2B5\uB2C8\uB2E4 \u2014 \uC7A0\uC2DC \uD6C4 \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC138\uC694",
|
|
602
1007
|
upstream_timeout: "\uC751\uB2F5 \uC2DC\uAC04\uC774 \uCD08\uACFC\uB418\uC5C8\uC2B5\uB2C8\uB2E4",
|
|
603
1008
|
upstream_5xx: "\uC678\uBD80 \uC11C\uBE44\uC2A4 \uC624\uB958",
|
|
@@ -605,7 +1010,7 @@ var CLI_I18N_KO = {
|
|
|
605
1010
|
not_found: "\uB9AC\uC18C\uC2A4\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4",
|
|
606
1011
|
invalid_argument: "\uC778\uC790\uAC00 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4",
|
|
607
1012
|
unknown: "\uC54C \uC218 \uC5C6\uB294 \uC624\uB958"
|
|
608
|
-
};
|
|
1013
|
+
});
|
|
609
1014
|
var CLI_I18N_EN = {
|
|
610
1015
|
AuthenticationRequired: "Authentication required",
|
|
611
1016
|
RunLoginToAuthenticate: "Run `01 login` to authenticate via browser, or",
|
|
@@ -619,6 +1024,24 @@ var CLI_I18N_EN = {
|
|
|
619
1024
|
Empty: "(empty)",
|
|
620
1025
|
Total: "{{n}} total",
|
|
621
1026
|
PageOf: "page {{page}}/{{total}}",
|
|
1027
|
+
DoctorProjectPackageJsonReady: "package.json is readable.",
|
|
1028
|
+
DoctorProjectPackageJsonBlocked: "Run this command in an app directory with package.json.",
|
|
1029
|
+
DoctorNodeEngineReady: "Current Node.js satisfies the declared engine.",
|
|
1030
|
+
DoctorNodeEngineAttention: "Check the package.json Node.js engine and current version.",
|
|
1031
|
+
DoctorNodeEngineNotDeclared: "Declare a supported Node.js engine range in package.json.",
|
|
1032
|
+
DoctorSdkDeclarationReady: "@01.software/sdk is declared in package.json.",
|
|
1033
|
+
DoctorSdkDeclarationBlocked: "Add @01.software/sdk to package.json.",
|
|
1034
|
+
DoctorSdkInstallationReady: "@01.software/sdk server export is installed and resolvable.",
|
|
1035
|
+
DoctorSdkInstallationAttention: "Install declared dependencies before running the app.",
|
|
1036
|
+
DoctorEnvCredentialsReady: "App credentials and the API target are structurally valid.",
|
|
1037
|
+
DoctorEnvCredentialsBlocked: "Use one pk01_/sk01_ app pair; never put a secret in a public env variable or use a PAT.",
|
|
1038
|
+
DoctorEnvFileInvalid: "Use a regular app env file and remove symlinks or special files.",
|
|
1039
|
+
DoctorOriginInputInvalid: "Use an absolute http(s) origin URL.",
|
|
1040
|
+
DoctorTenantContextReady: "Tenant context is reachable with the app credential pair.",
|
|
1041
|
+
DoctorTenantContextBlocked: "Check app credentials, tenant access, and API reachability.",
|
|
1042
|
+
DoctorOriginCorsReady: "Origin is allowed by the API CORS policy.",
|
|
1043
|
+
DoctorOriginCorsBlocked: "Add this origin to the tenant CORS policy.",
|
|
1044
|
+
DoctorOriginCorsAttention: "Check the API URL and CORS policy.",
|
|
622
1045
|
tenant_mismatch: "Tenant access denied",
|
|
623
1046
|
account_suspended: "Your account has been suspended",
|
|
624
1047
|
feature_disabled: "This feature is disabled",
|
|
@@ -749,7 +1172,7 @@ function printError(error, options = {}) {
|
|
|
749
1172
|
const rawMessage = rawErr && typeof rawErr.message === "string" ? rawErr.message : "";
|
|
750
1173
|
const stringErr = typeof error === "string" ? error : "";
|
|
751
1174
|
const detailMessage = rawErr && rawErr.detail && typeof rawErr.detail === "object" && typeof rawErr.detail.message === "string" ? String(rawErr.detail.message) : "";
|
|
752
|
-
const headline = rawMessage || stringErr || detailMessage || localized || adminError.code;
|
|
1175
|
+
const headline = (options.headlineKey ? t(options.headlineKey) : null) || rawMessage || stringErr || detailMessage || localized || adminError.code;
|
|
753
1176
|
console.error(pc.red(`Error: ${headline}`));
|
|
754
1177
|
if (rawErr && typeof rawErr.code === "string" && rawErr.code !== adminError.code) {
|
|
755
1178
|
console.error(pc.dim(`Code: ${rawErr.code}`));
|
|
@@ -830,6 +1253,7 @@ function resolveClientOrThrow(apiKeyFlag) {
|
|
|
830
1253
|
),
|
|
831
1254
|
commerce: new ServerCommerceClient(serverOptions),
|
|
832
1255
|
tenant: new TenantIntrospectionApi(serverOptions),
|
|
1256
|
+
embeddedAdmin: new EmbeddedAdminManagementClient(serverOptions),
|
|
833
1257
|
publishableKey,
|
|
834
1258
|
secretKey
|
|
835
1259
|
};
|
|
@@ -929,15 +1353,15 @@ function readFileAsBlob(filePath) {
|
|
|
929
1353
|
const buffer = readFileSync2(filePath);
|
|
930
1354
|
return { blob: new Blob([buffer]), filename: basename(filePath) };
|
|
931
1355
|
}
|
|
932
|
-
function registerCrudCommands(
|
|
933
|
-
|
|
1356
|
+
function registerCrudCommands(program, getClient, getFormat) {
|
|
1357
|
+
program.command("query <collection>").description("Query documents from a collection").option("--where <json>", "Filter conditions (JSON)").option("--limit <n>", "Max results", (v) => parseInt(v, 10)).option("--page <n>", "Page number", (v) => parseInt(v, 10)).option("--sort <field>", "Sort field (prefix with - for descending)").option(
|
|
934
1358
|
"--depth <n>",
|
|
935
1359
|
"Relationship depth (0 = no population)",
|
|
936
1360
|
(v) => parseInt(v, 10)
|
|
937
1361
|
).option("--select <fields>", "Comma-separated fields to select").action(async (collection, opts) => {
|
|
938
1362
|
try {
|
|
939
1363
|
const col = validateCollection(collection);
|
|
940
|
-
const client =
|
|
1364
|
+
const client = getClient();
|
|
941
1365
|
const options = {};
|
|
942
1366
|
if (opts.where) options.where = parseJson(opts.where, "where");
|
|
943
1367
|
if (opts.limit) options.limit = opts.limit;
|
|
@@ -946,29 +1370,29 @@ function registerCrudCommands(program2, getClient2, getFormat2) {
|
|
|
946
1370
|
if (opts.depth != null) options.depth = opts.depth;
|
|
947
1371
|
if (opts.select) options.select = parseSelect(opts.select);
|
|
948
1372
|
const result = await client.collections.from(col).find(options);
|
|
949
|
-
printResult(result,
|
|
1373
|
+
printResult(result, getFormat());
|
|
950
1374
|
} catch (e) {
|
|
951
1375
|
exitWithError(e);
|
|
952
1376
|
}
|
|
953
1377
|
});
|
|
954
|
-
|
|
1378
|
+
program.command("get <collection> <id>").description("Get a document by ID").option(
|
|
955
1379
|
"--depth <n>",
|
|
956
1380
|
"Relationship depth (0 = no population)",
|
|
957
1381
|
(v) => parseInt(v, 10)
|
|
958
1382
|
).option("--select <fields>", "Comma-separated fields to select").action(async (collection, id, opts) => {
|
|
959
1383
|
try {
|
|
960
1384
|
const col = validateCollection(collection);
|
|
961
|
-
const client =
|
|
1385
|
+
const client = getClient();
|
|
962
1386
|
const options = {};
|
|
963
1387
|
if (opts.depth != null) options.depth = opts.depth;
|
|
964
1388
|
if (opts.select) options.select = parseSelect(opts.select);
|
|
965
1389
|
const result = await client.collections.from(col).findById(id, options);
|
|
966
|
-
printResult(result,
|
|
1390
|
+
printResult(result, getFormat());
|
|
967
1391
|
} catch (e) {
|
|
968
1392
|
exitWithError(e);
|
|
969
1393
|
}
|
|
970
1394
|
});
|
|
971
|
-
|
|
1395
|
+
program.command("create <collection>").description("Create a new document").requiredOption("--data <json>", "Document data (JSON)").option("--file <path>", "File to upload (for upload collections)").option("--dry-run", "Validate inputs without executing").action(async (collection, opts) => {
|
|
972
1396
|
try {
|
|
973
1397
|
const col = validateCollection(collection);
|
|
974
1398
|
const data = parseJson(opts.data, "data");
|
|
@@ -981,23 +1405,23 @@ function registerCrudCommands(program2, getClient2, getFormat2) {
|
|
|
981
1405
|
collection: col,
|
|
982
1406
|
data
|
|
983
1407
|
},
|
|
984
|
-
|
|
1408
|
+
getFormat()
|
|
985
1409
|
);
|
|
986
1410
|
return;
|
|
987
1411
|
}
|
|
988
|
-
const client =
|
|
1412
|
+
const client = getClient();
|
|
989
1413
|
let fileOpts;
|
|
990
1414
|
if (opts.file) {
|
|
991
1415
|
const { blob, filename } = readFileAsBlob(opts.file);
|
|
992
1416
|
fileOpts = { file: blob, filename };
|
|
993
1417
|
}
|
|
994
1418
|
const result = await client.collections.from(col).create(data, fileOpts);
|
|
995
|
-
printResult(result,
|
|
1419
|
+
printResult(result, getFormat());
|
|
996
1420
|
} catch (e) {
|
|
997
1421
|
exitWithError(e);
|
|
998
1422
|
}
|
|
999
1423
|
});
|
|
1000
|
-
|
|
1424
|
+
program.command("update <collection> <id>").description("Update a document by ID").requiredOption("--data <json>", "Document data (JSON)").option("--file <path>", "File to upload (for upload collections)").option("--dry-run", "Validate inputs without executing").action(async (collection, id, opts) => {
|
|
1001
1425
|
try {
|
|
1002
1426
|
const col = validateCollection(collection);
|
|
1003
1427
|
const data = parseJson(opts.data, "data");
|
|
@@ -1011,23 +1435,23 @@ function registerCrudCommands(program2, getClient2, getFormat2) {
|
|
|
1011
1435
|
id,
|
|
1012
1436
|
data
|
|
1013
1437
|
},
|
|
1014
|
-
|
|
1438
|
+
getFormat()
|
|
1015
1439
|
);
|
|
1016
1440
|
return;
|
|
1017
1441
|
}
|
|
1018
|
-
const client =
|
|
1442
|
+
const client = getClient();
|
|
1019
1443
|
let fileOpts;
|
|
1020
1444
|
if (opts.file) {
|
|
1021
1445
|
const { blob, filename } = readFileAsBlob(opts.file);
|
|
1022
1446
|
fileOpts = { file: blob, filename };
|
|
1023
1447
|
}
|
|
1024
1448
|
const result = await client.collections.from(col).update(id, data, fileOpts);
|
|
1025
|
-
printResult(result,
|
|
1449
|
+
printResult(result, getFormat());
|
|
1026
1450
|
} catch (e) {
|
|
1027
1451
|
exitWithError(e);
|
|
1028
1452
|
}
|
|
1029
1453
|
});
|
|
1030
|
-
|
|
1454
|
+
program.command("delete <collection> <id>").description("Delete a document by ID").option("--dry-run", "Validate inputs without executing").action(async (collection, id, opts) => {
|
|
1031
1455
|
try {
|
|
1032
1456
|
const col = validateCollection(collection);
|
|
1033
1457
|
if (opts.dryRun) {
|
|
@@ -1039,18 +1463,18 @@ function registerCrudCommands(program2, getClient2, getFormat2) {
|
|
|
1039
1463
|
collection: col,
|
|
1040
1464
|
id
|
|
1041
1465
|
},
|
|
1042
|
-
|
|
1466
|
+
getFormat()
|
|
1043
1467
|
);
|
|
1044
1468
|
return;
|
|
1045
1469
|
}
|
|
1046
|
-
const client =
|
|
1470
|
+
const client = getClient();
|
|
1047
1471
|
const result = await client.collections.from(col).remove(id);
|
|
1048
|
-
printResult(result,
|
|
1472
|
+
printResult(result, getFormat());
|
|
1049
1473
|
} catch (e) {
|
|
1050
1474
|
exitWithError(e);
|
|
1051
1475
|
}
|
|
1052
1476
|
});
|
|
1053
|
-
|
|
1477
|
+
program.command("update-many <collection>").description("Update multiple documents matching a filter").requiredOption("--where <json>", "Filter conditions (JSON)").requiredOption("--data <json>", "Update data (JSON)").option("--dry-run", "Validate inputs without executing").action(async (collection, opts) => {
|
|
1054
1478
|
try {
|
|
1055
1479
|
const col = validateCollection(collection);
|
|
1056
1480
|
const where = parseJson(opts.where, "where");
|
|
@@ -1065,18 +1489,18 @@ function registerCrudCommands(program2, getClient2, getFormat2) {
|
|
|
1065
1489
|
where,
|
|
1066
1490
|
data
|
|
1067
1491
|
},
|
|
1068
|
-
|
|
1492
|
+
getFormat()
|
|
1069
1493
|
);
|
|
1070
1494
|
return;
|
|
1071
1495
|
}
|
|
1072
|
-
const client =
|
|
1496
|
+
const client = getClient();
|
|
1073
1497
|
const result = await client.collections.from(col).updateMany(where, data);
|
|
1074
|
-
printResult(result,
|
|
1498
|
+
printResult(result, getFormat());
|
|
1075
1499
|
} catch (e) {
|
|
1076
1500
|
exitWithError(e);
|
|
1077
1501
|
}
|
|
1078
1502
|
});
|
|
1079
|
-
|
|
1503
|
+
program.command("delete-many <collection>").description("Delete multiple documents matching a filter").requiredOption("--where <json>", "Filter conditions (JSON)").option("--dry-run", "Validate inputs without executing").action(async (collection, opts) => {
|
|
1080
1504
|
try {
|
|
1081
1505
|
const col = validateCollection(collection);
|
|
1082
1506
|
const where = parseJson(opts.where, "where");
|
|
@@ -1089,13 +1513,13 @@ function registerCrudCommands(program2, getClient2, getFormat2) {
|
|
|
1089
1513
|
collection: col,
|
|
1090
1514
|
where
|
|
1091
1515
|
},
|
|
1092
|
-
|
|
1516
|
+
getFormat()
|
|
1093
1517
|
);
|
|
1094
1518
|
return;
|
|
1095
1519
|
}
|
|
1096
|
-
const client =
|
|
1520
|
+
const client = getClient();
|
|
1097
1521
|
const result = await client.collections.from(col).removeMany(where);
|
|
1098
|
-
printResult(result,
|
|
1522
|
+
printResult(result, getFormat());
|
|
1099
1523
|
} catch (e) {
|
|
1100
1524
|
exitWithError(e);
|
|
1101
1525
|
}
|
|
@@ -1868,6 +2292,9 @@ var updateCartAttributesParamsSchema = updateCartAttributesBodySchema.extend({
|
|
|
1868
2292
|
// ../../internal/contracts/src/ecommerce/checkout.ts
|
|
1869
2293
|
import { z as z6 } from "zod";
|
|
1870
2294
|
|
|
2295
|
+
// ../../internal/contracts/src/ecommerce/managed-payment-provider.ts
|
|
2296
|
+
var CHECKOUT_PAYMENT_SESSION_PROVIDERS = ["toss", "portone"];
|
|
2297
|
+
|
|
1871
2298
|
// ../../internal/contracts/src/ecommerce/payment-session.ts
|
|
1872
2299
|
import { z as z5 } from "zod";
|
|
1873
2300
|
var tossProviderOrderIdSchema = z5.string().min(6).max(64).regex(
|
|
@@ -1943,20 +2370,29 @@ var createPortOnePaymentSessionBodySchema = z5.object({
|
|
|
1943
2370
|
portOneStandardProviderOptionsSchema
|
|
1944
2371
|
])
|
|
1945
2372
|
}).strict();
|
|
1946
|
-
var
|
|
1947
|
-
createTossPaymentSessionBodySchema,
|
|
1948
|
-
createPortOnePaymentSessionBodySchema
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
2373
|
+
var createPaymentSessionBodySchemasByProvider = {
|
|
2374
|
+
toss: createTossPaymentSessionBodySchema,
|
|
2375
|
+
portone: createPortOnePaymentSessionBodySchema
|
|
2376
|
+
};
|
|
2377
|
+
function providerDiscriminatedUnion(schemas) {
|
|
2378
|
+
const variants = CHECKOUT_PAYMENT_SESSION_PROVIDERS.map(
|
|
2379
|
+
(provider) => schemas[provider]
|
|
2380
|
+
);
|
|
2381
|
+
return z5.discriminatedUnion("provider", variants);
|
|
2382
|
+
}
|
|
2383
|
+
var createPaymentSessionBodySchema = providerDiscriminatedUnion(
|
|
2384
|
+
createPaymentSessionBodySchemasByProvider
|
|
2385
|
+
);
|
|
2386
|
+
var createPaymentSessionParamsSchemasByProvider = {
|
|
2387
|
+
toss: createTossPaymentSessionBodySchema.extend({
|
|
2388
|
+
idempotencyKey: commerceIdempotencyKeySchema
|
|
2389
|
+
}),
|
|
2390
|
+
portone: createPortOnePaymentSessionBodySchema.extend({
|
|
2391
|
+
idempotencyKey: commerceIdempotencyKeySchema
|
|
2392
|
+
})
|
|
2393
|
+
};
|
|
2394
|
+
var createPaymentSessionParamsSchema = providerDiscriminatedUnion(
|
|
2395
|
+
createPaymentSessionParamsSchemasByProvider
|
|
1960
2396
|
);
|
|
1961
2397
|
var retrieveBrowserPaymentSessionParamsSchema = z5.object({
|
|
1962
2398
|
paymentSessionId: commerceResourceIdSchema,
|
|
@@ -1991,6 +2427,17 @@ var confirmTossPaymentSessionBodySchema = z5.object({
|
|
|
1991
2427
|
var confirmTossPaymentSessionParamsSchema = confirmTossPaymentSessionBodySchema.extend({
|
|
1992
2428
|
idempotencyKey: commerceIdempotencyKeySchema
|
|
1993
2429
|
});
|
|
2430
|
+
var portOneProviderIdentitySchema = z5.string().min(1).max(512).refine((value) => /\S/u.test(value), "Provider identity must not be blank");
|
|
2431
|
+
var portOnePaymentSelectorSchema = z5.object({
|
|
2432
|
+
provider: z5.literal("portone"),
|
|
2433
|
+
providerAccountKey: portOneProviderIdentitySchema,
|
|
2434
|
+
environment: z5.enum(["test", "live"]),
|
|
2435
|
+
providerPaymentId: portOneProviderIdentitySchema
|
|
2436
|
+
}).strict();
|
|
2437
|
+
var reconcilePortOnePaymentBodySchema = portOnePaymentSelectorSchema;
|
|
2438
|
+
var reconcilePortOnePaymentParamsSchema = reconcilePortOnePaymentBodySchema.extend({
|
|
2439
|
+
idempotencyKey: commerceIdempotencyKeySchema
|
|
2440
|
+
});
|
|
1994
2441
|
var PAYMENT_PROVIDER_STATUSES = [
|
|
1995
2442
|
"requires_payment_method",
|
|
1996
2443
|
"requires_action",
|
|
@@ -2059,6 +2506,15 @@ var confirmCustomPaymentSessionResponseSchema = z5.object({
|
|
|
2059
2506
|
status: z5.literal("paid"),
|
|
2060
2507
|
alreadyConfirmed: z5.boolean().optional()
|
|
2061
2508
|
}).strict();
|
|
2509
|
+
var PORTONE_RECONCILIATION_DISPOSITIONS = [
|
|
2510
|
+
"applied",
|
|
2511
|
+
"observed",
|
|
2512
|
+
"recovered_after_ambiguous_result",
|
|
2513
|
+
"requires_attention"
|
|
2514
|
+
];
|
|
2515
|
+
var portOneReconciliationDispositionSchema = z5.enum(
|
|
2516
|
+
PORTONE_RECONCILIATION_DISPOSITIONS
|
|
2517
|
+
);
|
|
2062
2518
|
var tossPaymentNextActionSchema = z5.object({
|
|
2063
2519
|
type: z5.literal("toss_widget"),
|
|
2064
2520
|
clientKey: z5.string().min(1).max(255),
|
|
@@ -2077,7 +2533,8 @@ var portOnePaymentNextActionSchema = z5.object({
|
|
|
2077
2533
|
return url.username === "" && url.password === "";
|
|
2078
2534
|
}, "checkoutUrl must not contain embedded credentials")
|
|
2079
2535
|
}).strict();
|
|
2080
|
-
var
|
|
2536
|
+
var PORTONE_STANDARD_ACTION_RETRY_POLICY = "same_action_only";
|
|
2537
|
+
var portOneSdkPaymentRequestSchema = z5.object({
|
|
2081
2538
|
type: z5.literal("portone_sdk"),
|
|
2082
2539
|
version: z5.literal("v2"),
|
|
2083
2540
|
storeId: z5.string().min(1).max(255),
|
|
@@ -2093,7 +2550,21 @@ var portOneSdkPaymentNextActionSchema = z5.object({
|
|
|
2093
2550
|
return (url.protocol === "https:" || loopback) && !url.username && !url.password;
|
|
2094
2551
|
}, "redirectUrl must be HTTPS (or development loopback) without embedded credentials")
|
|
2095
2552
|
}).strict();
|
|
2096
|
-
var
|
|
2553
|
+
var portOneSdkPaymentCapabilityNextActionSchema = portOneSdkPaymentRequestSchema.extend({
|
|
2554
|
+
cancelable: z5.literal(false),
|
|
2555
|
+
retryPolicy: z5.literal(PORTONE_STANDARD_ACTION_RETRY_POLICY)
|
|
2556
|
+
}).strict();
|
|
2557
|
+
var portOneSdkPaymentNextActionSchema = z5.union([
|
|
2558
|
+
portOneSdkPaymentCapabilityNextActionSchema,
|
|
2559
|
+
portOneSdkPaymentRequestSchema
|
|
2560
|
+
]).transform(
|
|
2561
|
+
(action) => "cancelable" in action ? action : {
|
|
2562
|
+
...action,
|
|
2563
|
+
cancelable: false,
|
|
2564
|
+
retryPolicy: PORTONE_STANDARD_ACTION_RETRY_POLICY
|
|
2565
|
+
}
|
|
2566
|
+
);
|
|
2567
|
+
var paymentNextActionSchema = z5.union([
|
|
2097
2568
|
tossPaymentNextActionSchema,
|
|
2098
2569
|
portOnePaymentNextActionSchema,
|
|
2099
2570
|
portOneSdkPaymentNextActionSchema
|
|
@@ -2304,17 +2775,61 @@ function providerSessionSchemas(provider, action) {
|
|
|
2304
2775
|
}).strict()
|
|
2305
2776
|
);
|
|
2306
2777
|
}
|
|
2307
|
-
var
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2778
|
+
var paymentNextActionSchemasByProvider = {
|
|
2779
|
+
toss: tossPaymentNextActionSchema,
|
|
2780
|
+
portone: z5.union([
|
|
2781
|
+
portOnePaymentNextActionSchema,
|
|
2782
|
+
portOneSdkPaymentNextActionSchema
|
|
2783
|
+
])
|
|
2784
|
+
};
|
|
2785
|
+
var publicPaymentSessionVariants = CHECKOUT_PAYMENT_SESSION_PROVIDERS.flatMap(
|
|
2786
|
+
(provider) => providerSessionSchemas(
|
|
2787
|
+
provider,
|
|
2788
|
+
paymentNextActionSchemasByProvider[provider]
|
|
2315
2789
|
)
|
|
2316
|
-
|
|
2790
|
+
);
|
|
2317
2791
|
var publicPaymentSessionSchema = z5.union(publicPaymentSessionVariants);
|
|
2792
|
+
var portOneReconciliationSummarySchema = z5.union([
|
|
2793
|
+
noReconciliationSchema,
|
|
2794
|
+
z5.object({
|
|
2795
|
+
status: z5.literal("required"),
|
|
2796
|
+
reasons: z5.array(paymentReconciliationReasonSchema).min(1).readonly()
|
|
2797
|
+
}).strict()
|
|
2798
|
+
]);
|
|
2799
|
+
var portOnePaymentCurrentStateSchema = z5.object({
|
|
2800
|
+
paymentSession: z5.object({
|
|
2801
|
+
id: commerceResourceIdSchema,
|
|
2802
|
+
provider: z5.literal("portone"),
|
|
2803
|
+
providerStatus: paymentProviderStatusSchema,
|
|
2804
|
+
finalizationStatus: z5.enum(["not_ready", "pending", "committed"]),
|
|
2805
|
+
sessionRole: paymentSessionRoleSchema,
|
|
2806
|
+
reconciliation: portOneReconciliationSummarySchema
|
|
2807
|
+
}).strict(),
|
|
2808
|
+
checkout: z5.object({ id: commerceResourceIdSchema }).strict(),
|
|
2809
|
+
order: orderReferenceSchema.nullable(),
|
|
2810
|
+
money: moneySchema
|
|
2811
|
+
}).strict();
|
|
2812
|
+
var findPortOnePaymentResultSchema = z5.discriminatedUnion("found", [
|
|
2813
|
+
z5.object({ found: z5.literal(false) }).strict(),
|
|
2814
|
+
z5.object({
|
|
2815
|
+
found: z5.literal(true),
|
|
2816
|
+
current: portOnePaymentCurrentStateSchema
|
|
2817
|
+
}).strict()
|
|
2818
|
+
]);
|
|
2819
|
+
var reconcilePortOnePaymentResultSchema = z5.discriminatedUnion(
|
|
2820
|
+
"found",
|
|
2821
|
+
[
|
|
2822
|
+
z5.object({
|
|
2823
|
+
found: z5.literal(false),
|
|
2824
|
+
disposition: z5.literal("requires_attention")
|
|
2825
|
+
}).strict(),
|
|
2826
|
+
z5.object({
|
|
2827
|
+
found: z5.literal(true),
|
|
2828
|
+
disposition: portOneReconciliationDispositionSchema,
|
|
2829
|
+
current: portOnePaymentCurrentStateSchema
|
|
2830
|
+
}).strict()
|
|
2831
|
+
]
|
|
2832
|
+
);
|
|
2318
2833
|
var CreatePaymentSessionParamsSchema = createPaymentSessionParamsSchema;
|
|
2319
2834
|
var CancelServerPaymentSessionParamsSchema = cancelServerPaymentSessionParamsSchema;
|
|
2320
2835
|
var ConfirmTossPaymentSessionParamsSchema = confirmTossPaymentSessionParamsSchema;
|
|
@@ -2367,7 +2882,6 @@ var checkoutAmountsSchema = z6.object({
|
|
|
2367
2882
|
});
|
|
2368
2883
|
}
|
|
2369
2884
|
});
|
|
2370
|
-
var CHECKOUT_PAYMENT_SESSION_PROVIDERS = ["toss", "portone"];
|
|
2371
2885
|
var checkoutPaymentSessionRefSchema = z6.object({
|
|
2372
2886
|
id: z6.string().min(1),
|
|
2373
2887
|
provider: z6.enum(CHECKOUT_PAYMENT_SESSION_PROVIDERS),
|
|
@@ -2564,40 +3078,62 @@ var returnCancellationReasonCodeSchema = z7.enum(
|
|
|
2564
3078
|
RETURN_CANCELLATION_REASON_CODES
|
|
2565
3079
|
);
|
|
2566
3080
|
var restockActionSchema = z7.enum(["return_to_stock", "discard"]);
|
|
3081
|
+
var returnRefundMoneySchema = z7.number().int("amount must be an integer minor-unit value").safe("amount must be a safe integer").nonnegative("amount must be non-negative");
|
|
3082
|
+
var positiveReturnRefundMoneySchema = z7.number().int("amount must be an integer minor-unit value").safe("amount must be a safe integer").positive("amount must be positive");
|
|
3083
|
+
function trimmedReturnRefundScalarString(maxScalars, emptyMessage, maximumMessage) {
|
|
3084
|
+
return z7.string().trim().min(1, emptyMessage).refine((value) => Array.from(value).length <= maxScalars, maximumMessage);
|
|
3085
|
+
}
|
|
2567
3086
|
var returnWithRefundItemSchema = z7.object({
|
|
2568
|
-
orderItem: z7.union([z7.string().min(1), z7.number()]).transform(String),
|
|
2569
|
-
quantity: z7.number().int().positive("quantity must be a positive integer"),
|
|
3087
|
+
orderItem: z7.union([z7.string().trim().min(1), z7.number().int().safe().positive()]).transform(String),
|
|
3088
|
+
quantity: z7.number().int("quantity must be an integer").safe("quantity must be a safe integer").positive("quantity must be a positive integer"),
|
|
2570
3089
|
restockAction: restockActionSchema.default("return_to_stock"),
|
|
2571
|
-
restockingFee:
|
|
3090
|
+
restockingFee: returnRefundMoneySchema.optional().describe("Restocking fee charged for this line (ADR 0005 \xA7Gap 1)")
|
|
2572
3091
|
}).strict();
|
|
2573
3092
|
var returnWithRefundSchema = z7.object({
|
|
2574
|
-
orderNumber: z7.string().min(1, "orderNumber is required").describe("Order number (required)"),
|
|
3093
|
+
orderNumber: z7.string().trim().min(1, "orderNumber is required").describe("Order number (required)"),
|
|
2575
3094
|
reason: returnReasonSchema.optional().describe("Return reason (optional)"),
|
|
2576
|
-
reasonDetail:
|
|
3095
|
+
reasonDetail: trimmedReturnRefundScalarString(
|
|
3096
|
+
2e3,
|
|
3097
|
+
"reasonDetail must not be empty",
|
|
3098
|
+
"reasonDetail must be 2000 Unicode code points or fewer"
|
|
3099
|
+
).optional().describe("Detailed reason text (optional)"),
|
|
2577
3100
|
returnItems: z7.array(returnWithRefundItemSchema).min(1, "At least one return item is required").max(100, "Too many return items").describe("Array of products to return (required)"),
|
|
2578
|
-
refundAmount:
|
|
2579
|
-
|
|
3101
|
+
refundAmount: positiveReturnRefundMoneySchema.describe(
|
|
3102
|
+
"Refund amount (required, min 1)"
|
|
3103
|
+
),
|
|
3104
|
+
returnShippingFee: returnRefundMoneySchema.optional().describe(
|
|
2580
3105
|
"Return shipping fee charged to the customer (ADR 0005 \xA7Gap 1)"
|
|
2581
3106
|
),
|
|
2582
|
-
initialShippingRefundAmount:
|
|
2583
|
-
initialShippingRefundOverrideNote:
|
|
3107
|
+
initialShippingRefundAmount: returnRefundMoneySchema.optional().describe("Initial order shipping amount refunded to the customer"),
|
|
3108
|
+
initialShippingRefundOverrideNote: trimmedReturnRefundScalarString(
|
|
3109
|
+
2e3,
|
|
3110
|
+
"initialShippingRefundOverrideNote must not be empty",
|
|
3111
|
+
"initialShippingRefundOverrideNote must be 2000 Unicode code points or fewer"
|
|
3112
|
+
).optional().describe(
|
|
2584
3113
|
"Operator audit note required when overriding policy suggestion"
|
|
2585
3114
|
),
|
|
2586
|
-
pgPaymentId: z7.string().min(1, "pgPaymentId is required").describe("PG payment ID for refund (required)"),
|
|
2587
|
-
paymentKey: z7.string().min(1).optional().describe("Provider payment key for verified refund"),
|
|
2588
|
-
refundReceiptUrl:
|
|
3115
|
+
pgPaymentId: z7.string().trim().min(1, "pgPaymentId is required").describe("PG payment ID for refund (required)"),
|
|
3116
|
+
paymentKey: z7.string().trim().min(1).optional().describe("Provider payment key for verified refund"),
|
|
3117
|
+
refundReceiptUrl: trimmedReturnRefundScalarString(
|
|
3118
|
+
2048,
|
|
3119
|
+
"refundReceiptUrl must not be empty",
|
|
3120
|
+
"refundReceiptUrl must be 2048 Unicode code points or fewer"
|
|
3121
|
+
).optional().describe("Refund receipt URL (optional)")
|
|
2589
3122
|
}).strict();
|
|
2590
3123
|
var createReturnSchema = z7.object({
|
|
2591
3124
|
orderNumber: z7.string().min(1, "orderNumber is required").describe("Order number (required)"),
|
|
2592
3125
|
reason: returnReasonSchema.optional().describe("Return reason (optional)"),
|
|
2593
|
-
reasonDetail: z7.string().optional().describe("Detailed reason text (optional)"),
|
|
3126
|
+
reasonDetail: z7.string().max(2e3, "reasonDetail must be 2000 characters or fewer").optional().describe("Detailed reason text (optional)"),
|
|
2594
3127
|
returnItems: z7.array(returnWithRefundItemSchema).min(1, "At least one return item is required").max(100, "Too many return items").describe("Array of products to return (required)"),
|
|
2595
|
-
refundAmount:
|
|
3128
|
+
refundAmount: returnRefundMoneySchema.describe(
|
|
2596
3129
|
"Line refund amount before initial shipping refund (required, min 0)"
|
|
2597
3130
|
),
|
|
2598
|
-
returnShippingFee:
|
|
2599
|
-
initialShippingRefundAmount:
|
|
2600
|
-
initialShippingRefundOverrideNote: z7.string().min(1).
|
|
3131
|
+
returnShippingFee: returnRefundMoneySchema.optional().describe("Return shipping fee charged to the customer"),
|
|
3132
|
+
initialShippingRefundAmount: returnRefundMoneySchema.optional().describe("Initial order shipping amount refunded to the customer"),
|
|
3133
|
+
initialShippingRefundOverrideNote: z7.string().min(1).max(
|
|
3134
|
+
2e3,
|
|
3135
|
+
"initialShippingRefundOverrideNote must be 2000 characters or fewer"
|
|
3136
|
+
).optional().describe(
|
|
2601
3137
|
"Operator audit note required when overriding policy suggestion"
|
|
2602
3138
|
)
|
|
2603
3139
|
}).strict();
|
|
@@ -2773,8 +3309,8 @@ var fulfillmentItemsSchema = z8.array(
|
|
|
2773
3309
|
quantity: z8.number().int().positive("quantity must be a positive integer")
|
|
2774
3310
|
}).strict()
|
|
2775
3311
|
).min(1, "At least one fulfillment item is required").max(100, "Maximum 100 items per fulfillment");
|
|
2776
|
-
function registerOrderCommands(
|
|
2777
|
-
const order =
|
|
3312
|
+
function registerOrderCommands(program, getClient, getFormat) {
|
|
3313
|
+
const order = program.command("order").description("Order management");
|
|
2778
3314
|
order.command("update <orderNumber>").description("Confirm a delivered order purchase").requiredOption("--status <status>", "New status (confirmed only)").option("--dry-run", "Validate inputs without executing").action(async (orderNumber, opts) => {
|
|
2779
3315
|
try {
|
|
2780
3316
|
const status = parseWithSchema(opts.status, "status", orderStatusSchema);
|
|
@@ -2782,13 +3318,13 @@ function registerOrderCommands(program2, getClient2, getFormat2) {
|
|
|
2782
3318
|
if (opts.dryRun) {
|
|
2783
3319
|
printResult(
|
|
2784
3320
|
{ dryRun: true, valid: true, action: "order update", data },
|
|
2785
|
-
|
|
3321
|
+
getFormat()
|
|
2786
3322
|
);
|
|
2787
3323
|
return;
|
|
2788
3324
|
}
|
|
2789
|
-
const client =
|
|
3325
|
+
const client = getClient();
|
|
2790
3326
|
const result = await client.commerce.orders.update(data);
|
|
2791
|
-
printResult(result,
|
|
3327
|
+
printResult(result, getFormat());
|
|
2792
3328
|
} catch (e) {
|
|
2793
3329
|
exitWithError(e);
|
|
2794
3330
|
}
|
|
@@ -2810,13 +3346,13 @@ function registerOrderCommands(program2, getClient2, getFormat2) {
|
|
|
2810
3346
|
if (opts.dryRun) {
|
|
2811
3347
|
printResult(
|
|
2812
3348
|
{ dryRun: true, valid: true, action: "order cancel", data },
|
|
2813
|
-
|
|
3349
|
+
getFormat()
|
|
2814
3350
|
);
|
|
2815
3351
|
return;
|
|
2816
3352
|
}
|
|
2817
|
-
const client =
|
|
3353
|
+
const client = getClient();
|
|
2818
3354
|
const result = await client.commerce.orders.cancelOrder(data);
|
|
2819
|
-
printResult(result,
|
|
3355
|
+
printResult(result, getFormat());
|
|
2820
3356
|
} catch (e) {
|
|
2821
3357
|
exitWithError(e);
|
|
2822
3358
|
}
|
|
@@ -2827,13 +3363,13 @@ function registerOrderCommands(program2, getClient2, getFormat2) {
|
|
|
2827
3363
|
if (opts.dryRun) {
|
|
2828
3364
|
printResult(
|
|
2829
3365
|
{ dryRun: true, valid: true, action: "order prepare", data },
|
|
2830
|
-
|
|
3366
|
+
getFormat()
|
|
2831
3367
|
);
|
|
2832
3368
|
return;
|
|
2833
3369
|
}
|
|
2834
|
-
const client =
|
|
3370
|
+
const client = getClient();
|
|
2835
3371
|
const result = await client.commerce.orders.prepareFulfillmentOrder(data);
|
|
2836
|
-
printResult(result,
|
|
3372
|
+
printResult(result, getFormat());
|
|
2837
3373
|
} catch (e) {
|
|
2838
3374
|
exitWithError(e);
|
|
2839
3375
|
}
|
|
@@ -2854,18 +3390,18 @@ function registerOrderCommands(program2, getClient2, getFormat2) {
|
|
|
2854
3390
|
if (opts.dryRun) {
|
|
2855
3391
|
printResult(
|
|
2856
3392
|
{ dryRun: true, valid: true, action: "order fulfill", data },
|
|
2857
|
-
|
|
3393
|
+
getFormat()
|
|
2858
3394
|
);
|
|
2859
3395
|
return;
|
|
2860
3396
|
}
|
|
2861
|
-
const client =
|
|
3397
|
+
const client = getClient();
|
|
2862
3398
|
const result = await client.commerce.orders.createFulfillment({
|
|
2863
3399
|
...data,
|
|
2864
3400
|
...items ? {
|
|
2865
3401
|
items
|
|
2866
3402
|
} : {}
|
|
2867
3403
|
});
|
|
2868
|
-
printResult(result,
|
|
3404
|
+
printResult(result, getFormat());
|
|
2869
3405
|
} catch (e) {
|
|
2870
3406
|
exitWithError(e);
|
|
2871
3407
|
}
|
|
@@ -2890,13 +3426,13 @@ function registerOrderCommands(program2, getClient2, getFormat2) {
|
|
|
2890
3426
|
action: "order update-fulfillment",
|
|
2891
3427
|
data
|
|
2892
3428
|
},
|
|
2893
|
-
|
|
3429
|
+
getFormat()
|
|
2894
3430
|
);
|
|
2895
3431
|
return;
|
|
2896
3432
|
}
|
|
2897
|
-
const client =
|
|
3433
|
+
const client = getClient();
|
|
2898
3434
|
const result = await client.commerce.orders.updateFulfillment(data);
|
|
2899
|
-
printResult(result,
|
|
3435
|
+
printResult(result, getFormat());
|
|
2900
3436
|
} catch (e) {
|
|
2901
3437
|
exitWithError(e);
|
|
2902
3438
|
}
|
|
@@ -2911,8 +3447,8 @@ var returnStatusSchema = z9.enum([
|
|
|
2911
3447
|
"rejected",
|
|
2912
3448
|
"completed"
|
|
2913
3449
|
]);
|
|
2914
|
-
function registerReturnCommands(
|
|
2915
|
-
const ret =
|
|
3450
|
+
function registerReturnCommands(program, getClient, getFormat) {
|
|
3451
|
+
const ret = program.command("return").description("Return management");
|
|
2916
3452
|
ret.command("create <orderNumber>").description("Create a return request").requiredOption("--products <json>", "Return products array (JSON)").requiredOption("--refund-amount <n>", "Refund amount", parseFloat).option(
|
|
2917
3453
|
"--return-shipping-fee <n>",
|
|
2918
3454
|
"Return shipping fee charged to the customer",
|
|
@@ -2946,16 +3482,16 @@ function registerReturnCommands(program2, getClient2, getFormat2) {
|
|
|
2946
3482
|
if (opts.dryRun) {
|
|
2947
3483
|
printResult(
|
|
2948
3484
|
{ dryRun: true, valid: true, action: "return create", data },
|
|
2949
|
-
|
|
3485
|
+
getFormat()
|
|
2950
3486
|
);
|
|
2951
3487
|
return;
|
|
2952
3488
|
}
|
|
2953
|
-
const client =
|
|
3489
|
+
const client = getClient();
|
|
2954
3490
|
const result = await client.commerce.orders.createReturn({
|
|
2955
3491
|
...data,
|
|
2956
3492
|
returnItems: data.returnItems
|
|
2957
3493
|
});
|
|
2958
|
-
printResult(result,
|
|
3494
|
+
printResult(result, getFormat());
|
|
2959
3495
|
} catch (e) {
|
|
2960
3496
|
exitWithError(e);
|
|
2961
3497
|
}
|
|
@@ -2974,13 +3510,13 @@ function registerReturnCommands(program2, getClient2, getFormat2) {
|
|
|
2974
3510
|
if (opts.dryRun) {
|
|
2975
3511
|
printResult(
|
|
2976
3512
|
{ dryRun: true, valid: true, action: "return update", data },
|
|
2977
|
-
|
|
3513
|
+
getFormat()
|
|
2978
3514
|
);
|
|
2979
3515
|
return;
|
|
2980
3516
|
}
|
|
2981
|
-
const client =
|
|
3517
|
+
const client = getClient();
|
|
2982
3518
|
const result = await client.commerce.orders.updateReturn(data);
|
|
2983
|
-
printResult(result,
|
|
3519
|
+
printResult(result, getFormat());
|
|
2984
3520
|
} catch (e) {
|
|
2985
3521
|
exitWithError(e);
|
|
2986
3522
|
}
|
|
@@ -3018,16 +3554,16 @@ function registerReturnCommands(program2, getClient2, getFormat2) {
|
|
|
3018
3554
|
if (opts.dryRun) {
|
|
3019
3555
|
printResult(
|
|
3020
3556
|
{ dryRun: true, valid: true, action: "return refund", data },
|
|
3021
|
-
|
|
3557
|
+
getFormat()
|
|
3022
3558
|
);
|
|
3023
3559
|
return;
|
|
3024
3560
|
}
|
|
3025
|
-
const client =
|
|
3561
|
+
const client = getClient();
|
|
3026
3562
|
const result = await client.commerce.orders.returnWithRefund({
|
|
3027
3563
|
...data,
|
|
3028
3564
|
returnItems: data.returnItems
|
|
3029
3565
|
});
|
|
3030
|
-
printResult(result,
|
|
3566
|
+
printResult(result, getFormat());
|
|
3031
3567
|
} catch (e) {
|
|
3032
3568
|
exitWithError(e);
|
|
3033
3569
|
}
|
|
@@ -3112,8 +3648,8 @@ function sensitiveDryRunResult(action) {
|
|
|
3112
3648
|
}
|
|
3113
3649
|
|
|
3114
3650
|
// src/commands/cart.ts
|
|
3115
|
-
function registerCartCommands(
|
|
3116
|
-
const cart =
|
|
3651
|
+
function registerCartCommands(program, getClient, getFormat) {
|
|
3652
|
+
const cart = program.command("cart").description("Cart management");
|
|
3117
3653
|
cart.command("create").description("Create a cart and print its cartToken capability").option("--data-stdin", "Read market and attributes JSON from stdin").option("--data-file <path>", "Read market and attributes JSON from file").option("--dry-run", "Validate inputs without executing").action(async (opts) => {
|
|
3118
3654
|
try {
|
|
3119
3655
|
const input = opts.dataStdin || opts.dataFile ? await readSensitiveJsonObject(opts) : {};
|
|
@@ -3123,10 +3659,10 @@ function registerCartCommands(program2, getClient2, getFormat2) {
|
|
|
3123
3659
|
createCartParamsSchema
|
|
3124
3660
|
);
|
|
3125
3661
|
if (opts.dryRun) {
|
|
3126
|
-
printResult(sensitiveDryRunResult("cart create"),
|
|
3662
|
+
printResult(sensitiveDryRunResult("cart create"), getFormat());
|
|
3127
3663
|
return;
|
|
3128
3664
|
}
|
|
3129
|
-
printResult(await
|
|
3665
|
+
printResult(await getClient().commerce.carts.create(data), getFormat());
|
|
3130
3666
|
} catch (error) {
|
|
3131
3667
|
exitWithError(error);
|
|
3132
3668
|
}
|
|
@@ -3139,8 +3675,8 @@ function registerCartCommands(program2, getClient2, getFormat2) {
|
|
|
3139
3675
|
retrieveCartParamsSchema
|
|
3140
3676
|
);
|
|
3141
3677
|
printResult(
|
|
3142
|
-
await
|
|
3143
|
-
|
|
3678
|
+
await getClient().commerce.carts.retrieve(data),
|
|
3679
|
+
getFormat()
|
|
3144
3680
|
);
|
|
3145
3681
|
} catch (error) {
|
|
3146
3682
|
exitWithError(error);
|
|
@@ -3154,10 +3690,10 @@ function registerCartCommands(program2, getClient2, getFormat2) {
|
|
|
3154
3690
|
addItemParamsSchema
|
|
3155
3691
|
);
|
|
3156
3692
|
if (opts.dryRun) {
|
|
3157
|
-
printResult(sensitiveDryRunResult("cart add"),
|
|
3693
|
+
printResult(sensitiveDryRunResult("cart add"), getFormat());
|
|
3158
3694
|
return;
|
|
3159
3695
|
}
|
|
3160
|
-
printResult(await
|
|
3696
|
+
printResult(await getClient().commerce.carts.addItem(data), getFormat());
|
|
3161
3697
|
} catch (error) {
|
|
3162
3698
|
exitWithError(error);
|
|
3163
3699
|
}
|
|
@@ -3170,12 +3706,12 @@ function registerCartCommands(program2, getClient2, getFormat2) {
|
|
|
3170
3706
|
updateItemParamsSchema
|
|
3171
3707
|
);
|
|
3172
3708
|
if (opts.dryRun) {
|
|
3173
|
-
printResult(sensitiveDryRunResult("cart update"),
|
|
3709
|
+
printResult(sensitiveDryRunResult("cart update"), getFormat());
|
|
3174
3710
|
return;
|
|
3175
3711
|
}
|
|
3176
3712
|
printResult(
|
|
3177
|
-
await
|
|
3178
|
-
|
|
3713
|
+
await getClient().commerce.carts.updateItem(data),
|
|
3714
|
+
getFormat()
|
|
3179
3715
|
);
|
|
3180
3716
|
} catch (error) {
|
|
3181
3717
|
exitWithError(error);
|
|
@@ -3189,12 +3725,12 @@ function registerCartCommands(program2, getClient2, getFormat2) {
|
|
|
3189
3725
|
removeItemParamsSchema
|
|
3190
3726
|
);
|
|
3191
3727
|
if (opts.dryRun) {
|
|
3192
|
-
printResult(sensitiveDryRunResult("cart remove"),
|
|
3728
|
+
printResult(sensitiveDryRunResult("cart remove"), getFormat());
|
|
3193
3729
|
return;
|
|
3194
3730
|
}
|
|
3195
3731
|
printResult(
|
|
3196
|
-
await
|
|
3197
|
-
|
|
3732
|
+
await getClient().commerce.carts.removeItem(data),
|
|
3733
|
+
getFormat()
|
|
3198
3734
|
);
|
|
3199
3735
|
} catch (error) {
|
|
3200
3736
|
exitWithError(error);
|
|
@@ -3208,10 +3744,10 @@ function registerCartCommands(program2, getClient2, getFormat2) {
|
|
|
3208
3744
|
clearCartParamsSchema
|
|
3209
3745
|
);
|
|
3210
3746
|
if (opts.dryRun) {
|
|
3211
|
-
printResult(sensitiveDryRunResult("cart clear"),
|
|
3747
|
+
printResult(sensitiveDryRunResult("cart clear"), getFormat());
|
|
3212
3748
|
return;
|
|
3213
3749
|
}
|
|
3214
|
-
printResult(await
|
|
3750
|
+
printResult(await getClient().commerce.carts.clear(data), getFormat());
|
|
3215
3751
|
} catch (error) {
|
|
3216
3752
|
exitWithError(error);
|
|
3217
3753
|
}
|
|
@@ -3224,12 +3760,12 @@ function registerCartCommands(program2, getClient2, getFormat2) {
|
|
|
3224
3760
|
updateDiscountCodesParamsSchema
|
|
3225
3761
|
);
|
|
3226
3762
|
if (opts.dryRun) {
|
|
3227
|
-
printResult(sensitiveDryRunResult("cart discounts"),
|
|
3763
|
+
printResult(sensitiveDryRunResult("cart discounts"), getFormat());
|
|
3228
3764
|
return;
|
|
3229
3765
|
}
|
|
3230
3766
|
printResult(
|
|
3231
|
-
await
|
|
3232
|
-
|
|
3767
|
+
await getClient().commerce.carts.updateDiscountCodes(data),
|
|
3768
|
+
getFormat()
|
|
3233
3769
|
);
|
|
3234
3770
|
} catch (error) {
|
|
3235
3771
|
exitWithError(error);
|
|
@@ -3246,12 +3782,12 @@ function registerCartCommands(program2, getClient2, getFormat2) {
|
|
|
3246
3782
|
updateCartAttributesParamsSchema
|
|
3247
3783
|
);
|
|
3248
3784
|
if (opts.dryRun) {
|
|
3249
|
-
printResult(sensitiveDryRunResult("cart attributes"),
|
|
3785
|
+
printResult(sensitiveDryRunResult("cart attributes"), getFormat());
|
|
3250
3786
|
return;
|
|
3251
3787
|
}
|
|
3252
3788
|
printResult(
|
|
3253
|
-
await
|
|
3254
|
-
|
|
3789
|
+
await getClient().commerce.carts.updateAttributes(data),
|
|
3790
|
+
getFormat()
|
|
3255
3791
|
);
|
|
3256
3792
|
} catch (error) {
|
|
3257
3793
|
exitWithError(error);
|
|
@@ -3260,17 +3796,17 @@ function registerCartCommands(program2, getClient2, getFormat2) {
|
|
|
3260
3796
|
}
|
|
3261
3797
|
|
|
3262
3798
|
// src/commands/stock.ts
|
|
3263
|
-
function registerStockCommands(
|
|
3264
|
-
const stock =
|
|
3799
|
+
function registerStockCommands(program, getClient, getFormat) {
|
|
3800
|
+
const stock = program.command("stock").description("Stock management");
|
|
3265
3801
|
stock.command("check").description("Check stock availability").requiredOption(
|
|
3266
3802
|
"--items <json>",
|
|
3267
3803
|
"Items to check (JSON array of { optionId, quantity })"
|
|
3268
3804
|
).action(async (opts) => {
|
|
3269
3805
|
try {
|
|
3270
|
-
const client =
|
|
3806
|
+
const client = getClient();
|
|
3271
3807
|
const items = parseJsonArray(opts.items, "items");
|
|
3272
3808
|
const result = await client.commerce.product.stockCheck({ items });
|
|
3273
|
-
printResult(result,
|
|
3809
|
+
printResult(result, getFormat());
|
|
3274
3810
|
} catch (e) {
|
|
3275
3811
|
exitWithError(e);
|
|
3276
3812
|
}
|
|
@@ -3282,8 +3818,8 @@ function paymentProvider(value) {
|
|
|
3282
3818
|
if (value === "toss" || value === "portone") return value;
|
|
3283
3819
|
throw new Error("payment provider must be toss or portone");
|
|
3284
3820
|
}
|
|
3285
|
-
function registerCommerceSessionCommands(
|
|
3286
|
-
const checkout =
|
|
3821
|
+
function registerCommerceSessionCommands(program, getClient, getFormat) {
|
|
3822
|
+
const checkout = program.command("checkout").description("Checkout management");
|
|
3287
3823
|
checkout.command("create").description("Create a Checkout from a server-authoritative Cart").option("--data-stdin", "Read capability and customer JSON from stdin").option("--data-file <path>", "Read capability and customer JSON from file").option("--dry-run", "Validate inputs without executing").action(async (opts) => {
|
|
3288
3824
|
try {
|
|
3289
3825
|
const data = parseWithSchema(
|
|
@@ -3292,12 +3828,12 @@ function registerCommerceSessionCommands(program2, getClient2, getFormat2) {
|
|
|
3292
3828
|
CreateServerCheckoutParamsSchema
|
|
3293
3829
|
);
|
|
3294
3830
|
if (opts.dryRun) {
|
|
3295
|
-
printResult(sensitiveDryRunResult("checkout create"),
|
|
3831
|
+
printResult(sensitiveDryRunResult("checkout create"), getFormat());
|
|
3296
3832
|
return;
|
|
3297
3833
|
}
|
|
3298
3834
|
printResult(
|
|
3299
|
-
await
|
|
3300
|
-
|
|
3835
|
+
await getClient().commerce.checkouts.create(data),
|
|
3836
|
+
getFormat()
|
|
3301
3837
|
);
|
|
3302
3838
|
} catch (error) {
|
|
3303
3839
|
exitWithError(error);
|
|
@@ -3306,8 +3842,8 @@ function registerCommerceSessionCommands(program2, getClient2, getFormat2) {
|
|
|
3306
3842
|
checkout.command("retrieve <checkoutId>").description("Retrieve a Checkout by ID with server credentials").action(async (checkoutId) => {
|
|
3307
3843
|
try {
|
|
3308
3844
|
printResult(
|
|
3309
|
-
await
|
|
3310
|
-
|
|
3845
|
+
await getClient().commerce.checkouts.retrieve({ checkoutId }),
|
|
3846
|
+
getFormat()
|
|
3311
3847
|
);
|
|
3312
3848
|
} catch (error) {
|
|
3313
3849
|
exitWithError(error);
|
|
@@ -3321,14 +3857,14 @@ function registerCommerceSessionCommands(program2, getClient2, getFormat2) {
|
|
|
3321
3857
|
CanonicalCheckoutQuerySchema
|
|
3322
3858
|
);
|
|
3323
3859
|
printResult(
|
|
3324
|
-
await
|
|
3325
|
-
|
|
3860
|
+
await getClient().commerce.checkouts.query(data),
|
|
3861
|
+
getFormat()
|
|
3326
3862
|
);
|
|
3327
3863
|
} catch (error) {
|
|
3328
3864
|
exitWithError(error);
|
|
3329
3865
|
}
|
|
3330
3866
|
});
|
|
3331
|
-
const sessions =
|
|
3867
|
+
const sessions = program.command("payment-session").description("PaymentSession management");
|
|
3332
3868
|
sessions.command("create").description("Create a canonical provider-configured PaymentSession").option("--data-stdin", "Read canonical create parameters from stdin").option("--data-file <path>", "Read canonical create parameters from file").option("--dry-run", "Validate inputs without executing").action(async (opts) => {
|
|
3333
3869
|
try {
|
|
3334
3870
|
const data = parseWithSchema(
|
|
@@ -3339,28 +3875,27 @@ function registerCommerceSessionCommands(program2, getClient2, getFormat2) {
|
|
|
3339
3875
|
if (opts.dryRun) {
|
|
3340
3876
|
printResult(
|
|
3341
3877
|
sensitiveDryRunResult("payment-session create"),
|
|
3342
|
-
|
|
3878
|
+
getFormat()
|
|
3343
3879
|
);
|
|
3344
3880
|
return;
|
|
3345
3881
|
}
|
|
3346
|
-
const paymentSessions =
|
|
3882
|
+
const paymentSessions = getClient().commerce.paymentSessions;
|
|
3347
3883
|
const result = data.provider === "portone" ? await paymentSessions.createPortOne(data) : await paymentSessions.create(data);
|
|
3348
|
-
printResult(result,
|
|
3884
|
+
printResult(result, getFormat());
|
|
3349
3885
|
} catch (error) {
|
|
3350
3886
|
exitWithError(error);
|
|
3351
3887
|
}
|
|
3352
3888
|
});
|
|
3353
|
-
sessions.command("retrieve <paymentSessionId>").description("Retrieve a PaymentSession").
|
|
3889
|
+
sessions.command("retrieve <paymentSessionId>").description("Retrieve a PaymentSession").requiredOption(
|
|
3354
3890
|
"--provider <provider>",
|
|
3355
|
-
"Payment provider (toss or portone)"
|
|
3356
|
-
"toss"
|
|
3891
|
+
"Payment provider (toss or portone)"
|
|
3357
3892
|
).action(async (paymentSessionId, opts) => {
|
|
3358
3893
|
try {
|
|
3359
3894
|
const provider = paymentProvider(opts.provider);
|
|
3360
|
-
const paymentSessions =
|
|
3895
|
+
const paymentSessions = getClient().commerce.paymentSessions;
|
|
3361
3896
|
printResult(
|
|
3362
3897
|
provider === "portone" ? await paymentSessions.retrievePortOne({ paymentSessionId }) : await paymentSessions.retrieve({ paymentSessionId }),
|
|
3363
|
-
|
|
3898
|
+
getFormat()
|
|
3364
3899
|
);
|
|
3365
3900
|
} catch (error) {
|
|
3366
3901
|
exitWithError(error);
|
|
@@ -3369,10 +3904,9 @@ function registerCommerceSessionCommands(program2, getClient2, getFormat2) {
|
|
|
3369
3904
|
sessions.command("cancel").description("Cancel a PaymentSession and release its payment slot").option("--data-stdin", "Read session ID and idempotency key from stdin").option(
|
|
3370
3905
|
"--data-file <path>",
|
|
3371
3906
|
"Read session ID and idempotency key from file"
|
|
3372
|
-
).
|
|
3907
|
+
).requiredOption(
|
|
3373
3908
|
"--provider <provider>",
|
|
3374
|
-
"Payment provider (toss or portone)"
|
|
3375
|
-
"toss"
|
|
3909
|
+
"Payment provider (toss or portone)"
|
|
3376
3910
|
).option("--dry-run", "Validate inputs without executing").action(async (opts) => {
|
|
3377
3911
|
try {
|
|
3378
3912
|
const data = parseWithSchema(
|
|
@@ -3384,14 +3918,14 @@ function registerCommerceSessionCommands(program2, getClient2, getFormat2) {
|
|
|
3384
3918
|
if (opts.dryRun) {
|
|
3385
3919
|
printResult(
|
|
3386
3920
|
sensitiveDryRunResult("payment-session cancel"),
|
|
3387
|
-
|
|
3921
|
+
getFormat()
|
|
3388
3922
|
);
|
|
3389
3923
|
return;
|
|
3390
3924
|
}
|
|
3391
|
-
const paymentSessions =
|
|
3925
|
+
const paymentSessions = getClient().commerce.paymentSessions;
|
|
3392
3926
|
printResult(
|
|
3393
3927
|
provider === "portone" ? await paymentSessions.cancelPortOne(data) : await paymentSessions.cancel(data),
|
|
3394
|
-
|
|
3928
|
+
getFormat()
|
|
3395
3929
|
);
|
|
3396
3930
|
} catch (error) {
|
|
3397
3931
|
exitWithError(error);
|
|
@@ -3407,13 +3941,13 @@ function registerCommerceSessionCommands(program2, getClient2, getFormat2) {
|
|
|
3407
3941
|
if (opts.dryRun) {
|
|
3408
3942
|
printResult(
|
|
3409
3943
|
sensitiveDryRunResult("payment-session confirm-toss"),
|
|
3410
|
-
|
|
3944
|
+
getFormat()
|
|
3411
3945
|
);
|
|
3412
3946
|
return;
|
|
3413
3947
|
}
|
|
3414
3948
|
printResult(
|
|
3415
|
-
await
|
|
3416
|
-
|
|
3949
|
+
await getClient().commerce.paymentSessions.confirm(data),
|
|
3950
|
+
getFormat()
|
|
3417
3951
|
);
|
|
3418
3952
|
} catch (error) {
|
|
3419
3953
|
exitWithError(error);
|
|
@@ -3469,14 +4003,14 @@ function productDetailParamsFromOptions(options) {
|
|
|
3469
4003
|
}
|
|
3470
4004
|
|
|
3471
4005
|
// src/commands/product.ts
|
|
3472
|
-
function registerProductCommands(
|
|
3473
|
-
const product =
|
|
4006
|
+
function registerProductCommands(program, getClient, getFormat) {
|
|
4007
|
+
const product = program.command("product").description("Product management");
|
|
3474
4008
|
product.command("detail").description("Get shaped product detail by slug or ID").option("--slug <slug>", "Product slug").option("--id <id>", "Product ID").option("--market <market>", "Market slug").option("--locale <locale>", "Locale: ko, en, or all").option("--fallback-locale <locale>", "Fallback locale: ko, en, or none").action(async (opts) => {
|
|
3475
4009
|
try {
|
|
3476
4010
|
const params = productDetailParamsFromOptions(opts);
|
|
3477
|
-
const client =
|
|
4011
|
+
const client = getClient();
|
|
3478
4012
|
const result = await client.commerce.product.detail(params);
|
|
3479
|
-
printResult(result,
|
|
4013
|
+
printResult(result, getFormat());
|
|
3480
4014
|
} catch (e) {
|
|
3481
4015
|
exitWithError(e);
|
|
3482
4016
|
}
|
|
@@ -3491,15 +4025,15 @@ function registerProductCommands(program2, getClient2, getFormat2) {
|
|
|
3491
4025
|
if (opts.dryRun) {
|
|
3492
4026
|
printResult(
|
|
3493
4027
|
{ dryRun: true, valid: true, action: "product upsert", data },
|
|
3494
|
-
|
|
4028
|
+
getFormat()
|
|
3495
4029
|
);
|
|
3496
4030
|
return;
|
|
3497
4031
|
}
|
|
3498
|
-
const client =
|
|
4032
|
+
const client = getClient();
|
|
3499
4033
|
const result = await client.commerce.product.upsert(
|
|
3500
4034
|
data
|
|
3501
4035
|
);
|
|
3502
|
-
printResult(result,
|
|
4036
|
+
printResult(result, getFormat());
|
|
3503
4037
|
} catch (e) {
|
|
3504
4038
|
exitWithError(e);
|
|
3505
4039
|
}
|
|
@@ -3507,20 +4041,20 @@ function registerProductCommands(program2, getClient2, getFormat2) {
|
|
|
3507
4041
|
}
|
|
3508
4042
|
|
|
3509
4043
|
// src/commands/discount.ts
|
|
3510
|
-
function registerDiscountCommands(
|
|
3511
|
-
const discount =
|
|
4044
|
+
function registerDiscountCommands(program, getClient, getFormat) {
|
|
4045
|
+
const discount = program.command("discount").description("Discount management");
|
|
3512
4046
|
discount.command("validate").description("Validate a discount code against an order amount").requiredOption("--code <code>", "Discount code").requiredOption(
|
|
3513
4047
|
"--order-amount <n>",
|
|
3514
4048
|
"Order amount",
|
|
3515
4049
|
(v) => parseInt(v, 10)
|
|
3516
4050
|
).action(async (opts) => {
|
|
3517
4051
|
try {
|
|
3518
|
-
const client =
|
|
4052
|
+
const client = getClient();
|
|
3519
4053
|
const result = await client.commerce.discounts.validate({
|
|
3520
4054
|
code: opts.code,
|
|
3521
4055
|
orderAmount: opts.orderAmount
|
|
3522
4056
|
});
|
|
3523
|
-
printResult(result,
|
|
4057
|
+
printResult(result, getFormat());
|
|
3524
4058
|
} catch (e) {
|
|
3525
4059
|
exitWithError(e);
|
|
3526
4060
|
}
|
|
@@ -3528,15 +4062,15 @@ function registerDiscountCommands(program2, getClient2, getFormat2) {
|
|
|
3528
4062
|
}
|
|
3529
4063
|
|
|
3530
4064
|
// src/commands/shipping.ts
|
|
3531
|
-
function registerShippingCommands(
|
|
3532
|
-
const shipping =
|
|
4065
|
+
function registerShippingCommands(program, getClient, getFormat) {
|
|
4066
|
+
const shipping = program.command("shipping").description("Shipping calculation");
|
|
3533
4067
|
shipping.command("calculate").description("Calculate shipping for an order amount").requiredOption(
|
|
3534
4068
|
"--order-amount <n>",
|
|
3535
4069
|
"Order amount",
|
|
3536
4070
|
(v) => parseInt(v, 10)
|
|
3537
4071
|
).option("--shipping-policy-id <id>", "Shipping policy ID").option("--country-code <code>", "Destination country code").option("--region-code <code>", "Destination region code").option("--postal-code <code>", "Destination postal code").action(async (opts) => {
|
|
3538
4072
|
try {
|
|
3539
|
-
const client =
|
|
4073
|
+
const client = getClient();
|
|
3540
4074
|
const result = await client.commerce.shipping.calculate({
|
|
3541
4075
|
orderAmount: opts.orderAmount,
|
|
3542
4076
|
...opts.shippingPolicyId ? { shippingPolicyId: opts.shippingPolicyId } : {},
|
|
@@ -3544,7 +4078,7 @@ function registerShippingCommands(program2, getClient2, getFormat2) {
|
|
|
3544
4078
|
...opts.regionCode ? { regionCode: opts.regionCode } : {},
|
|
3545
4079
|
...opts.postalCode ? { postalCode: opts.postalCode } : {}
|
|
3546
4080
|
});
|
|
3547
|
-
printResult(result,
|
|
4081
|
+
printResult(result, getFormat());
|
|
3548
4082
|
} catch (e) {
|
|
3549
4083
|
exitWithError(e);
|
|
3550
4084
|
}
|
|
@@ -3560,6 +4094,8 @@ import { URL as URL2 } from "url";
|
|
|
3560
4094
|
import pc2 from "picocolors";
|
|
3561
4095
|
var WEB_URL = process.env.SOFTWARE_WEB_URL || "https://01.software";
|
|
3562
4096
|
var TIMEOUT_MS = 3 * 60 * 1e3;
|
|
4097
|
+
var EXCHANGE_TIMEOUT_MS = 3e4;
|
|
4098
|
+
var MAX_EXCHANGE_RESPONSE_BYTES = 1024 * 1024;
|
|
3563
4099
|
function escapeHtml(s) {
|
|
3564
4100
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
3565
4101
|
}
|
|
@@ -3602,16 +4138,72 @@ var ERROR_HTML = (msg) => `<!DOCTYPE html>
|
|
|
3602
4138
|
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width"><title>CLI Login Error</title>
|
|
3603
4139
|
<style>${PAGE_STYLE}</style>
|
|
3604
4140
|
</head><body><div class="card"><div class="icon err">!</div><h1>Authentication failed</h1><p>${escapeHtml(msg)}</p></div></body></html>`;
|
|
3605
|
-
async function
|
|
4141
|
+
async function readBoundedResponseBody(response, signal) {
|
|
4142
|
+
const contentLength = response.headers.get("content-length");
|
|
4143
|
+
if (contentLength !== null && /^\d+$/.test(contentLength) && Number(contentLength) > MAX_EXCHANGE_RESPONSE_BYTES) {
|
|
4144
|
+
void response.body?.cancel().catch(() => void 0);
|
|
4145
|
+
throw new Error("response body exceeded 1 MiB");
|
|
4146
|
+
}
|
|
4147
|
+
const reader = response.body?.getReader();
|
|
4148
|
+
if (!reader) return "";
|
|
4149
|
+
const decoder = new TextDecoder();
|
|
4150
|
+
let body = "";
|
|
4151
|
+
let totalBytes = 0;
|
|
4152
|
+
let completed = false;
|
|
4153
|
+
let rejectAbort;
|
|
4154
|
+
const aborted = new Promise((_, reject) => {
|
|
4155
|
+
rejectAbort = reject;
|
|
4156
|
+
});
|
|
4157
|
+
const onAbort = () => rejectAbort(new Error("request timed out"));
|
|
4158
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
4159
|
+
if (signal.aborted) onAbort();
|
|
4160
|
+
try {
|
|
4161
|
+
while (true) {
|
|
4162
|
+
const { done, value } = await Promise.race([reader.read(), aborted]);
|
|
4163
|
+
if (done) {
|
|
4164
|
+
completed = true;
|
|
4165
|
+
return body + decoder.decode();
|
|
4166
|
+
}
|
|
4167
|
+
totalBytes += value.byteLength;
|
|
4168
|
+
if (totalBytes > MAX_EXCHANGE_RESPONSE_BYTES) {
|
|
4169
|
+
throw new Error("response body exceeded 1 MiB");
|
|
4170
|
+
}
|
|
4171
|
+
body += decoder.decode(value, { stream: true });
|
|
4172
|
+
}
|
|
4173
|
+
} finally {
|
|
4174
|
+
signal.removeEventListener("abort", onAbort);
|
|
4175
|
+
if (!completed) void reader.cancel().catch(() => void 0);
|
|
4176
|
+
}
|
|
4177
|
+
}
|
|
4178
|
+
async function exchangeCode(code, options = {}) {
|
|
3606
4179
|
const url = `${WEB_URL}/api/cli/exchange`;
|
|
4180
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
4181
|
+
const timeoutMs = options.timeoutMs ?? EXCHANGE_TIMEOUT_MS;
|
|
4182
|
+
const controller = new AbortController();
|
|
4183
|
+
let timeoutId;
|
|
4184
|
+
let rejectTimeout;
|
|
4185
|
+
const timedOut = new Promise((_, reject) => {
|
|
4186
|
+
rejectTimeout = reject;
|
|
4187
|
+
});
|
|
3607
4188
|
try {
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
4189
|
+
timeoutId = setTimeout(() => {
|
|
4190
|
+
controller.abort();
|
|
4191
|
+
rejectTimeout(new Error("request timed out"));
|
|
4192
|
+
}, timeoutMs);
|
|
4193
|
+
const res = await Promise.race([
|
|
4194
|
+
fetchImpl(url, {
|
|
4195
|
+
method: "POST",
|
|
4196
|
+
headers: { "Content-Type": "application/json" },
|
|
4197
|
+
body: JSON.stringify({ code }),
|
|
4198
|
+
signal: controller.signal
|
|
4199
|
+
}),
|
|
4200
|
+
timedOut
|
|
4201
|
+
]);
|
|
4202
|
+
const body = await Promise.race([
|
|
4203
|
+
readBoundedResponseBody(res, controller.signal),
|
|
4204
|
+
timedOut
|
|
4205
|
+
]);
|
|
3613
4206
|
if (!res.ok) {
|
|
3614
|
-
const body = await res.text().catch(() => "");
|
|
3615
4207
|
console.error(
|
|
3616
4208
|
pc2.red(
|
|
3617
4209
|
`Exchange failed: HTTP ${res.status} from ${url}${body ? ` \u2014 ${body.slice(0, 200)}` : ""}`
|
|
@@ -3619,7 +4211,13 @@ async function exchangeCode(code) {
|
|
|
3619
4211
|
);
|
|
3620
4212
|
return null;
|
|
3621
4213
|
}
|
|
3622
|
-
|
|
4214
|
+
let data;
|
|
4215
|
+
try {
|
|
4216
|
+
data = JSON.parse(body);
|
|
4217
|
+
} catch {
|
|
4218
|
+
console.error(pc2.red(`Exchange failed: malformed response from ${url}`));
|
|
4219
|
+
return null;
|
|
4220
|
+
}
|
|
3623
4221
|
if (typeof data.publishableKey !== "string" || typeof data.secretKey !== "string" || typeof data.tenantName !== "string" || typeof data.tenantId !== "string") {
|
|
3624
4222
|
console.error(pc2.red(`Exchange failed: malformed response from ${url}`));
|
|
3625
4223
|
return null;
|
|
@@ -3640,10 +4238,12 @@ async function exchangeCode(code) {
|
|
|
3640
4238
|
)
|
|
3641
4239
|
);
|
|
3642
4240
|
return null;
|
|
4241
|
+
} finally {
|
|
4242
|
+
clearTimeout(timeoutId);
|
|
3643
4243
|
}
|
|
3644
4244
|
}
|
|
3645
4245
|
function startAuthServer(options) {
|
|
3646
|
-
return new Promise((
|
|
4246
|
+
return new Promise((resolve3, reject) => {
|
|
3647
4247
|
const server = createServer((req, res) => {
|
|
3648
4248
|
if (!req.url) {
|
|
3649
4249
|
res.writeHead(400).end();
|
|
@@ -3656,7 +4256,10 @@ function startAuthServer(options) {
|
|
|
3656
4256
|
}
|
|
3657
4257
|
const error = url.searchParams.get("error");
|
|
3658
4258
|
if (error) {
|
|
3659
|
-
res.writeHead(200, {
|
|
4259
|
+
res.writeHead(200, {
|
|
4260
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
4261
|
+
Connection: "close"
|
|
4262
|
+
}).end(ERROR_HTML(error));
|
|
3660
4263
|
console.error(pc2.red(`Login failed: ${error}`));
|
|
3661
4264
|
cleanup(2);
|
|
3662
4265
|
return;
|
|
@@ -3664,19 +4267,32 @@ function startAuthServer(options) {
|
|
|
3664
4267
|
const code = url.searchParams.get("code");
|
|
3665
4268
|
const receivedState = url.searchParams.get("state");
|
|
3666
4269
|
if (!code || !receivedState) {
|
|
3667
|
-
res.writeHead(400, {
|
|
4270
|
+
res.writeHead(400, {
|
|
4271
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
4272
|
+
Connection: "close"
|
|
4273
|
+
}).end(ERROR_HTML('Missing code or state. Start over with "01 login".'));
|
|
3668
4274
|
cleanup(2);
|
|
3669
4275
|
return;
|
|
3670
4276
|
}
|
|
3671
4277
|
if (receivedState !== options.state) {
|
|
3672
|
-
res.writeHead(403, {
|
|
4278
|
+
res.writeHead(403, {
|
|
4279
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
4280
|
+
Connection: "close"
|
|
4281
|
+
}).end(ERROR_HTML('State mismatch. Start over with "01 login".'));
|
|
3673
4282
|
console.error(pc2.red("Login failed: state mismatch."));
|
|
3674
4283
|
cleanup(2);
|
|
3675
4284
|
return;
|
|
3676
4285
|
}
|
|
3677
4286
|
exchangeCode(code).then((creds) => {
|
|
3678
4287
|
if (!creds) {
|
|
3679
|
-
res.writeHead(400, {
|
|
4288
|
+
res.writeHead(400, {
|
|
4289
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
4290
|
+
Connection: "close"
|
|
4291
|
+
}).end(
|
|
4292
|
+
ERROR_HTML(
|
|
4293
|
+
'Invalid or expired code. Start over with "01 login".'
|
|
4294
|
+
)
|
|
4295
|
+
);
|
|
3680
4296
|
console.error(pc2.red("Login failed: code exchange failed."));
|
|
3681
4297
|
cleanup(2);
|
|
3682
4298
|
return;
|
|
@@ -3693,7 +4309,10 @@ function startAuthServer(options) {
|
|
|
3693
4309
|
console.log(pc2.green(`
|
|
3694
4310
|
Logged in successfully!`));
|
|
3695
4311
|
console.log(pc2.dim(`Tenant: ${creds.tenantName}`));
|
|
3696
|
-
res.writeHead(200, {
|
|
4312
|
+
res.writeHead(200, {
|
|
4313
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
4314
|
+
Connection: "close"
|
|
4315
|
+
}).end(SUCCESS_HTML);
|
|
3697
4316
|
cleanup(0);
|
|
3698
4317
|
});
|
|
3699
4318
|
});
|
|
@@ -3718,15 +4337,15 @@ Logged in successfully!`));
|
|
|
3718
4337
|
);
|
|
3719
4338
|
cleanup(4);
|
|
3720
4339
|
}, TIMEOUT_MS);
|
|
3721
|
-
|
|
4340
|
+
resolve3({ port: addr.port, cleanup });
|
|
3722
4341
|
});
|
|
3723
4342
|
server.on("error", (err) => {
|
|
3724
4343
|
reject(err);
|
|
3725
4344
|
});
|
|
3726
4345
|
});
|
|
3727
4346
|
}
|
|
3728
|
-
function registerAuthCommands(
|
|
3729
|
-
|
|
4347
|
+
function registerAuthCommands(program) {
|
|
4348
|
+
program.command("login").description("Login via browser and store credentials").action(async () => {
|
|
3730
4349
|
const state = randomBytes2(32).toString("hex");
|
|
3731
4350
|
try {
|
|
3732
4351
|
const { port } = await startAuthServer({
|
|
@@ -3751,7 +4370,7 @@ ${loginUrl}`));
|
|
|
3751
4370
|
process.exit(4);
|
|
3752
4371
|
}
|
|
3753
4372
|
});
|
|
3754
|
-
|
|
4373
|
+
program.command("logout").description("Remove stored credentials").action(() => {
|
|
3755
4374
|
const deleted = deleteCredentials();
|
|
3756
4375
|
if (deleted) {
|
|
3757
4376
|
console.log(pc2.green("Logged out. Credentials removed."));
|
|
@@ -3759,7 +4378,7 @@ ${loginUrl}`));
|
|
|
3759
4378
|
console.log(pc2.dim("No stored credentials found."));
|
|
3760
4379
|
}
|
|
3761
4380
|
});
|
|
3762
|
-
|
|
4381
|
+
program.command("whoami").description("Show current authentication status").action(() => {
|
|
3763
4382
|
const localCreds = loadLocalCredentials();
|
|
3764
4383
|
const globalCreds = loadCredentials();
|
|
3765
4384
|
const creds = localCreds || globalCreds;
|
|
@@ -3777,7 +4396,7 @@ ${loginUrl}`));
|
|
|
3777
4396
|
`File: ${pc2.dim(isLocal ? getLocalCredentialsPath() : getCredentialsPath())}`
|
|
3778
4397
|
);
|
|
3779
4398
|
});
|
|
3780
|
-
const tenant =
|
|
4399
|
+
const tenant = program.command("tenant").description("Manage tenant switching");
|
|
3781
4400
|
tenant.command("list").description("Show cached tenant list").action(() => {
|
|
3782
4401
|
const tenants = loadTenantList();
|
|
3783
4402
|
if (!tenants || tenants.length === 0) {
|
|
@@ -3858,17 +4477,17 @@ ${loginUrl}`));
|
|
|
3858
4477
|
|
|
3859
4478
|
// src/commands/schema.ts
|
|
3860
4479
|
import { SERVER_COLLECTIONS as SERVER_COLLECTIONS2 } from "@01.software/sdk";
|
|
3861
|
-
function registerSchemaCommands(
|
|
3862
|
-
const schema =
|
|
4480
|
+
function registerSchemaCommands(program, getClient, getFormat) {
|
|
4481
|
+
const schema = program.command("schema").description("Collection schema introspection");
|
|
3863
4482
|
schema.command("list").description("List available collections").action(() => {
|
|
3864
|
-
printResult(SERVER_COLLECTIONS2,
|
|
4483
|
+
printResult(SERVER_COLLECTIONS2, getFormat());
|
|
3865
4484
|
});
|
|
3866
4485
|
schema.command("show <collection>").description("Show collection field schema").action(async (collection) => {
|
|
3867
4486
|
try {
|
|
3868
4487
|
const col = validateCollection(collection);
|
|
3869
|
-
const client =
|
|
4488
|
+
const client = getClient();
|
|
3870
4489
|
const result = await client.tenant.collectionSchema(col);
|
|
3871
|
-
printResult(result,
|
|
4490
|
+
printResult(result, getFormat());
|
|
3872
4491
|
} catch (e) {
|
|
3873
4492
|
exitWithError(e);
|
|
3874
4493
|
}
|
|
@@ -3887,8 +4506,8 @@ function flattenProgress(progress) {
|
|
|
3887
4506
|
}))
|
|
3888
4507
|
);
|
|
3889
4508
|
}
|
|
3890
|
-
function registerFeatureCommands(
|
|
3891
|
-
const feature =
|
|
4509
|
+
function registerFeatureCommands(program, getClient, getFormat) {
|
|
4510
|
+
const feature = program.command("feature").description("Feature implementation progress checks");
|
|
3892
4511
|
feature.command("check <feature>").description("Check tenant implementation progress for a feature").option("--evidence", "Include sanitized evidence counts and surface flags").action(async (featureName, options) => {
|
|
3893
4512
|
try {
|
|
3894
4513
|
const input = parseWithSchema(
|
|
@@ -3899,11 +4518,11 @@ function registerFeatureCommands(program2, getClient2, getFormat2) {
|
|
|
3899
4518
|
"feature",
|
|
3900
4519
|
tenantFeatureProgressInputSchema
|
|
3901
4520
|
);
|
|
3902
|
-
const client =
|
|
4521
|
+
const client = getClient();
|
|
3903
4522
|
const result = tenantFeatureProgressResponseSchema.parse(
|
|
3904
4523
|
await client.tenant.featureProgress(input)
|
|
3905
4524
|
);
|
|
3906
|
-
const format =
|
|
4525
|
+
const format = getFormat();
|
|
3907
4526
|
printResult(
|
|
3908
4527
|
format === "table" ? flattenProgress(result) : result,
|
|
3909
4528
|
format
|
|
@@ -4160,18 +4779,18 @@ function assertAgentPlanCapabilityMatrix(matrix) {
|
|
|
4160
4779
|
);
|
|
4161
4780
|
}
|
|
4162
4781
|
const seen = /* @__PURE__ */ new Set();
|
|
4163
|
-
for (const
|
|
4164
|
-
if (!AGENT_PLAN_OPERATIONS.has(
|
|
4782
|
+
for (const operation2 of operations) {
|
|
4783
|
+
if (!AGENT_PLAN_OPERATIONS.has(operation2)) {
|
|
4165
4784
|
throw new Error(
|
|
4166
|
-
`Agent plan capability operation "${
|
|
4785
|
+
`Agent plan capability operation "${operation2}" is invalid for "${collection}".`
|
|
4167
4786
|
);
|
|
4168
4787
|
}
|
|
4169
|
-
if (seen.has(
|
|
4788
|
+
if (seen.has(operation2)) {
|
|
4170
4789
|
throw new Error(
|
|
4171
|
-
`Agent plan capability operation "${
|
|
4790
|
+
`Agent plan capability operation "${operation2}" is duplicated for "${collection}".`
|
|
4172
4791
|
);
|
|
4173
4792
|
}
|
|
4174
|
-
seen.add(
|
|
4793
|
+
seen.add(operation2);
|
|
4175
4794
|
}
|
|
4176
4795
|
}
|
|
4177
4796
|
}
|
|
@@ -4185,19 +4804,19 @@ function isAgentPlanCollection(collection) {
|
|
|
4185
4804
|
function getAgentPlanOperations(collection) {
|
|
4186
4805
|
return isAgentPlanCollection(collection) ? AGENT_PLAN_CAPABILITIES[collection] : [];
|
|
4187
4806
|
}
|
|
4188
|
-
function isAgentPlanCapability(collection,
|
|
4807
|
+
function isAgentPlanCapability(collection, operation2) {
|
|
4189
4808
|
if (!isAgentPlanCollection(collection)) return false;
|
|
4190
4809
|
return AGENT_PLAN_CAPABILITIES[collection].includes(
|
|
4191
|
-
|
|
4810
|
+
operation2
|
|
4192
4811
|
);
|
|
4193
4812
|
}
|
|
4194
|
-
function assertAgentPlanCapability(collection,
|
|
4195
|
-
if (isAgentPlanCapability(collection,
|
|
4813
|
+
function assertAgentPlanCapability(collection, operation2) {
|
|
4814
|
+
if (isAgentPlanCapability(collection, operation2)) {
|
|
4196
4815
|
return collection;
|
|
4197
4816
|
}
|
|
4198
4817
|
throw agentPlanError(
|
|
4199
4818
|
"UNSUPPORTED_OPERATION",
|
|
4200
|
-
`Operation "${
|
|
4819
|
+
`Operation "${operation2}" is not supported for collection "${collection}" in agent plan mutations.`
|
|
4201
4820
|
);
|
|
4202
4821
|
}
|
|
4203
4822
|
|
|
@@ -4296,11 +4915,11 @@ function parseStoredAgentPlan(raw, planId) {
|
|
|
4296
4915
|
throw agentPlanError("PLAN_MISMATCH", "Stored plan has unsupported collection.");
|
|
4297
4916
|
}
|
|
4298
4917
|
const collection = record.collection;
|
|
4299
|
-
const
|
|
4300
|
-
if (
|
|
4918
|
+
const operation2 = record.operation;
|
|
4919
|
+
if (operation2 !== "create" && operation2 !== "update" && operation2 !== "delete") {
|
|
4301
4920
|
throw agentPlanError("PLAN_MISMATCH", "Stored plan has invalid operation.");
|
|
4302
4921
|
}
|
|
4303
|
-
if (!isAgentPlanCapability(collection,
|
|
4922
|
+
if (!isAgentPlanCapability(collection, operation2)) {
|
|
4304
4923
|
throw agentPlanError(
|
|
4305
4924
|
"PLAN_MISMATCH",
|
|
4306
4925
|
"Stored plan has unsupported collection operation."
|
|
@@ -4318,7 +4937,7 @@ function parseStoredAgentPlan(raw, planId) {
|
|
|
4318
4937
|
return {
|
|
4319
4938
|
planId,
|
|
4320
4939
|
planHash: record.planHash,
|
|
4321
|
-
operation,
|
|
4940
|
+
operation: operation2,
|
|
4322
4941
|
collection,
|
|
4323
4942
|
documentId,
|
|
4324
4943
|
payload,
|
|
@@ -4444,8 +5063,8 @@ function readDocumentUpdatedAt(doc) {
|
|
|
4444
5063
|
const updatedAt = doc.updatedAt;
|
|
4445
5064
|
return typeof updatedAt === "string" && updatedAt.length > 0 ? updatedAt : void 0;
|
|
4446
5065
|
}
|
|
4447
|
-
function assertPlanBaseUpdatedAt(
|
|
4448
|
-
if (
|
|
5066
|
+
function assertPlanBaseUpdatedAt(operation2, baseUpdatedAt) {
|
|
5067
|
+
if (operation2 === "create") {
|
|
4449
5068
|
return;
|
|
4450
5069
|
}
|
|
4451
5070
|
if (!baseUpdatedAt) {
|
|
@@ -4711,7 +5330,7 @@ async function runPlanAction(input) {
|
|
|
4711
5330
|
input.outputOptions
|
|
4712
5331
|
);
|
|
4713
5332
|
}
|
|
4714
|
-
function registerAgentPlanCommands(agent,
|
|
5333
|
+
function registerAgentPlanCommands(agent, getClient) {
|
|
4715
5334
|
const plan = configureAgentParser(
|
|
4716
5335
|
agent.command("plan").description("Plan a mutation without executing")
|
|
4717
5336
|
);
|
|
@@ -4730,7 +5349,7 @@ function registerAgentPlanCommands(agent, getClient2) {
|
|
|
4730
5349
|
dataStdin: opts.dataStdin,
|
|
4731
5350
|
dataFile: opts.dataFile,
|
|
4732
5351
|
outputOptions,
|
|
4733
|
-
getClient
|
|
5352
|
+
getClient
|
|
4734
5353
|
});
|
|
4735
5354
|
} catch (error) {
|
|
4736
5355
|
exitWithAgentError(error, outputOptions);
|
|
@@ -4754,7 +5373,7 @@ function registerAgentPlanCommands(agent, getClient2) {
|
|
|
4754
5373
|
dataStdin: opts.dataStdin,
|
|
4755
5374
|
dataFile: opts.dataFile,
|
|
4756
5375
|
outputOptions,
|
|
4757
|
-
getClient
|
|
5376
|
+
getClient
|
|
4758
5377
|
});
|
|
4759
5378
|
} catch (error) {
|
|
4760
5379
|
exitWithAgentError(error, outputOptions);
|
|
@@ -4776,7 +5395,7 @@ function registerAgentPlanCommands(agent, getClient2) {
|
|
|
4776
5395
|
collection,
|
|
4777
5396
|
documentId: id,
|
|
4778
5397
|
outputOptions,
|
|
4779
|
-
getClient
|
|
5398
|
+
getClient
|
|
4780
5399
|
});
|
|
4781
5400
|
} catch (error) {
|
|
4782
5401
|
exitWithAgentError(error, outputOptions);
|
|
@@ -4800,7 +5419,7 @@ function registerAgentPlanCommands(agent, getClient2) {
|
|
|
4800
5419
|
"Plan token does not match --hash."
|
|
4801
5420
|
);
|
|
4802
5421
|
}
|
|
4803
|
-
const client =
|
|
5422
|
+
const client = getClient();
|
|
4804
5423
|
const authFingerprint = buildAuthContextFingerprint({
|
|
4805
5424
|
publishableKey: client.publishableKey,
|
|
4806
5425
|
secretKey: client.secretKey
|
|
@@ -4915,7 +5534,7 @@ function buildAgentManifest() {
|
|
|
4915
5534
|
...AGENT_READ_OPERATIONS,
|
|
4916
5535
|
...collection === "products" ? AGENT_PRODUCT_OPERATIONS : [],
|
|
4917
5536
|
...getAgentPlanOperations(collection).map(
|
|
4918
|
-
(
|
|
5537
|
+
(operation2) => `plan:${operation2}`
|
|
4919
5538
|
)
|
|
4920
5539
|
];
|
|
4921
5540
|
collections[collection] = {
|
|
@@ -4927,7 +5546,8 @@ function buildAgentManifest() {
|
|
|
4927
5546
|
version: AGENT_PROTOCOL_VERSION,
|
|
4928
5547
|
discovery: {
|
|
4929
5548
|
context: { counts: true },
|
|
4930
|
-
schema: { mode: "effective" }
|
|
5549
|
+
schema: { mode: "effective" },
|
|
5550
|
+
doctor: { appIntegration: true }
|
|
4931
5551
|
},
|
|
4932
5552
|
collections
|
|
4933
5553
|
};
|
|
@@ -4940,9 +5560,9 @@ function validateAgentCollection(collection) {
|
|
|
4940
5560
|
throw invalidInput3(message, "collection", collection);
|
|
4941
5561
|
}
|
|
4942
5562
|
}
|
|
4943
|
-
function registerAgentCommands(
|
|
5563
|
+
function registerAgentCommands(program, getClient) {
|
|
4944
5564
|
const agent = configureAgentParser2(
|
|
4945
|
-
|
|
5565
|
+
program.command("agent").description("Machine-stable CLI namespace for coding agents").option("--pretty", "Print 2-space indented success JSON").option(
|
|
4946
5566
|
"--output-file <path>",
|
|
4947
5567
|
"Write success JSON to a secure file and print a receipt"
|
|
4948
5568
|
).addHelpText(
|
|
@@ -4972,7 +5592,7 @@ function registerAgentCommands(program2, getClient2) {
|
|
|
4972
5592
|
const outputOptions = resolveAgentPrintOptions(command);
|
|
4973
5593
|
try {
|
|
4974
5594
|
validateAgentOutputTarget(outputOptions);
|
|
4975
|
-
const client =
|
|
5595
|
+
const client = getClient();
|
|
4976
5596
|
const result = opts.counts ? await client.tenant.context({ includeCounts: true }) : await client.tenant.context();
|
|
4977
5597
|
printAgentSuccess(result, outputOptions);
|
|
4978
5598
|
} catch (error) {
|
|
@@ -4989,7 +5609,7 @@ function registerAgentCommands(program2, getClient2) {
|
|
|
4989
5609
|
try {
|
|
4990
5610
|
validateAgentOutputTarget(outputOptions);
|
|
4991
5611
|
const col = validateAgentCollection(collection);
|
|
4992
|
-
const client =
|
|
5612
|
+
const client = getClient();
|
|
4993
5613
|
const result = await client.tenant.collectionSchema(col);
|
|
4994
5614
|
printAgentSuccess(result, outputOptions);
|
|
4995
5615
|
} catch (error) {
|
|
@@ -5016,7 +5636,7 @@ function registerAgentCommands(program2, getClient2) {
|
|
|
5016
5636
|
if (page != null) options.page = page;
|
|
5017
5637
|
if (opts.sort) options.sort = opts.sort;
|
|
5018
5638
|
if (opts.select) options.select = parseSelect(opts.select);
|
|
5019
|
-
const client =
|
|
5639
|
+
const client = getClient();
|
|
5020
5640
|
const result = await client.collections.from(col).find(options);
|
|
5021
5641
|
printAgentSuccess(result, outputOptions);
|
|
5022
5642
|
} catch (error) {
|
|
@@ -5040,7 +5660,7 @@ function registerAgentCommands(program2, getClient2) {
|
|
|
5040
5660
|
}
|
|
5041
5661
|
const options = {};
|
|
5042
5662
|
if (opts.select) options.select = parseSelect(opts.select);
|
|
5043
|
-
const client =
|
|
5663
|
+
const client = getClient();
|
|
5044
5664
|
const result = await client.collections.from(col).findById(id, options);
|
|
5045
5665
|
printAgentSuccess(result, outputOptions);
|
|
5046
5666
|
} catch (error) {
|
|
@@ -5062,7 +5682,7 @@ function registerAgentCommands(program2, getClient2) {
|
|
|
5062
5682
|
try {
|
|
5063
5683
|
validateAgentOutputTarget(outputOptions);
|
|
5064
5684
|
const params = productDetailParamsFromOptions(opts);
|
|
5065
|
-
const client =
|
|
5685
|
+
const client = getClient();
|
|
5066
5686
|
const result = await client.commerce.product.detail(params);
|
|
5067
5687
|
printAgentSuccess(result, outputOptions);
|
|
5068
5688
|
} catch (error) {
|
|
@@ -5071,37 +5691,542 @@ function registerAgentCommands(program2, getClient2) {
|
|
|
5071
5691
|
}
|
|
5072
5692
|
)
|
|
5073
5693
|
);
|
|
5074
|
-
registerAgentPlanCommands(agent,
|
|
5694
|
+
registerAgentPlanCommands(agent, getClient);
|
|
5695
|
+
return agent;
|
|
5696
|
+
}
|
|
5697
|
+
|
|
5698
|
+
// src/commands/embedded-app.ts
|
|
5699
|
+
function registerEmbeddedAppCommands(program, getClient, getFormat) {
|
|
5700
|
+
const embeddedApp = program.command("embedded-app").description("Manage the active tenant embedded admin app binding");
|
|
5701
|
+
embeddedApp.command("show").description("Show the active tenant embedded app binding").action(async () => {
|
|
5702
|
+
try {
|
|
5703
|
+
const result = await getClient().embeddedAdmin.show();
|
|
5704
|
+
printResult(result, getFormat());
|
|
5705
|
+
} catch (error) {
|
|
5706
|
+
exitWithError(error);
|
|
5707
|
+
}
|
|
5708
|
+
});
|
|
5709
|
+
embeddedApp.command("configure").description("Configure and enable the active tenant embedded app").requiredOption("--label <label>", "Display label shown in Console").requiredOption("--origin <origin>", "Exact HTTPS app origin").option("--path <path>", "Relative app path", "/").option("--dry-run", "Validate inputs without executing").action(
|
|
5710
|
+
async (options) => {
|
|
5711
|
+
try {
|
|
5712
|
+
const client = getClient();
|
|
5713
|
+
const input = {
|
|
5714
|
+
label: options.label,
|
|
5715
|
+
origin: options.origin,
|
|
5716
|
+
path: options.path
|
|
5717
|
+
};
|
|
5718
|
+
const binding = client.embeddedAdmin.validateConfiguration(input);
|
|
5719
|
+
if (options.dryRun) {
|
|
5720
|
+
printResult(
|
|
5721
|
+
{
|
|
5722
|
+
action: "embedded app configure",
|
|
5723
|
+
binding,
|
|
5724
|
+
dryRun: true,
|
|
5725
|
+
valid: true
|
|
5726
|
+
},
|
|
5727
|
+
getFormat()
|
|
5728
|
+
);
|
|
5729
|
+
return;
|
|
5730
|
+
}
|
|
5731
|
+
const result = await client.embeddedAdmin.configure(input);
|
|
5732
|
+
printResult(result, getFormat());
|
|
5733
|
+
} catch (error) {
|
|
5734
|
+
exitWithError(error);
|
|
5735
|
+
}
|
|
5736
|
+
}
|
|
5737
|
+
);
|
|
5738
|
+
embeddedApp.command("disable").description("Disable the active tenant embedded app binding").option("--dry-run", "Validate without executing").action(async (options) => {
|
|
5739
|
+
try {
|
|
5740
|
+
const client = getClient();
|
|
5741
|
+
client.embeddedAdmin.validateManagementAccess();
|
|
5742
|
+
if (options.dryRun) {
|
|
5743
|
+
printResult(
|
|
5744
|
+
{
|
|
5745
|
+
action: "embedded app disable",
|
|
5746
|
+
dryRun: true,
|
|
5747
|
+
valid: true
|
|
5748
|
+
},
|
|
5749
|
+
getFormat()
|
|
5750
|
+
);
|
|
5751
|
+
return;
|
|
5752
|
+
}
|
|
5753
|
+
const result = await client.embeddedAdmin.disable();
|
|
5754
|
+
printResult(result, getFormat());
|
|
5755
|
+
} catch (error) {
|
|
5756
|
+
exitWithError(error);
|
|
5757
|
+
}
|
|
5758
|
+
});
|
|
5759
|
+
}
|
|
5760
|
+
|
|
5761
|
+
// src/lib/doctor.ts
|
|
5762
|
+
import { existsSync as existsSync2, lstatSync as lstatSync2, readFileSync as readFileSync4 } from "fs";
|
|
5763
|
+
import { createRequire } from "module";
|
|
5764
|
+
import { join as join3, resolve as resolve2 } from "path";
|
|
5765
|
+
import { satisfies, validRange } from "semver";
|
|
5766
|
+
import {
|
|
5767
|
+
TenantIntrospectionApi as TenantIntrospectionApi2,
|
|
5768
|
+
TENANT_CONTEXT_PATH
|
|
5769
|
+
} from "@01.software/sdk/server";
|
|
5770
|
+
var PUBLIC_ENV_PREFIXES = [
|
|
5771
|
+
"NEXT_PUBLIC_",
|
|
5772
|
+
"VITE_",
|
|
5773
|
+
"REACT_APP_",
|
|
5774
|
+
"PUBLIC_"
|
|
5775
|
+
];
|
|
5776
|
+
var APP_ENV_PREFIXES = ["", ...PUBLIC_ENV_PREFIXES];
|
|
5777
|
+
var envKey = (prefix, suffix) => `${prefix}${suffix}`;
|
|
5778
|
+
var PUBLISHABLE_KEYS = APP_ENV_PREFIXES.map(
|
|
5779
|
+
(prefix) => envKey(prefix, "SOFTWARE_PUBLISHABLE_KEY")
|
|
5780
|
+
);
|
|
5781
|
+
var SECRET_KEYS = APP_ENV_PREFIXES.map(
|
|
5782
|
+
(prefix) => envKey(prefix, "SOFTWARE_SECRET_KEY")
|
|
5783
|
+
);
|
|
5784
|
+
var SDK_API_URL_KEYS = [
|
|
5785
|
+
"SOFTWARE_API_URL",
|
|
5786
|
+
"NEXT_PUBLIC_SOFTWARE_API_URL"
|
|
5787
|
+
];
|
|
5788
|
+
var DoctorInputError = class extends Error {
|
|
5789
|
+
constructor(field = "envFile") {
|
|
5790
|
+
const message = field === "origin" ? "--origin must be an absolute http(s) URL." : "--app-env-file must name a readable regular environment file.";
|
|
5791
|
+
super(message);
|
|
5792
|
+
Object.assign(this, {
|
|
5793
|
+
type: "validation",
|
|
5794
|
+
code: "invalid_argument",
|
|
5795
|
+
field,
|
|
5796
|
+
detail: {
|
|
5797
|
+
message,
|
|
5798
|
+
field
|
|
5799
|
+
}
|
|
5800
|
+
});
|
|
5801
|
+
this.field = field;
|
|
5802
|
+
}
|
|
5803
|
+
};
|
|
5804
|
+
function doctorInputMessageKey(error) {
|
|
5805
|
+
if (!(error instanceof DoctorInputError)) return void 0;
|
|
5806
|
+
return error.field === "origin" ? "DoctorOriginInputInvalid" : "DoctorEnvFileInvalid";
|
|
5807
|
+
}
|
|
5808
|
+
function statusFromChecks(checks) {
|
|
5809
|
+
if (checks.some((check2) => check2.status === "blocked")) return "blocked";
|
|
5810
|
+
if (checks.some((check2) => check2.status === "attention")) return "attention";
|
|
5811
|
+
return "ready";
|
|
5812
|
+
}
|
|
5813
|
+
function compositeExitCode(checks) {
|
|
5814
|
+
const codes = checks.map((check2) => check2.exitCode).filter((code) => typeof code === "number");
|
|
5815
|
+
for (const preferred of [3, 2, 6, 4, 5, 1]) {
|
|
5816
|
+
if (codes.includes(preferred)) return preferred;
|
|
5817
|
+
}
|
|
5818
|
+
return 0;
|
|
5819
|
+
}
|
|
5820
|
+
function check(id, status, action, exitCode) {
|
|
5821
|
+
return { id, status, action, ...exitCode !== void 0 && { exitCode } };
|
|
5822
|
+
}
|
|
5823
|
+
function readPackage(cwd) {
|
|
5824
|
+
const path2 = join3(cwd, "package.json");
|
|
5825
|
+
if (!existsSync2(path2)) return null;
|
|
5826
|
+
try {
|
|
5827
|
+
const value = JSON.parse(readFileSync4(path2, "utf8"));
|
|
5828
|
+
return value && typeof value === "object" ? value : null;
|
|
5829
|
+
} catch {
|
|
5830
|
+
return null;
|
|
5831
|
+
}
|
|
5832
|
+
}
|
|
5833
|
+
function nodeEngineCheck(engine, nodeVersion = process.versions.node) {
|
|
5834
|
+
if (engine === void 0)
|
|
5835
|
+
return check("node.engine", "attention", "DoctorNodeEngineNotDeclared");
|
|
5836
|
+
if (typeof engine !== "string")
|
|
5837
|
+
return check("node.engine", "attention", "DoctorNodeEngineAttention");
|
|
5838
|
+
const range = validRange(engine);
|
|
5839
|
+
if (!range)
|
|
5840
|
+
return check("node.engine", "attention", "DoctorNodeEngineAttention");
|
|
5841
|
+
return satisfies(nodeVersion, range) ? check("node.engine", "ready", "DoctorNodeEngineReady") : check("node.engine", "attention", "DoctorNodeEngineAttention");
|
|
5842
|
+
}
|
|
5843
|
+
function parseEnv(content, file) {
|
|
5844
|
+
const declarations = [];
|
|
5845
|
+
for (const line of content.split(/\r?\n/)) {
|
|
5846
|
+
const match = line.match(
|
|
5847
|
+
/^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*?)\s*$/
|
|
5848
|
+
);
|
|
5849
|
+
if (!match) continue;
|
|
5850
|
+
let value = match[2] ?? "";
|
|
5851
|
+
if (value.length >= 2 && (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'"))) {
|
|
5852
|
+
value = value.slice(1, -1);
|
|
5853
|
+
} else {
|
|
5854
|
+
value = value.replace(/\s+#.*$/, "");
|
|
5855
|
+
}
|
|
5856
|
+
declarations.push({ key: match[1], value: value.trim(), file });
|
|
5857
|
+
}
|
|
5858
|
+
return declarations;
|
|
5859
|
+
}
|
|
5860
|
+
function readEnvFile(file) {
|
|
5861
|
+
try {
|
|
5862
|
+
if (!lstatSync2(file).isFile()) return null;
|
|
5863
|
+
return parseEnv(readFileSync4(file, "utf8"), file);
|
|
5864
|
+
} catch {
|
|
5865
|
+
return null;
|
|
5866
|
+
}
|
|
5867
|
+
}
|
|
5868
|
+
function existsIncludingSymlink(file) {
|
|
5869
|
+
try {
|
|
5870
|
+
lstatSync2(file);
|
|
5871
|
+
return true;
|
|
5872
|
+
} catch {
|
|
5873
|
+
return false;
|
|
5874
|
+
}
|
|
5875
|
+
}
|
|
5876
|
+
function resolveEnv(declarations) {
|
|
5877
|
+
const values = /* @__PURE__ */ new Map();
|
|
5878
|
+
const ambiguousKeys = /* @__PURE__ */ new Set();
|
|
5879
|
+
const declaredInFile = /* @__PURE__ */ new Set();
|
|
5880
|
+
for (const declaration of declarations) {
|
|
5881
|
+
const identity = `${declaration.file}\0${declaration.key}`;
|
|
5882
|
+
if (declaredInFile.has(identity)) ambiguousKeys.add(declaration.key);
|
|
5883
|
+
declaredInFile.add(identity);
|
|
5884
|
+
values.set(declaration.key, declaration);
|
|
5885
|
+
}
|
|
5886
|
+
return { values, ambiguousKeys, invalid: false };
|
|
5887
|
+
}
|
|
5888
|
+
function envFilesForPackage(pkg) {
|
|
5889
|
+
const deps = {
|
|
5890
|
+
...pkg?.dependencies ?? {},
|
|
5891
|
+
...pkg?.devDependencies ?? {}
|
|
5892
|
+
};
|
|
5893
|
+
if ("next" in deps || "react-scripts" in deps) {
|
|
5894
|
+
return [".env", ".env.development", ".env.local", ".env.development.local"];
|
|
5895
|
+
}
|
|
5896
|
+
if ("vite" in deps) {
|
|
5897
|
+
return [".env", ".env.local", ".env.development", ".env.development.local"];
|
|
5898
|
+
}
|
|
5899
|
+
return [".env", ".env.local"];
|
|
5900
|
+
}
|
|
5901
|
+
function readDoctorEnv(cwd, pkg, explicit) {
|
|
5902
|
+
if (explicit !== void 0) {
|
|
5903
|
+
const file = resolve2(cwd, explicit);
|
|
5904
|
+
const declarations2 = readEnvFile(file);
|
|
5905
|
+
if (!declarations2) throw new DoctorInputError();
|
|
5906
|
+
return resolveEnv(declarations2);
|
|
5907
|
+
}
|
|
5908
|
+
const declarations = [];
|
|
5909
|
+
let found = false;
|
|
5910
|
+
for (const name of envFilesForPackage(pkg)) {
|
|
5911
|
+
const file = join3(cwd, name);
|
|
5912
|
+
if (!existsIncludingSymlink(file)) continue;
|
|
5913
|
+
found = true;
|
|
5914
|
+
const parsed = readEnvFile(file);
|
|
5915
|
+
if (!parsed)
|
|
5916
|
+
return { values: /* @__PURE__ */ new Map(), ambiguousKeys: /* @__PURE__ */ new Set(), invalid: true };
|
|
5917
|
+
declarations.push(...parsed);
|
|
5918
|
+
}
|
|
5919
|
+
return found ? resolveEnv(declarations) : null;
|
|
5920
|
+
}
|
|
5921
|
+
function normalizeOrigin(origin) {
|
|
5922
|
+
try {
|
|
5923
|
+
const value = new URL(origin);
|
|
5924
|
+
if (value.protocol !== "http:" && value.protocol !== "https:" || value.username || value.password || value.origin === "null") {
|
|
5925
|
+
throw new TypeError("invalid origin");
|
|
5926
|
+
}
|
|
5927
|
+
return value.origin;
|
|
5928
|
+
} catch {
|
|
5929
|
+
throw new DoctorInputError("origin");
|
|
5930
|
+
}
|
|
5931
|
+
}
|
|
5932
|
+
function resolveDoctorApiUrl(env) {
|
|
5933
|
+
const buildDefault = true ? "https://api.01.software" : "https://api.01.software";
|
|
5934
|
+
const configured = SDK_API_URL_KEYS.map(
|
|
5935
|
+
(key) => env.values.get(key)?.value
|
|
5936
|
+
).find((value2) => Boolean(value2));
|
|
5937
|
+
const value = configured ?? buildDefault;
|
|
5938
|
+
try {
|
|
5939
|
+
return new URL(value).toString().replace(/\/$/, "");
|
|
5940
|
+
} catch {
|
|
5941
|
+
return null;
|
|
5942
|
+
}
|
|
5943
|
+
}
|
|
5944
|
+
function inspectAppCredentials(declarations) {
|
|
5945
|
+
if (!declarations || declarations.invalid) {
|
|
5946
|
+
return {
|
|
5947
|
+
credential: { ok: false },
|
|
5948
|
+
check: check(
|
|
5949
|
+
"env.app-credentials",
|
|
5950
|
+
"blocked",
|
|
5951
|
+
declarations?.invalid ? "DoctorEnvFileInvalid" : "DoctorEnvCredentialsBlocked",
|
|
5952
|
+
3
|
|
5953
|
+
)
|
|
5954
|
+
};
|
|
5955
|
+
}
|
|
5956
|
+
const publicSecret = SECRET_KEYS.slice(1).some(
|
|
5957
|
+
(key) => declarations.values.has(key)
|
|
5958
|
+
);
|
|
5959
|
+
const publishable = PUBLISHABLE_KEYS.map(
|
|
5960
|
+
(key) => declarations.values.get(key)
|
|
5961
|
+
).filter((value) => value !== void 0);
|
|
5962
|
+
const secret = declarations.values.get("SOFTWARE_SECRET_KEY");
|
|
5963
|
+
const ambiguous = [
|
|
5964
|
+
...PUBLISHABLE_KEYS,
|
|
5965
|
+
...SECRET_KEYS,
|
|
5966
|
+
...SDK_API_URL_KEYS
|
|
5967
|
+
].some((key) => declarations.ambiguousKeys.has(key));
|
|
5968
|
+
const publishableKey = publishable[0]?.value ?? "";
|
|
5969
|
+
const secretKey = secret?.value ?? "";
|
|
5970
|
+
const apiUrl = resolveDoctorApiUrl(declarations);
|
|
5971
|
+
if (publicSecret || ambiguous || publishable.length !== 1 || !secret || !publishableKey || !secretKey || !publishableKey.startsWith("pk01_") || !/^sk01_[a-f0-9]{40}$/.test(secretKey) || !apiUrl) {
|
|
5972
|
+
return {
|
|
5973
|
+
credential: { ok: false },
|
|
5974
|
+
check: check(
|
|
5975
|
+
"env.app-credentials",
|
|
5976
|
+
"blocked",
|
|
5977
|
+
"DoctorEnvCredentialsBlocked",
|
|
5978
|
+
3
|
|
5979
|
+
)
|
|
5980
|
+
};
|
|
5981
|
+
}
|
|
5982
|
+
return {
|
|
5983
|
+
credential: { ok: true, publishableKey, secretKey, apiUrl },
|
|
5984
|
+
check: check("env.app-credentials", "ready", "DoctorEnvCredentialsReady")
|
|
5985
|
+
};
|
|
5986
|
+
}
|
|
5987
|
+
async function defaultOriginProbe(input) {
|
|
5988
|
+
try {
|
|
5989
|
+
const response = await fetch(new URL(TENANT_CONTEXT_PATH, input.apiUrl), {
|
|
5990
|
+
method: "OPTIONS",
|
|
5991
|
+
signal: AbortSignal.timeout(1e4),
|
|
5992
|
+
credentials: "omit",
|
|
5993
|
+
headers: {
|
|
5994
|
+
Origin: input.origin,
|
|
5995
|
+
"X-Publishable-Key": input.publishableKey,
|
|
5996
|
+
"Access-Control-Request-Method": "GET",
|
|
5997
|
+
"Access-Control-Request-Headers": "x-publishable-key"
|
|
5998
|
+
}
|
|
5999
|
+
});
|
|
6000
|
+
if (response.status === 403) return "denied";
|
|
6001
|
+
if (!response.ok || response.status === 408 || response.status === 429 || response.status === 404 || response.status >= 500) {
|
|
6002
|
+
return "indeterminate";
|
|
6003
|
+
}
|
|
6004
|
+
const allowedOrigin = response.headers.get("access-control-allow-origin");
|
|
6005
|
+
const allowsCredentials = response.headers.get("access-control-allow-credentials")?.toLowerCase() === "true";
|
|
6006
|
+
if (allowedOrigin === input.origin) return "allowed";
|
|
6007
|
+
if (allowedOrigin === "*" && !allowsCredentials) return "allowed";
|
|
6008
|
+
return "denied";
|
|
6009
|
+
} catch {
|
|
6010
|
+
return "indeterminate";
|
|
6011
|
+
}
|
|
6012
|
+
}
|
|
6013
|
+
async function runDoctor(options = {}) {
|
|
6014
|
+
const cwd = options.cwd ?? process.cwd();
|
|
6015
|
+
const origin = options.origin === void 0 ? void 0 : normalizeOrigin(options.origin);
|
|
6016
|
+
const checks = [];
|
|
6017
|
+
const pkg = readPackage(cwd);
|
|
6018
|
+
checks.push(
|
|
6019
|
+
pkg ? check("project.package-json", "ready", "DoctorProjectPackageJsonReady") : check(
|
|
6020
|
+
"project.package-json",
|
|
6021
|
+
"blocked",
|
|
6022
|
+
"DoctorProjectPackageJsonBlocked",
|
|
6023
|
+
3
|
|
6024
|
+
)
|
|
6025
|
+
);
|
|
6026
|
+
const engine = pkg?.engines?.node;
|
|
6027
|
+
checks.push(nodeEngineCheck(engine));
|
|
6028
|
+
const deps = {
|
|
6029
|
+
...pkg?.dependencies ?? {},
|
|
6030
|
+
...pkg?.devDependencies ?? {}
|
|
6031
|
+
};
|
|
6032
|
+
checks.push(
|
|
6033
|
+
"@01.software/sdk" in deps ? check("sdk.declaration", "ready", "DoctorSdkDeclarationReady") : check("sdk.declaration", "blocked", "DoctorSdkDeclarationBlocked", 3)
|
|
6034
|
+
);
|
|
6035
|
+
let sdkInstalled = false;
|
|
6036
|
+
try {
|
|
6037
|
+
createRequire(join3(cwd, "package.json")).resolve("@01.software/sdk/server");
|
|
6038
|
+
sdkInstalled = true;
|
|
6039
|
+
} catch {
|
|
6040
|
+
}
|
|
6041
|
+
checks.push(
|
|
6042
|
+
sdkInstalled ? check("sdk.installation", "ready", "DoctorSdkInstallationReady") : check(
|
|
6043
|
+
"sdk.installation",
|
|
6044
|
+
"attention",
|
|
6045
|
+
"DoctorSdkInstallationAttention"
|
|
6046
|
+
)
|
|
6047
|
+
);
|
|
6048
|
+
const inspected = inspectAppCredentials(
|
|
6049
|
+
readDoctorEnv(cwd, pkg, options.envFile)
|
|
6050
|
+
);
|
|
6051
|
+
checks.push(inspected.check);
|
|
6052
|
+
if (inspected.credential.ok) {
|
|
6053
|
+
const { publishableKey, secretKey, apiUrl } = inspected.credential;
|
|
6054
|
+
try {
|
|
6055
|
+
if (options.tenantContext) {
|
|
6056
|
+
await options.tenantContext({ publishableKey, secretKey, apiUrl });
|
|
6057
|
+
} else {
|
|
6058
|
+
await new TenantIntrospectionApi2({
|
|
6059
|
+
publishableKey,
|
|
6060
|
+
secretKey,
|
|
6061
|
+
apiUrl
|
|
6062
|
+
}).context();
|
|
6063
|
+
}
|
|
6064
|
+
checks.push(check("tenant.context", "ready", "DoctorTenantContextReady"));
|
|
6065
|
+
} catch (error) {
|
|
6066
|
+
checks.push(
|
|
6067
|
+
check(
|
|
6068
|
+
"tenant.context",
|
|
6069
|
+
"blocked",
|
|
6070
|
+
"DoctorTenantContextBlocked",
|
|
6071
|
+
getExitCode(error)
|
|
6072
|
+
)
|
|
6073
|
+
);
|
|
6074
|
+
}
|
|
6075
|
+
if (origin) {
|
|
6076
|
+
const outcome = await (options.originProbe ?? defaultOriginProbe)({
|
|
6077
|
+
origin,
|
|
6078
|
+
apiUrl,
|
|
6079
|
+
publishableKey
|
|
6080
|
+
});
|
|
6081
|
+
checks.push(
|
|
6082
|
+
outcome === "allowed" ? check("origin.cors", "ready", "DoctorOriginCorsReady") : outcome === "denied" ? check("origin.cors", "blocked", "DoctorOriginCorsBlocked", 2) : check("origin.cors", "attention", "DoctorOriginCorsAttention")
|
|
6083
|
+
);
|
|
6084
|
+
}
|
|
6085
|
+
} else {
|
|
6086
|
+
checks.push(
|
|
6087
|
+
check("tenant.context", "blocked", "DoctorTenantContextBlocked", 3)
|
|
6088
|
+
);
|
|
6089
|
+
if (origin)
|
|
6090
|
+
checks.push(
|
|
6091
|
+
check("origin.cors", "attention", "DoctorOriginCorsAttention")
|
|
6092
|
+
);
|
|
6093
|
+
}
|
|
6094
|
+
return {
|
|
6095
|
+
version: 1,
|
|
6096
|
+
status: statusFromChecks(checks),
|
|
6097
|
+
exitCode: compositeExitCode(checks),
|
|
6098
|
+
checks
|
|
6099
|
+
};
|
|
6100
|
+
}
|
|
6101
|
+
function actionText(key, locale) {
|
|
6102
|
+
const table = locale === "ko" ? CLI_I18N_KO : CLI_I18N_EN;
|
|
6103
|
+
return table[key];
|
|
6104
|
+
}
|
|
6105
|
+
function doctorHumanLines(result, locale) {
|
|
6106
|
+
const copy = locale === "ko" ? {
|
|
6107
|
+
status: "\uC0C1\uD0DC",
|
|
6108
|
+
ready: "\uC900\uBE44\uB428",
|
|
6109
|
+
attention: "\uD655\uC778 \uD544\uC694",
|
|
6110
|
+
blocked: "\uCC28\uB2E8\uB428"
|
|
6111
|
+
} : {
|
|
6112
|
+
status: "Status",
|
|
6113
|
+
ready: "ready",
|
|
6114
|
+
attention: "attention",
|
|
6115
|
+
blocked: "blocked"
|
|
6116
|
+
};
|
|
6117
|
+
return [
|
|
6118
|
+
`${copy.status}: ${copy[result.status]}`,
|
|
6119
|
+
...result.checks.map(
|
|
6120
|
+
(item) => `[${copy[item.status]}] ${item.id}: ${actionText(item.action, locale)}`
|
|
6121
|
+
)
|
|
6122
|
+
];
|
|
6123
|
+
}
|
|
6124
|
+
|
|
6125
|
+
// src/commands/doctor.ts
|
|
6126
|
+
function selectedHumanFormat(command) {
|
|
6127
|
+
const options = command.optsWithGlobals();
|
|
6128
|
+
return options.format ?? process.env.OUTPUT_FORMAT;
|
|
6129
|
+
}
|
|
6130
|
+
function registerDoctorCommands(program, agent) {
|
|
6131
|
+
program.command("doctor").description("Check local app integration without exposing credentials").option("--app-env-file <path>", "Read one explicit app environment file").option("--origin <origin>", "Optionally probe one browser origin for CORS").action(async (options, command) => {
|
|
6132
|
+
const format = selectedHumanFormat(command);
|
|
6133
|
+
try {
|
|
6134
|
+
const result = await runDoctor({
|
|
6135
|
+
envFile: options.appEnvFile,
|
|
6136
|
+
origin: options.origin
|
|
6137
|
+
});
|
|
6138
|
+
if (format === "json") {
|
|
6139
|
+
printJson(result);
|
|
6140
|
+
} else if (format === "ndjson") {
|
|
6141
|
+
printResult(result, "ndjson");
|
|
6142
|
+
} else {
|
|
6143
|
+
for (const line of doctorHumanLines(result, detectLocale()))
|
|
6144
|
+
console.log(line);
|
|
6145
|
+
}
|
|
6146
|
+
process.exitCode = result.exitCode;
|
|
6147
|
+
} catch (error) {
|
|
6148
|
+
printError(error, {
|
|
6149
|
+
format: format ?? "table",
|
|
6150
|
+
headlineKey: doctorInputMessageKey(error)
|
|
6151
|
+
});
|
|
6152
|
+
process.exitCode = getExitCode(error);
|
|
6153
|
+
}
|
|
6154
|
+
});
|
|
6155
|
+
configureAgentParser2(
|
|
6156
|
+
agent.command("doctor").description("Check local app integration with stable JSON output").option("--app-env-file <path>", "Read one explicit app environment file").option(
|
|
6157
|
+
"--origin <origin>",
|
|
6158
|
+
"Optionally probe one browser origin for CORS"
|
|
6159
|
+
).option("--pretty", "Print 2-space indented success JSON").option(
|
|
6160
|
+
"--output-file <path>",
|
|
6161
|
+
"Write success JSON to a secure file and print a receipt"
|
|
6162
|
+
).action(async (options, command) => {
|
|
6163
|
+
const output = resolveAgentPrintOptions(command);
|
|
6164
|
+
try {
|
|
6165
|
+
validateAgentOutputTarget(output);
|
|
6166
|
+
const result = await runDoctor({
|
|
6167
|
+
envFile: options.appEnvFile,
|
|
6168
|
+
origin: options.origin
|
|
6169
|
+
});
|
|
6170
|
+
printAgentSuccess(result, output);
|
|
6171
|
+
process.exitCode = 0;
|
|
6172
|
+
} catch (error) {
|
|
6173
|
+
const envelope = printAgentError(error, output);
|
|
6174
|
+
process.exitCode = agentErrorExitCode(envelope.error.code);
|
|
6175
|
+
}
|
|
6176
|
+
})
|
|
6177
|
+
);
|
|
5075
6178
|
}
|
|
5076
6179
|
|
|
5077
6180
|
// src/index.ts
|
|
5078
|
-
var require2 =
|
|
6181
|
+
var require2 = createRequire2(import.meta.url);
|
|
5079
6182
|
var { version } = require2("../package.json");
|
|
5080
|
-
|
|
5081
|
-
program
|
|
5082
|
-
|
|
5083
|
-
|
|
5084
|
-
|
|
5085
|
-
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
registerCrudCommands(program, getClient, getFormat);
|
|
5095
|
-
registerOrderCommands(program, getClient, getFormat);
|
|
5096
|
-
registerReturnCommands(program, getClient, getFormat);
|
|
5097
|
-
registerCartCommands(program, getClient, getFormat);
|
|
5098
|
-
registerStockCommands(program, getClient, getFormat);
|
|
5099
|
-
registerCommerceSessionCommands(program, getClient, getFormat);
|
|
5100
|
-
registerProductCommands(program, getClient, getFormat);
|
|
5101
|
-
registerDiscountCommands(program, getClient, getFormat);
|
|
5102
|
-
registerShippingCommands(program, getClient, getFormat);
|
|
5103
|
-
registerSchemaCommands(program, getClient, getFormat);
|
|
5104
|
-
registerFeatureCommands(program, getClient, getFormat);
|
|
5105
|
-
|
|
5106
|
-
program
|
|
6183
|
+
function createCliProgram() {
|
|
6184
|
+
const program = new Command();
|
|
6185
|
+
program.name("01").description("CLI for the 01.software platform").version(version).option("--api-key <key>", "API key (sk01_... or pat01_... token)").option("--format <format>", "Output format: json, table, or ndjson").option("--lang <locale>", "Force locale (ko or en)");
|
|
6186
|
+
const getFormat = () => program.opts().format ?? process.env.OUTPUT_FORMAT ?? "json";
|
|
6187
|
+
program.hook("preAction", () => {
|
|
6188
|
+
const lang = program.opts().lang;
|
|
6189
|
+
if (lang === "ko" || lang === "en") setLocale(lang);
|
|
6190
|
+
const format = program.opts().format;
|
|
6191
|
+
if (format) process.env.OUTPUT_FORMAT = format;
|
|
6192
|
+
});
|
|
6193
|
+
const getClient = () => resolveClient(program.opts().apiKey);
|
|
6194
|
+
const getAgentClient = () => resolveClientOrThrow(program.opts().apiKey);
|
|
6195
|
+
const agent = registerAgentCommands(program, getAgentClient);
|
|
6196
|
+
registerDoctorCommands(program, agent);
|
|
6197
|
+
registerCrudCommands(program, getClient, getFormat);
|
|
6198
|
+
registerOrderCommands(program, getClient, getFormat);
|
|
6199
|
+
registerReturnCommands(program, getClient, getFormat);
|
|
6200
|
+
registerCartCommands(program, getClient, getFormat);
|
|
6201
|
+
registerStockCommands(program, getClient, getFormat);
|
|
6202
|
+
registerCommerceSessionCommands(program, getClient, getFormat);
|
|
6203
|
+
registerProductCommands(program, getClient, getFormat);
|
|
6204
|
+
registerDiscountCommands(program, getClient, getFormat);
|
|
6205
|
+
registerShippingCommands(program, getClient, getFormat);
|
|
6206
|
+
registerSchemaCommands(program, getClient, getFormat);
|
|
6207
|
+
registerFeatureCommands(program, getClient, getFormat);
|
|
6208
|
+
registerEmbeddedAppCommands(program, getClient, getFormat);
|
|
6209
|
+
registerAuthCommands(program);
|
|
6210
|
+
return program;
|
|
6211
|
+
}
|
|
6212
|
+
function isDirectExecution() {
|
|
6213
|
+
if (process.argv[1] === void 0) return false;
|
|
6214
|
+
try {
|
|
6215
|
+
return realpathSync(process.argv[1]) === realpathSync(fileURLToPath(import.meta.url));
|
|
6216
|
+
} catch {
|
|
6217
|
+
return false;
|
|
6218
|
+
}
|
|
6219
|
+
}
|
|
6220
|
+
if (isDirectExecution()) {
|
|
6221
|
+
const program = createCliProgram();
|
|
6222
|
+
process.on("unhandledRejection", (err) => {
|
|
6223
|
+
exitWithError(err, {
|
|
6224
|
+
format: program.opts().format ?? process.env.OUTPUT_FORMAT ?? "json"
|
|
6225
|
+
});
|
|
6226
|
+
});
|
|
6227
|
+
program.parse();
|
|
6228
|
+
}
|
|
6229
|
+
export {
|
|
6230
|
+
createCliProgram
|
|
6231
|
+
};
|
|
5107
6232
|
//# sourceMappingURL=index.js.map
|