@cimplify/cli 0.13.4 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{add-542NLKYG.mjs → add-PPUGTTDA.mjs} +1 -1
- package/dist/{chunk-OE7YRDLH.mjs → chunk-7CI5RWNE.mjs} +22 -4
- package/dist/{chunk-VCDGYXFU.mjs → chunk-JOF7ESSA.mjs} +9 -9
- package/dist/{chunk-7NUSJVN3.mjs → chunk-KAZMZD4X.mjs} +2 -2
- package/dist/{chunk-HJQ6PF5N.mjs → chunk-SOYZZZVT.mjs} +2 -2
- package/dist/{chunk-MLVBE5V2.mjs → chunk-YIBOOKQQ.mjs} +15 -1
- package/dist/{deploy-SLRFPGTH.mjs → deploy-64ZVAQ3R.mjs} +36 -3
- package/dist/dispatcher.mjs +14 -14
- package/dist/{doctor-E6JH4VSN.mjs → doctor-6ZIFM5J5.mjs} +3 -3
- package/dist/{explain-SZPLL5MP.mjs → explain-REIDDRKC.mjs} +2 -2
- package/dist/{introspect-SDHD3PVX.mjs → introspect-APRI7R7K.mjs} +3 -3
- package/dist/{link-KGNQWCSZ.mjs → link-AWC7VJNN.mjs} +18 -1
- package/dist/{lint-NM3APP7L.mjs → lint-EYKIQ6RO.mjs} +9 -5
- package/dist/{list-W5JABY7B.mjs → list-7ZL6FRKT.mjs} +1 -1
- package/dist/{projects-U75DOOR7.mjs → projects-P65SUETQ.mjs} +2 -2
- package/dist/{repo-IE5IOLR5.mjs → repo-ZPYZK3KW.mjs} +2 -1
- package/dist/{update-447FR363.mjs → update-MBEPZANS.mjs} +1 -1
- package/package.json +2 -2
- package/templates/storefront-auto/package.json +1 -1
- package/templates/storefront-bakery/package.json +1 -1
- package/templates/storefront-fashion/package.json +1 -1
- package/templates/storefront-grocery/package.json +1 -1
- package/templates/storefront-pharmacy/package.json +1 -1
- package/templates/storefront-restaurant/package.json +1 -1
- package/templates/storefront-retail/package.json +1 -1
- package/templates/storefront-services/package.json +1 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// package.json
|
|
3
3
|
var package_default = {
|
|
4
4
|
name: "@cimplify/cli",
|
|
5
|
-
version: "0.
|
|
5
|
+
version: "0.14.0",
|
|
6
6
|
description: "Cimplify CLI \u2014 deploy, manage env vars, link projects, and scaffold storefronts",
|
|
7
7
|
keywords: [
|
|
8
8
|
"cimplify",
|
|
@@ -43,7 +43,7 @@ var package_default = {
|
|
|
43
43
|
"@babel/parser": "^8.0.4",
|
|
44
44
|
"@babel/traverse": "^8.0.4",
|
|
45
45
|
"@babel/types": "^8.0.4",
|
|
46
|
-
"@cimplify/sdk": "^0.
|
|
46
|
+
"@cimplify/sdk": "^0.101.1",
|
|
47
47
|
re2js: "^1.4.0"
|
|
48
48
|
},
|
|
49
49
|
devDependencies: {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { gitDetectRoot, gitCurrentBranch, gitCurrentSha, gitStatusPorcelain } from './chunk-MLVBE5V2.mjs';
|
|
3
2
|
import { parseEnvFile } from './chunk-RU53TQLZ.mjs';
|
|
4
|
-
import { package_default } from './chunk-
|
|
3
|
+
import { package_default } from './chunk-KAZMZD4X.mjs';
|
|
4
|
+
import { gitDetectRoot, gitCurrentBranch, gitCurrentSha, gitStatusPorcelain } from './chunk-YIBOOKQQ.mjs';
|
|
5
5
|
import { parseArgs } from './chunk-5KYR6WJB.mjs';
|
|
6
6
|
import { readAuthOrNull, readProjectLinkOrNull, readProjectState } from './chunk-6CHBU7O4.mjs';
|
|
7
7
|
import { bold, dim, yellow, green, info, result, red } from './chunk-4O4G2CDE.mjs';
|
|
@@ -10,6 +10,8 @@ var ARGS_REV_PARSE_HEAD = ["rev-parse", "HEAD"];
|
|
|
10
10
|
var ARGS_REV_PARSE_ABBREV_REF = ["rev-parse", "--abbrev-ref", "HEAD"];
|
|
11
11
|
var ARGS_REV_PARSE_SHOW_TOPLEVEL = ["rev-parse", "--show-toplevel"];
|
|
12
12
|
var ARGS_REMOTE_GET_URL = ["remote", "get-url"];
|
|
13
|
+
var ARGS_REMOTE_ADD = ["remote", "add"];
|
|
14
|
+
var ARGS_LS_REMOTE = ["ls-remote"];
|
|
13
15
|
var ARGS_PUSH = ["push"];
|
|
14
16
|
async function runGit(args, cwd) {
|
|
15
17
|
return new Promise((resolve, reject) => {
|
|
@@ -59,6 +61,18 @@ async function gitGetRemoteUrl(cwd, name = REMOTE_DEFAULT) {
|
|
|
59
61
|
if (code !== 0) return null;
|
|
60
62
|
return stdout.trimEnd() || null;
|
|
61
63
|
}
|
|
64
|
+
async function gitAddRemote(cwd, url, name = REMOTE_DEFAULT) {
|
|
65
|
+
await runGitOk([...ARGS_REMOTE_ADD, name, url], cwd);
|
|
66
|
+
}
|
|
67
|
+
async function gitRemoteHead(cwd, url, branch) {
|
|
68
|
+
const { code, stdout } = await runGit(
|
|
69
|
+
[...ARGS_LS_REMOTE, url, `refs/heads/${branch}`],
|
|
70
|
+
cwd
|
|
71
|
+
);
|
|
72
|
+
if (code !== 0) return null;
|
|
73
|
+
const sha = stdout.split(/\s+/)[0]?.trim();
|
|
74
|
+
return sha || null;
|
|
75
|
+
}
|
|
62
76
|
async function gitPush(cwd, branch) {
|
|
63
77
|
const args = branch ? [...ARGS_PUSH, REMOTE_DEFAULT, branch] : [...ARGS_PUSH];
|
|
64
78
|
await runGitOk(args, cwd);
|
|
@@ -76,4 +90,4 @@ function isFreestyleRemote(url) {
|
|
|
76
90
|
}
|
|
77
91
|
}
|
|
78
92
|
|
|
79
|
-
export { gitCurrentBranch, gitCurrentSha, gitDetectRoot, gitGetRemoteUrl, gitPush, gitPushToUrl, gitStatusPorcelain, isFreestyleRemote };
|
|
93
|
+
export { gitAddRemote, gitCurrentBranch, gitCurrentSha, gitDetectRoot, gitGetRemoteUrl, gitPush, gitPushToUrl, gitRemoteHead, gitStatusPorcelain, isFreestyleRemote };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { isFreestyleRemote, gitDetectRoot, gitStatusPorcelain, gitCurrentBranch, gitCurrentSha, gitGetRemoteUrl, gitPushToUrl, gitPush } from './chunk-MLVBE5V2.mjs';
|
|
3
2
|
import { pollDeployment } from './chunk-PDGKBATF.mjs';
|
|
4
|
-
import { fetchRepoRecord, fetchCloneToken } from './chunk-
|
|
3
|
+
import { fetchRepoRecord, fetchCloneToken } from './chunk-7CI5RWNE.mjs';
|
|
5
4
|
import { promptYesNo } from './chunk-5ZQURRIM.mjs';
|
|
6
5
|
import { REPO_PROVIDER, ENV_SCOPE, DEPLOY_TRIGGER, DEPLOYMENT_STATUS, TOKEN_PURPOSE } from './chunk-MXYUAJEW.mjs';
|
|
6
|
+
import { isFreestyleRemote, gitDetectRoot, gitStatusPorcelain, gitCurrentBranch, gitCurrentSha, gitGetRemoteUrl, gitPushToUrl, gitPush } from './chunk-YIBOOKQQ.mjs';
|
|
7
7
|
import { parseArgs, flagBool, flagString } from './chunk-5KYR6WJB.mjs';
|
|
8
8
|
import { ApiClient } from './chunk-TOQGLBWF.mjs';
|
|
9
9
|
import { readAuth, readProjectLink, writeProjectState } from './chunk-6CHBU7O4.mjs';
|
|
@@ -15,9 +15,39 @@ var FLAG_REF = "ref";
|
|
|
15
15
|
var FLAG_NO_PUSH = "no-push";
|
|
16
16
|
var FLAG_ALLOW_DIRTY = "allow-dirty";
|
|
17
17
|
var FLAG_NO_POLL = "no-poll";
|
|
18
|
+
var FLAG_SKIP_ENV_CHECK = "skip-env-check";
|
|
18
19
|
function deployEndpoint(businessId, projectId) {
|
|
19
20
|
return `/v1/businesses/${encodeURIComponent(businessId)}/projects/${encodeURIComponent(projectId)}/deploy`;
|
|
20
21
|
}
|
|
22
|
+
function envEndpoint(businessId, projectId) {
|
|
23
|
+
return `/v1/businesses/${encodeURIComponent(businessId)}/projects/${encodeURIComponent(projectId)}/env-vars`;
|
|
24
|
+
}
|
|
25
|
+
function missingProductionKeys(preview, production) {
|
|
26
|
+
const productionKeys = new Set(production.map((record) => record.key));
|
|
27
|
+
return [...new Set(preview.map((record) => record.key))].filter((key) => !productionKeys.has(key)).sort();
|
|
28
|
+
}
|
|
29
|
+
async function checkProductionEnv(client, businessId, projectId) {
|
|
30
|
+
const [preview, production] = await Promise.all([
|
|
31
|
+
client.get(envEndpoint(businessId, projectId), {
|
|
32
|
+
query: { scope: ENV_SCOPE.PREVIEW }
|
|
33
|
+
}),
|
|
34
|
+
client.get(envEndpoint(businessId, projectId), {
|
|
35
|
+
query: { scope: ENV_SCOPE.PRODUCTION }
|
|
36
|
+
})
|
|
37
|
+
]);
|
|
38
|
+
const missing = missingProductionKeys(preview, production);
|
|
39
|
+
if (missing.length === 0) return;
|
|
40
|
+
const lines = missing.map(
|
|
41
|
+
(key) => ` cimplify env add ${key}=<value> --scope ${ENV_SCOPE.PRODUCTION}`
|
|
42
|
+
);
|
|
43
|
+
throw new CliError(
|
|
44
|
+
CLI_ERROR_CODE.INVALID_INPUT,
|
|
45
|
+
`Production is missing ${missing.length} env var${missing.length === 1 ? "" : "s"} that preview has: ${missing.join(", ")}.
|
|
46
|
+
Set them first:
|
|
47
|
+
${lines.join("\n")}
|
|
48
|
+
Or deploy anyway with --${FLAG_SKIP_ENV_CHECK}.`
|
|
49
|
+
);
|
|
50
|
+
}
|
|
21
51
|
function resolvePushStrategy(originUrl, linkRemoteUrl, repo) {
|
|
22
52
|
if (isFreestyleRemote(originUrl) || isFreestyleRemote(linkRemoteUrl)) {
|
|
23
53
|
return { kind: "managed" };
|
|
@@ -88,6 +118,9 @@ async function run(argv) {
|
|
|
88
118
|
const branch = await gitCurrentBranch(root);
|
|
89
119
|
const localSha = await gitCurrentSha(root);
|
|
90
120
|
const gitRef = explicitRef ?? localSha;
|
|
121
|
+
if (flagBool(args, FLAG_PROD) && !flagBool(args, FLAG_SKIP_ENV_CHECK)) {
|
|
122
|
+
await checkProductionEnv(client, link.businessId, link.projectId);
|
|
123
|
+
}
|
|
91
124
|
if (!flagBool(args, FLAG_NO_PUSH)) {
|
|
92
125
|
await pushForDeploy(client, link.businessId, link.projectId, root, branch, link.remoteUrl);
|
|
93
126
|
} else {
|
|
@@ -158,4 +191,4 @@ async function run(argv) {
|
|
|
158
191
|
process.exitCode = EXIT_CODE.ERROR;
|
|
159
192
|
}
|
|
160
193
|
|
|
161
|
-
export { run as default, resolvePushStrategy };
|
|
194
|
+
export { run as default, missingProductionKeys, resolvePushStrategy };
|
package/dist/dispatcher.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { TEMPLATES } from './chunk-
|
|
3
|
-
import { package_default } from './chunk-
|
|
2
|
+
import { TEMPLATES } from './chunk-JOF7ESSA.mjs';
|
|
3
|
+
import { package_default } from './chunk-KAZMZD4X.mjs';
|
|
4
4
|
|
|
5
5
|
// src/dispatcher.ts
|
|
6
6
|
var VERSION = package_default.version ?? "unknown";
|
|
@@ -137,10 +137,10 @@ var COMMANDS = {
|
|
|
137
137
|
login: () => import('./login-NCO4P5G5.mjs'),
|
|
138
138
|
logout: () => import('./logout-MF6SOLPE.mjs'),
|
|
139
139
|
whoami: () => import('./whoami-B5Y5KSOZ.mjs'),
|
|
140
|
-
projects: () => import('./projects-
|
|
141
|
-
link: () => import('./link-
|
|
140
|
+
projects: () => import('./projects-P65SUETQ.mjs'),
|
|
141
|
+
link: () => import('./link-AWC7VJNN.mjs'),
|
|
142
142
|
unlink: () => import('./unlink-TCG3NBAR.mjs'),
|
|
143
|
-
deploy: () => import('./deploy-
|
|
143
|
+
deploy: () => import('./deploy-64ZVAQ3R.mjs'),
|
|
144
144
|
cancel: () => import('./cancel-FD66LTTS.mjs'),
|
|
145
145
|
rollback: () => import('./rollback-ZL3V7SYH.mjs'),
|
|
146
146
|
env: () => import('./env-PAENNABF.mjs'),
|
|
@@ -149,17 +149,17 @@ var COMMANDS = {
|
|
|
149
149
|
status: () => import('./status-52HG63FE.mjs'),
|
|
150
150
|
dev: () => import('./dev-L3W6UXYN.mjs'),
|
|
151
151
|
mock: () => import('./mock-CAWNXSGC.mjs'),
|
|
152
|
-
introspect: () => import('./introspect-
|
|
152
|
+
introspect: () => import('./introspect-APRI7R7K.mjs'),
|
|
153
153
|
inspect: () => import('./inspect-MGVG4Z44.mjs'),
|
|
154
|
-
doctor: () => import('./doctor-
|
|
155
|
-
lint: () => import('./lint-
|
|
156
|
-
explain: () => import('./explain-
|
|
154
|
+
doctor: () => import('./doctor-6ZIFM5J5.mjs'),
|
|
155
|
+
lint: () => import('./lint-EYKIQ6RO.mjs'),
|
|
156
|
+
explain: () => import('./explain-REIDDRKC.mjs'),
|
|
157
157
|
assets: () => import('./assets-OEY6FHHZ.mjs'),
|
|
158
|
-
repo: () => import('./repo-
|
|
159
|
-
list: () => import('./list-
|
|
160
|
-
add: () => import('./add-
|
|
161
|
-
update: () => import('./update-
|
|
162
|
-
upgrade: () => import('./update-
|
|
158
|
+
repo: () => import('./repo-ZPYZK3KW.mjs'),
|
|
159
|
+
list: () => import('./list-7ZL6FRKT.mjs'),
|
|
160
|
+
add: () => import('./add-PPUGTTDA.mjs'),
|
|
161
|
+
update: () => import('./update-MBEPZANS.mjs'),
|
|
162
|
+
upgrade: () => import('./update-MBEPZANS.mjs'),
|
|
163
163
|
"auth-step-up": () => import('./auth-step-up-ALEUQUCE.mjs')
|
|
164
164
|
};
|
|
165
165
|
var COMMAND_PREFIXES = {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { gatherIntrospection } from './chunk-
|
|
3
|
-
import './chunk-MLVBE5V2.mjs';
|
|
2
|
+
import { gatherIntrospection } from './chunk-SOYZZZVT.mjs';
|
|
4
3
|
import './chunk-RU53TQLZ.mjs';
|
|
5
|
-
import './chunk-
|
|
4
|
+
import './chunk-KAZMZD4X.mjs';
|
|
5
|
+
import './chunk-YIBOOKQQ.mjs';
|
|
6
6
|
import { parseArgs, flagBool } from './chunk-5KYR6WJB.mjs';
|
|
7
7
|
import { SDK_ENV_API_URL, DEFAULT_API_BASE_URL, ApiClient, ENV_API_BASE_URL } from './chunk-TOQGLBWF.mjs';
|
|
8
8
|
import { readAuthOrNull } from './chunk-6CHBU7O4.mjs';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { package_default } from './chunk-
|
|
2
|
+
import { package_default } from './chunk-KAZMZD4X.mjs';
|
|
3
3
|
import { parseArgs } from './chunk-5KYR6WJB.mjs';
|
|
4
4
|
import { bold, dim, info, result, CliError, CLI_ERROR_CODE } from './chunk-4O4G2CDE.mjs';
|
|
5
5
|
|
|
@@ -129,7 +129,7 @@ var TOPICS = [
|
|
|
129
129
|
"title": "Assets",
|
|
130
130
|
"description": "Storefront brand assets \u2014 upload to CDN, build URLs, render through next/image",
|
|
131
131
|
"source_url": "https://cimplify.dev/docs/sdk/assets",
|
|
132
|
-
"body": 'The asset surface on the SDK is **read-side only**: building URLs for images you\'ve already uploaded via [`cimplify assets upload`](/docs/cli/assets). Customer-runtime uploads still go through `client.uploads.upload(file)`.\n\n## `assetUrl(path, opts?)`\n\nPure URL builder. Prepends the CDN base for relative paths, passes absolute URLs through with the transform query contract appended.\n\n```ts\n\nassetUrl("hero/main.jpg")\n// "https://storefrontassetscdn.cimplify.io/hero/main.jpg"\n\nassetUrl("hero/main.jpg", { w: 1200, format: "webp", quality: 80 })\n// "https://storefrontassetscdn.cimplify.io/hero/main.jpg?w=1200&format=webp&quality=80"\n\nassetUrl("hero/main.jpg", { base: "http://localhost:8787/storage" })\n// "http://localhost:8787/storage/hero/main.jpg"\n\nassetUrl("https://res.cloudinary.com/foo/bar.jpg")\n// "https://res.cloudinary.com/foo/bar.jpg" (absolute \u2192 passthrough)\n```\n\n### Options\n\n| Field | Type | Notes |\n| --- | --- | --- |\n| `base` | `string` | Override the CDN base. Defaults to `DEFAULT_CDN_BASE_URL`. |\n| `w` / `h` | `number` | Width / height in pixels (on-the-fly resizing) |\n| `quality` | `number` | 0\u2013100 |\n| `format` | `"auto" \\| "webp" \\| "avif" \\| "jpeg"` | `"auto"` lets the CDN pick by `Accept` header |\n\nThe transform query is only meaningful when the URL terminates on the Cimplify storefront CDN (which supports on-the-fly resizing). For external hosts, unknown params are typically ignored; the image still loads at its original size.\n\n## `isCimplifyAsset(src, base?)`\n\nDecides whether `src` is hosted on a Cimplify CDN. Used by the storefront\'s `next/image` loader to skip transforms for external URLs.\n\n```ts\n\nisCimplifyAsset("hero/main.jpg") // true (relative \u2192 ours)\nisCimplifyAsset("/img/seed/bakery/x.jpg") // true (dev mock passthrough)\nisCimplifyAsset("https://storefrontassetscdn.cimplify.io/x.jpg") // true\nisCimplifyAsset("https://cdn.cimplify.io/x.jpg") // true\nisCimplifyAsset("https://static-tmp.cimplify.io/seed/x.jpg") // true\nisCimplifyAsset("https://res.cloudinary.com/demo/upload/x.jpg") // false\nisCimplifyAsset("https://images.unsplash.com/photo-xyz") // false\n```\n\n## Built-in `next/image` loader\n\nEvery storefront template scaffolded by `cimplify init` ships `lib/cimplify-loader.ts` and points `images.loaderFile` at it. The loader:\n\n```ts\n\nconst cdnBase = process.env.NEXT_PUBLIC_CIMPLIFY_CDN_URL?.trim() || undefined;\n\nconst cimplifyImageLoader: ImageLoader = ({ src, width, quality }) => {\n if (isCimplifyAsset(src, cdnBase)) {\n return assetUrl(src, { base: cdnBase, w: width, quality, format: "auto" });\n }\n return src;\n};\n\nexport default cimplifyImageLoader;\n```\n\n**Cloudinary URLs from `client.catalogue.getProducts()` flow through untouched.** Cimplify-hosted URLs get the transform query. The result: every `<Image>` works regardless of where its asset lives, and Cimplify-hosted ones get edge-optimized.\n\nTo point the loader at a different CDN (for testing, multi-CDN setups, etc.) set `NEXT_PUBLIC_CIMPLIFY_CDN_URL` in your `.env.local`:\n\n```\nNEXT_PUBLIC_CIMPLIFY_CDN_URL=http://localhost:8787/storage\n```\n\n## `useImage(path, opts?)` (React)\n\nThin hook that returns `{ src, loader }` for `<Image>`:\n\n```tsx\n\nexport function Hero() {\n const { src, loader } = useImage("hero/main.jpg", { format: "webp", quality: 85 });\n return <Image src={src} loader={loader} alt="..." width={1200} height={800} />;\n}\n```\n\nIf `images.loaderFile` is already set globally in your `next.config.ts`, you typically don\'t need `useImage`; just `<Image src={assetUrl("hero/main.jpg")} />` works. `useImage` is useful when you want per-component transform overrides on a project that doesn\'t use a global loader.\n\n### Options\n\n| Field | Notes |\n| --- | --- |\n| `base` | Per-call CDN base override |\n| `w`, `h` | Default transform values; per-image `width` from `<Image>` still wins |\n| `format`, `quality` | Default transform values |\n\n`useImage` is `useMemo`-stable across renders when the path + opts don\'t change.\n\n## Constants\n\n```ts\n\nDEFAULT_CDN_BASE_URL // "https://storefrontassetscdn.cimplify.io"\nCIMPLIFY_CDN_HOSTS // readonly ["storefrontassetscdn.cimplify.io", "cdn.cimplify.io", "static-tmp.cimplify.io"]\n```\n\n## What\'s not in v1\n\n- **`useUpload` hook**: runtime customer-facing uploads with progress + cancel. Deferred to v1.1. Customer uploads today go through `client.uploads.upload(file)` (no progress, no cancel; just `await`).\n- **`SEED_IDS` typed const tree**: demo-only convenience for referencing seed-image slugs in code. Generate-from-seed-source step deferred to v1.1; today demos use `seedImage(industry, slug)` from the SDK\'s mock module.\n- **Cloudinary / S3 path-transform support**: the loader passes external hosts through unchanged; Cloudinary\'s `c_fill,w_500/` path transforms aren\'t synthesized.\n- **`assets rm` server-side delete**: CLI removes manifest entries; the remote blob stays until v1.1\'s media-manager `DELETE` wiring.\n\n## Where it lives in the platform\n\n- Wire format: `POST /v1/businesses/{id}/assets/{init,confirm}`; see the management API reference\n- Backend service: `crate::uploads::service::UploadService::init_storefront_asset`\n- Served from the Cimplify asset CDN at `storefrontassetscdn.cimplify.io`\n- Storage key: `assets/{business_id}/{folder}/{filename}`:
|
|
132
|
+
"body": 'The asset surface on the SDK is **read-side only**: building URLs for images you\'ve already uploaded via [`cimplify assets upload`](/docs/cli/assets). Customer-runtime uploads still go through `client.uploads.upload(file)`.\n\n## `assetUrl(path, opts?)`\n\nPure URL builder. Prepends the CDN base for relative paths, passes absolute URLs through with the transform query contract appended.\n\n```ts\n\nassetUrl("hero/main.jpg")\n// "https://storefrontassetscdn.cimplify.io/hero/main.jpg"\n\nassetUrl("hero/main.jpg", { w: 1200, format: "webp", quality: 80 })\n// "https://storefrontassetscdn.cimplify.io/hero/main.jpg?w=1200&format=webp&quality=80"\n\nassetUrl("hero/main.jpg", { base: "http://localhost:8787/storage" })\n// "http://localhost:8787/storage/hero/main.jpg"\n\nassetUrl("https://res.cloudinary.com/foo/bar.jpg")\n// "https://res.cloudinary.com/foo/bar.jpg" (absolute \u2192 passthrough)\n```\n\n### Options\n\n| Field | Type | Notes |\n| --- | --- | --- |\n| `base` | `string` | Override the CDN base. Defaults to `DEFAULT_CDN_BASE_URL`. |\n| `w` / `h` | `number` | Width / height in pixels (on-the-fly resizing) |\n| `quality` | `number` | 0\u2013100 |\n| `format` | `"auto" \\| "webp" \\| "avif" \\| "jpeg"` | `"auto"` lets the CDN pick by `Accept` header |\n\nThe transform query is only meaningful when the URL terminates on the Cimplify storefront CDN (which supports on-the-fly resizing). For external hosts, unknown params are typically ignored; the image still loads at its original size.\n\n## `isCimplifyAsset(src, base?)`\n\nDecides whether `src` is hosted on a Cimplify CDN. Used by the storefront\'s `next/image` loader to skip transforms for external URLs.\n\n```ts\n\nisCimplifyAsset("hero/main.jpg") // true (relative \u2192 ours)\nisCimplifyAsset("/img/seed/bakery/x.jpg") // true (dev mock passthrough)\nisCimplifyAsset("https://storefrontassetscdn.cimplify.io/x.jpg") // true\nisCimplifyAsset("https://cdn.cimplify.io/x.jpg") // true\nisCimplifyAsset("https://static-tmp.cimplify.io/seed/x.jpg") // true\nisCimplifyAsset("https://res.cloudinary.com/demo/upload/x.jpg") // false\nisCimplifyAsset("https://images.unsplash.com/photo-xyz") // false\n```\n\n## Built-in `next/image` loader\n\nEvery storefront template scaffolded by `cimplify init` ships `lib/cimplify-loader.ts` and points `images.loaderFile` at it. The loader:\n\n```ts\n\nconst cdnBase = process.env.NEXT_PUBLIC_CIMPLIFY_CDN_URL?.trim() || undefined;\n\nconst cimplifyImageLoader: ImageLoader = ({ src, width, quality }) => {\n if (isCimplifyAsset(src, cdnBase)) {\n return assetUrl(src, { base: cdnBase, w: width, quality, format: "auto" });\n }\n return src;\n};\n\nexport default cimplifyImageLoader;\n```\n\n**Cloudinary URLs from `client.catalogue.getProducts()` flow through untouched.** Cimplify-hosted URLs get the transform query. The result: every `<Image>` works regardless of where its asset lives, and Cimplify-hosted ones get edge-optimized.\n\nTo point the loader at a different CDN (for testing, multi-CDN setups, etc.) set `NEXT_PUBLIC_CIMPLIFY_CDN_URL` in your `.env.local`:\n\n```\nNEXT_PUBLIC_CIMPLIFY_CDN_URL=http://localhost:8787/storage\n```\n\n## `useImage(path, opts?)` (React)\n\nThin hook that returns `{ src, loader }` for `<Image>`:\n\n```tsx\n\nexport function Hero() {\n const { src, loader } = useImage("hero/main.jpg", { format: "webp", quality: 85 });\n return <Image src={src} loader={loader} alt="..." width={1200} height={800} />;\n}\n```\n\nIf `images.loaderFile` is already set globally in your `next.config.ts`, you typically don\'t need `useImage`; just `<Image src={assetUrl("hero/main.jpg")} />` works. `useImage` is useful when you want per-component transform overrides on a project that doesn\'t use a global loader.\n\n### Options\n\n| Field | Notes |\n| --- | --- |\n| `base` | Per-call CDN base override |\n| `w`, `h` | Default transform values; per-image `width` from `<Image>` still wins |\n| `format`, `quality` | Default transform values |\n\n`useImage` is `useMemo`-stable across renders when the path + opts don\'t change.\n\n## Constants\n\n```ts\n\nDEFAULT_CDN_BASE_URL // "https://storefrontassetscdn.cimplify.io"\nCIMPLIFY_CDN_HOSTS // readonly ["storefrontassetscdn.cimplify.io", "cdn.cimplify.io", "static-tmp.cimplify.io"]\n```\n\n## What\'s not in v1\n\n- **`useUpload` hook**: runtime customer-facing uploads with progress + cancel. Deferred to v1.1. Customer uploads today go through `client.uploads.upload(file)` (no progress, no cancel; just `await`).\n- **`SEED_IDS` typed const tree**: demo-only convenience for referencing seed-image slugs in code. Generate-from-seed-source step deferred to v1.1; today demos use `seedImage(industry, slug)` from the SDK\'s mock module.\n- **Cloudinary / S3 path-transform support**: the loader passes external hosts through unchanged; Cloudinary\'s `c_fill,w_500/` path transforms aren\'t synthesized.\n- **`assets rm` server-side delete**: CLI removes manifest entries; the remote blob stays until v1.1\'s media-manager `DELETE` wiring.\n\n## Where it lives in the platform\n\n- Wire format: `POST /v1/businesses/{id}/assets/{init,confirm}`; see the management API reference\n- Backend service: `crate::uploads::service::UploadService::init_storefront_asset`\n- Served from the Cimplify asset CDN at `storefrontassetscdn.cimplify.io`\n- Storage key: `assets/{business_id}/{folder}/{upload_id}/{filename}`: immutable per upload; use the returned preview URL\n\n## Related\n\n- [`cimplify assets`](/docs/cli/assets): CLI surface for upload/ls/rm\n- [Uploads (customer-runtime)](/docs/sdk/uploads): `client.uploads.upload(file)` for private 7-day-presigned uploads\n'
|
|
133
133
|
},
|
|
134
134
|
{
|
|
135
135
|
"name": "exit-codes",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
export { run as default, extractMockSeed, gatherIntrospection, renderIntrospection } from './chunk-
|
|
3
|
-
import './chunk-MLVBE5V2.mjs';
|
|
2
|
+
export { run as default, extractMockSeed, gatherIntrospection, renderIntrospection } from './chunk-SOYZZZVT.mjs';
|
|
4
3
|
import './chunk-RU53TQLZ.mjs';
|
|
5
|
-
import './chunk-
|
|
4
|
+
import './chunk-KAZMZD4X.mjs';
|
|
5
|
+
import './chunk-YIBOOKQQ.mjs';
|
|
6
6
|
import './chunk-5KYR6WJB.mjs';
|
|
7
7
|
import './chunk-6CHBU7O4.mjs';
|
|
8
8
|
import './chunk-4O4G2CDE.mjs';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { gitDetectRoot, gitGetRemoteUrl, gitAddRemote } from './chunk-YIBOOKQQ.mjs';
|
|
2
3
|
import { parseArgs } from './chunk-5KYR6WJB.mjs';
|
|
3
4
|
import { ApiClient } from './chunk-TOQGLBWF.mjs';
|
|
4
5
|
import { readAuth, writeProjectLink } from './chunk-6CHBU7O4.mjs';
|
|
@@ -32,14 +33,30 @@ async function run(argv) {
|
|
|
32
33
|
linkedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
33
34
|
};
|
|
34
35
|
await writeProjectLink(link);
|
|
36
|
+
const originConfigured = await configureOrigin(link.remoteUrl);
|
|
35
37
|
success(`Linked to ${project.name} (${project.id})`);
|
|
36
38
|
if (link.remoteUrl) info(dim(`remote: ${link.remoteUrl}`));
|
|
37
39
|
result({
|
|
38
40
|
project: { id: project.id, name: project.name },
|
|
39
41
|
business: { id: project.business_id },
|
|
40
42
|
remote_url: link.remoteUrl ?? null,
|
|
41
|
-
default_branch: link.defaultBranch ?? null
|
|
43
|
+
default_branch: link.defaultBranch ?? null,
|
|
44
|
+
origin_configured: originConfigured
|
|
42
45
|
});
|
|
43
46
|
}
|
|
47
|
+
async function configureOrigin(remoteUrl) {
|
|
48
|
+
if (!remoteUrl) return false;
|
|
49
|
+
const root = await gitDetectRoot(process.cwd());
|
|
50
|
+
if (!root) return false;
|
|
51
|
+
const existing = await gitGetRemoteUrl(root);
|
|
52
|
+
if (existing === remoteUrl) return true;
|
|
53
|
+
if (existing) {
|
|
54
|
+
info(dim(`origin already points at ${existing}; project remote is ${remoteUrl}`));
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
await gitAddRemote(root, remoteUrl);
|
|
58
|
+
info(dim(`origin \u2192 ${remoteUrl}`));
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
44
61
|
|
|
45
62
|
export { run as default };
|
|
@@ -473,6 +473,13 @@ function subjectName(node) {
|
|
|
473
473
|
}
|
|
474
474
|
return null;
|
|
475
475
|
}
|
|
476
|
+
function normalizedSubjectName(name) {
|
|
477
|
+
return name.replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2").replace(/([a-z\d])([A-Z])/g, "$1_$2").replace(/[^A-Za-z\d]+/g, "_").toLowerCase();
|
|
478
|
+
}
|
|
479
|
+
function subjectMatches(node, pattern) {
|
|
480
|
+
const name = subjectName(node);
|
|
481
|
+
return name !== null && pattern !== void 0 && (pattern.test(name) || pattern.test(normalizedSubjectName(name)));
|
|
482
|
+
}
|
|
476
483
|
function sourceMatches(source, primitive) {
|
|
477
484
|
return primitive.sources.some((pattern) => sourcePatternMatches(source, pattern));
|
|
478
485
|
}
|
|
@@ -784,11 +791,9 @@ function analyzeSource(source, file, compiledRules, maxDiagnostics) {
|
|
|
784
791
|
if (!path4.parentPath.isJSXElement() && !path4.parentPath.isJSXFragment()) return;
|
|
785
792
|
const expression = unwrapExpression(path4.node.expression);
|
|
786
793
|
if (!expression || !t.isExpression(expression)) return;
|
|
787
|
-
const name = subjectName(expression);
|
|
788
|
-
if (!name) return;
|
|
789
794
|
for (const compiled of compiledRules) {
|
|
790
795
|
const primitive = compiled.rule.primitive;
|
|
791
|
-
if (primitive.kind !== "required-wrapper-call" || primitive.context !== "jsx-child" || !hasActivatingImport(importSources, primitive.activationImports) || !compiled.subjectPattern
|
|
796
|
+
if (primitive.kind !== "required-wrapper-call" || primitive.context !== "jsx-child" || !hasActivatingImport(importSources, primitive.activationImports) || !subjectMatches(expression, compiled.subjectPattern)) {
|
|
792
797
|
continue;
|
|
793
798
|
}
|
|
794
799
|
const fix = compiled.rule.fix ? jsxWrapperFix(ast, source, path4.node, expression, primitive, imports, path4) : void 0;
|
|
@@ -808,8 +813,7 @@ function analyzeSource(source, file, compiledRules, maxDiagnostics) {
|
|
|
808
813
|
if (t.isCallExpression(value) && t.isIdentifier(value.callee) && primitive.wrapper.syntax === "call" && bindingMatches(value.callee.name, primitive.wrapper.imports, imports)) {
|
|
809
814
|
continue;
|
|
810
815
|
}
|
|
811
|
-
|
|
812
|
-
if (name && compiled.subjectPattern?.test(name)) {
|
|
816
|
+
if (subjectMatches(value, compiled.subjectPattern)) {
|
|
813
817
|
emit(diagnostic(file, compiled.rule, value));
|
|
814
818
|
}
|
|
815
819
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { REGISTRY_INDEX } from './chunk-
|
|
2
|
+
import { REGISTRY_INDEX } from './chunk-JOF7ESSA.mjs';
|
|
3
3
|
import { parseArgs, flagBool } from './chunk-5KYR6WJB.mjs';
|
|
4
4
|
import { CliError, CLI_ERROR_CODE, info, bold, dim, green, result } from './chunk-4O4G2CDE.mjs';
|
|
5
5
|
|
|
@@ -176,8 +176,8 @@ async function createProject(client, businessId, name, options = {}) {
|
|
|
176
176
|
info(dim(` remote: ${repo.remote_url}`));
|
|
177
177
|
info("");
|
|
178
178
|
info(dim("Wire your local repo:"));
|
|
179
|
-
info(dim(
|
|
180
|
-
info(dim(`
|
|
179
|
+
info(dim(" git init"));
|
|
180
|
+
info(dim(` cimplify link ${project.id} # configures origin for you`));
|
|
181
181
|
info(dim(` git add . && git commit -m "Initial commit"`));
|
|
182
182
|
info(dim(` cimplify deploy`));
|
|
183
183
|
result({
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
export { run as default, fetchCloneToken, fetchRepoRecord } from './chunk-
|
|
2
|
+
export { run as default, fetchCloneToken, fetchRepoRecord } from './chunk-7CI5RWNE.mjs';
|
|
3
3
|
import './chunk-5ZQURRIM.mjs';
|
|
4
4
|
import './chunk-MXYUAJEW.mjs';
|
|
5
|
+
import './chunk-YIBOOKQQ.mjs';
|
|
5
6
|
import './chunk-5KYR6WJB.mjs';
|
|
6
7
|
import './chunk-TOQGLBWF.mjs';
|
|
7
8
|
import './chunk-6CHBU7O4.mjs';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { package_default } from './chunk-
|
|
2
|
+
import { package_default } from './chunk-KAZMZD4X.mjs';
|
|
3
3
|
import { promptYesNo } from './chunk-5ZQURRIM.mjs';
|
|
4
4
|
import { parseArgs, flagBool, flagString } from './chunk-5KYR6WJB.mjs';
|
|
5
5
|
import { success, bold, info, dim, result, failure, CliError, CLI_ERROR_CODE, step, isJsonMode } from './chunk-4O4G2CDE.mjs';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cimplify/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "Cimplify CLI — deploy, manage env vars, link projects, and scaffold storefronts",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cimplify",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"@babel/parser": "^8.0.4",
|
|
42
42
|
"@babel/traverse": "^8.0.4",
|
|
43
43
|
"@babel/types": "^8.0.4",
|
|
44
|
-
"@cimplify/sdk": "^0.
|
|
44
|
+
"@cimplify/sdk": "^0.101.1",
|
|
45
45
|
"re2js": "^1.4.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|