@osimart/create-storefront 1.0.0 → 1.0.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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # @osimart/osimart-storefront
1
+ # @osimart/create-storefront
2
2
 
3
3
  The Osimart storefront **platform**, published as a private Nuxt layer. It has no look of
4
4
  its own. Every theme repo extends it:
@@ -77,5 +77,5 @@ developer (read).
77
77
  ## Working on the platform and a theme together
78
78
 
79
79
  ```bash
80
- cd osimart-theme-base && npm link ../osimart-storefront && npm run dev
80
+ cd osimart-theme-base && npm link ../create-storefront && npm run dev
81
81
  ```
@@ -21,4 +21,4 @@ export default defineNuxtPlugin(async () => {
21
21
  console.error('[GEO] Client-side fetch error:', err)
22
22
  }
23
23
  }
24
- })
24
+ })
@@ -2,4 +2,4 @@ import { VueQueryPlugin } from '@tanstack/vue-query'
2
2
 
3
3
  export default defineNuxtPlugin((nuxtApp) => {
4
4
  nuxtApp.vueApp.use(VueQueryPlugin)
5
- })
5
+ })
@@ -18,7 +18,8 @@
18
18
  *
19
19
  * Env (read from .env too):
20
20
  * OSIMART_THEME_TOKEN Theme access token (dashboard → Theme access)
21
- * OSIMART_THEME_DEV_URL default: ${NUXT_PUBLIC_STORE_API_BASE}theme-dev/
21
+ * NUXT_PUBLIC_STORE_API_BASE the store's API (already set for `npm run dev`); the CLI calls
22
+ * <its origin>/store/apis/theme-dev/
22
23
  *
23
24
  * Backend contract: THEME_DEV_API.md in @ositcom/osimart-storefront.
24
25
  */
@@ -51,25 +52,33 @@ function fail(message) {
51
52
  process.exit(1);
52
53
  }
53
54
 
55
+ /**
56
+ * The builder API's theme-dev route, on the same backend the storefront
57
+ * already talks to (NUXT_PUBLIC_STORE_API_BASE). OSIMART_THEME_DEV_URL only
58
+ * overrides it if the routes are mounted somewhere other than /store/apis/theme-dev/.
59
+ */
60
+ const BUILDER_PATH = "/store/apis/theme-dev/";
61
+
54
62
  function baseUrl() {
55
- const explicit = process.env.OSIMART_THEME_DEV_URL;
63
+ const override = process.env.OSIMART_THEME_DEV_URL;
64
+ if (override) return override.endsWith("/") ? override : `${override}/`;
56
65
  const api = process.env.NUXT_PUBLIC_STORE_API_BASE;
57
- const url = explicit || (api ? `${api.replace(/\/+$/, "")}/theme-dev/` : "");
58
- if (!url) fail("Set OSIMART_THEME_DEV_URL or NUXT_PUBLIC_STORE_API_BASE in .env");
59
- return url.endsWith("/") ? url : `${url}/`;
66
+ if (!api) fail("Set NUXT_PUBLIC_STORE_API_BASE in .env (the store's API, e.g. http://test6.192.168.1.12.nip.io:8000/)");
67
+ return new URL(BUILDER_PATH, api).toString();
60
68
  }
61
69
 
62
70
  async function request(method, path, body) {
63
71
  const token = process.env.OSIMART_THEME_TOKEN;
64
72
  if (!token) fail("Set OSIMART_THEME_TOKEN in .env (dashboard → Theme access)");
65
- const res = await fetch(new URL(path, baseUrl()), {
73
+ const url = new URL(path, baseUrl());
74
+ const res = await fetch(url, {
66
75
  method,
67
76
  headers: { Authorization: `ThemeToken ${token}`, "Content-Type": "application/json", Accept: "application/json" },
68
77
  body: body === undefined ? undefined : JSON.stringify(body),
69
78
  });
70
79
  const text = await res.text();
71
80
  let data = null;
72
- try { data = text ? JSON.parse(text) : null; } catch { data = { detail: text.slice(0, 300) }; }
81
+ try { data = text ? JSON.parse(text) : null; } catch { data = { detail: `not a theme-dev endpoint: ${url}` }; }
73
82
  if (!res.ok) {
74
83
  const err = new Error(data?.detail || data?.message || `HTTP ${res.status}`);
75
84
  err.status = res.status;
@@ -184,8 +193,12 @@ async function pull(args) {
184
193
  console.log(` (schemas not saved: ${e.message})`);
185
194
  }
186
195
 
187
- saveState({ theme_id: data.theme.id, theme_name: data.theme.name, role: data.theme.role, version: data.theme.version, pulled_at: new Date().toISOString() });
188
- console.log(`✔ pulled "${data.theme.name}" (${data.theme.role}) — ${data.templates?.length ?? 0} templates, ${Object.keys(groups).length} groups`);
196
+ saveState({
197
+ store_id: data.theme.store?.id, store_name: data.theme.store?.name,
198
+ theme_id: data.theme.id, theme_name: data.theme.name, role: data.theme.role,
199
+ version: data.theme.version, pulled_at: new Date().toISOString(),
200
+ });
201
+ console.log(`✔ pulled "${data.theme.name}" (${data.theme.role}) from ${data.theme.store?.name ?? "the store"} — ${data.templates?.length ?? 0} templates, ${Object.keys(groups).length} groups`);
189
202
  }
190
203
 
191
204
  async function push(args) {
@@ -197,7 +210,15 @@ async function push(args) {
197
210
  // 1. Section types the theme adds (their schemas), so the editor can place them.
198
211
  const sections = readLocalSchemas();
199
212
  if (sections.length || prune) {
200
- const report = await request("POST", "sections/sync/", { sections, prune, dry_run: dryRun });
213
+ let report;
214
+ try {
215
+ report = await request("POST", "sections/sync/", {
216
+ sections, prune, dry_run: dryRun, expected_store: force ? null : state().store_id ?? null,
217
+ });
218
+ } catch (e) {
219
+ if (e.status === 400 && e.data) fail(`Section schemas rejected:\n${JSON.stringify(e.data, null, 2)}`);
220
+ throw e;
221
+ }
201
222
  console.log(`${dryRun ? "◌" : "✔"} section schemas: ${sections.length}`);
202
223
  for (const key of ["created", "updated", "unchanged", "deleted", "kept_in_use"]) {
203
224
  if (report?.[key]?.length) console.log(` ${key.padEnd(11)} ${report[key].join(", ")}`);
@@ -210,17 +231,19 @@ async function push(args) {
210
231
  console.log(" nothing in theme/ to push (run pull first)");
211
232
  return;
212
233
  }
213
- const { version, theme_id, role } = state();
234
+ const { version, theme_id, role, store_id } = state();
214
235
  const sameTheme = theme === theme_id || theme === String(role || "").toLowerCase();
215
236
  try {
216
237
  const res = await request("PUT", "theme/", {
217
238
  theme,
218
239
  // The merchant may have edited the theme in the dashboard since the pull.
219
240
  base_version: force || !sameTheme ? null : version ?? null,
241
+ // Files pulled from another store (token swapped)? The backend refuses.
242
+ expected_store: force ? null : store_id ?? null,
220
243
  dry_run: dryRun,
221
244
  ...local,
222
245
  });
223
- console.log(`${dryRun ? "◌ dry run" : "✔ pushed"} to "${res.theme.name}" (${res.theme.role}) — ${local.templates.length} templates`);
246
+ console.log(`${dryRun ? "◌ dry run" : "✔ pushed"} to "${res.theme.name}" (${res.theme.role}) on ${res.theme.store?.name ?? "the store"} — ${local.templates.length} templates`);
224
247
  for (const key of ["created", "updated", "unchanged"]) {
225
248
  if (res[key]?.length) console.log(` ${key.padEnd(9)} ${res[key].join(", ")}`);
226
249
  }
package/nuxt.config.ts CHANGED
@@ -2,9 +2,9 @@ import { fileURLToPath } from "node:url";
2
2
  import osiSections from "./nuxt/osi-sections";
3
3
 
4
4
  /**
5
- * @ositcom/osimart-storefront — the platform. Extended by every theme repo:
5
+ * @ositcom/create-storefront — the platform. Extended by every theme repo:
6
6
  *
7
- * extends: ["@ositcom/osimart-storefront"]
7
+ * extends: ["@ositcom/create-storefront"]
8
8
  *
9
9
  * This package holds the logic (composables, services, the script of every
10
10
  * theme section/component under app/logic), the platform pages (routing,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@osimart/create-storefront",
3
- "version": "1.0.0",
4
- "description": "Osimart storefront platform \u2014 logic, platform pages and CLI; extended by every theme repo",
3
+ "version": "1.0.1",
4
+ "description": "Osimart storefront platform — logic, platform pages and CLI; extended by every theme repo",
5
5
  "type": "module",
6
6
  "main": "./nuxt.config.ts",
7
7
  "bin": {
@@ -43,4 +43,4 @@
43
43
  },
44
44
  "license": "UNLICENSED",
45
45
  "homepage": "https://osimart.com"
46
- }
46
+ }