@cimplify/cli 0.2.8 → 0.3.1
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/{add-7PTWJV4F.mjs → add-OUMIT4YX.mjs} +10 -10
- package/dist/assets-DMK2QOPD.mjs +208 -0
- package/dist/chunk-42PFJBC6.mjs +5707 -0
- package/dist/{chunk-4SBJVRGM.mjs → chunk-C4M3DXKC.mjs} +3 -1
- package/dist/{chunk-NC3GKHDD.mjs → chunk-D7WMSGKK.mjs} +1 -1
- package/dist/{chunk-NZ4RG62Z.mjs → chunk-I3XQSSOT.mjs} +4 -1
- package/dist/chunk-I6P3I2YJ.mjs +259 -0
- package/dist/{chunk-UPEHLREA.mjs → chunk-IQJ45AK3.mjs} +3 -3
- package/dist/{chunk-JJYWETGA.mjs → chunk-LS2VTSMQ.mjs} +8 -2
- package/dist/{chunk-JOUXICGV.mjs → chunk-MOZQODQS.mjs} +1 -1
- package/dist/{chunk-KPGRCXQY.mjs → chunk-QGBXGDA5.mjs} +5 -5
- package/dist/chunk-RRY3NEZZ.mjs +79 -0
- package/dist/{chunk-L6474RPL.mjs → chunk-RZQTHTXX.mjs} +1 -1
- package/dist/{chunk-4YSOZ6LY.mjs → chunk-YI7UMMM7.mjs} +1 -1
- package/dist/{deploy-6KVOROT3.mjs → deploy-UKOOPJAE.mjs} +8 -82
- package/dist/{dev-AQP6TMYK.mjs → dev-FD4PM3UD.mjs} +5 -5
- package/dist/dispatcher.mjs +34 -22
- package/dist/doctor-AY7VDIJZ.mjs +314 -0
- package/dist/{domains-2ZQ7AG27.mjs → domains-JQMV6GAP.mjs} +5 -5
- package/dist/{env-FDBPGU3W.mjs → env-EVMYQUIK.mjs} +6 -6
- package/dist/explain-QZVAK5I3.mjs +223 -0
- package/dist/introspect-MNTC26UY.mjs +8 -0
- package/dist/{link-P4K2HRXY.mjs → link-X3E4UZBF.mjs} +4 -4
- package/dist/{list-44MLIFI2.mjs → list-TEQ73IR7.mjs} +3 -3
- package/dist/{login-RSKGT6GU.mjs → login-7O7ZXKU3.mjs} +9 -15
- package/dist/{logout-ZFZLSJ32.mjs → logout-DJDINVDF.mjs} +2 -2
- package/dist/{logs-E2AGTDCF.mjs → logs-KUKGEXR2.mjs} +4 -4
- package/dist/{projects-5CJOZ3MT.mjs → projects-364HGWHO.mjs} +13 -11
- package/dist/repo-26N2CHF6.mjs +8 -0
- package/dist/{rollback-36O4NOEL.mjs → rollback-5YALPQXL.mjs} +5 -5
- package/dist/{status-6AT4HF63.mjs → status-W4HW3CX3.mjs} +4 -4
- package/dist/{unlink-5ABCT7B6.mjs → unlink-HIIW57OO.mjs} +2 -2
- package/dist/{update-6KEG7EWK.mjs → update-2DCENLHM.mjs} +7 -7
- package/dist/{whoami-DIJZYZIN.mjs → whoami-LACWBSNL.mjs} +3 -3
- package/package.json +3 -3
- package/templates/storefront-auto/.claude/skills/cimplify-storefront/SKILL.md +145 -0
- package/templates/storefront-auto/.cursor/rules/cimplify-storefront.mdc +25 -0
- package/templates/storefront-auto/.env.example +22 -0
- package/templates/storefront-auto/AGENTS.md +95 -0
- package/templates/storefront-auto/CLAUDE.md +22 -0
- package/templates/storefront-auto/README.md +48 -0
- package/templates/storefront-auto/__tests__/brand.test.ts +4 -0
- package/templates/storefront-auto/__tests__/cart-flow.test.ts +4 -0
- package/templates/storefront-auto/__tests__/contract.test.ts +4 -0
- package/templates/storefront-auto/app/.well-known/ucp/route.ts +65 -0
- package/templates/storefront-auto/app/about/page.tsx +41 -0
- package/templates/storefront-auto/app/accessibility/page.tsx +11 -0
- package/templates/storefront-auto/app/account/addresses/page.tsx +21 -0
- package/templates/storefront-auto/app/account/orders/page.tsx +21 -0
- package/templates/storefront-auto/app/account/page.tsx +22 -0
- package/templates/storefront-auto/app/account/settings/page.tsx +21 -0
- package/templates/storefront-auto/app/cart/page.tsx +9 -0
- package/templates/storefront-auto/app/categories/[slug]/listing-client.tsx +19 -0
- package/templates/storefront-auto/app/categories/[slug]/page.tsx +130 -0
- package/templates/storefront-auto/app/checkout/page.tsx +17 -0
- package/templates/storefront-auto/app/collections/[slug]/listing-client.tsx +20 -0
- package/templates/storefront-auto/app/collections/[slug]/page.tsx +130 -0
- package/templates/storefront-auto/app/contact/contact-form.tsx +109 -0
- package/templates/storefront-auto/app/contact/page.tsx +54 -0
- package/templates/storefront-auto/app/error.tsx +61 -0
- package/templates/storefront-auto/app/faq/page.tsx +46 -0
- package/templates/storefront-auto/app/globals.css +47 -0
- package/templates/storefront-auto/app/layout.tsx +77 -0
- package/templates/storefront-auto/app/llms.txt/route.ts +94 -0
- package/templates/storefront-auto/app/login/page.tsx +17 -0
- package/templates/storefront-auto/app/not-found.tsx +39 -0
- package/templates/storefront-auto/app/opensearch.xml/route.ts +37 -0
- package/templates/storefront-auto/app/orders/[id]/page.tsx +24 -0
- package/templates/storefront-auto/app/page.tsx +94 -0
- package/templates/storefront-auto/app/privacy/page.tsx +44 -0
- package/templates/storefront-auto/app/products/[slug]/page.tsx +165 -0
- package/templates/storefront-auto/app/products/[slug]/product-detail.tsx +70 -0
- package/templates/storefront-auto/app/returns/page.tsx +11 -0
- package/templates/storefront-auto/app/robots.ts +18 -0
- package/templates/storefront-auto/app/search/page.tsx +38 -0
- package/templates/storefront-auto/app/search/search-client.tsx +7 -0
- package/templates/storefront-auto/app/shipping/page.tsx +16 -0
- package/templates/storefront-auto/app/shop/page.tsx +63 -0
- package/templates/storefront-auto/app/shop/shop-client.tsx +32 -0
- package/templates/storefront-auto/app/signup/page.tsx +17 -0
- package/templates/storefront-auto/app/sitemap-page/page.tsx +167 -0
- package/templates/storefront-auto/app/sitemap.ts +59 -0
- package/templates/storefront-auto/app/terms/page.tsx +44 -0
- package/templates/storefront-auto/app/track-order/page.tsx +24 -0
- package/templates/storefront-auto/app/track-order/track-order-form.tsx +69 -0
- package/templates/storefront-auto/components/account-iframe.tsx +13 -0
- package/templates/storefront-auto/components/auto-hero.tsx +85 -0
- package/templates/storefront-auto/components/brand-marquee.tsx +27 -0
- package/templates/storefront-auto/components/cart-drawer.tsx +14 -0
- package/templates/storefront-auto/components/cart-pill.tsx +36 -0
- package/templates/storefront-auto/components/category-grid.tsx +28 -0
- package/templates/storefront-auto/components/category-tiles.tsx +104 -0
- package/templates/storefront-auto/components/collection-strip.tsx +45 -0
- package/templates/storefront-auto/components/feature-hero.tsx +84 -0
- package/templates/storefront-auto/components/fitment-finder.tsx +184 -0
- package/templates/storefront-auto/components/footer.tsx +153 -0
- package/templates/storefront-auto/components/header.tsx +45 -0
- package/templates/storefront-auto/components/hero.tsx +28 -0
- package/templates/storefront-auto/components/nav-link.tsx +20 -0
- package/templates/storefront-auto/components/newsletter.tsx +50 -0
- package/templates/storefront-auto/components/policy-page.tsx +49 -0
- package/templates/storefront-auto/components/promo-banner.tsx +41 -0
- package/templates/storefront-auto/components/providers.tsx +35 -0
- package/templates/storefront-auto/components/section-heading.tsx +37 -0
- package/templates/storefront-auto/components/service-brief.tsx +65 -0
- package/templates/storefront-auto/components/store-product-card.tsx +88 -0
- package/templates/storefront-auto/components/trade-in-cta.tsx +54 -0
- package/templates/storefront-auto/components/trust-bar.tsx +66 -0
- package/templates/storefront-auto/lib/brand.ts +744 -0
- package/templates/storefront-auto/lib/cart.ts +12 -0
- package/templates/storefront-auto/lib/cimplify-loader.ts +19 -0
- package/templates/storefront-auto/next.config.ts +45 -0
- package/templates/storefront-auto/package.json +35 -0
- package/templates/storefront-auto/postcss.config.mjs +7 -0
- package/templates/storefront-auto/tsconfig.json +23 -0
- package/templates/storefront-auto/vitest.config.ts +9 -0
- package/templates/storefront-bakery/.env.example +2 -2
- package/templates/storefront-bakery/README.md +1 -1
- package/templates/storefront-bakery/lib/cimplify-loader.ts +19 -0
- package/templates/storefront-bakery/next.config.ts +3 -0
- package/templates/storefront-bakery/package.json +1 -1
- package/templates/storefront-fashion/.env.example +2 -2
- package/templates/storefront-fashion/README.md +1 -1
- package/templates/storefront-fashion/lib/cimplify-loader.ts +19 -0
- package/templates/storefront-fashion/next.config.ts +3 -0
- package/templates/storefront-fashion/package.json +1 -1
- package/templates/storefront-grocery/.env.example +2 -2
- package/templates/storefront-grocery/README.md +1 -1
- package/templates/storefront-grocery/lib/cimplify-loader.ts +19 -0
- package/templates/storefront-grocery/next.config.ts +3 -0
- package/templates/storefront-grocery/package.json +1 -1
- package/templates/storefront-pharmacy/.claude/skills/cimplify-storefront/SKILL.md +145 -0
- package/templates/storefront-pharmacy/.cursor/rules/cimplify-storefront.mdc +25 -0
- package/templates/storefront-pharmacy/.env.example +22 -0
- package/templates/storefront-pharmacy/AGENTS.md +118 -0
- package/templates/storefront-pharmacy/CLAUDE.md +22 -0
- package/templates/storefront-pharmacy/README.md +87 -0
- package/templates/storefront-pharmacy/__tests__/brand.test.ts +4 -0
- package/templates/storefront-pharmacy/__tests__/cart-flow.test.ts +4 -0
- package/templates/storefront-pharmacy/__tests__/contract.test.ts +4 -0
- package/templates/storefront-pharmacy/app/.well-known/ucp/route.ts +65 -0
- package/templates/storefront-pharmacy/app/about/page.tsx +41 -0
- package/templates/storefront-pharmacy/app/accessibility/page.tsx +11 -0
- package/templates/storefront-pharmacy/app/account/addresses/page.tsx +21 -0
- package/templates/storefront-pharmacy/app/account/orders/page.tsx +21 -0
- package/templates/storefront-pharmacy/app/account/page.tsx +22 -0
- package/templates/storefront-pharmacy/app/account/settings/page.tsx +21 -0
- package/templates/storefront-pharmacy/app/cart/page.tsx +9 -0
- package/templates/storefront-pharmacy/app/categories/[slug]/listing-client.tsx +19 -0
- package/templates/storefront-pharmacy/app/categories/[slug]/page.tsx +130 -0
- package/templates/storefront-pharmacy/app/checkout/page.tsx +17 -0
- package/templates/storefront-pharmacy/app/collections/[slug]/listing-client.tsx +20 -0
- package/templates/storefront-pharmacy/app/collections/[slug]/page.tsx +130 -0
- package/templates/storefront-pharmacy/app/contact/contact-form.tsx +109 -0
- package/templates/storefront-pharmacy/app/contact/page.tsx +54 -0
- package/templates/storefront-pharmacy/app/error.tsx +61 -0
- package/templates/storefront-pharmacy/app/faq/page.tsx +46 -0
- package/templates/storefront-pharmacy/app/globals.css +47 -0
- package/templates/storefront-pharmacy/app/layout.tsx +77 -0
- package/templates/storefront-pharmacy/app/llms.txt/route.ts +94 -0
- package/templates/storefront-pharmacy/app/login/page.tsx +17 -0
- package/templates/storefront-pharmacy/app/not-found.tsx +39 -0
- package/templates/storefront-pharmacy/app/opensearch.xml/route.ts +37 -0
- package/templates/storefront-pharmacy/app/orders/[id]/page.tsx +24 -0
- package/templates/storefront-pharmacy/app/page.tsx +78 -0
- package/templates/storefront-pharmacy/app/privacy/page.tsx +44 -0
- package/templates/storefront-pharmacy/app/products/[slug]/page.tsx +165 -0
- package/templates/storefront-pharmacy/app/products/[slug]/product-detail.tsx +70 -0
- package/templates/storefront-pharmacy/app/returns/page.tsx +11 -0
- package/templates/storefront-pharmacy/app/robots.ts +18 -0
- package/templates/storefront-pharmacy/app/search/page.tsx +38 -0
- package/templates/storefront-pharmacy/app/search/search-client.tsx +7 -0
- package/templates/storefront-pharmacy/app/shipping/page.tsx +16 -0
- package/templates/storefront-pharmacy/app/shop/page.tsx +63 -0
- package/templates/storefront-pharmacy/app/shop/shop-client.tsx +32 -0
- package/templates/storefront-pharmacy/app/signup/page.tsx +17 -0
- package/templates/storefront-pharmacy/app/sitemap-page/page.tsx +167 -0
- package/templates/storefront-pharmacy/app/sitemap.ts +59 -0
- package/templates/storefront-pharmacy/app/terms/page.tsx +44 -0
- package/templates/storefront-pharmacy/app/track-order/page.tsx +24 -0
- package/templates/storefront-pharmacy/app/track-order/track-order-form.tsx +69 -0
- package/templates/storefront-pharmacy/components/account-iframe.tsx +13 -0
- package/templates/storefront-pharmacy/components/brand-marquee.tsx +27 -0
- package/templates/storefront-pharmacy/components/cart-drawer.tsx +14 -0
- package/templates/storefront-pharmacy/components/cart-pill.tsx +36 -0
- package/templates/storefront-pharmacy/components/category-grid.tsx +28 -0
- package/templates/storefront-pharmacy/components/category-tiles.tsx +104 -0
- package/templates/storefront-pharmacy/components/collection-strip.tsx +45 -0
- package/templates/storefront-pharmacy/components/feature-hero.tsx +84 -0
- package/templates/storefront-pharmacy/components/footer.tsx +153 -0
- package/templates/storefront-pharmacy/components/header.tsx +45 -0
- package/templates/storefront-pharmacy/components/health-brief.tsx +65 -0
- package/templates/storefront-pharmacy/components/hero.tsx +28 -0
- package/templates/storefront-pharmacy/components/nav-link.tsx +20 -0
- package/templates/storefront-pharmacy/components/newsletter.tsx +50 -0
- package/templates/storefront-pharmacy/components/pharmacy-hero.tsx +95 -0
- package/templates/storefront-pharmacy/components/policy-page.tsx +49 -0
- package/templates/storefront-pharmacy/components/promo-banner.tsx +41 -0
- package/templates/storefront-pharmacy/components/providers.tsx +35 -0
- package/templates/storefront-pharmacy/components/section-heading.tsx +37 -0
- package/templates/storefront-pharmacy/components/store-product-card.tsx +88 -0
- package/templates/storefront-pharmacy/components/symptom-finder.tsx +108 -0
- package/templates/storefront-pharmacy/components/trade-in-cta.tsx +54 -0
- package/templates/storefront-pharmacy/components/trust-bar.tsx +66 -0
- package/templates/storefront-pharmacy/components/urgent-ctas.tsx +117 -0
- package/templates/storefront-pharmacy/lib/brand.ts +790 -0
- package/templates/storefront-pharmacy/lib/cart.ts +12 -0
- package/templates/storefront-pharmacy/lib/cimplify-loader.ts +19 -0
- package/templates/storefront-pharmacy/next.config.ts +45 -0
- package/templates/storefront-pharmacy/package.json +35 -0
- package/templates/storefront-pharmacy/postcss.config.mjs +7 -0
- package/templates/storefront-pharmacy/tsconfig.json +23 -0
- package/templates/storefront-pharmacy/vitest.config.ts +9 -0
- package/templates/storefront-restaurant/.env.example +2 -2
- package/templates/storefront-restaurant/README.md +1 -1
- package/templates/storefront-restaurant/lib/cimplify-loader.ts +19 -0
- package/templates/storefront-restaurant/next.config.ts +3 -0
- package/templates/storefront-restaurant/package.json +1 -1
- package/templates/storefront-retail/.env.example +2 -2
- package/templates/storefront-retail/README.md +1 -1
- package/templates/storefront-retail/lib/cimplify-loader.ts +19 -0
- package/templates/storefront-retail/next.config.ts +3 -0
- package/templates/storefront-retail/package.json +1 -1
- package/templates/storefront-services/.env.example +2 -2
- package/templates/storefront-services/README.md +1 -1
- package/templates/storefront-services/lib/cimplify-loader.ts +19 -0
- package/templates/storefront-services/next.config.ts +3 -0
- package/templates/storefront-services/package.json +1 -1
- package/dist/chunk-H2HJQGFY.mjs +0 -3911
- package/dist/repo-E6SBKVDG.mjs +0 -8
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { REGISTRY_INDEX, REGISTRY } from './chunk-
|
|
3
|
-
import { promptYesNo } from './chunk-
|
|
4
|
-
import { parseArgs, flagString, flagBool } from './chunk-
|
|
5
|
-
import { CliError, CLI_ERROR_CODE, info, bold, dim, success, result, yellow } from './chunk-
|
|
2
|
+
import { REGISTRY_INDEX, REGISTRY } from './chunk-42PFJBC6.mjs';
|
|
3
|
+
import { promptYesNo } from './chunk-RZQTHTXX.mjs';
|
|
4
|
+
import { parseArgs, flagString, flagBool } from './chunk-C4M3DXKC.mjs';
|
|
5
|
+
import { CliError, CLI_ERROR_CODE, info, bold, dim, success, result, yellow } from './chunk-I3XQSSOT.mjs';
|
|
6
6
|
import { mkdirSync, existsSync, writeFileSync } from 'fs';
|
|
7
7
|
import { resolve, join, dirname } from 'path';
|
|
8
8
|
|
|
@@ -54,21 +54,21 @@ async function writeComponent(component, options) {
|
|
|
54
54
|
}
|
|
55
55
|
return outcome;
|
|
56
56
|
}
|
|
57
|
-
function
|
|
57
|
+
function resolveOrder(roots, getDeps) {
|
|
58
58
|
const visited = /* @__PURE__ */ new Set();
|
|
59
59
|
const order = [];
|
|
60
60
|
function visit(name) {
|
|
61
61
|
if (visited.has(name)) return;
|
|
62
62
|
visited.add(name);
|
|
63
|
-
const
|
|
64
|
-
for (const dep of component.registryDependencies) {
|
|
65
|
-
visit(dep);
|
|
66
|
-
}
|
|
63
|
+
for (const dep of getDeps(name)) visit(dep);
|
|
67
64
|
order.push(name);
|
|
68
65
|
}
|
|
69
66
|
for (const root of roots) visit(root);
|
|
70
67
|
return order;
|
|
71
68
|
}
|
|
69
|
+
function resolveDependencyOrder(roots) {
|
|
70
|
+
return resolveOrder(roots, (name) => loadComponent(name).registryDependencies);
|
|
71
|
+
}
|
|
72
72
|
async function run(argv) {
|
|
73
73
|
const args = parseArgs(argv);
|
|
74
74
|
const dirFlag = flagString(args, "dir");
|
|
@@ -122,4 +122,4 @@ async function run(argv) {
|
|
|
122
122
|
});
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
export { run as default };
|
|
125
|
+
export { run as default, resolveOrder };
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { parseArgs, flagString, flagBool } from './chunk-C4M3DXKC.mjs';
|
|
3
|
+
import { ApiClient } from './chunk-D7WMSGKK.mjs';
|
|
4
|
+
import { readAuth } from './chunk-LS2VTSMQ.mjs';
|
|
5
|
+
import { CliError, CLI_ERROR_CODE, step, yellow, dim, success, info, result, bold, green } from './chunk-I3XQSSOT.mjs';
|
|
6
|
+
import { createHash } from 'crypto';
|
|
7
|
+
import { promises } from 'fs';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
|
|
10
|
+
var MANIFEST_FILE = "cimplify-assets.json";
|
|
11
|
+
var DEFAULT_FOLDER = "assets";
|
|
12
|
+
var MAX_FILE_SIZE_BYTES = 50 * 1024 * 1024;
|
|
13
|
+
var CONTENT_TYPE_FALLBACK = "application/octet-stream";
|
|
14
|
+
var MIME_BY_EXT = {
|
|
15
|
+
".jpg": "image/jpeg",
|
|
16
|
+
".jpeg": "image/jpeg",
|
|
17
|
+
".png": "image/png",
|
|
18
|
+
".gif": "image/gif",
|
|
19
|
+
".webp": "image/webp",
|
|
20
|
+
".avif": "image/avif",
|
|
21
|
+
".svg": "image/svg+xml",
|
|
22
|
+
".pdf": "application/pdf",
|
|
23
|
+
".mp4": "video/mp4",
|
|
24
|
+
".webm": "video/webm",
|
|
25
|
+
".woff2": "font/woff2",
|
|
26
|
+
".woff": "font/woff",
|
|
27
|
+
".ttf": "font/ttf"
|
|
28
|
+
};
|
|
29
|
+
function endpointInit(businessId) {
|
|
30
|
+
return `/v1/businesses/${encodeURIComponent(businessId)}/assets/init`;
|
|
31
|
+
}
|
|
32
|
+
function endpointConfirm(businessId) {
|
|
33
|
+
return `/v1/businesses/${encodeURIComponent(businessId)}/assets/confirm`;
|
|
34
|
+
}
|
|
35
|
+
function manifestPath(cwd = process.cwd()) {
|
|
36
|
+
return path.join(cwd, MANIFEST_FILE);
|
|
37
|
+
}
|
|
38
|
+
async function readManifest(cwd = process.cwd()) {
|
|
39
|
+
try {
|
|
40
|
+
const raw = await promises.readFile(manifestPath(cwd), "utf8");
|
|
41
|
+
return JSON.parse(raw);
|
|
42
|
+
} catch (err) {
|
|
43
|
+
if (err.code === "ENOENT") return {};
|
|
44
|
+
throw err;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async function writeManifest(manifest, cwd = process.cwd()) {
|
|
48
|
+
const payload = `${JSON.stringify(manifest, null, 2)}
|
|
49
|
+
`;
|
|
50
|
+
await promises.writeFile(manifestPath(cwd), payload, "utf8");
|
|
51
|
+
}
|
|
52
|
+
function mimeOf(filename) {
|
|
53
|
+
const ext = path.extname(filename).toLowerCase();
|
|
54
|
+
return MIME_BY_EXT[ext] ?? CONTENT_TYPE_FALLBACK;
|
|
55
|
+
}
|
|
56
|
+
function sha256Hex(buf) {
|
|
57
|
+
return createHash("sha256").update(buf).digest("hex");
|
|
58
|
+
}
|
|
59
|
+
async function walkFiles(root) {
|
|
60
|
+
const out = [];
|
|
61
|
+
async function visit(dir) {
|
|
62
|
+
const entries = await promises.readdir(dir, { withFileTypes: true });
|
|
63
|
+
for (const e of entries) {
|
|
64
|
+
const abs = path.join(dir, e.name);
|
|
65
|
+
if (e.isDirectory()) await visit(abs);
|
|
66
|
+
else if (e.isFile()) out.push(abs);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
await visit(root);
|
|
70
|
+
return out;
|
|
71
|
+
}
|
|
72
|
+
async function run(argv) {
|
|
73
|
+
const args = parseArgs(argv);
|
|
74
|
+
const sub = args.positional[0];
|
|
75
|
+
if (!sub) {
|
|
76
|
+
throw new CliError(CLI_ERROR_CODE.INVALID_INPUT, "Usage: cimplify assets <upload|ls|rm>");
|
|
77
|
+
}
|
|
78
|
+
switch (sub) {
|
|
79
|
+
case "upload":
|
|
80
|
+
return runUpload(args);
|
|
81
|
+
case "ls":
|
|
82
|
+
return runLs(args);
|
|
83
|
+
case "rm":
|
|
84
|
+
return runRm(args);
|
|
85
|
+
default:
|
|
86
|
+
throw new CliError(
|
|
87
|
+
CLI_ERROR_CODE.INVALID_INPUT,
|
|
88
|
+
`Unknown subcommand "${sub}". Use upload, ls, or rm.`
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async function runUpload(args) {
|
|
93
|
+
const dir = args.positional[1];
|
|
94
|
+
if (!dir) {
|
|
95
|
+
throw new CliError(CLI_ERROR_CODE.INVALID_INPUT, "Usage: cimplify assets upload <dir> [--folder <path>]");
|
|
96
|
+
}
|
|
97
|
+
const folder = flagString(args, "folder") ?? DEFAULT_FOLDER;
|
|
98
|
+
const force = flagBool(args, "force");
|
|
99
|
+
const root = path.resolve(process.cwd(), dir);
|
|
100
|
+
const stat = await promises.stat(root).catch(() => null);
|
|
101
|
+
if (!stat?.isDirectory()) {
|
|
102
|
+
throw new CliError(CLI_ERROR_CODE.NOT_FOUND, `Directory not found: ${root}`);
|
|
103
|
+
}
|
|
104
|
+
const auth = await readAuth();
|
|
105
|
+
const client = ApiClient.fromAuth(auth);
|
|
106
|
+
const manifest = await readManifest();
|
|
107
|
+
const files = await walkFiles(root);
|
|
108
|
+
const uploaded = [];
|
|
109
|
+
const skipped = [];
|
|
110
|
+
for (const abs of files) {
|
|
111
|
+
const rel = path.relative(root, abs).replaceAll(path.sep, "/");
|
|
112
|
+
const filename = path.basename(rel);
|
|
113
|
+
const keyForManifest = `${folder}/${rel}`;
|
|
114
|
+
const contentType = mimeOf(filename);
|
|
115
|
+
const buf = await promises.readFile(abs);
|
|
116
|
+
if (buf.byteLength > MAX_FILE_SIZE_BYTES) {
|
|
117
|
+
throw new CliError(
|
|
118
|
+
CLI_ERROR_CODE.INVALID_INPUT,
|
|
119
|
+
`${rel}: ${buf.byteLength} bytes exceeds 50 MB limit`
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
const hash = sha256Hex(buf);
|
|
123
|
+
const existing = manifest[keyForManifest];
|
|
124
|
+
if (existing && existing.sha256 === hash && !force) {
|
|
125
|
+
step(`${yellow("skip")} ${keyForManifest} ${dim("(unchanged)")}`);
|
|
126
|
+
skipped.push(keyForManifest);
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
const subfolder = path.posix.join(folder, path.posix.dirname(rel));
|
|
130
|
+
const init = await client.post(endpointInit(auth.businessId), {
|
|
131
|
+
folder: subfolder,
|
|
132
|
+
filename,
|
|
133
|
+
content_type: contentType,
|
|
134
|
+
size_bytes: buf.byteLength
|
|
135
|
+
});
|
|
136
|
+
step(`${dim("\u2192")} ${keyForManifest} ${dim(`(${buf.byteLength} bytes)`)}`);
|
|
137
|
+
const putRes = await fetch(init.upload_url, {
|
|
138
|
+
method: "PUT",
|
|
139
|
+
headers: { "content-type": contentType },
|
|
140
|
+
body: buf
|
|
141
|
+
});
|
|
142
|
+
if (!putRes.ok) {
|
|
143
|
+
throw new CliError(
|
|
144
|
+
CLI_ERROR_CODE.NETWORK_ERROR,
|
|
145
|
+
`PUT to R2 failed for ${keyForManifest}: ${putRes.status} ${putRes.statusText}`
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
const confirmed = await client.post(endpointConfirm(auth.businessId), {
|
|
149
|
+
upload_id: init.upload_id
|
|
150
|
+
});
|
|
151
|
+
manifest[keyForManifest] = {
|
|
152
|
+
url: confirmed.url,
|
|
153
|
+
upload_id: init.upload_id,
|
|
154
|
+
folder: subfolder,
|
|
155
|
+
filename,
|
|
156
|
+
content_type: contentType,
|
|
157
|
+
size_bytes: buf.byteLength,
|
|
158
|
+
sha256: hash,
|
|
159
|
+
uploaded_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
160
|
+
};
|
|
161
|
+
uploaded.push(keyForManifest);
|
|
162
|
+
}
|
|
163
|
+
await writeManifest(manifest);
|
|
164
|
+
success(`Uploaded ${uploaded.length} file${uploaded.length === 1 ? "" : "s"} (${skipped.length} skipped)`);
|
|
165
|
+
info(dim(`Manifest: ${manifestPath()}`));
|
|
166
|
+
result({
|
|
167
|
+
uploaded_count: uploaded.length,
|
|
168
|
+
skipped_count: skipped.length,
|
|
169
|
+
manifest_path: manifestPath(),
|
|
170
|
+
uploaded,
|
|
171
|
+
skipped
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
async function runLs(args) {
|
|
175
|
+
const prefix = flagString(args, "prefix");
|
|
176
|
+
const manifest = await readManifest();
|
|
177
|
+
const entries = Object.entries(manifest).filter(([k]) => prefix ? k.startsWith(prefix) : true).sort(([a], [b]) => a.localeCompare(b));
|
|
178
|
+
if (entries.length === 0) {
|
|
179
|
+
info(dim("No assets uploaded yet."));
|
|
180
|
+
} else {
|
|
181
|
+
info(bold(`Assets in ${MANIFEST_FILE}:`));
|
|
182
|
+
for (const [key, entry] of entries) {
|
|
183
|
+
info(` ${green("\u25CF")} ${key} ${dim(`\u2192 ${entry.url}`)}`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
result({
|
|
187
|
+
count: entries.length,
|
|
188
|
+
assets: entries.map(([key, entry]) => ({ key, ...entry }))
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
async function runRm(args) {
|
|
192
|
+
const key = args.positional[1];
|
|
193
|
+
if (!key) {
|
|
194
|
+
throw new CliError(CLI_ERROR_CODE.INVALID_INPUT, "Usage: cimplify assets rm <key>");
|
|
195
|
+
}
|
|
196
|
+
const manifest = await readManifest();
|
|
197
|
+
if (!(key in manifest)) {
|
|
198
|
+
throw new CliError(CLI_ERROR_CODE.NOT_FOUND, `Key not found in manifest: ${key}`);
|
|
199
|
+
}
|
|
200
|
+
const removed = manifest[key];
|
|
201
|
+
delete manifest[key];
|
|
202
|
+
await writeManifest(manifest);
|
|
203
|
+
success(`Removed ${key} from manifest`);
|
|
204
|
+
info(dim("Note: remote blob is not deleted in v1 \u2014 only the manifest entry."));
|
|
205
|
+
result({ removed_key: key, removed_url: removed.url });
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export { run as default, endpointConfirm, endpointInit, mimeOf, readManifest, sha256Hex, walkFiles, writeManifest };
|