@shop-on/create-theme 0.0.0-stage → 0.1.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 (261) hide show
  1. package/dist/LICENSE.md +39 -0
  2. package/dist/cli.d.mts +1 -0
  3. package/dist/cli.mjs +40 -0
  4. package/dist/index.d.mts +32 -0
  5. package/dist/index.mjs +81 -0
  6. package/package.json +28 -3
  7. package/template/.claude/skills/react-best-practices/AGENTS.md +3663 -0
  8. package/template/.claude/skills/react-best-practices/LICENSE.md +26 -0
  9. package/template/.claude/skills/react-best-practices/SKILL.md +178 -0
  10. package/template/.claude/skills/react-best-practices/metadata.json +15 -0
  11. package/template/.claude/skills/react-best-practices/rules/_sections.md +56 -0
  12. package/template/.claude/skills/react-best-practices/rules/_template.md +28 -0
  13. package/template/.claude/skills/react-best-practices/rules/advanced-effect-event-deps.md +50 -0
  14. package/template/.claude/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  15. package/template/.claude/skills/react-best-practices/rules/advanced-init-once.md +42 -0
  16. package/template/.claude/skills/react-best-practices/rules/advanced-use-latest.md +39 -0
  17. package/template/.claude/skills/react-best-practices/rules/async-api-routes.md +35 -0
  18. package/template/.claude/skills/react-best-practices/rules/async-cheap-condition-before-await.md +37 -0
  19. package/template/.claude/skills/react-best-practices/rules/async-defer-await.md +82 -0
  20. package/template/.claude/skills/react-best-practices/rules/async-dependencies.md +48 -0
  21. package/template/.claude/skills/react-best-practices/rules/async-parallel.md +24 -0
  22. package/template/.claude/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
  23. package/template/.claude/skills/react-best-practices/rules/bundle-barrel-imports.md +60 -0
  24. package/template/.claude/skills/react-best-practices/rules/bundle-conditional.md +37 -0
  25. package/template/.claude/skills/react-best-practices/rules/bundle-defer-third-party.md +48 -0
  26. package/template/.claude/skills/react-best-practices/rules/bundle-dynamic-imports.md +34 -0
  27. package/template/.claude/skills/react-best-practices/rules/bundle-preload.md +44 -0
  28. package/template/.claude/skills/react-best-practices/rules/client-event-listeners.md +78 -0
  29. package/template/.claude/skills/react-best-practices/rules/client-localstorage-schema.md +74 -0
  30. package/template/.claude/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
  31. package/template/.claude/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
  32. package/template/.claude/skills/react-best-practices/rules/compose-compound-components.md +42 -0
  33. package/template/.claude/skills/react-best-practices/rules/compose-context-shared-state.md +80 -0
  34. package/template/.claude/skills/react-best-practices/rules/compose-extract-render-methods.md +55 -0
  35. package/template/.claude/skills/react-best-practices/rules/compose-transparent-props.md +65 -0
  36. package/template/.claude/skills/react-best-practices/rules/effect-chains.md +67 -0
  37. package/template/.claude/skills/react-best-practices/rules/effect-data-fetching.md +57 -0
  38. package/template/.claude/skills/react-best-practices/rules/effect-external-store.md +59 -0
  39. package/template/.claude/skills/react-best-practices/rules/effect-reset-state-with-key.md +41 -0
  40. package/template/.claude/skills/react-best-practices/rules/js-batch-dom-css.md +110 -0
  41. package/template/.claude/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
  42. package/template/.claude/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
  43. package/template/.claude/skills/react-best-practices/rules/js-cache-storage.md +68 -0
  44. package/template/.claude/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
  45. package/template/.claude/skills/react-best-practices/rules/js-early-exit.md +50 -0
  46. package/template/.claude/skills/react-best-practices/rules/js-flatmap-filter.md +51 -0
  47. package/template/.claude/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
  48. package/template/.claude/skills/react-best-practices/rules/js-index-maps.md +37 -0
  49. package/template/.claude/skills/react-best-practices/rules/js-length-check-first.md +50 -0
  50. package/template/.claude/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
  51. package/template/.claude/skills/react-best-practices/rules/js-request-idle-callback.md +104 -0
  52. package/template/.claude/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
  53. package/template/.claude/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  54. package/template/.claude/skills/react-best-practices/rules/rendering-activity.md +26 -0
  55. package/template/.claude/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +38 -0
  56. package/template/.claude/skills/react-best-practices/rules/rendering-conditional-render.md +32 -0
  57. package/template/.claude/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
  58. package/template/.claude/skills/react-best-practices/rules/rendering-hoist-jsx.md +36 -0
  59. package/template/.claude/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +72 -0
  60. package/template/.claude/skills/react-best-practices/rules/rendering-hydration-suppress-warning.md +26 -0
  61. package/template/.claude/skills/react-best-practices/rules/rendering-resource-hints.md +85 -0
  62. package/template/.claude/skills/react-best-practices/rules/rendering-script-defer-async.md +68 -0
  63. package/template/.claude/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
  64. package/template/.claude/skills/react-best-practices/rules/rendering-usetransition-loading.md +75 -0
  65. package/template/.claude/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
  66. package/template/.claude/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
  67. package/template/.claude/skills/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  68. package/template/.claude/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
  69. package/template/.claude/skills/react-best-practices/rules/rerender-functional-setstate.md +77 -0
  70. package/template/.claude/skills/react-best-practices/rules/rerender-lazy-state-init.md +56 -0
  71. package/template/.claude/skills/react-best-practices/rules/rerender-memo-with-default-value.md +36 -0
  72. package/template/.claude/skills/react-best-practices/rules/rerender-memo.md +44 -0
  73. package/template/.claude/skills/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  74. package/template/.claude/skills/react-best-practices/rules/rerender-no-inline-components.md +75 -0
  75. package/template/.claude/skills/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  76. package/template/.claude/skills/react-best-practices/rules/rerender-split-combined-hooks.md +64 -0
  77. package/template/.claude/skills/react-best-practices/rules/rerender-transitions.md +40 -0
  78. package/template/.claude/skills/react-best-practices/rules/rerender-use-deferred-value.md +59 -0
  79. package/template/.claude/skills/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  80. package/template/.claude/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
  81. package/template/.claude/skills/react-best-practices/rules/server-auth-actions.md +96 -0
  82. package/template/.claude/skills/react-best-practices/rules/server-cache-lru.md +41 -0
  83. package/template/.claude/skills/react-best-practices/rules/server-cache-react.md +76 -0
  84. package/template/.claude/skills/react-best-practices/rules/server-dedup-props.md +65 -0
  85. package/template/.claude/skills/react-best-practices/rules/server-hoist-static-io.md +142 -0
  86. package/template/.claude/skills/react-best-practices/rules/server-no-shared-module-state.md +50 -0
  87. package/template/.claude/skills/react-best-practices/rules/server-parallel-fetching.md +83 -0
  88. package/template/.claude/skills/react-best-practices/rules/server-parallel-nested-fetching.md +30 -0
  89. package/template/.claude/skills/react-best-practices/rules/server-serialization.md +38 -0
  90. package/template/.claude/skills/react-start/LICENSE.md +25 -0
  91. package/template/.claude/skills/react-start/SKILL.md +282 -0
  92. package/template/.claude/skills/router-core/LICENSE.md +25 -0
  93. package/template/.claude/skills/router-core/SKILL.md +139 -0
  94. package/template/.claude/skills/router-core-auth-and-guards/LICENSE.md +25 -0
  95. package/template/.claude/skills/router-core-auth-and-guards/SKILL.md +454 -0
  96. package/template/.claude/skills/router-core-code-splitting/LICENSE.md +25 -0
  97. package/template/.claude/skills/router-core-code-splitting/SKILL.md +317 -0
  98. package/template/.claude/skills/router-core-data-loading/LICENSE.md +25 -0
  99. package/template/.claude/skills/router-core-data-loading/SKILL.md +478 -0
  100. package/template/.claude/skills/router-core-navigation/LICENSE.md +25 -0
  101. package/template/.claude/skills/router-core-navigation/SKILL.md +432 -0
  102. package/template/.claude/skills/router-core-not-found-and-errors/LICENSE.md +25 -0
  103. package/template/.claude/skills/router-core-not-found-and-errors/SKILL.md +435 -0
  104. package/template/.claude/skills/router-core-path-params/LICENSE.md +25 -0
  105. package/template/.claude/skills/router-core-path-params/SKILL.md +382 -0
  106. package/template/.claude/skills/router-core-search-params/LICENSE.md +25 -0
  107. package/template/.claude/skills/router-core-search-params/SKILL.md +342 -0
  108. package/template/.claude/skills/router-core-ssr/LICENSE.md +25 -0
  109. package/template/.claude/skills/router-core-ssr/SKILL.md +419 -0
  110. package/template/.claude/skills/router-core-type-safety/LICENSE.md +25 -0
  111. package/template/.claude/skills/router-core-type-safety/SKILL.md +485 -0
  112. package/template/.claude/skills/start-core/LICENSE.md +25 -0
  113. package/template/.claude/skills/start-core/SKILL.md +205 -0
  114. package/template/.claude/skills/start-core-execution-model/LICENSE.md +25 -0
  115. package/template/.claude/skills/start-core-execution-model/SKILL.md +298 -0
  116. package/template/.claude/skills/start-core-middleware/LICENSE.md +25 -0
  117. package/template/.claude/skills/start-core-middleware/SKILL.md +350 -0
  118. package/template/.claude/skills/start-core-server-functions/LICENSE.md +25 -0
  119. package/template/.claude/skills/start-core-server-functions/SKILL.md +331 -0
  120. package/template/.claude/skills/start-core-server-routes/LICENSE.md +25 -0
  121. package/template/.claude/skills/start-core-server-routes/SKILL.md +280 -0
  122. package/template/.claude/skills/start-server-core/LICENSE.md +25 -0
  123. package/template/.claude/skills/start-server-core/SKILL.md +252 -0
  124. package/template/.claude/skills/theme-dev/SKILL.md +285 -0
  125. package/template/.claude/skills/theme-dev/recipes/block.md +116 -0
  126. package/template/.claude/skills/theme-dev/recipes/concepts.md +114 -0
  127. package/template/.claude/skills/theme-dev/recipes/container-block.md +122 -0
  128. package/template/.claude/skills/theme-dev/recipes/customer-auth.md +92 -0
  129. package/template/.claude/skills/theme-dev/recipes/data-fetching.md +126 -0
  130. package/template/.claude/skills/theme-dev/recipes/dynamic-sources.md +251 -0
  131. package/template/.claude/skills/theme-dev/recipes/input-settings.md +549 -0
  132. package/template/.claude/skills/theme-dev/recipes/locales.md +146 -0
  133. package/template/.claude/skills/theme-dev/recipes/picker-data.md +181 -0
  134. package/template/.claude/skills/theme-dev/recipes/quality.md +150 -0
  135. package/template/.claude/skills/theme-dev/recipes/section-group.md +140 -0
  136. package/template/.claude/skills/theme-dev/recipes/section.md +164 -0
  137. package/template/.claude/skills/theme-dev/recipes/snippet.md +75 -0
  138. package/template/.claude/skills/theme-dev/recipes/static-block.md +143 -0
  139. package/template/.claude/skills/theme-dev/recipes/styling.md +225 -0
  140. package/template/.claude/skills/theme-dev/recipes/template.md +129 -0
  141. package/template/.env.example +9 -0
  142. package/template/.oxfmtrc.json +11 -0
  143. package/template/CLAUDE.md +13 -0
  144. package/template/LICENSE.md +39 -0
  145. package/template/README.md +82 -0
  146. package/template/_gitignore +17 -0
  147. package/template/package.json +52 -0
  148. package/template/release-notes.md +4 -0
  149. package/template/scripts/backfill-defaults.mjs +8 -0
  150. package/template/scripts/check-locales.mjs +4 -0
  151. package/template/scripts/postbuild.mjs +12 -0
  152. package/template/scripts/theme-check.mjs +4 -0
  153. package/template/src/assets/icons/arrow-right.svg +4 -0
  154. package/template/src/assets/rte.css +89 -0
  155. package/template/src/assets/theme.css +25 -0
  156. package/template/src/components/template-renderer.test.ts +33 -0
  157. package/template/src/components/template-renderer.tsx +59 -0
  158. package/template/src/config/settings-schema.json +21 -0
  159. package/template/src/layouts/empty.json +4 -0
  160. package/template/src/layouts/empty.tsx +8 -0
  161. package/template/src/layouts/main.json +7 -0
  162. package/template/src/layouts/main.tsx +24 -0
  163. package/template/src/lib/i18n.server.ts +36 -0
  164. package/template/src/lib/i18n.ts +39 -0
  165. package/template/src/lib/listing-search.ts +109 -0
  166. package/template/src/lib/seo-head.ts +12 -0
  167. package/template/src/lib/theme-events.test.ts +67 -0
  168. package/template/src/lib/theme-events.ts +68 -0
  169. package/template/src/lib/use-analytics.ts +163 -0
  170. package/template/src/locales/en.default.json +22 -0
  171. package/template/src/locales/en.default.schema.json +60 -0
  172. package/template/src/locales/mn.default.json +22 -0
  173. package/template/src/locales/mn.default.schema.json +60 -0
  174. package/template/src/route-adapter.tsx +75 -0
  175. package/template/src/routeTree.gen.ts +613 -0
  176. package/template/src/router.tsx +10 -0
  177. package/template/src/routes/__root.tsx +274 -0
  178. package/template/src/routes/analytics.events.tsx +21 -0
  179. package/template/src/routes/analytics.script.tsx +22 -0
  180. package/template/src/routes/analytics.visits.tsx +21 -0
  181. package/template/src/routes/customer_logout.tsx +26 -0
  182. package/template/src/routes/robots[.]txt.tsx +27 -0
  183. package/template/src/routes/sitemap[.]xml.tsx +20 -0
  184. package/template/src/routes/{-$locale}/404.tsx +15 -0
  185. package/template/src/routes/{-$locale}/account/index.tsx +12 -0
  186. package/template/src/routes/{-$locale}/account/login.tsx +14 -0
  187. package/template/src/routes/{-$locale}/account/orders.tsx +14 -0
  188. package/template/src/routes/{-$locale}/account/verify.tsx +14 -0
  189. package/template/src/routes/{-$locale}/blogs/$blogHandle.tsx +15 -0
  190. package/template/src/routes/{-$locale}/blogs/$blogHandle_/articles/$articleHandle.tsx +16 -0
  191. package/template/src/routes/{-$locale}/cart.tsx +15 -0
  192. package/template/src/routes/{-$locale}/collections/$collectionHandle.tsx +15 -0
  193. package/template/src/routes/{-$locale}/collections/$collectionHandle_/products/$handle.tsx +18 -0
  194. package/template/src/routes/{-$locale}/collections/index.tsx +15 -0
  195. package/template/src/routes/{-$locale}/index.tsx +15 -0
  196. package/template/src/routes/{-$locale}/pages/$handle.tsx +15 -0
  197. package/template/src/routes/{-$locale}/password.tsx +15 -0
  198. package/template/src/routes/{-$locale}/policies/$handle.tsx +15 -0
  199. package/template/src/routes/{-$locale}/preview/section.tsx +23 -0
  200. package/template/src/routes/{-$locale}/products/$handle.tsx +21 -0
  201. package/template/src/routes/{-$locale}/search.tsx +15 -0
  202. package/template/src/routes/{-$locale}.tsx +14 -0
  203. package/template/src/section-groups/footer-group.json +11 -0
  204. package/template/src/section-groups/header-group.json +11 -0
  205. package/template/src/sections/footer.json +14 -0
  206. package/template/src/sections/footer.tsx +13 -0
  207. package/template/src/sections/header.json +15 -0
  208. package/template/src/sections/header.tsx +41 -0
  209. package/template/src/sections/hero.json +27 -0
  210. package/template/src/sections/hero.tsx +45 -0
  211. package/template/src/sections/main-article.json +7 -0
  212. package/template/src/sections/main-article.tsx +41 -0
  213. package/template/src/sections/main-blog.json +14 -0
  214. package/template/src/sections/main-blog.tsx +46 -0
  215. package/template/src/sections/main-cart.json +7 -0
  216. package/template/src/sections/main-cart.tsx +32 -0
  217. package/template/src/sections/main-collection-list.json +14 -0
  218. package/template/src/sections/main-collection-list.tsx +42 -0
  219. package/template/src/sections/main-collection.json +7 -0
  220. package/template/src/sections/main-collection.test.tsx +86 -0
  221. package/template/src/sections/main-collection.tsx +53 -0
  222. package/template/src/sections/main-page.json +14 -0
  223. package/template/src/sections/main-page.tsx +39 -0
  224. package/template/src/sections/main-password.json +19 -0
  225. package/template/src/sections/main-password.tsx +44 -0
  226. package/template/src/sections/main-policy.json +7 -0
  227. package/template/src/sections/main-policy.tsx +36 -0
  228. package/template/src/sections/main-product.json +7 -0
  229. package/template/src/sections/main-product.tsx +54 -0
  230. package/template/src/sections/main-search.json +7 -0
  231. package/template/src/sections/main-search.tsx +62 -0
  232. package/template/src/server/customer.ts +48 -0
  233. package/template/src/server/enrich-adapter.ts +43 -0
  234. package/template/src/server/i18n.server.test.ts +22 -0
  235. package/template/src/server/i18n.server.ts +41 -0
  236. package/template/src/server/i18n.ts +14 -0
  237. package/template/src/server/settings.ts +210 -0
  238. package/template/src/server/template-loader.ts +36 -0
  239. package/template/src/server.ts +27 -0
  240. package/template/src/snippets/link.tsx +25 -0
  241. package/template/src/snippets/localized-link.tsx +30 -0
  242. package/template/src/snippets/product-card.tsx +33 -0
  243. package/template/src/start.ts +6 -0
  244. package/template/src/templates/404.json +6 -0
  245. package/template/src/templates/article.json +8 -0
  246. package/template/src/templates/blog.json +8 -0
  247. package/template/src/templates/cart.json +8 -0
  248. package/template/src/templates/collection.json +8 -0
  249. package/template/src/templates/index.json +11 -0
  250. package/template/src/templates/list-collections.json +8 -0
  251. package/template/src/templates/page.json +8 -0
  252. package/template/src/templates/password.json +8 -0
  253. package/template/src/templates/policy.json +8 -0
  254. package/template/src/templates/product.json +8 -0
  255. package/template/src/templates/search.json +8 -0
  256. package/template/test/prose-coverage.test.ts +12 -0
  257. package/template/theme.config.json +3 -0
  258. package/template/tsconfig.json +30 -0
  259. package/template/vite.config.ts +6 -0
  260. package/template/vitest.config.ts +3 -0
  261. package/README.md +0 -3
@@ -0,0 +1,39 @@
1
+ # Cody Theme Development License
2
+
3
+ Copyright (c) 2026 Cody LLC. All rights reserved except as granted below.
4
+
5
+ "The Software" is this package, its source, and its documentation. "The
6
+ Platform" is Cody, the commerce platform operated by Cody LLC.
7
+
8
+ ## 1. Grant
9
+
10
+ You may use, copy and modify the Software, and distribute modified copies, solely
11
+ to develop, test, and distribute themes, apps and other extensions that run on
12
+ the Platform.
13
+
14
+ ## 2. Restrictions
15
+
16
+ You may not:
17
+
18
+ 1. use the Software, or anything derived from it, with any commerce platform,
19
+ storefront or hosting service other than the Platform;
20
+ 2. use the Software to build a product that competes with the Platform;
21
+ 3. sublicense the Software, or distribute it other than as part of a theme,
22
+ app or extension for the Platform;
23
+ 4. remove or alter this license or any copyright notice in the Software.
24
+
25
+ ## 3. Your work
26
+
27
+ Themes, apps and extensions you build with the Software are yours. The parts of
28
+ the Software they include stay under this license.
29
+
30
+ ## 4. Termination
31
+
32
+ This license ends automatically if you break any of its terms. You must then
33
+ stop using the Software and delete your copies of it.
34
+
35
+ ## 5. No warranty
36
+
37
+ The Software is provided "as is", without warranty of any kind. Cody LLC is not
38
+ liable for any claim, damages or other liability arising from the Software or
39
+ its use.
package/dist/cli.d.mts ADDED
@@ -0,0 +1 @@
1
+ export {}
package/dist/cli.mjs ADDED
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env node
2
+ import { packageManagerCommands, scaffoldTheme } from "./index.mjs";
3
+ import path from "node:path";
4
+ //#region src/cli.ts
5
+ const USAGE = "usage: npm create @shop-on/theme <dir>";
6
+ const dir = process.argv[2];
7
+ if (dir === "-h" || dir === "--help") {
8
+ console.log(USAGE);
9
+ process.exit(0);
10
+ }
11
+ if (!dir || dir.startsWith("-")) {
12
+ console.error(USAGE);
13
+ process.exit(1);
14
+ }
15
+ let theme;
16
+ try {
17
+ theme = scaffoldTheme({ dir });
18
+ } catch (error) {
19
+ console.error(error instanceof Error ? error.message : error);
20
+ process.exit(1);
21
+ }
22
+ const commands = packageManagerCommands(process.env.npm_config_user_agent);
23
+ const [install, dev] = [commands.install.join(" "), commands.dev.join(" ")];
24
+ const relative = path.relative(process.cwd(), theme.dir);
25
+ const steps = [
26
+ ...relative ? [`cd ${/\s/.test(relative) ? JSON.stringify(relative) : relative}`] : [],
27
+ install,
28
+ "cp .env.example .env # then fill in your store's storefront credentials",
29
+ dev
30
+ ];
31
+ console.log(`
32
+ Theme scaffolded in ${theme.dir}
33
+
34
+ Next:
35
+ ${steps.map((step, i) => ` ${i + 1}. ${step}`).join("\n")}
36
+
37
+ Once the Shop-On CLI is published, \`shop-on theme init\` does all this and fills in .env for you.
38
+ `);
39
+ //#endregion
40
+ export {};
@@ -0,0 +1,32 @@
1
+ //#region src/index.d.ts
2
+ /**
3
+ * `{ [name]: packedName }`: the files `npm pack` leaves out of a tarball, which
4
+ * `template/` stores renamed and `scaffoldTheme` restores.
5
+ */
6
+ export declare const PACKED_NAMES: Record<string, string>;
7
+ export type ScaffoldThemeResult = {
8
+ /** Absolute path of the new theme. */
9
+ dir: string;
10
+ /** The `name` written to its `package.json`: `dir`'s basename, slugified. */
11
+ name: string;
12
+ /** Every file written, relative to `dir`, `/`-separated, sorted. */
13
+ files: string[];
14
+ };
15
+ /**
16
+ * Copies the theme starter into `dir`, creating it if needed, and names the
17
+ * package after it. Throws if `dir` exists and holds anything but `.git`.
18
+ * Writes no `.env` and touches no network.
19
+ */
20
+ export declare function scaffoldTheme({ dir }: {
21
+ dir: string;
22
+ }): ScaffoldThemeResult;
23
+ /**
24
+ * The install and dev commands of the package manager that ran this process,
25
+ * which `npm_config_user_agent` names (e.g. `pnpm/10.33.0 npm/? node/v24.0.0
26
+ * darwin arm64`). npm when it names none.
27
+ */
28
+ export declare function packageManagerCommands(userAgent: string | undefined): {
29
+ install: string[];
30
+ dev: string[];
31
+ };
32
+ //#endregion
package/dist/index.mjs ADDED
@@ -0,0 +1,81 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ //#region src/index.ts
5
+ /**
6
+ * `{ [name]: packedName }`: the files `npm pack` leaves out of a tarball, which
7
+ * `template/` stores renamed and `scaffoldTheme` restores.
8
+ */
9
+ const PACKED_NAMES = { ".gitignore": "_gitignore" };
10
+ const RESTORED_NAMES = Object.fromEntries(Object.entries(PACKED_NAMES).map(([name, packed]) => [packed, name]));
11
+ const TEMPLATE = fileURLToPath(new URL("../template", import.meta.url));
12
+ const isEmptyDir = (dir) => fs.statSync(dir).isDirectory() && fs.readdirSync(dir).every((entry) => entry === ".git");
13
+ const toPackageName = (dir) => path.basename(dir).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "shop-on-theme";
14
+ /**
15
+ * Copies the theme starter into `dir`, creating it if needed, and names the
16
+ * package after it. Throws if `dir` exists and holds anything but `.git`.
17
+ * Writes no `.env` and touches no network.
18
+ */
19
+ function scaffoldTheme({ dir }) {
20
+ const target = path.resolve(dir);
21
+ if (fs.existsSync(target) && !fs.statSync(target).isDirectory()) throw new Error(`${target} is a file, not a directory. Pick a new directory.`);
22
+ if (fs.existsSync(target) && !isEmptyDir(target)) throw new Error(`${target} is not empty. Pick a new directory, or empty this one first.`);
23
+ if (!fs.existsSync(TEMPLATE)) throw new Error(`${TEMPLATE} is missing. In the repo, run \`pnpm -C packages/create-theme template\`.`);
24
+ const files = [];
25
+ for (const entry of fs.readdirSync(TEMPLATE, {
26
+ recursive: true,
27
+ withFileTypes: true
28
+ })) {
29
+ if (!entry.isFile()) continue;
30
+ const relativeDir = path.relative(TEMPLATE, entry.parentPath);
31
+ const file = path.join(relativeDir, RESTORED_NAMES[entry.name] ?? entry.name);
32
+ fs.mkdirSync(path.join(target, relativeDir), { recursive: true });
33
+ fs.copyFileSync(path.join(entry.parentPath, entry.name), path.join(target, file));
34
+ files.push(file.split(path.sep).join("/"));
35
+ }
36
+ const name = toPackageName(target);
37
+ const manifestPath = path.join(target, "package.json");
38
+ const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
39
+ manifest.name = name;
40
+ fs.writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
41
+ return {
42
+ dir: target,
43
+ name,
44
+ files: files.sort()
45
+ };
46
+ }
47
+ /**
48
+ * The install and dev commands of the package manager that ran this process,
49
+ * which `npm_config_user_agent` names (e.g. `pnpm/10.33.0 npm/? node/v24.0.0
50
+ * darwin arm64`). npm when it names none.
51
+ */
52
+ function packageManagerCommands(userAgent) {
53
+ switch (userAgent?.split("/")[0]) {
54
+ case "pnpm": return {
55
+ install: ["pnpm", "install"],
56
+ dev: ["pnpm", "dev"]
57
+ };
58
+ case "yarn": return {
59
+ install: ["yarn"],
60
+ dev: ["yarn", "dev"]
61
+ };
62
+ case "bun": return {
63
+ install: ["bun", "install"],
64
+ dev: [
65
+ "bun",
66
+ "run",
67
+ "dev"
68
+ ]
69
+ };
70
+ default: return {
71
+ install: ["npm", "install"],
72
+ dev: [
73
+ "npm",
74
+ "run",
75
+ "dev"
76
+ ]
77
+ };
78
+ }
79
+ }
80
+ //#endregion
81
+ export { PACKED_NAMES, packageManagerCommands, scaffoldTheme };
package/package.json CHANGED
@@ -1,6 +1,31 @@
1
1
  {
2
2
  "name": "@shop-on/create-theme",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.1.0",
4
+ "description": "Scaffolds a Shop-On storefront theme: `npm create @shop-on/theme <dir>`.",
5
+ "license": "SEE LICENSE IN dist/LICENSE.md",
6
+ "bin": {
7
+ "create-theme": "./dist/cli.mjs"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "template"
12
+ ],
13
+ "type": "module",
14
+ "exports": {
15
+ ".": "./dist/index.mjs",
16
+ "./package.json": "./package.json"
17
+ },
18
+ "devDependencies": {
19
+ "@types/node": "26.6.3",
20
+ "typescript": "7.0.2",
21
+ "vitest": "5.0.3"
22
+ },
23
+ "engines": {
24
+ "node": "^20.19.0 || >=22.12.0"
25
+ },
26
+ "scripts": {
27
+ "template": "node scripts/template.mts",
28
+ "check-types": "tsc --noEmit",
29
+ "test": "vitest run"
30
+ }
6
31
  }