@cimplify/cli 0.7.23 → 0.8.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.
Files changed (60) hide show
  1. package/dist/{add-LABPJFW7.mjs → add-TCU5T7Q2.mjs} +1 -1
  2. package/dist/{assets-74SK63TR.mjs → assets-EHRFAWZI.mjs} +1 -1
  3. package/dist/{auth-step-up-BIUYQJP6.mjs → auth-step-up-RWBXYJKR.mjs} +1 -1
  4. package/dist/{cancel-HANLRA6Q.mjs → cancel-DAO23NIX.mjs} +1 -1
  5. package/dist/{chunk-FIMXBNN3.mjs → chunk-7DOC7MLJ.mjs} +1 -1
  6. package/dist/{chunk-TKFUMOQQ.mjs → chunk-BQ5CWVHQ.mjs} +7 -7
  7. package/dist/{chunk-MAOO6ZZ5.mjs → chunk-CV3ZFCX6.mjs} +33 -9
  8. package/dist/{chunk-CLNS2NBR.mjs → chunk-IV7SOUH3.mjs} +1 -1
  9. package/dist/{chunk-5VJ5VV27.mjs → chunk-MBLJKDCR.mjs} +34 -34
  10. package/dist/{deploy-YVCYHNSS.mjs → deploy-M63QHHOD.mjs} +2 -2
  11. package/dist/{dev-ONW2S77K.mjs → dev-VE6VVDEU.mjs} +1 -1
  12. package/dist/dispatcher.mjs +24 -24
  13. package/dist/{doctor-ARURW6E5.mjs → doctor-TBQN7ZSR.mjs} +3 -3
  14. package/dist/{domains-6GJASWJU.mjs → domains-7QM444PU.mjs} +1 -1
  15. package/dist/{env-7ISJ73YI.mjs → env-VKTOPGSZ.mjs} +1 -1
  16. package/dist/{explain-Z4FKFZOA.mjs → explain-LFL4IXXK.mjs} +1 -1
  17. package/dist/{introspect-XL6Y35PZ.mjs → introspect-SHUBKCPY.mjs} +2 -2
  18. package/dist/{link-DZSILT5N.mjs → link-746RR2HY.mjs} +1 -1
  19. package/dist/{list-EZTRRY4Z.mjs → list-BVSFEBG7.mjs} +1 -1
  20. package/dist/{login-3OD4ND2H.mjs → login-EMJ33OD4.mjs} +31 -37
  21. package/dist/{logs-YNN2PQ24.mjs → logs-DSYUOYQJ.mjs} +1 -1
  22. package/dist/{projects-QSUWVTJZ.mjs → projects-QKI6CTCD.mjs} +1 -1
  23. package/dist/{repo-KNQMSPVV.mjs → repo-3BEDOFZX.mjs} +2 -2
  24. package/dist/{rollback-DD4RNRFM.mjs → rollback-ZR6X6IQ5.mjs} +1 -1
  25. package/dist/{status-JSYXM5RT.mjs → status-AIENVHAV.mjs} +1 -1
  26. package/dist/{update-6NCPLWGV.mjs → update-THXRRDNG.mjs} +1 -1
  27. package/dist/{whoami-DNZ7RUTH.mjs → whoami-LPQMPYTE.mjs} +1 -1
  28. package/package.json +7 -7
  29. package/templates/storefront-auto/app/products/[slug]/page.tsx +4 -9
  30. package/templates/storefront-auto/bun.lock +2 -2
  31. package/templates/storefront-auto/components/account-pill.tsx +1 -1
  32. package/templates/storefront-auto/lib/product-offer.ts +46 -0
  33. package/templates/storefront-auto/package.json +1 -1
  34. package/templates/storefront-bakery/bun.lock +2 -2
  35. package/templates/storefront-bakery/components/account-pill.tsx +1 -1
  36. package/templates/storefront-bakery/package.json +1 -1
  37. package/templates/storefront-fashion/app/products/[slug]/page.tsx +4 -9
  38. package/templates/storefront-fashion/bun.lock +2 -2
  39. package/templates/storefront-fashion/components/account-pill.tsx +1 -1
  40. package/templates/storefront-fashion/lib/product-offer.ts +46 -0
  41. package/templates/storefront-fashion/package.json +1 -1
  42. package/templates/storefront-grocery/bun.lock +2 -2
  43. package/templates/storefront-grocery/components/account-pill.tsx +1 -1
  44. package/templates/storefront-grocery/package.json +1 -1
  45. package/templates/storefront-pharmacy/app/products/[slug]/page.tsx +4 -9
  46. package/templates/storefront-pharmacy/bun.lock +2 -2
  47. package/templates/storefront-pharmacy/components/account-pill.tsx +1 -1
  48. package/templates/storefront-pharmacy/lib/product-offer.ts +46 -0
  49. package/templates/storefront-pharmacy/package.json +1 -1
  50. package/templates/storefront-restaurant/bun.lock +2 -2
  51. package/templates/storefront-restaurant/components/account-pill.tsx +1 -1
  52. package/templates/storefront-restaurant/package.json +1 -1
  53. package/templates/storefront-retail/app/products/[slug]/page.tsx +4 -9
  54. package/templates/storefront-retail/bun.lock +2 -2
  55. package/templates/storefront-retail/components/account-pill.tsx +1 -1
  56. package/templates/storefront-retail/lib/product-offer.ts +46 -0
  57. package/templates/storefront-retail/package.json +1 -1
  58. package/templates/storefront-services/bun.lock +2 -2
  59. package/templates/storefront-services/components/account-pill.tsx +1 -1
  60. package/templates/storefront-services/package.json +1 -1
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import { isFreestyleRemote, gitDetectRoot, gitStatusPorcelain, gitCurrentBranch, gitCurrentSha, gitGetRemoteUrl, gitPushToUrl, gitPush } from './chunk-K5464A3L.mjs';
3
3
  import { pollDeployment } from './chunk-VTR5R5NQ.mjs';
4
- import { fetchRepoRecord, fetchCloneToken } from './chunk-CLNS2NBR.mjs';
4
+ import { fetchRepoRecord, fetchCloneToken } from './chunk-IV7SOUH3.mjs';
5
5
  import { promptYesNo } from './chunk-ITAFAORS.mjs';
6
6
  import { REPO_PROVIDER, ENV_SCOPE, DEPLOY_TRIGGER, DEPLOYMENT_STATUS, TOKEN_PURPOSE } from './chunk-MXYUAJEW.mjs';
7
7
  import { parseArgs, flagBool, flagString } from './chunk-C4M3DXKC.mjs';
8
- import { ApiClient } from './chunk-MAOO6ZZ5.mjs';
8
+ import { ApiClient } from './chunk-CV3ZFCX6.mjs';
9
9
  import { readAuth, readProjectLink, writeProjectState } from './chunk-UBAI443T.mjs';
10
10
  import { CliError, CLI_ERROR_CODE, info, dim, step, success, result, EXIT_CODE } from './chunk-E2T2SBP5.mjs';
11
11
 
@@ -2,7 +2,7 @@
2
2
  import { parseEnvFile, formatEnvFile } from './chunk-DBZ3UOQ2.mjs';
3
3
  import { ENV_SCOPE, PUBLIC_ENV_PREFIX } from './chunk-MXYUAJEW.mjs';
4
4
  import { parseArgs, flagBool } from './chunk-C4M3DXKC.mjs';
5
- import { ApiClient } from './chunk-MAOO6ZZ5.mjs';
5
+ import { ApiClient } from './chunk-CV3ZFCX6.mjs';
6
6
  import { readAuth, readProjectLink } from './chunk-UBAI443T.mjs';
7
7
  import { info, CliError, CLI_ERROR_CODE, dim } from './chunk-E2T2SBP5.mjs';
8
8
  import { spawn } from 'child_process';
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { package_default } from './chunk-TKFUMOQQ.mjs';
3
- import { TEMPLATES } from './chunk-5VJ5VV27.mjs';
2
+ import { package_default } from './chunk-BQ5CWVHQ.mjs';
3
+ import { TEMPLATES } from './chunk-MBLJKDCR.mjs';
4
4
 
5
5
  // src/dispatcher.ts
6
6
  var VERSION = package_default.version ?? "unknown";
@@ -129,32 +129,32 @@ Local mock server (custom demo data, no fork needed):
129
129
  cimplify mock --seed-module ./seed.ts Boot from a seed module (defineSeed from @cimplify/sdk/mock)
130
130
  `;
131
131
  var COMMANDS = {
132
- login: () => import('./login-3OD4ND2H.mjs'),
132
+ login: () => import('./login-EMJ33OD4.mjs'),
133
133
  logout: () => import('./logout-3RLBZ33M.mjs'),
134
- whoami: () => import('./whoami-DNZ7RUTH.mjs'),
135
- projects: () => import('./projects-QSUWVTJZ.mjs'),
136
- link: () => import('./link-DZSILT5N.mjs'),
134
+ whoami: () => import('./whoami-LPQMPYTE.mjs'),
135
+ projects: () => import('./projects-QKI6CTCD.mjs'),
136
+ link: () => import('./link-746RR2HY.mjs'),
137
137
  unlink: () => import('./unlink-RFK74SFP.mjs'),
138
- deploy: () => import('./deploy-YVCYHNSS.mjs'),
139
- cancel: () => import('./cancel-HANLRA6Q.mjs'),
140
- rollback: () => import('./rollback-DD4RNRFM.mjs'),
141
- env: () => import('./env-7ISJ73YI.mjs'),
142
- domains: () => import('./domains-6GJASWJU.mjs'),
143
- logs: () => import('./logs-YNN2PQ24.mjs'),
144
- status: () => import('./status-JSYXM5RT.mjs'),
145
- dev: () => import('./dev-ONW2S77K.mjs'),
138
+ deploy: () => import('./deploy-M63QHHOD.mjs'),
139
+ cancel: () => import('./cancel-DAO23NIX.mjs'),
140
+ rollback: () => import('./rollback-ZR6X6IQ5.mjs'),
141
+ env: () => import('./env-VKTOPGSZ.mjs'),
142
+ domains: () => import('./domains-7QM444PU.mjs'),
143
+ logs: () => import('./logs-DSYUOYQJ.mjs'),
144
+ status: () => import('./status-AIENVHAV.mjs'),
145
+ dev: () => import('./dev-VE6VVDEU.mjs'),
146
146
  mock: () => import('./mock-TSUKCLWU.mjs'),
147
- introspect: () => import('./introspect-XL6Y35PZ.mjs'),
147
+ introspect: () => import('./introspect-SHUBKCPY.mjs'),
148
148
  inspect: () => import('./inspect-CGYX4DDF.mjs'),
149
- doctor: () => import('./doctor-ARURW6E5.mjs'),
150
- explain: () => import('./explain-Z4FKFZOA.mjs'),
151
- assets: () => import('./assets-74SK63TR.mjs'),
152
- repo: () => import('./repo-KNQMSPVV.mjs'),
153
- list: () => import('./list-EZTRRY4Z.mjs'),
154
- add: () => import('./add-LABPJFW7.mjs'),
155
- update: () => import('./update-6NCPLWGV.mjs'),
156
- upgrade: () => import('./update-6NCPLWGV.mjs'),
157
- "auth-step-up": () => import('./auth-step-up-BIUYQJP6.mjs')
149
+ doctor: () => import('./doctor-TBQN7ZSR.mjs'),
150
+ explain: () => import('./explain-LFL4IXXK.mjs'),
151
+ assets: () => import('./assets-EHRFAWZI.mjs'),
152
+ repo: () => import('./repo-3BEDOFZX.mjs'),
153
+ list: () => import('./list-BVSFEBG7.mjs'),
154
+ add: () => import('./add-TCU5T7Q2.mjs'),
155
+ update: () => import('./update-THXRRDNG.mjs'),
156
+ upgrade: () => import('./update-THXRRDNG.mjs'),
157
+ "auth-step-up": () => import('./auth-step-up-RWBXYJKR.mjs')
158
158
  };
159
159
  var COMMAND_PREFIXES = {
160
160
  auth: { "step-up": "auth-step-up" }
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { gatherIntrospection } from './chunk-FIMXBNN3.mjs';
2
+ import { gatherIntrospection } from './chunk-7DOC7MLJ.mjs';
3
3
  import './chunk-K5464A3L.mjs';
4
4
  import './chunk-DBZ3UOQ2.mjs';
5
- import './chunk-TKFUMOQQ.mjs';
5
+ import './chunk-BQ5CWVHQ.mjs';
6
6
  import { parseArgs, flagBool } from './chunk-C4M3DXKC.mjs';
7
- import { ApiClient } from './chunk-MAOO6ZZ5.mjs';
7
+ import { ApiClient } from './chunk-CV3ZFCX6.mjs';
8
8
  import { readAuthOrNull } from './chunk-UBAI443T.mjs';
9
9
  import { bold, dim, info, result, isCliError, CLI_ERROR_CODE, red, yellow, green } from './chunk-E2T2SBP5.mjs';
10
10
  import { promises } from 'fs';
@@ -2,7 +2,7 @@
2
2
  import { promptYesNo } from './chunk-ITAFAORS.mjs';
3
3
  import { ENV_SCOPE, DOMAIN_TYPE } from './chunk-MXYUAJEW.mjs';
4
4
  import { parseArgs, flagBool, flagString } from './chunk-C4M3DXKC.mjs';
5
- import { ApiClient } from './chunk-MAOO6ZZ5.mjs';
5
+ import { ApiClient } from './chunk-CV3ZFCX6.mjs';
6
6
  import { readAuth, readProjectLink } from './chunk-UBAI443T.mjs';
7
7
  import { CliError, CLI_ERROR_CODE, result, info, dim, bold, success } from './chunk-E2T2SBP5.mjs';
8
8
 
@@ -3,7 +3,7 @@ import { formatEnvFile, parseEnvFile, parseKeyValueArg } from './chunk-DBZ3UOQ2.
3
3
  import { promptYesNo } from './chunk-ITAFAORS.mjs';
4
4
  import { ENV_SCOPE, PUBLIC_ENV_PREFIX, SECRET_MASK } from './chunk-MXYUAJEW.mjs';
5
5
  import { parseArgs, flagString, flagBool } from './chunk-C4M3DXKC.mjs';
6
- import { ApiClient } from './chunk-MAOO6ZZ5.mjs';
6
+ import { ApiClient } from './chunk-CV3ZFCX6.mjs';
7
7
  import { readAuth, readProjectLink } from './chunk-UBAI443T.mjs';
8
8
  import { CliError, CLI_ERROR_CODE, info, dim, result, bold, success } from './chunk-E2T2SBP5.mjs';
9
9
  import { promises } from 'fs';
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { package_default } from './chunk-TKFUMOQQ.mjs';
2
+ import { package_default } from './chunk-BQ5CWVHQ.mjs';
3
3
  import { parseArgs } from './chunk-C4M3DXKC.mjs';
4
4
  import { bold, dim, info, result, CliError, CLI_ERROR_CODE } from './chunk-E2T2SBP5.mjs';
5
5
 
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- export { run as default, extractMockSeed, gatherIntrospection, renderIntrospection } from './chunk-FIMXBNN3.mjs';
2
+ export { run as default, extractMockSeed, gatherIntrospection, renderIntrospection } from './chunk-7DOC7MLJ.mjs';
3
3
  import './chunk-K5464A3L.mjs';
4
4
  import './chunk-DBZ3UOQ2.mjs';
5
- import './chunk-TKFUMOQQ.mjs';
5
+ import './chunk-BQ5CWVHQ.mjs';
6
6
  import './chunk-C4M3DXKC.mjs';
7
7
  import './chunk-UBAI443T.mjs';
8
8
  import './chunk-E2T2SBP5.mjs';
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { parseArgs } from './chunk-C4M3DXKC.mjs';
3
- import { ApiClient } from './chunk-MAOO6ZZ5.mjs';
3
+ import { ApiClient } from './chunk-CV3ZFCX6.mjs';
4
4
  import { readAuth, writeProjectLink } from './chunk-UBAI443T.mjs';
5
5
  import { CliError, CLI_ERROR_CODE, success, info, dim, result } from './chunk-E2T2SBP5.mjs';
6
6
 
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { REGISTRY_INDEX } from './chunk-5VJ5VV27.mjs';
2
+ import { REGISTRY_INDEX } from './chunk-MBLJKDCR.mjs';
3
3
  import { parseArgs, flagBool } from './chunk-C4M3DXKC.mjs';
4
4
  import { CliError, CLI_ERROR_CODE, info, bold, dim, green, result } from './chunk-E2T2SBP5.mjs';
5
5
 
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { generatePkcePair, generateState, startLoopbackServer, openBrowser } from './chunk-GLXONXS3.mjs';
2
+ import { generatePkcePair, openBrowser } from './chunk-GLXONXS3.mjs';
3
3
  import { parseArgs, flagString, flagBool } from './chunk-C4M3DXKC.mjs';
4
- import { resolveBaseUrl, ApiClient } from './chunk-MAOO6ZZ5.mjs';
4
+ import { resolveBaseUrl, ApiClient } from './chunk-CV3ZFCX6.mjs';
5
5
  import { writeAuth } from './chunk-UBAI443T.mjs';
6
6
  import { CliError, CLI_ERROR_CODE, success, result, isJsonMode, step, info, dim } from './chunk-E2T2SBP5.mjs';
7
7
  import os from 'os';
@@ -22,6 +22,7 @@ var ENDPOINT_CLI_TOKEN = "/v1/auth/cli/token";
22
22
  var KEY_PREFIX_CAK = "cak_";
23
23
  var KEY_PREFIX_CSK = "csk_";
24
24
  var PRODUCT_NAME = "cimplify-cli";
25
+ var POLL_INTERVAL_MS = 2e3;
25
26
  async function run(argv) {
26
27
  const args = parseArgs(argv);
27
28
  const baseUrl = resolveBaseUrl(flagString(args, FLAG_BASE_URL));
@@ -81,13 +82,10 @@ async function loginWithBrowser(baseUrl, noBrowser, requestedScopes) {
81
82
  );
82
83
  }
83
84
  const pkce = generatePkcePair();
84
- const state = generateState();
85
- const loopback = await startLoopbackServer(baseUrl);
86
- const startBody = {
85
+ const unauthClient = ApiClient.unauthenticated(baseUrl);
86
+ const startResponse = await unauthClient.post(ENDPOINT_CLI_START, {
87
87
  code_challenge: pkce.codeChallenge,
88
88
  code_challenge_method: pkce.codeChallengeMethod,
89
- redirect_uri: loopback.redirectUri,
90
- state,
91
89
  client_meta: {
92
90
  hostname: os.hostname(),
93
91
  platform: process.platform,
@@ -96,12 +94,7 @@ async function loginWithBrowser(baseUrl, noBrowser, requestedScopes) {
96
94
  product: PRODUCT_NAME
97
95
  },
98
96
  requested_scopes: requestedScopes
99
- };
100
- const unauthClient = ApiClient.unauthenticated(baseUrl);
101
- const startResponse = await unauthClient.post(
102
- ENDPOINT_CLI_START,
103
- startBody
104
- );
97
+ });
105
98
  step("Opening browser to authorize this CLI...");
106
99
  info(dim(startResponse.approval_url));
107
100
  if (!noBrowser) {
@@ -110,30 +103,13 @@ async function loginWithBrowser(baseUrl, noBrowser, requestedScopes) {
110
103
  info("");
111
104
  info(dim("Open the URL above in any browser to continue."));
112
105
  }
113
- let callback;
114
- try {
115
- callback = await loopback.awaitCallback(startResponse.expires_in_secs * 1e3);
116
- } catch (err) {
117
- loopback.close();
118
- throw err;
119
- }
120
- if (callback.state !== state) {
121
- throw new CliError(
122
- CLI_ERROR_CODE.UNAUTHORIZED,
123
- "OAuth state mismatch. Possible CSRF attempt \u2014 try again."
124
- );
125
- }
126
- if (!callback.code) {
127
- throw new CliError(
128
- CLI_ERROR_CODE.UNAUTHORIZED,
129
- "Login callback missing auth_code."
130
- );
131
- }
132
- const token = await unauthClient.post(ENDPOINT_CLI_TOKEN, {
133
- auth_code: callback.code,
134
- code_verifier: pkce.codeVerifier,
135
- redirect_uri: loopback.redirectUri
136
- });
106
+ step("Waiting for approval...");
107
+ const token = await pollForToken(
108
+ unauthClient,
109
+ startResponse.request_id,
110
+ pkce.codeVerifier,
111
+ startResponse.expires_in_secs
112
+ );
137
113
  await writeAuth({
138
114
  apiKey: token.access_token,
139
115
  apiBaseUrl: baseUrl,
@@ -149,5 +125,23 @@ async function loginWithBrowser(baseUrl, noBrowser, requestedScopes) {
149
125
  method: "oauth_pkce"
150
126
  });
151
127
  }
128
+ async function pollForToken(client, requestId, codeVerifier, expiresInSecs) {
129
+ const deadline = Date.now() + expiresInSecs * 1e3;
130
+ while (Date.now() < deadline) {
131
+ const resp = await client.post(ENDPOINT_CLI_TOKEN, {
132
+ request_id: requestId,
133
+ code_verifier: codeVerifier
134
+ });
135
+ if (resp.status === "complete") return resp;
136
+ await delay(POLL_INTERVAL_MS);
137
+ }
138
+ throw new CliError(
139
+ CLI_ERROR_CODE.TIMEOUT,
140
+ "Login timed out waiting for approval. Re-run `cimplify login`."
141
+ );
142
+ }
143
+ function delay(ms) {
144
+ return new Promise((resolve) => setTimeout(resolve, ms));
145
+ }
152
146
 
153
147
  export { run as default };
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { TERMINAL_DEPLOYMENT_STATUSES } from './chunk-MXYUAJEW.mjs';
3
3
  import { parseArgs, flagString, flagBool } from './chunk-C4M3DXKC.mjs';
4
- import { ApiClient } from './chunk-MAOO6ZZ5.mjs';
4
+ import { ApiClient } from './chunk-CV3ZFCX6.mjs';
5
5
  import { readAuth, readProjectLink, readProjectState } from './chunk-UBAI443T.mjs';
6
6
  import { CliError, CLI_ERROR_CODE, isJsonMode, failure, result, red } from './chunk-E2T2SBP5.mjs';
7
7
 
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { REPO_PROVIDER } from './chunk-MXYUAJEW.mjs';
3
3
  import { parseArgs, flagString, flagBool } from './chunk-C4M3DXKC.mjs';
4
- import { ApiClient } from './chunk-MAOO6ZZ5.mjs';
4
+ import { ApiClient } from './chunk-CV3ZFCX6.mjs';
5
5
  import { readAuth } from './chunk-UBAI443T.mjs';
6
6
  import { CliError, CLI_ERROR_CODE, info, dim, result, bold, success } from './chunk-E2T2SBP5.mjs';
7
7
 
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- export { run as default, fetchCloneToken, fetchRepoRecord } from './chunk-CLNS2NBR.mjs';
2
+ export { run as default, fetchCloneToken, fetchRepoRecord } from './chunk-IV7SOUH3.mjs';
3
3
  import './chunk-ITAFAORS.mjs';
4
4
  import './chunk-MXYUAJEW.mjs';
5
5
  import './chunk-C4M3DXKC.mjs';
6
- import './chunk-MAOO6ZZ5.mjs';
6
+ import './chunk-CV3ZFCX6.mjs';
7
7
  import './chunk-UBAI443T.mjs';
8
8
  import './chunk-E2T2SBP5.mjs';
@@ -2,7 +2,7 @@
2
2
  import { pollDeployment } from './chunk-VTR5R5NQ.mjs';
3
3
  import { DEPLOYMENT_STATUS, DEPLOY_TRIGGER } from './chunk-MXYUAJEW.mjs';
4
4
  import { parseArgs, flagBool } from './chunk-C4M3DXKC.mjs';
5
- import { ApiClient } from './chunk-MAOO6ZZ5.mjs';
5
+ import { ApiClient } from './chunk-CV3ZFCX6.mjs';
6
6
  import { readAuth, readProjectLink, writeProjectState } from './chunk-UBAI443T.mjs';
7
7
  import { CliError, CLI_ERROR_CODE, step, success, info, dim, result, EXIT_CODE } from './chunk-E2T2SBP5.mjs';
8
8
 
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { DEPLOYMENT_STATUS } from './chunk-MXYUAJEW.mjs';
3
3
  import { parseArgs } from './chunk-C4M3DXKC.mjs';
4
- import { ApiClient } from './chunk-MAOO6ZZ5.mjs';
4
+ import { ApiClient } from './chunk-CV3ZFCX6.mjs';
5
5
  import { readAuth, readProjectLink, readProjectState } from './chunk-UBAI443T.mjs';
6
6
  import { bold, dim, info, result } from './chunk-E2T2SBP5.mjs';
7
7
 
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { package_default } from './chunk-TKFUMOQQ.mjs';
2
+ import { package_default } from './chunk-BQ5CWVHQ.mjs';
3
3
  import { promptYesNo } from './chunk-ITAFAORS.mjs';
4
4
  import { parseArgs, flagBool, flagString } from './chunk-C4M3DXKC.mjs';
5
5
  import { success, bold, info, dim, result, failure, CliError, CLI_ERROR_CODE, step, isJsonMode } from './chunk-E2T2SBP5.mjs';
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { ApiClient } from './chunk-MAOO6ZZ5.mjs';
2
+ import { ApiClient } from './chunk-CV3ZFCX6.mjs';
3
3
  import { readAuth } from './chunk-UBAI443T.mjs';
4
4
  import { info, bold, dim, result } from './chunk-E2T2SBP5.mjs';
5
5
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cimplify/cli",
3
- "version": "0.7.23",
3
+ "version": "0.8.0",
4
4
  "description": "Cimplify CLI — deploy, manage env vars, link projects, and scaffold storefronts",
5
5
  "keywords": [
6
6
  "cimplify",
@@ -37,14 +37,14 @@
37
37
  "test:run": "vitest run"
38
38
  },
39
39
  "devDependencies": {
40
- "@aws-sdk/client-s3": "^3.700.0",
41
- "@types/node": "^25.6.0",
42
- "@typescript/native-preview": "^7.0.0-dev.20260503.1",
40
+ "@aws-sdk/client-s3": "^3.1070.0",
41
+ "@types/node": "^25.9.3",
42
+ "@typescript/native-preview": "^7.0.0-dev.20260616.1",
43
43
  "tsup": "^8.5.1",
44
- "typescript": "5.9.3",
45
- "vitest": "^4.1.5"
44
+ "typescript": "6.0.3",
45
+ "vitest": "^4.1.9"
46
46
  },
47
47
  "dependencies": {
48
- "@cimplify/sdk": "^0.84.0"
48
+ "@cimplify/sdk": "^0.86.0"
49
49
  }
50
50
  }
@@ -11,6 +11,7 @@ import {
11
11
  import { ProductDetail } from "./product-detail";
12
12
  import { brand } from "@/lib/brand";
13
13
  import { getSiteUrl } from "@/lib/site-url";
14
+ import { buildProductOffer } from "@/lib/product-offer";
14
15
 
15
16
  // Pre-enumerate every product slug at build time so Next can emit cacheable
16
17
  // responses (s-maxage instead of no-store) for the route. Without this, every
@@ -29,7 +30,6 @@ export const revalidate = 3600;
29
30
 
30
31
  function productLd(product: ProductWithDetails, SITE_URL: string) {
31
32
  const image = product.image_url ?? product.images?.[0];
32
- const inStock = product.inventory_status?.in_stock !== false;
33
33
  return {
34
34
  "@context": "https://schema.org",
35
35
  "@type": "Product",
@@ -38,15 +38,10 @@ function productLd(product: ProductWithDetails, SITE_URL: string) {
38
38
  image: image ? [image] : undefined,
39
39
  sku: product.id,
40
40
  brand: { "@type": "Brand", name: brand.name },
41
- offers: {
42
- "@type": "Offer",
43
- price: product.default_price,
44
- priceCurrency: brand.currency,
45
- availability: inStock
46
- ? "https://schema.org/InStock"
47
- : "https://schema.org/OutOfStock",
41
+ offers: buildProductOffer(product, {
48
42
  url: `${SITE_URL}/products/${product.slug ?? product.id}`,
49
- },
43
+ currency: brand.currency,
44
+ }),
50
45
  };
51
46
  }
52
47
 
@@ -5,7 +5,7 @@
5
5
  "": {
6
6
  "name": "__STOREFRONT_NAME__",
7
7
  "dependencies": {
8
- "@cimplify/sdk": "^0.64.1",
8
+ "@cimplify/sdk": "^0.84.0",
9
9
  "next": "^16.2.6",
10
10
  "react": "^19.0.0",
11
11
  "react-dom": "^19.0.0",
@@ -31,7 +31,7 @@
31
31
 
32
32
  "@base-ui/utils": ["@base-ui/utils@0.2.9", "", { "dependencies": { "@babel/runtime": "^7.29.2", "@floating-ui/utils": "^0.2.11", "reselect": "^5.1.1", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "@types/react": "^17 || ^18 || ^19", "react": "^17 || ^18 || ^19", "react-dom": "^17 || ^18 || ^19" }, "optionalPeers": ["@types/react"] }, "sha512-x/PDDCYzoqPpjrdyb3VcyylTI2IjUXEtYDGi5foh7KsnmNJIIaVwA2GLgDH1dps1GgXiJbA60hM+AyuTfQzIvw=="],
33
33
 
34
- "@cimplify/sdk": ["@cimplify/sdk@0.64.1", "", { "dependencies": { "@base-ui/react": "^1.4.1", "clsx": "^2.1.1", "date-fns": "^4.1.0", "jose": "^6.2.3", "libphonenumber-js": "1.12.41", "react-day-picker": "^9.14.0", "tailwind-merge": "^3.5.0", "xss": "^1.0.15", "zod": "^4.4.3" }, "peerDependencies": { "@paystack/inline-js": "^2.22.8", "msw": ">=2.0.0", "react": ">=17.0.0", "vitest": ">=2.0.0" }, "optionalPeers": ["@paystack/inline-js", "msw", "react", "vitest"], "bin": { "cimplify-mock": "dist/mock/cli.mjs" } }, "sha512-qY3ngAxAyeRwHR5jJZ7eeeNKgvayZlVUuNglp779bJiwtwL3cZ8Ux4L+k3SgRzgAxtKz9YU2mmVBZxEu14frUw=="],
34
+ "@cimplify/sdk": ["@cimplify/sdk@0.84.0", "", { "dependencies": { "@base-ui/react": "^1.4.1", "clsx": "^2.1.1", "date-fns": "^4.1.0", "jose": "^6.2.3", "libphonenumber-js": "1.12.41", "react-day-picker": "^9.14.0", "tailwind-merge": "^3.5.0", "xss": "^1.0.15", "zod": "^4.4.3" }, "peerDependencies": { "@paystack/inline-js": "^2.22.8", "msw": ">=2.0.0", "react": ">=17.0.0", "react-dom": ">=17.0.0", "vitest": ">=2.0.0" }, "optionalPeers": ["@paystack/inline-js", "msw", "react", "react-dom", "vitest"], "bin": { "cimplify-mock": "dist/mock/cli.mjs" } }, "sha512-0fhHjNgBrxLt3pjI51gVfAj8lrd81NCw0DzsTdLIiM59UqOwCWCt166NqPOZg6VxpMITeE+z+fDKJn1tJpV/0Q=="],
35
35
 
36
36
  "@date-fns/tz": ["@date-fns/tz@1.4.1", "", {}, "sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA=="],
37
37
 
@@ -23,7 +23,7 @@ export function AccountPill() {
23
23
  });
24
24
  }, [session, refresh]);
25
25
 
26
- if (loading || !CLIENT_ID) return <span className="h-9 w-24" aria-hidden />;
26
+ if (loading) return <span className="h-9 w-24" aria-hidden />;
27
27
 
28
28
  return (
29
29
  <CimplifyUserButton
@@ -0,0 +1,46 @@
1
+ import { parsePrice, type ProductWithDetails } from "@cimplify/sdk";
2
+
3
+ const IN_STOCK = "https://schema.org/InStock";
4
+ const OUT_OF_STOCK = "https://schema.org/OutOfStock";
5
+
6
+ interface SaleOverlay {
7
+ price: string | number;
8
+ ends_at: string;
9
+ // Present only for capped, claims-driven sales, whose price moves per purchase.
10
+ cap?: { claimed: number; of: number } | null;
11
+ }
12
+
13
+ export interface ProductOffer {
14
+ "@type": "Offer";
15
+ price: number;
16
+ priceCurrency: string;
17
+ priceValidUntil?: string;
18
+ availability: string;
19
+ url: string;
20
+ }
21
+
22
+ /**
23
+ * schema.org Offer for a product page. Indexes the price a shopper actually
24
+ * sees: a scheduled/time sale carries the sale price plus a validity window; a
25
+ * capped (claims-driven) sale keeps the base price out of the index, since its
26
+ * number moves on every purchase and would mismatch the product feed.
27
+ */
28
+ export function buildProductOffer(
29
+ product: ProductWithDetails & { sale?: SaleOverlay | null },
30
+ opts: { url: string; currency: string },
31
+ ): ProductOffer {
32
+ const inStock = product.inventory_status?.in_stock !== false;
33
+ const sale = product.sale;
34
+ const indexableSale = sale && !sale.cap ? sale : null;
35
+ const offer: ProductOffer = {
36
+ "@type": "Offer",
37
+ price: parsePrice(indexableSale ? indexableSale.price : product.default_price),
38
+ priceCurrency: opts.currency,
39
+ availability: inStock ? IN_STOCK : OUT_OF_STOCK,
40
+ url: opts.url,
41
+ };
42
+ if (indexableSale) {
43
+ offer.priceValidUntil = indexableSale.ends_at;
44
+ }
45
+ return offer;
46
+ }
@@ -17,7 +17,7 @@
17
17
  "check": "bun run typecheck && bun run test:run"
18
18
  },
19
19
  "dependencies": {
20
- "@cimplify/sdk": "^0.84.0",
20
+ "@cimplify/sdk": "^0.86.0",
21
21
  "next": "^16.2.6",
22
22
  "react": "^19.0.0",
23
23
  "react-dom": "^19.0.0"
@@ -5,7 +5,7 @@
5
5
  "": {
6
6
  "name": "__STOREFRONT_NAME__",
7
7
  "dependencies": {
8
- "@cimplify/sdk": "^0.64.1",
8
+ "@cimplify/sdk": "^0.84.0",
9
9
  "next": "^16.2.6",
10
10
  "react": "^19.0.0",
11
11
  "react-dom": "^19.0.0",
@@ -31,7 +31,7 @@
31
31
 
32
32
  "@base-ui/utils": ["@base-ui/utils@0.2.9", "", { "dependencies": { "@babel/runtime": "^7.29.2", "@floating-ui/utils": "^0.2.11", "reselect": "^5.1.1", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "@types/react": "^17 || ^18 || ^19", "react": "^17 || ^18 || ^19", "react-dom": "^17 || ^18 || ^19" }, "optionalPeers": ["@types/react"] }, "sha512-x/PDDCYzoqPpjrdyb3VcyylTI2IjUXEtYDGi5foh7KsnmNJIIaVwA2GLgDH1dps1GgXiJbA60hM+AyuTfQzIvw=="],
33
33
 
34
- "@cimplify/sdk": ["@cimplify/sdk@0.64.1", "", { "dependencies": { "@base-ui/react": "^1.4.1", "clsx": "^2.1.1", "date-fns": "^4.1.0", "jose": "^6.2.3", "libphonenumber-js": "1.12.41", "react-day-picker": "^9.14.0", "tailwind-merge": "^3.5.0", "xss": "^1.0.15", "zod": "^4.4.3" }, "peerDependencies": { "@paystack/inline-js": "^2.22.8", "msw": ">=2.0.0", "react": ">=17.0.0", "vitest": ">=2.0.0" }, "optionalPeers": ["@paystack/inline-js", "msw", "react", "vitest"], "bin": { "cimplify-mock": "dist/mock/cli.mjs" } }, "sha512-qY3ngAxAyeRwHR5jJZ7eeeNKgvayZlVUuNglp779bJiwtwL3cZ8Ux4L+k3SgRzgAxtKz9YU2mmVBZxEu14frUw=="],
34
+ "@cimplify/sdk": ["@cimplify/sdk@0.84.0", "", { "dependencies": { "@base-ui/react": "^1.4.1", "clsx": "^2.1.1", "date-fns": "^4.1.0", "jose": "^6.2.3", "libphonenumber-js": "1.12.41", "react-day-picker": "^9.14.0", "tailwind-merge": "^3.5.0", "xss": "^1.0.15", "zod": "^4.4.3" }, "peerDependencies": { "@paystack/inline-js": "^2.22.8", "msw": ">=2.0.0", "react": ">=17.0.0", "react-dom": ">=17.0.0", "vitest": ">=2.0.0" }, "optionalPeers": ["@paystack/inline-js", "msw", "react", "react-dom", "vitest"], "bin": { "cimplify-mock": "dist/mock/cli.mjs" } }, "sha512-0fhHjNgBrxLt3pjI51gVfAj8lrd81NCw0DzsTdLIiM59UqOwCWCt166NqPOZg6VxpMITeE+z+fDKJn1tJpV/0Q=="],
35
35
 
36
36
  "@date-fns/tz": ["@date-fns/tz@1.5.0", "", {}, "sha512-lwYN/vDPeNRULcepoE/LO2Pgx+7/RV+S9ARfbc9lr2DtGkOD7pAiruHvbR1RX3Qyf6ja47EWJDMsNK5vK08DJg=="],
37
37
 
@@ -23,7 +23,7 @@ export function AccountPill() {
23
23
  });
24
24
  }, [session, refresh]);
25
25
 
26
- if (loading || !CLIENT_ID) return <span className="h-9 w-24" aria-hidden />;
26
+ if (loading) return <span className="h-9 w-24" aria-hidden />;
27
27
 
28
28
  return (
29
29
  <CimplifyUserButton
@@ -17,7 +17,7 @@
17
17
  "check": "bun run typecheck && bun run test:run"
18
18
  },
19
19
  "dependencies": {
20
- "@cimplify/sdk": "^0.84.0",
20
+ "@cimplify/sdk": "^0.86.0",
21
21
  "next": "^16.2.6",
22
22
  "react": "^19.0.0",
23
23
  "react-dom": "^19.0.0"
@@ -11,6 +11,7 @@ import {
11
11
  import { ProductDetail } from "./product-detail";
12
12
  import { brand } from "@/lib/brand";
13
13
  import { getSiteUrl } from "@/lib/site-url";
14
+ import { buildProductOffer } from "@/lib/product-offer";
14
15
 
15
16
  // Pre-enumerate every product slug at build time so Next can emit cacheable
16
17
  // responses (s-maxage instead of no-store) for the route. Without this, every
@@ -29,7 +30,6 @@ export const revalidate = 3600;
29
30
 
30
31
  function productLd(product: ProductWithDetails, SITE_URL: string) {
31
32
  const image = product.image_url ?? product.images?.[0];
32
- const inStock = product.inventory_status?.in_stock !== false;
33
33
  return {
34
34
  "@context": "https://schema.org",
35
35
  "@type": "Product",
@@ -38,15 +38,10 @@ function productLd(product: ProductWithDetails, SITE_URL: string) {
38
38
  image: image ? [image] : undefined,
39
39
  sku: product.id,
40
40
  brand: { "@type": "Brand", name: brand.name },
41
- offers: {
42
- "@type": "Offer",
43
- price: product.default_price,
44
- priceCurrency: brand.currency,
45
- availability: inStock
46
- ? "https://schema.org/InStock"
47
- : "https://schema.org/OutOfStock",
41
+ offers: buildProductOffer(product, {
48
42
  url: `${SITE_URL}/products/${product.slug ?? product.id}`,
49
- },
43
+ currency: brand.currency,
44
+ }),
50
45
  };
51
46
  }
52
47
 
@@ -5,7 +5,7 @@
5
5
  "": {
6
6
  "name": "__STOREFRONT_NAME__",
7
7
  "dependencies": {
8
- "@cimplify/sdk": "^0.64.1",
8
+ "@cimplify/sdk": "^0.84.0",
9
9
  "next": "^16.2.6",
10
10
  "react": "^19.0.0",
11
11
  "react-dom": "^19.0.0",
@@ -32,7 +32,7 @@
32
32
 
33
33
  "@base-ui/utils": ["@base-ui/utils@0.2.9", "", { "dependencies": { "@babel/runtime": "^7.29.2", "@floating-ui/utils": "^0.2.11", "reselect": "^5.1.1", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "@types/react": "^17 || ^18 || ^19", "react": "^17 || ^18 || ^19", "react-dom": "^17 || ^18 || ^19" }, "optionalPeers": ["@types/react"] }, "sha512-x/PDDCYzoqPpjrdyb3VcyylTI2IjUXEtYDGi5foh7KsnmNJIIaVwA2GLgDH1dps1GgXiJbA60hM+AyuTfQzIvw=="],
34
34
 
35
- "@cimplify/sdk": ["@cimplify/sdk@0.64.1", "", { "dependencies": { "@base-ui/react": "^1.4.1", "clsx": "^2.1.1", "date-fns": "^4.1.0", "jose": "^6.2.3", "libphonenumber-js": "1.12.41", "react-day-picker": "^9.14.0", "tailwind-merge": "^3.5.0", "xss": "^1.0.15", "zod": "^4.4.3" }, "peerDependencies": { "@paystack/inline-js": "^2.22.8", "msw": ">=2.0.0", "react": ">=17.0.0", "vitest": ">=2.0.0" }, "optionalPeers": ["@paystack/inline-js", "msw", "react", "vitest"], "bin": { "cimplify-mock": "dist/mock/cli.mjs" } }, "sha512-qY3ngAxAyeRwHR5jJZ7eeeNKgvayZlVUuNglp779bJiwtwL3cZ8Ux4L+k3SgRzgAxtKz9YU2mmVBZxEu14frUw=="],
35
+ "@cimplify/sdk": ["@cimplify/sdk@0.84.0", "", { "dependencies": { "@base-ui/react": "^1.4.1", "clsx": "^2.1.1", "date-fns": "^4.1.0", "jose": "^6.2.3", "libphonenumber-js": "1.12.41", "react-day-picker": "^9.14.0", "tailwind-merge": "^3.5.0", "xss": "^1.0.15", "zod": "^4.4.3" }, "peerDependencies": { "@paystack/inline-js": "^2.22.8", "msw": ">=2.0.0", "react": ">=17.0.0", "react-dom": ">=17.0.0", "vitest": ">=2.0.0" }, "optionalPeers": ["@paystack/inline-js", "msw", "react", "react-dom", "vitest"], "bin": { "cimplify-mock": "dist/mock/cli.mjs" } }, "sha512-0fhHjNgBrxLt3pjI51gVfAj8lrd81NCw0DzsTdLIiM59UqOwCWCt166NqPOZg6VxpMITeE+z+fDKJn1tJpV/0Q=="],
36
36
 
37
37
  "@date-fns/tz": ["@date-fns/tz@1.4.1", "", {}, "sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA=="],
38
38
 
@@ -23,7 +23,7 @@ export function AccountPill() {
23
23
  });
24
24
  }, [session, refresh]);
25
25
 
26
- if (loading || !CLIENT_ID) return <span className="h-9 w-24" aria-hidden />;
26
+ if (loading) return <span className="h-9 w-24" aria-hidden />;
27
27
 
28
28
  return (
29
29
  <CimplifyUserButton