create-quadrokit 0.1.0 → 0.2.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 (94) hide show
  1. package/README.md +2 -2
  2. package/biome.monorepo.json +67 -0
  3. package/dist/index.js +239 -0
  4. package/package.json +11 -4
  5. package/templates/README.md +37 -0
  6. package/templates/admin-shell/.cursor/rules/commitlint-conventional.mdc +47 -0
  7. package/templates/admin-shell/.env.example +2 -0
  8. package/templates/admin-shell/biome.json +12 -0
  9. package/templates/admin-shell/index.html +12 -0
  10. package/templates/admin-shell/package.json +45 -0
  11. package/templates/admin-shell/postcss.config.js +6 -0
  12. package/templates/admin-shell/src/components/AppShell.tsx +68 -0
  13. package/templates/admin-shell/src/i18n.ts +12 -0
  14. package/templates/admin-shell/src/lib/quadro-client.ts +4 -0
  15. package/templates/admin-shell/src/locales/en.json +15 -0
  16. package/templates/admin-shell/src/main.tsx +15 -0
  17. package/templates/admin-shell/src/pages/AgenciesPage.tsx +69 -0
  18. package/templates/admin-shell/src/pages/HomePage.tsx +67 -0
  19. package/templates/admin-shell/src/router.tsx +15 -0
  20. package/templates/admin-shell/src/stores/useSidebarHint.ts +12 -0
  21. package/templates/admin-shell/src/vite-env.d.ts +9 -0
  22. package/templates/admin-shell/tailwind.config.ts +7 -0
  23. package/templates/admin-shell/tsconfig.app.json +16 -0
  24. package/templates/admin-shell/tsconfig.json +4 -0
  25. package/templates/admin-shell/tsconfig.node.json +10 -0
  26. package/templates/admin-shell/vite.config.ts +25 -0
  27. package/templates/dashboard/.cursor/rules/commitlint-conventional.mdc +47 -0
  28. package/templates/dashboard/.env.example +2 -0
  29. package/templates/dashboard/biome.json +12 -0
  30. package/templates/dashboard/index.html +12 -0
  31. package/templates/dashboard/package.json +45 -0
  32. package/templates/dashboard/postcss.config.js +6 -0
  33. package/templates/dashboard/src/components/AppShell.tsx +44 -0
  34. package/templates/dashboard/src/i18n.ts +12 -0
  35. package/templates/dashboard/src/lib/quadro-client.ts +4 -0
  36. package/templates/dashboard/src/locales/en.json +15 -0
  37. package/templates/dashboard/src/main.tsx +15 -0
  38. package/templates/dashboard/src/pages/AgenciesPage.tsx +69 -0
  39. package/templates/dashboard/src/pages/HomePage.tsx +67 -0
  40. package/templates/dashboard/src/router.tsx +15 -0
  41. package/templates/dashboard/src/stores/useSidebarHint.ts +12 -0
  42. package/templates/dashboard/src/vite-env.d.ts +9 -0
  43. package/templates/dashboard/tailwind.config.ts +7 -0
  44. package/templates/dashboard/tsconfig.app.json +16 -0
  45. package/templates/dashboard/tsconfig.json +4 -0
  46. package/templates/dashboard/tsconfig.node.json +10 -0
  47. package/templates/dashboard/vite.config.ts +25 -0
  48. package/templates/ecommerce/.cursor/rules/commitlint-conventional.mdc +47 -0
  49. package/templates/ecommerce/.env.example +2 -0
  50. package/templates/ecommerce/biome.json +12 -0
  51. package/templates/ecommerce/index.html +12 -0
  52. package/templates/ecommerce/package.json +45 -0
  53. package/templates/ecommerce/postcss.config.js +6 -0
  54. package/templates/ecommerce/src/components/AppShell.tsx +44 -0
  55. package/templates/ecommerce/src/i18n.ts +12 -0
  56. package/templates/ecommerce/src/lib/quadro-client.ts +4 -0
  57. package/templates/ecommerce/src/locales/en.json +20 -0
  58. package/templates/ecommerce/src/main.tsx +15 -0
  59. package/templates/ecommerce/src/pages/AgenciesPage.tsx +69 -0
  60. package/templates/ecommerce/src/pages/HomePage.tsx +52 -0
  61. package/templates/ecommerce/src/router.tsx +15 -0
  62. package/templates/ecommerce/src/stores/useSidebarHint.ts +12 -0
  63. package/templates/ecommerce/src/vite-env.d.ts +9 -0
  64. package/templates/ecommerce/tailwind.config.ts +7 -0
  65. package/templates/ecommerce/tsconfig.app.json +16 -0
  66. package/templates/ecommerce/tsconfig.json +4 -0
  67. package/templates/ecommerce/tsconfig.node.json +10 -0
  68. package/templates/ecommerce/vite.config.ts +25 -0
  69. package/templates/website/.cursor/rules/commitlint-conventional.mdc +47 -0
  70. package/templates/website/.env.example +2 -0
  71. package/templates/website/biome.json +12 -0
  72. package/templates/website/index.html +12 -0
  73. package/templates/website/package.json +45 -0
  74. package/templates/website/postcss.config.js +6 -0
  75. package/templates/website/src/components/AppShell.tsx +44 -0
  76. package/templates/website/src/i18n.ts +12 -0
  77. package/templates/website/src/lib/quadro-client.ts +4 -0
  78. package/templates/website/src/locales/en.json +21 -0
  79. package/templates/website/src/main.tsx +15 -0
  80. package/templates/website/src/pages/AgenciesPage.tsx +69 -0
  81. package/templates/website/src/pages/HomePage.tsx +83 -0
  82. package/templates/website/src/router.tsx +15 -0
  83. package/templates/website/src/stores/useSidebarHint.ts +12 -0
  84. package/templates/website/src/vite-env.d.ts +9 -0
  85. package/templates/website/tailwind.config.ts +7 -0
  86. package/templates/website/tsconfig.app.json +16 -0
  87. package/templates/website/tsconfig.json +4 -0
  88. package/templates/website/tsconfig.node.json +10 -0
  89. package/templates/website/vite.config.ts +25 -0
  90. package/vendor/generated/client.gen.ts +2725 -0
  91. package/vendor/generated/meta.json +5 -0
  92. package/vendor/generated/types.gen.ts +991 -0
  93. package/src/index.ts +0 -237
  94. package/tsconfig.json +0 -9
package/src/index.ts DELETED
@@ -1,237 +0,0 @@
1
- #!/usr/bin/env bun
2
- import { cp, mkdir, readdir, readFile, stat, writeFile } from 'node:fs/promises'
3
- import path from 'node:path'
4
- import { fileURLToPath } from 'node:url'
5
- import prompts from 'prompts'
6
-
7
- const TEMPLATES = ['dashboard', 'website', 'ecommerce', 'admin-shell'] as const
8
- type TemplateId = (typeof TEMPLATES)[number]
9
-
10
- function repoRoot(): string {
11
- return path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..')
12
- }
13
-
14
- function parseArgs(argv: string[]) {
15
- let template: TemplateId | undefined
16
- let dir: string | undefined
17
- let keepWorkspace = false
18
- for (let i = 0; i < argv.length; i++) {
19
- const a = argv[i]
20
- if (a === '--template' && argv[i + 1]) {
21
- template = argv[++i] as TemplateId
22
- } else if (a === '--dir' && argv[i + 1]) {
23
- dir = argv[++i]
24
- } else if (a === '--keep-workspace') {
25
- keepWorkspace = true
26
- }
27
- }
28
- return { template, dir, keepWorkspace }
29
- }
30
-
31
- async function pathExists(p: string) {
32
- try {
33
- await stat(p)
34
- return true
35
- } catch {
36
- return false
37
- }
38
- }
39
-
40
- async function copyTemplate(src: string, dest: string) {
41
- await mkdir(dest, { recursive: true })
42
- const entries = await readdir(src, { withFileTypes: true })
43
- for (const e of entries) {
44
- if (e.name === 'node_modules' || e.name === 'dist' || e.name === '.turbo') {
45
- continue
46
- }
47
- const from = path.join(src, e.name)
48
- const to = path.join(dest, e.name)
49
- if (e.isDirectory()) {
50
- await copyTemplate(from, to)
51
- } else {
52
- await cp(from, to)
53
- }
54
- }
55
- }
56
-
57
- function rewriteWorkspaceDeps(pkg: Record<string, unknown>) {
58
- for (const key of ['dependencies', 'devDependencies'] as const) {
59
- const deps = pkg[key] as Record<string, string> | undefined
60
- if (!deps) {
61
- continue
62
- }
63
- for (const name of Object.keys(deps)) {
64
- if (deps[name] === 'workspace:*') {
65
- deps[name] = '^0.1.0'
66
- }
67
- }
68
- }
69
- }
70
-
71
- async function patchPackageJson(dest: string, projectName: string, keepWorkspace: boolean) {
72
- const pkgPath = path.join(dest, 'package.json')
73
- const raw = await readFile(pkgPath, 'utf8')
74
- const pkg = JSON.parse(raw) as Record<string, unknown> & {
75
- dependencies?: Record<string, string>
76
- }
77
- pkg.name = projectName
78
- if (pkg.dependencies) {
79
- pkg.dependencies = Object.fromEntries(
80
- Object.entries(pkg.dependencies).filter(([name]) => name !== '@quadrokit/sample-client')
81
- )
82
- }
83
- if (!keepWorkspace) {
84
- rewriteWorkspaceDeps(pkg)
85
- }
86
- await writeFile(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`, 'utf8')
87
- }
88
-
89
- /** Standalone Biome config for projects outside the monorepo (no `extends` to repo root). */
90
- async function writeStandaloneBiome(dest: string, keepWorkspace: boolean) {
91
- if (keepWorkspace) {
92
- return
93
- }
94
- const rootBiomePath = path.join(repoRoot(), 'biome.json')
95
- const rootCfg = JSON.parse(await readFile(rootBiomePath, 'utf8')) as Record<string, unknown>
96
- const { extends: _ext, ...rest } = rootCfg as Record<string, unknown> & { extends?: unknown }
97
- const projectBiome = {
98
- ...rest,
99
- vcs: {
100
- enabled: true,
101
- clientKind: 'git',
102
- useIgnoreFile: false,
103
- },
104
- files: {
105
- includes: ['**', '!**/node_modules', '!**/dist', '!**/.quadrokit'],
106
- },
107
- }
108
- await writeFile(
109
- path.join(dest, 'biome.json'),
110
- `${JSON.stringify(projectBiome, null, 2)}\n`,
111
- 'utf8'
112
- )
113
- }
114
-
115
- async function writeQuadroClientImport(dest: string) {
116
- const p = path.join(dest, 'src', 'lib', 'quadro-client.ts')
117
- const body = `import { createClient } from '../../.quadrokit/generated/client.gen.js';
118
-
119
- /** Same-origin \`/rest\` in dev (Vite proxy) and production (reverse proxy). */
120
- export const quadro = createClient({ baseURL: '/rest' });
121
- `
122
- await writeFile(p, body, 'utf8')
123
- }
124
-
125
- async function seedGenerated(dest: string) {
126
- const root = repoRoot()
127
- const genSrc = path.join(root, 'packages', 'sample-client', 'generated')
128
- const genDest = path.join(dest, '.quadrokit', 'generated')
129
- if (!(await pathExists(genSrc))) {
130
- console.warn(
131
- 'Warning: sample generated client not found at packages/sample-client/generated — run `quadrokit-client generate` after install.'
132
- )
133
- return
134
- }
135
- await mkdir(path.join(dest, '.quadrokit'), { recursive: true })
136
- await cp(genSrc, genDest, { recursive: true })
137
- }
138
-
139
- async function writeReadme(dest: string, template: TemplateId) {
140
- const text = `# ${path.basename(dest)}
141
-
142
- Created with **create-quadrokit** (template: \`${template}\`).
143
-
144
- ## Next steps
145
-
146
- 1. \`cd ${path.basename(dest)}\` and \`bun install\`
147
- 2. Copy \`.env.example\` to \`.env\` and set \`VITE_4D_ORIGIN\` to your 4D web server.
148
- 3. Regenerate the typed client when your REST catalog changes:
149
-
150
- \`\`\`bash
151
- bunx quadrokit-client generate --url "http://localhost:7080/rest/\\$catalog" --token YOUR_TOKEN --out .quadrokit/generated
152
- \`\`\`
153
-
154
- 4. \`bun run dev\` — the dev server proxies \`/rest\` to \`VITE_4D_ORIGIN\` so **4DSID_** cookies stay same-origin.
155
-
156
- Production: serve the SPA and reverse-proxy \`/rest\` to 4D on the **same host** as the UI.
157
- `
158
- await writeFile(path.join(dest, 'QUADROKIT.md'), text, 'utf8')
159
- }
160
-
161
- async function main() {
162
- const argv = process.argv.slice(2)
163
- const { template: tArg, dir: dirArg, keepWorkspace } = parseArgs(argv)
164
-
165
- const template =
166
- tArg && (TEMPLATES as readonly string[]).includes(tArg)
167
- ? tArg
168
- : (
169
- await prompts({
170
- type: 'select',
171
- name: 'template',
172
- message: 'Template',
173
- choices: TEMPLATES.map((value) => ({ title: value, value })),
174
- })
175
- ).template
176
-
177
- if (!template) {
178
- process.exit(1)
179
- }
180
-
181
- const dirAns =
182
- dirArg ??
183
- (
184
- await prompts({
185
- type: 'text',
186
- name: 'dir',
187
- message: 'Project directory',
188
- initial: `quadro-${template}`,
189
- })
190
- ).dir
191
-
192
- if (!dirAns || typeof dirAns !== 'string') {
193
- process.exit(1)
194
- }
195
-
196
- const dest = path.resolve(process.cwd(), dirAns)
197
- if (await pathExists(dest)) {
198
- const files = await readdir(dest)
199
- if (files.length > 0) {
200
- console.error(`Directory not empty: ${dest}`)
201
- process.exit(1)
202
- }
203
- }
204
-
205
- const src = path.join(repoRoot(), 'packages', 'templates', template)
206
- if (!(await pathExists(src))) {
207
- console.error(`Template not found: ${src}`)
208
- process.exit(1)
209
- }
210
-
211
- await copyTemplate(src, dest)
212
- await writeStandaloneBiome(dest, keepWorkspace)
213
- await seedGenerated(dest)
214
- await patchPackageJson(
215
- dest,
216
- path
217
- .basename(dest)
218
- .replace(/[^a-z0-9-]/gi, '-')
219
- .toLowerCase() || 'quadro-app',
220
- keepWorkspace
221
- )
222
- await writeQuadroClientImport(dest)
223
- await writeReadme(dest, template)
224
-
225
- console.log(`
226
- Created QuadroKit project at ${dest}
227
-
228
- cd ${path.basename(dest)}
229
- bun install
230
- bun run dev
231
- `)
232
- }
233
-
234
- main().catch((e) => {
235
- console.error(e)
236
- process.exit(1)
237
- })
package/tsconfig.json DELETED
@@ -1,9 +0,0 @@
1
- {
2
- "extends": "../tsconfig.base.json",
3
- "compilerOptions": {
4
- "rootDir": "src",
5
- "noEmit": true,
6
- "types": ["bun", "node"]
7
- },
8
- "include": ["src/**/*.ts"]
9
- }