create-cartwright 0.1.0 → 2.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.
Files changed (52) hide show
  1. package/README.md +21 -2
  2. package/dist/approve.d.ts +2 -0
  3. package/dist/approve.js +16 -0
  4. package/dist/approve.js.map +1 -0
  5. package/dist/approve.test.d.ts +1 -0
  6. package/dist/approve.test.js +23 -0
  7. package/dist/approve.test.js.map +1 -0
  8. package/dist/brief.d.ts +26 -0
  9. package/dist/brief.js +25 -0
  10. package/dist/brief.js.map +1 -0
  11. package/dist/brief.test.d.ts +1 -0
  12. package/dist/brief.test.js +23 -0
  13. package/dist/brief.test.js.map +1 -0
  14. package/dist/generate/index.d.ts +4 -0
  15. package/dist/generate/index.js +42 -0
  16. package/dist/generate/index.js.map +1 -0
  17. package/dist/generate/index.test.d.ts +1 -0
  18. package/dist/generate/index.test.js +47 -0
  19. package/dist/generate/index.test.js.map +1 -0
  20. package/dist/index.js +122 -82
  21. package/dist/index.js.map +1 -1
  22. package/dist/inject.d.ts +2 -0
  23. package/dist/inject.js +21 -0
  24. package/dist/inject.js.map +1 -0
  25. package/dist/inject.test.d.ts +1 -0
  26. package/dist/inject.test.js +37 -0
  27. package/dist/inject.test.js.map +1 -0
  28. package/dist/interview.d.ts +8 -0
  29. package/dist/interview.js +73 -0
  30. package/dist/interview.js.map +1 -0
  31. package/dist/interview.test.d.ts +1 -0
  32. package/dist/interview.test.js +50 -0
  33. package/dist/interview.test.js.map +1 -0
  34. package/dist/key-step.d.ts +12 -0
  35. package/dist/key-step.js +22 -0
  36. package/dist/key-step.js.map +1 -0
  37. package/dist/key-step.test.d.ts +1 -0
  38. package/dist/key-step.test.js +56 -0
  39. package/dist/key-step.test.js.map +1 -0
  40. package/dist/llm.d.ts +2 -0
  41. package/dist/llm.js +51 -0
  42. package/dist/llm.js.map +1 -0
  43. package/dist/llm.test.d.ts +1 -0
  44. package/dist/llm.test.js +32 -0
  45. package/dist/llm.test.js.map +1 -0
  46. package/dist/scaffold.d.ts +48 -0
  47. package/dist/scaffold.js +171 -0
  48. package/dist/scaffold.js.map +1 -0
  49. package/dist/scaffold.test.d.ts +1 -0
  50. package/dist/scaffold.test.js +109 -0
  51. package/dist/scaffold.test.js.map +1 -0
  52. package/package.json +5 -3
@@ -0,0 +1,171 @@
1
+ import { existsSync, readFileSync, writeFileSync, unlinkSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { execSync } from "node:child_process";
4
+ import { randomBytes } from "node:crypto";
5
+ import pc from "picocolors";
6
+ export const TEMPLATE_SLUGS = [
7
+ "website-corporate",
8
+ "coffee",
9
+ "sunglasses",
10
+ "agent-marketplace",
11
+ "generic",
12
+ ];
13
+ export const TEMPLATE_DEFAULTS = {
14
+ "website-corporate": {
15
+ mode: "website",
16
+ features: {
17
+ webshop: false,
18
+ acp: false,
19
+ a2a: false,
20
+ adminAgenticDashboard: false,
21
+ },
22
+ },
23
+ coffee: {
24
+ mode: "webshop",
25
+ features: {
26
+ webshop: true,
27
+ acp: false,
28
+ a2a: false,
29
+ adminAgenticDashboard: false,
30
+ },
31
+ },
32
+ sunglasses: {
33
+ mode: "webshop",
34
+ features: {
35
+ webshop: true,
36
+ acp: false,
37
+ a2a: false,
38
+ adminAgenticDashboard: false,
39
+ },
40
+ },
41
+ "agent-marketplace": {
42
+ mode: "agent-marketplace",
43
+ features: {
44
+ webshop: false,
45
+ acp: true,
46
+ a2a: true,
47
+ adminAgenticDashboard: true,
48
+ },
49
+ },
50
+ generic: {
51
+ mode: "webshop",
52
+ features: {
53
+ webshop: true,
54
+ acp: false,
55
+ a2a: false,
56
+ adminAgenticDashboard: false,
57
+ },
58
+ },
59
+ };
60
+ export function isTemplateSlug(value) {
61
+ return typeof value === "string" && TEMPLATE_SLUGS.includes(value);
62
+ }
63
+ export function detectPackageManager() {
64
+ const ua = process.env.npm_config_user_agent ?? "";
65
+ if (ua.startsWith("pnpm"))
66
+ return "pnpm";
67
+ if (ua.startsWith("yarn"))
68
+ return "yarn";
69
+ if (ua.startsWith("bun"))
70
+ return "bun";
71
+ return "npm";
72
+ }
73
+ export function generateAuthSecret() {
74
+ return randomBytes(32).toString("hex");
75
+ }
76
+ export function patchEnvLocal(targetDir, authSecret) {
77
+ const envExamplePath = join(targetDir, ".env.example");
78
+ if (!existsSync(envExamplePath))
79
+ return;
80
+ const example = readFileSync(envExamplePath, "utf8");
81
+ const patched = example.replace(/^AUTH_SECRET=.*/m, `AUTH_SECRET="${authSecret}"`);
82
+ writeFileSync(join(targetDir, ".env.local"), patched);
83
+ }
84
+ export function titleCase(projectName) {
85
+ return projectName
86
+ .split("-")
87
+ .map((s) => s.charAt(0).toUpperCase() + s.slice(1))
88
+ .join(" ");
89
+ }
90
+ export function patchBrandConfigContent(original, projectName) {
91
+ return original
92
+ .replace(/storeName:\s*"[^"]*"/, `storeName: "${titleCase(projectName)}"`)
93
+ .replace(/storeSlug:\s*"[^"]*"/, `storeSlug: "${projectName}"`);
94
+ }
95
+ /**
96
+ * Apply the per-template defaults to a brand.config.ts source string.
97
+ * Patches:
98
+ * - industryTemplate: "<slug>"
99
+ * - mode: "<mode>"
100
+ * - features.webshop, features.acp, features.a2a, features.adminAgenticDashboard
101
+ *
102
+ * The replacements are regex-anchored to the exact field shape produced by
103
+ * the upstream brand.config.ts. If that shape ever changes the regexes here
104
+ * will silently no-op (no replacement) — the corresponding unit test catches
105
+ * that case.
106
+ */
107
+ export function patchBrandConfigForTemplate(original, template) {
108
+ const defaults = TEMPLATE_DEFAULTS[template];
109
+ let out = original;
110
+ // industryTemplate: "xxx" (single-line)
111
+ out = out.replace(/industryTemplate:\s*"[^"]*"/, `industryTemplate: "${template}"`);
112
+ // mode: "xxx" as "website" | "webshop" | "agent-marketplace"
113
+ // We replace just the literal value inside the leading quotes, preserving
114
+ // the `as ...` type assertion if present.
115
+ out = out.replace(/mode:\s*"(?:website|webshop|agent-marketplace)"/, `mode: "${defaults.mode}"`);
116
+ // features.webshop|acp|a2a|adminAgenticDashboard: <bool>
117
+ for (const [key, value] of Object.entries(defaults.features)) {
118
+ const re = new RegExp(`(${key}:\\s*)(?:true|false)`, "g");
119
+ out = out.replace(re, `$1${value}`);
120
+ }
121
+ return out;
122
+ }
123
+ export function tryGitInit(targetDir) {
124
+ try {
125
+ execSync("git init -q && git add -A && git commit -q -m 'feat: initial commit from create-cartwright'", { cwd: targetDir, stdio: "ignore" });
126
+ return true;
127
+ }
128
+ catch {
129
+ return false;
130
+ }
131
+ }
132
+ export function tryInstall(targetDir, pm) {
133
+ try {
134
+ // Remove conflicting lockfiles from the template before installing
135
+ const lockfiles = ["package-lock.json", "pnpm-lock.yaml", "yarn.lock", "bun.lockb"];
136
+ for (const lockfile of lockfiles) {
137
+ const lockPath = join(targetDir, lockfile);
138
+ if (existsSync(lockPath)) {
139
+ unlinkSync(lockPath);
140
+ }
141
+ }
142
+ execSync(`${pm} install`, { cwd: targetDir, stdio: "ignore" });
143
+ return true;
144
+ }
145
+ catch {
146
+ return false;
147
+ }
148
+ }
149
+ export function databaseNote(db) {
150
+ switch (db) {
151
+ case "turso":
152
+ return [
153
+ pc.bold("Turso setup (production):"),
154
+ " turso db create my-shop-db",
155
+ " turso db tokens create my-shop-db",
156
+ pc.dim(" Set TURSO_DATABASE_URL + TURSO_AUTH_TOKEN in Vercel."),
157
+ ].join("\n");
158
+ case "postgres":
159
+ return [
160
+ pc.bold("Postgres setup:"),
161
+ " Update DATABASE_URL in .env.local to your Postgres URL.",
162
+ pc.dim(" Prisma schema currently uses 'sqlite' provider — switch to 'postgresql' in prisma/schema.prisma and run a fresh migration."),
163
+ ].join("\n");
164
+ case "sqlite":
165
+ return [
166
+ pc.bold("SQLite (local only):"),
167
+ " No extra setup. dev.db will be created on first migration.",
168
+ ].join("\n");
169
+ }
170
+ }
171
+ //# sourceMappingURL=scaffold.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,109 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { titleCase, patchBrandConfigContent, patchBrandConfigForTemplate, isTemplateSlug, TEMPLATE_SLUGS, TEMPLATE_DEFAULTS, } from "./scaffold";
3
+ describe("scaffold helpers", () => {
4
+ it("titleCase laver projektnavn til storeName", () => {
5
+ expect(titleCase("nord-kaffe")).toBe("Nord Kaffe");
6
+ });
7
+ it("patchBrandConfigContent erstatter storeName og storeSlug", () => {
8
+ const input = `{ storeName: "Demo", storeSlug: "demo" }`;
9
+ const out = patchBrandConfigContent(input, "min-shop");
10
+ expect(out).toContain(`storeName: "Min Shop"`);
11
+ expect(out).toContain(`storeSlug: "min-shop"`);
12
+ });
13
+ });
14
+ // Sample brand.config.ts fragments that mirror the actual shape produced
15
+ // by cartwright-private after Phase 4. Keeping these here (vs. importing
16
+ // the real file) lets the CLI tests stay independent of the template repo.
17
+ const BRAND_FRAGMENT = `
18
+ industryTemplate: "saas",
19
+ mode: "website" as "website" | "webshop" | "agent-marketplace",
20
+ ecommerceEnabled: false,
21
+ features: {
22
+ webshop: false,
23
+ acp: false,
24
+ a2a: false,
25
+ adminAgenticDashboard: false,
26
+ tryOn: false,
27
+ aiStylist: true,
28
+ },
29
+ `;
30
+ describe("isTemplateSlug", () => {
31
+ for (const slug of TEMPLATE_SLUGS) {
32
+ it(`recognises "${slug}"`, () => {
33
+ expect(isTemplateSlug(slug)).toBe(true);
34
+ });
35
+ }
36
+ it("rejects unknown slugs", () => {
37
+ expect(isTemplateSlug("not-a-template")).toBe(false);
38
+ expect(isTemplateSlug("")).toBe(false);
39
+ expect(isTemplateSlug(undefined)).toBe(false);
40
+ expect(isTemplateSlug(42)).toBe(false);
41
+ });
42
+ });
43
+ describe("patchBrandConfigForTemplate", () => {
44
+ it("agent-marketplace flips A2A+ACP+dashboard on, webshop off", () => {
45
+ const out = patchBrandConfigForTemplate(BRAND_FRAGMENT, "agent-marketplace");
46
+ expect(out).toContain(`industryTemplate: "agent-marketplace"`);
47
+ expect(out).toContain(`mode: "agent-marketplace"`);
48
+ expect(out).toContain(`webshop: false`);
49
+ expect(out).toContain(`acp: true`);
50
+ expect(out).toContain(`a2a: true`);
51
+ expect(out).toContain(`adminAgenticDashboard: true`);
52
+ });
53
+ it("coffee flips webshop on, A2A off", () => {
54
+ const out = patchBrandConfigForTemplate(BRAND_FRAGMENT, "coffee");
55
+ expect(out).toContain(`industryTemplate: "coffee"`);
56
+ expect(out).toContain(`mode: "webshop"`);
57
+ expect(out).toContain(`webshop: true`);
58
+ expect(out).toContain(`a2a: false`);
59
+ });
60
+ it("sunglasses → webshop mode, legacy template name in industryTemplate", () => {
61
+ const out = patchBrandConfigForTemplate(BRAND_FRAGMENT, "sunglasses");
62
+ expect(out).toContain(`industryTemplate: "sunglasses"`);
63
+ expect(out).toContain(`mode: "webshop"`);
64
+ expect(out).toContain(`webshop: true`);
65
+ });
66
+ it("website-corporate → website mode, all A2A/webshop off", () => {
67
+ const out = patchBrandConfigForTemplate(BRAND_FRAGMENT, "website-corporate");
68
+ expect(out).toContain(`industryTemplate: "website-corporate"`);
69
+ expect(out).toContain(`mode: "website"`);
70
+ expect(out).toContain(`webshop: false`);
71
+ expect(out).toContain(`a2a: false`);
72
+ expect(out).toContain(`adminAgenticDashboard: false`);
73
+ });
74
+ it("generic preserves webshop mode with no A2A flags on", () => {
75
+ const out = patchBrandConfigForTemplate(BRAND_FRAGMENT, "generic");
76
+ expect(out).toContain(`industryTemplate: "generic"`);
77
+ expect(out).toContain(`mode: "webshop"`);
78
+ expect(out).toContain(`webshop: true`);
79
+ expect(out).toContain(`a2a: false`);
80
+ });
81
+ it("does not touch unrelated feature flags (tryOn, aiStylist)", () => {
82
+ const out = patchBrandConfigForTemplate(BRAND_FRAGMENT, "coffee");
83
+ expect(out).toContain(`tryOn: false`);
84
+ expect(out).toContain(`aiStylist: true`);
85
+ });
86
+ });
87
+ describe("TEMPLATE_DEFAULTS — invariants", () => {
88
+ it("every template has all four mode-features defined", () => {
89
+ for (const slug of TEMPLATE_SLUGS) {
90
+ const d = TEMPLATE_DEFAULTS[slug];
91
+ expect(typeof d.features.webshop).toBe("boolean");
92
+ expect(typeof d.features.acp).toBe("boolean");
93
+ expect(typeof d.features.a2a).toBe("boolean");
94
+ expect(typeof d.features.adminAgenticDashboard).toBe("boolean");
95
+ }
96
+ });
97
+ it("agent-marketplace is the only template that turns a2a on", () => {
98
+ for (const slug of TEMPLATE_SLUGS) {
99
+ const a2aOn = TEMPLATE_DEFAULTS[slug].features.a2a;
100
+ if (slug === "agent-marketplace") {
101
+ expect(a2aOn).toBe(true);
102
+ }
103
+ else {
104
+ expect(a2aOn).toBe(false);
105
+ }
106
+ }
107
+ });
108
+ });
109
+ //# sourceMappingURL=scaffold.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffold.test.js","sourceRoot":"","sources":["../src/scaffold.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-cartwright",
3
- "version": "0.1.0",
3
+ "version": "2.0.1",
4
4
  "description": "Scaffolder for AI-first webshops powered by Cartwright",
5
5
  "keywords": [
6
6
  "cartwright",
@@ -26,7 +26,8 @@
26
26
  "dev": "tsx src/index.ts",
27
27
  "typecheck": "tsc --noEmit",
28
28
  "lint": "eslint src --max-warnings=0",
29
- "test": "echo 'TODO: vitest'",
29
+ "test": "vitest run",
30
+ "test:watch": "vitest",
30
31
  "prepublishOnly": "pnpm build"
31
32
  },
32
33
  "dependencies": {
@@ -39,7 +40,8 @@
39
40
  "@types/node": "^22.10.0",
40
41
  "eslint": "^9.0.0",
41
42
  "tsx": "^4.19.0",
42
- "typescript": "^5.7.0"
43
+ "typescript": "^5.7.0",
44
+ "vitest": "^4.1.7"
43
45
  },
44
46
  "engines": {
45
47
  "node": ">=22"