create-objectstack 4.0.4 → 4.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.
package/dist/index.js CHANGED
@@ -70,7 +70,7 @@ export default defineStack({
70
70
  include: ["*.ts", "src/**/*"],
71
71
  exclude: ["dist", "node_modules"]
72
72
  }, null, 2) + "\n",
73
- "src/objects/task.ts": () => `import { Data } from '@objectstack/spec';
73
+ "src/objects/task.ts": () => `import * as Data from '@objectstack/spec/data';
74
74
 
75
75
  const task: Data.Object = {
76
76
  name: 'task',
@@ -204,7 +204,7 @@ export default defineStack({
204
204
  include: ["*.ts", "src/**/*"],
205
205
  exclude: ["dist", "node_modules"]
206
206
  }, null, 2) + "\n",
207
- "src/objects/contact.ts": () => `import { Data } from '@objectstack/spec';
207
+ "src/objects/contact.ts": () => `import * as Data from '@objectstack/spec/data';
208
208
 
209
209
  const contact: Data.Object = {
210
210
  name: 'contact',
@@ -239,7 +239,7 @@ const contact: Data.Object = {
239
239
 
240
240
  export default contact;
241
241
  `,
242
- "src/objects/company.ts": () => `import { Data } from '@objectstack/spec';
242
+ "src/objects/company.ts": () => `import * as Data from '@objectstack/spec/data';
243
243
 
244
244
  const company: Data.Object = {
245
245
  name: 'company',
@@ -270,7 +270,7 @@ const company: Data.Object = {
270
270
 
271
271
  export default company;
272
272
  `,
273
- "src/objects/deal.ts": () => `import { Data } from '@objectstack/spec';
273
+ "src/objects/deal.ts": () => `import * as Data from '@objectstack/spec/data';
274
274
 
275
275
  const deal: Data.Object = {
276
276
  name: 'deal',
@@ -321,7 +321,7 @@ export default deal;
321
321
  export { default as company } from './company';
322
322
  export { default as deal } from './deal';
323
323
  `,
324
- "src/views/contact_list.ts": () => `import { UI } from '@objectstack/spec';
324
+ "src/views/contact_list.ts": () => `import * as UI from '@objectstack/spec/ui';
325
325
 
326
326
  const contactList: UI.View = {
327
327
  name: 'contact_list',
@@ -333,7 +333,7 @@ const contactList: UI.View = {
333
333
 
334
334
  export default contactList;
335
335
  `,
336
- "src/views/company_list.ts": () => `import { UI } from '@objectstack/spec';
336
+ "src/views/company_list.ts": () => `import * as UI from '@objectstack/spec/ui';
337
337
 
338
338
  const companyList: UI.View = {
339
339
  name: 'company_list',
@@ -345,7 +345,7 @@ const companyList: UI.View = {
345
345
 
346
346
  export default companyList;
347
347
  `,
348
- "src/views/deal_list.ts": () => `import { UI } from '@objectstack/spec';
348
+ "src/views/deal_list.ts": () => `import * as UI from '@objectstack/spec/ui';
349
349
 
350
350
  const dealList: UI.View = {
351
351
  name: 'deal_list',
@@ -357,7 +357,7 @@ const dealList: UI.View = {
357
357
 
358
358
  export default dealList;
359
359
  `,
360
- "src/apps/crm.ts": () => `import { UI } from '@objectstack/spec';
360
+ "src/apps/crm.ts": () => `import * as UI from '@objectstack/spec/ui';
361
361
 
362
362
  const crm: UI.App = {
363
363
  name: 'crm',
@@ -469,7 +469,7 @@ export default defineStack({
469
469
  */
470
470
  export * as objects from './objects';
471
471
  `,
472
- "src/objects/sample.ts": (name) => `import { Data } from '@objectstack/spec';
472
+ "src/objects/sample.ts": (name) => `import * as Data from '@objectstack/spec/data';
473
473
 
474
474
  const sample: Data.Object = {
475
475
  name: '${name}_sample',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-objectstack",
3
- "version": "4.0.4",
3
+ "version": "4.1.0",
4
4
  "description": "Create a new ObjectStack project — npx create-objectstack",
5
5
  "bin": {
6
6
  "create-objectstack": "./bin/create-objectstack.js"
@@ -19,9 +19,26 @@
19
19
  "commander": "^14.0.3"
20
20
  },
21
21
  "devDependencies": {
22
- "@types/node": "^25.6.0",
22
+ "@types/node": "^25.9.1",
23
23
  "tsup": "^8.5.1",
24
- "typescript": "^6.0.2"
24
+ "typescript": "^6.0.3"
25
+ },
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "https://github.com/objectstack-ai/framework.git",
29
+ "directory": "packages/create-objectstack"
30
+ },
31
+ "homepage": "https://objectstack.ai/docs",
32
+ "bugs": "https://github.com/objectstack-ai/framework/issues",
33
+ "publishConfig": {
34
+ "access": "public"
35
+ },
36
+ "files": [
37
+ "dist",
38
+ "README.md"
39
+ ],
40
+ "engines": {
41
+ "node": ">=18.0.0"
25
42
  },
26
43
  "scripts": {
27
44
  "build": "tsup",
@@ -1,13 +0,0 @@
1
-
2
- > create-objectstack@4.0.4 build /home/runner/work/framework/framework/packages/create-objectstack
3
- > tsup
4
-
5
- CLI Building entry: src/index.ts
6
- CLI Using tsconfig: tsconfig.json
7
- CLI tsup v8.5.1
8
- CLI Using tsup config: /home/runner/work/framework/framework/packages/create-objectstack/tsup.config.ts
9
- CLI Target: es2022
10
- CLI Cleaning output folder
11
- ESM Build start
12
- ESM dist/index.js 17.97 KB
13
- ESM ⚡️ Build success in 45ms
package/CHANGELOG.md DELETED
@@ -1,45 +0,0 @@
1
- # create-objectstack
2
-
3
- ## 4.0.4
4
-
5
- ## 4.0.3
6
-
7
- ## 4.0.2
8
-
9
- ## 4.0.0
10
-
11
- ## 3.3.1
12
-
13
- ## 3.3.0
14
-
15
- ## 3.2.9
16
-
17
- ## 3.2.8
18
-
19
- ## 3.2.7
20
-
21
- ## 3.2.6
22
-
23
- ## 3.2.5
24
-
25
- ## 3.2.4
26
-
27
- ## 3.2.3
28
-
29
- ## 3.2.2
30
-
31
- ## 3.2.1
32
-
33
- ## 3.2.0
34
-
35
- ## 3.1.1
36
-
37
- ## 3.1.0
38
-
39
- ## 3.0.11
40
-
41
- ## 3.0.10
42
-
43
- ## 3.0.9
44
-
45
- ## 3.0.8
package/src/index.ts DELETED
@@ -1,768 +0,0 @@
1
- // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
-
3
- import { Command } from 'commander';
4
- import chalk from 'chalk';
5
- import fs from 'fs';
6
- import path from 'path';
7
- import { execSync } from 'child_process';
8
- import { fileURLToPath } from 'url';
9
-
10
- const __filename = fileURLToPath(import.meta.url);
11
- const __dirname = path.dirname(__filename);
12
- const TEMPLATES_DIR = path.resolve(__dirname, 'templates');
13
-
14
- // ─── Template Registry ──────────────────────────────────────────────
15
-
16
- type TemplateFiles = Record<string, (name: string) => string>;
17
-
18
- interface Template {
19
- description: string;
20
- files: TemplateFiles;
21
- }
22
-
23
- const TEMPLATES: Record<string, Template> = {
24
- 'minimal-api': {
25
- description: 'Server + memory driver + 1 object + REST API',
26
- files: {
27
- 'objectstack.config.ts': (name) => `import { defineStack } from '@objectstack/spec';
28
- import * as objects from './src/objects';
29
-
30
- export default defineStack({
31
- manifest: {
32
- id: 'com.example.${name}',
33
- namespace: '${name}',
34
- version: '0.1.0',
35
- type: 'app',
36
- name: '${toTitleCase(name)}',
37
- description: '${toTitleCase(name)} — built with ObjectStack',
38
- },
39
-
40
- objects: Object.values(objects),
41
-
42
- api: {
43
- rest: { enabled: true, basePath: '/api' },
44
- },
45
- });
46
- `,
47
- 'package.json': (name) => JSON.stringify({
48
- name,
49
- version: '0.1.0',
50
- private: true,
51
- type: 'module',
52
- scripts: {
53
- dev: 'objectstack dev',
54
- start: 'objectstack serve',
55
- build: 'objectstack compile',
56
- validate: 'objectstack validate',
57
- typecheck: 'tsc --noEmit',
58
- },
59
- dependencies: {
60
- '@objectstack/spec': '^3.0.0',
61
- '@objectstack/runtime': '^3.0.0',
62
- '@objectstack/driver-memory': '^3.0.0',
63
- '@objectstack/plugin-hono-server': '^3.0.0',
64
- },
65
- devDependencies: {
66
- '@objectstack/cli': '^3.0.0',
67
- 'typescript': '^5.3.0',
68
- },
69
- }, null, 2) + '\n',
70
- 'tsconfig.json': () => JSON.stringify({
71
- compilerOptions: {
72
- target: 'ES2022',
73
- module: 'ESNext',
74
- moduleResolution: 'bundler',
75
- strict: true,
76
- esModuleInterop: true,
77
- skipLibCheck: true,
78
- outDir: 'dist',
79
- rootDir: '.',
80
- declaration: true,
81
- },
82
- include: ['*.ts', 'src/**/*'],
83
- exclude: ['dist', 'node_modules'],
84
- }, null, 2) + '\n',
85
- 'src/objects/task.ts': () => `import { Data } from '@objectstack/spec';
86
-
87
- const task: Data.Object = {
88
- name: 'task',
89
- label: 'Task',
90
- ownership: 'own',
91
- fields: {
92
- title: {
93
- type: 'text',
94
- label: 'Title',
95
- required: true,
96
- },
97
- description: {
98
- type: 'textarea',
99
- label: 'Description',
100
- },
101
- status: {
102
- type: 'select',
103
- label: 'Status',
104
- options: [
105
- { label: 'Open', value: 'open' },
106
- { label: 'In Progress', value: 'in_progress' },
107
- { label: 'Done', value: 'done' },
108
- ],
109
- defaultValue: 'open',
110
- },
111
- due_date: {
112
- type: 'date',
113
- label: 'Due Date',
114
- },
115
- },
116
- };
117
-
118
- export default task;
119
- `,
120
- 'src/objects/index.ts': () => `export { default as task } from './task';
121
- `,
122
- '.gitignore': () => `node_modules/
123
- dist/
124
- *.tsbuildinfo
125
- `,
126
- 'README.md': (name) => `# ${toTitleCase(name)}
127
-
128
- Built with [ObjectStack](https://objectstack.com).
129
-
130
- ## Quick Start
131
-
132
- \`\`\`bash
133
- # Install dependencies
134
- npm install
135
-
136
- # Start development server
137
- npm run dev
138
-
139
- # Validate configuration
140
- npm run validate
141
- \`\`\`
142
-
143
- ## Project Structure
144
-
145
- - \`objectstack.config.ts\` — Stack definition (objects, API, settings)
146
- - \`src/objects/\` — Object definitions
147
- - \`dist/\` — Compiled output
148
-
149
- ## Learn More
150
-
151
- - [ObjectStack Documentation](https://objectstack.com/docs)
152
- `,
153
- },
154
- },
155
-
156
- 'full-stack': {
157
- description: 'Server + UI + auth + 3 CRM objects',
158
- files: {
159
- 'objectstack.config.ts': (name) => `import { defineStack } from '@objectstack/spec';
160
- import * as objects from './src/objects';
161
- import * as apps from './src/apps';
162
-
163
- export default defineStack({
164
- manifest: {
165
- id: 'com.example.${name}',
166
- namespace: '${name}',
167
- version: '0.1.0',
168
- type: 'app',
169
- name: '${toTitleCase(name)}',
170
- description: '${toTitleCase(name)} CRM — built with ObjectStack',
171
- },
172
-
173
- objects: Object.values(objects),
174
- apps: Object.values(apps),
175
-
176
- api: {
177
- rest: { enabled: true, basePath: '/api' },
178
- },
179
- });
180
- `,
181
- 'package.json': (name) => JSON.stringify({
182
- name,
183
- version: '0.1.0',
184
- private: true,
185
- type: 'module',
186
- scripts: {
187
- dev: 'objectstack dev',
188
- start: 'objectstack serve',
189
- build: 'objectstack compile',
190
- validate: 'objectstack validate',
191
- typecheck: 'tsc --noEmit',
192
- },
193
- dependencies: {
194
- '@objectstack/spec': '^3.0.0',
195
- '@objectstack/runtime': '^3.0.0',
196
- '@objectstack/driver-memory': '^3.0.0',
197
- '@objectstack/plugin-hono-server': '^3.0.0',
198
- '@objectstack/plugin-auth': '^3.0.0',
199
- },
200
- devDependencies: {
201
- '@objectstack/cli': '^3.0.0',
202
- 'typescript': '^5.3.0',
203
- },
204
- }, null, 2) + '\n',
205
- 'tsconfig.json': () => JSON.stringify({
206
- compilerOptions: {
207
- target: 'ES2022',
208
- module: 'ESNext',
209
- moduleResolution: 'bundler',
210
- strict: true,
211
- esModuleInterop: true,
212
- skipLibCheck: true,
213
- outDir: 'dist',
214
- rootDir: '.',
215
- declaration: true,
216
- },
217
- include: ['*.ts', 'src/**/*'],
218
- exclude: ['dist', 'node_modules'],
219
- }, null, 2) + '\n',
220
- 'src/objects/contact.ts': () => `import { Data } from '@objectstack/spec';
221
-
222
- const contact: Data.Object = {
223
- name: 'contact',
224
- label: 'Contact',
225
- ownership: 'own',
226
- fields: {
227
- first_name: {
228
- type: 'text',
229
- label: 'First Name',
230
- required: true,
231
- },
232
- last_name: {
233
- type: 'text',
234
- label: 'Last Name',
235
- required: true,
236
- },
237
- email: {
238
- type: 'text',
239
- label: 'Email',
240
- },
241
- phone: {
242
- type: 'text',
243
- label: 'Phone',
244
- },
245
- company: {
246
- type: 'lookup',
247
- label: 'Company',
248
- reference: 'company',
249
- },
250
- },
251
- };
252
-
253
- export default contact;
254
- `,
255
- 'src/objects/company.ts': () => `import { Data } from '@objectstack/spec';
256
-
257
- const company: Data.Object = {
258
- name: 'company',
259
- label: 'Company',
260
- ownership: 'own',
261
- fields: {
262
- name: {
263
- type: 'text',
264
- label: 'Company Name',
265
- required: true,
266
- },
267
- website: {
268
- type: 'text',
269
- label: 'Website',
270
- },
271
- industry: {
272
- type: 'select',
273
- label: 'Industry',
274
- options: [
275
- { label: 'Technology', value: 'technology' },
276
- { label: 'Finance', value: 'finance' },
277
- { label: 'Healthcare', value: 'healthcare' },
278
- { label: 'Other', value: 'other' },
279
- ],
280
- },
281
- },
282
- };
283
-
284
- export default company;
285
- `,
286
- 'src/objects/deal.ts': () => `import { Data } from '@objectstack/spec';
287
-
288
- const deal: Data.Object = {
289
- name: 'deal',
290
- label: 'Deal',
291
- ownership: 'own',
292
- fields: {
293
- name: {
294
- type: 'text',
295
- label: 'Deal Name',
296
- required: true,
297
- },
298
- amount: {
299
- type: 'number',
300
- label: 'Amount',
301
- },
302
- stage: {
303
- type: 'select',
304
- label: 'Stage',
305
- options: [
306
- { label: 'Prospecting', value: 'prospecting' },
307
- { label: 'Qualification', value: 'qualification' },
308
- { label: 'Proposal', value: 'proposal' },
309
- { label: 'Closed Won', value: 'closed_won' },
310
- { label: 'Closed Lost', value: 'closed_lost' },
311
- ],
312
- defaultValue: 'prospecting',
313
- },
314
- contact: {
315
- type: 'lookup',
316
- label: 'Contact',
317
- reference: 'contact',
318
- },
319
- company: {
320
- type: 'lookup',
321
- label: 'Company',
322
- reference: 'company',
323
- },
324
- close_date: {
325
- type: 'date',
326
- label: 'Close Date',
327
- },
328
- },
329
- };
330
-
331
- export default deal;
332
- `,
333
- 'src/objects/index.ts': () => `export { default as contact } from './contact';
334
- export { default as company } from './company';
335
- export { default as deal } from './deal';
336
- `,
337
- 'src/views/contact_list.ts': () => `import { UI } from '@objectstack/spec';
338
-
339
- const contactList: UI.View = {
340
- name: 'contact_list',
341
- label: 'All Contacts',
342
- object: 'contact',
343
- type: 'list',
344
- columns: ['first_name', 'last_name', 'email', 'phone', 'company'],
345
- };
346
-
347
- export default contactList;
348
- `,
349
- 'src/views/company_list.ts': () => `import { UI } from '@objectstack/spec';
350
-
351
- const companyList: UI.View = {
352
- name: 'company_list',
353
- label: 'All Companies',
354
- object: 'company',
355
- type: 'list',
356
- columns: ['name', 'website', 'industry'],
357
- };
358
-
359
- export default companyList;
360
- `,
361
- 'src/views/deal_list.ts': () => `import { UI } from '@objectstack/spec';
362
-
363
- const dealList: UI.View = {
364
- name: 'deal_list',
365
- label: 'All Deals',
366
- object: 'deal',
367
- type: 'list',
368
- columns: ['name', 'amount', 'stage', 'contact', 'close_date'],
369
- };
370
-
371
- export default dealList;
372
- `,
373
- 'src/apps/crm.ts': () => `import { UI } from '@objectstack/spec';
374
-
375
- const crm: UI.App = {
376
- name: 'crm',
377
- label: 'CRM',
378
- description: 'Customer Relationship Management',
379
- navigation: [
380
- { type: 'object', object: 'contact', label: 'Contacts' },
381
- { type: 'object', object: 'company', label: 'Companies' },
382
- { type: 'object', object: 'deal', label: 'Deals' },
383
- ],
384
- };
385
-
386
- export default crm;
387
- `,
388
- 'src/apps/index.ts': () => `export { default as crm } from './crm';
389
- `,
390
- '.gitignore': () => `node_modules/
391
- dist/
392
- *.tsbuildinfo
393
- `,
394
- 'README.md': (name) => `# ${toTitleCase(name)}
395
-
396
- A full-stack CRM application built with [ObjectStack](https://objectstack.com).
397
-
398
- ## Quick Start
399
-
400
- \`\`\`bash
401
- npm install
402
- npm run dev
403
- \`\`\`
404
-
405
- ## Project Structure
406
-
407
- - \`objectstack.config.ts\` — Stack definition
408
- - \`src/objects/\` — Data objects (Contact, Company, Deal)
409
- - \`src/views/\` — List views
410
- - \`src/apps/crm.ts\` — CRM app with navigation
411
-
412
- ## Learn More
413
-
414
- - [ObjectStack Documentation](https://objectstack.com/docs)
415
- `,
416
- },
417
- },
418
-
419
- plugin: {
420
- description: 'Plugin skeleton with test setup',
421
- files: {
422
- 'objectstack.config.ts': (name) => `import { defineStack } from '@objectstack/spec';
423
- import * as objects from './src/objects';
424
-
425
- export default defineStack({
426
- manifest: {
427
- id: 'com.objectstack.plugin-${name}',
428
- namespace: 'plugin_${name}',
429
- version: '0.1.0',
430
- type: 'plugin',
431
- name: '${toTitleCase(name)} Plugin',
432
- description: 'ObjectStack Plugin: ${toTitleCase(name)}',
433
- },
434
-
435
- objects: Object.values(objects),
436
- });
437
- `,
438
- 'package.json': (name) => JSON.stringify({
439
- name: `@objectstack/plugin-${name}`,
440
- version: '0.1.0',
441
- description: `ObjectStack Plugin: ${toTitleCase(name)}`,
442
- main: 'dist/index.js',
443
- types: 'dist/index.d.ts',
444
- type: 'module',
445
- scripts: {
446
- build: 'tsc',
447
- dev: 'tsc --watch',
448
- test: 'vitest run',
449
- validate: 'objectstack validate',
450
- typecheck: 'tsc --noEmit',
451
- },
452
- keywords: ['objectstack', 'plugin', name],
453
- author: '',
454
- license: 'MIT',
455
- dependencies: {
456
- '@objectstack/spec': '^3.0.0',
457
- },
458
- devDependencies: {
459
- '@types/node': '^22.0.0',
460
- 'typescript': '^5.3.0',
461
- 'vitest': '^4.0.0',
462
- },
463
- }, null, 2) + '\n',
464
- 'tsconfig.json': () => JSON.stringify({
465
- compilerOptions: {
466
- target: 'ES2022',
467
- module: 'ESNext',
468
- moduleResolution: 'bundler',
469
- strict: true,
470
- esModuleInterop: true,
471
- skipLibCheck: true,
472
- outDir: 'dist',
473
- rootDir: '.',
474
- declaration: true,
475
- },
476
- include: ['*.ts', 'src/**/*'],
477
- exclude: ['dist', 'node_modules'],
478
- }, null, 2) + '\n',
479
- 'src/index.ts': (name) => `/**
480
- * ${toTitleCase(name)} Plugin for ObjectStack
481
- *
482
- * Entry point — re-exports all plugin metadata.
483
- */
484
- export * as objects from './objects';
485
- `,
486
- 'src/objects/sample.ts': (name) => `import { Data } from '@objectstack/spec';
487
-
488
- const sample: Data.Object = {
489
- name: '${name}_sample',
490
- label: '${toTitleCase(name)} Sample',
491
- ownership: 'own',
492
- fields: {
493
- name: {
494
- type: 'text',
495
- label: 'Name',
496
- required: true,
497
- },
498
- },
499
- };
500
-
501
- export default sample;
502
- `,
503
- 'src/objects/index.ts': () => `export { default as sample } from './sample';
504
- `,
505
- 'test/sample.test.ts': (name) => `import { describe, it, expect } from 'vitest';
506
- import sample from '../src/objects/sample';
507
-
508
- describe('${name} plugin', () => {
509
- it('should export a valid sample object', () => {
510
- expect(sample).toBeDefined();
511
- expect(sample.name).toBe('${name}_sample');
512
- expect(sample.fields).toHaveProperty('name');
513
- });
514
- });
515
- `,
516
- '.gitignore': () => `node_modules/
517
- dist/
518
- *.tsbuildinfo
519
- `,
520
- 'README.md': (name) => `# @objectstack/plugin-${name}
521
-
522
- ObjectStack Plugin: ${toTitleCase(name)}
523
-
524
- ## Installation
525
-
526
- \`\`\`bash
527
- npm install @objectstack/plugin-${name}
528
- \`\`\`
529
-
530
- ## Usage
531
-
532
- \`\`\`typescript
533
- import { defineStack } from '@objectstack/spec';
534
-
535
- export default defineStack({
536
- plugins: [
537
- '@objectstack/plugin-${name}',
538
- ],
539
- });
540
- \`\`\`
541
-
542
- ## Development
543
-
544
- \`\`\`bash
545
- # Run tests
546
- npm test
547
-
548
- # Build
549
- npm run build
550
-
551
- # Validate metadata
552
- npm run validate
553
- \`\`\`
554
-
555
- ## License
556
-
557
- MIT
558
- `,
559
- },
560
- },
561
- };
562
-
563
- // ─── Shared AI Configuration Files ──────────────────────────────────
564
- // These files are added to every template so third-party developers
565
- // get AI-assisted development (Copilot + Claude) out of the box.
566
- // Templates are maintained as standalone files in src/templates/ for
567
- // easy editing — no need to modify TypeScript code.
568
-
569
- function readTemplate(filename: string): string {
570
- return fs.readFileSync(path.join(TEMPLATES_DIR, filename), 'utf-8');
571
- }
572
-
573
- const AI_CONFIG_FILES: TemplateFiles = {
574
- '.github/copilot-instructions.md': (name) =>
575
- readTemplate('copilot-instructions.md')
576
- .replaceAll('{{PROJECT_NAME}}', name)
577
- .replaceAll('{{PROJECT_TITLE}}', toTitleCase(name)),
578
- };
579
-
580
- // ─── Helpers ────────────────────────────────────────────────────────
581
-
582
- function toCamelCase(str: string): string {
583
- return str.replace(/[-_]([a-z])/g, (_, c) => c.toUpperCase());
584
- }
585
-
586
- function toTitleCase(str: string): string {
587
- return str.replace(/[-_]/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase());
588
- }
589
-
590
- // ─── Formatting (matches @objectstack/cli style) ────────────────────
591
-
592
- function printHeader(title: string) {
593
- console.log(chalk.bold(`\n◆ ${title}`));
594
- console.log(chalk.dim('─'.repeat(40)));
595
- }
596
-
597
- function printKV(key: string, value: string) {
598
- console.log(` ${chalk.dim(key + ':')} ${chalk.white(value)}`);
599
- }
600
-
601
- function printSuccess(msg: string) {
602
- console.log(chalk.green(` ✓ ${msg}`));
603
- }
604
-
605
- function printError(msg: string) {
606
- console.log(chalk.red(` ✗ ${msg}`));
607
- }
608
-
609
- function printStep(msg: string) {
610
- console.log(chalk.yellow(` → ${msg}`));
611
- }
612
-
613
- function printWarning(msg: string) {
614
- console.log(chalk.yellow(` ⚠ ${msg}`));
615
- }
616
-
617
- // ─── CLI Program ────────────────────────────────────────────────────
618
-
619
- const program = new Command()
620
- .name('create-objectstack')
621
- .description('Create a new ObjectStack project')
622
- .version('3.0.0')
623
- .argument('[name]', 'Project name (defaults to current directory name)')
624
- .option(
625
- '-t, --template <template>',
626
- 'Project template: minimal-api, full-stack, plugin',
627
- 'minimal-api',
628
- )
629
- .option('--skip-install', 'Skip dependency installation')
630
- .action(async (name: string | undefined, options: { template: string; skipInstall?: boolean }) => {
631
- // Banner
632
- console.log('');
633
- console.log(chalk.bold.cyan(' ╔═══════════════════════════════════╗'));
634
- console.log(chalk.bold.cyan(' ║') + chalk.bold(' ◆ Create ObjectStack ') + chalk.dim('v3.0') + chalk.bold.cyan(' ║'));
635
- console.log(chalk.bold.cyan(' ╚═══════════════════════════════════╝'));
636
-
637
- printHeader('New Project');
638
-
639
- // Resolve template
640
- const template = TEMPLATES[options.template];
641
- if (!template) {
642
- printError(`Unknown template: ${options.template}`);
643
- console.log(chalk.dim(` Available: ${Object.keys(TEMPLATES).join(', ')}`));
644
- process.exit(1);
645
- }
646
-
647
- // Resolve project name and directory
648
- const cwd = process.cwd();
649
- const projectName = name || path.basename(cwd);
650
- const targetDir = name ? path.resolve(cwd, name) : cwd;
651
- const isCurrentDir = targetDir === cwd;
652
-
653
- printKV('Project', projectName);
654
- printKV('Template', `${options.template} — ${template.description}`);
655
- printKV('Directory', targetDir);
656
- console.log('');
657
-
658
- // Guard: if creating in a sub-directory, check it doesn't already exist
659
- if (!isCurrentDir && fs.existsSync(targetDir)) {
660
- const existing = fs.readdirSync(targetDir);
661
- if (existing.length > 0) {
662
- printError(`Directory already exists and is not empty: ${targetDir}`);
663
- process.exit(1);
664
- }
665
- }
666
-
667
- const createdFiles: string[] = [];
668
-
669
- try {
670
- // Ensure target directory exists
671
- if (!fs.existsSync(targetDir)) {
672
- fs.mkdirSync(targetDir, { recursive: true });
673
- }
674
-
675
- // Merge template files with shared AI configuration files
676
- const allFiles: TemplateFiles = { ...template.files, ...AI_CONFIG_FILES };
677
-
678
- // Write every file defined by the template + AI config
679
- for (const [filePath, contentFn] of Object.entries(allFiles)) {
680
- const fullPath = path.join(targetDir, filePath);
681
- const dir = path.dirname(fullPath);
682
-
683
- if (!fs.existsSync(dir)) {
684
- fs.mkdirSync(dir, { recursive: true });
685
- }
686
-
687
- fs.writeFileSync(fullPath, contentFn(projectName));
688
- createdFiles.push(filePath);
689
- }
690
-
691
- // Summary
692
- console.log(chalk.bold(' Created files:'));
693
- for (const f of createdFiles) {
694
- console.log(chalk.green(` + ${f}`));
695
- }
696
- console.log('');
697
-
698
- // Install dependencies
699
- if (!options.skipInstall) {
700
- printStep('Installing dependencies...');
701
- try {
702
- // Detect package manager — prefer pnpm, fall back to npm
703
- const pm = detectPackageManager();
704
- execSync(`${pm} install`, { stdio: 'inherit', cwd: targetDir });
705
- console.log('');
706
- } catch {
707
- printWarning('Dependency installation failed. Run `npm install` manually.');
708
- console.log('');
709
- }
710
- }
711
-
712
- // Install ObjectStack AI skills via the standard skills CLI
713
- if (!options.skipInstall) {
714
- printStep('Installing AI skills for your coding agent...');
715
- try {
716
- execSync('npx -y skills add objectstack-ai/framework --all', {
717
- stdio: 'inherit',
718
- cwd: targetDir,
719
- });
720
- console.log('');
721
- } catch {
722
- printWarning(
723
- 'Skills installation skipped. Run manually:\n' +
724
- ' npx skills add objectstack-ai/framework',
725
- );
726
- console.log('');
727
- }
728
- }
729
-
730
- printSuccess('Project created!');
731
- console.log('');
732
-
733
- // Next steps
734
- console.log(chalk.bold(' Next steps:'));
735
- if (!isCurrentDir) {
736
- console.log(chalk.dim(` cd ${name}`));
737
- }
738
- if (options.skipInstall) {
739
- console.log(chalk.dim(' npm install'));
740
- }
741
- console.log(chalk.dim(' npm run dev # Start development server'));
742
- console.log(chalk.dim(' npm run validate # Check configuration'));
743
- if (options.skipInstall) {
744
- console.log('');
745
- console.log(chalk.bold(' AI Skills (recommended):'));
746
- console.log(chalk.dim(' npx skills add objectstack-ai/framework'));
747
- }
748
- console.log('');
749
-
750
- } catch (error: any) {
751
- printError(error.message || String(error));
752
- process.exit(1);
753
- }
754
- });
755
-
756
- /**
757
- * Detect available package manager (pnpm > npm).
758
- */
759
- function detectPackageManager(): string {
760
- try {
761
- execSync('pnpm --version', { stdio: 'ignore' });
762
- return 'pnpm';
763
- } catch {
764
- return 'npm';
765
- }
766
- }
767
-
768
- program.parse();
@@ -1,74 +0,0 @@
1
- # {{PROJECT_TITLE}} — Copilot Instructions
2
-
3
- > Auto-generated by `create-objectstack`. Customise freely.
4
-
5
- ## Project Context
6
-
7
- This is an **ObjectStack** application — a metadata-driven low-code project
8
- that defines business objects, views, automations, and AI agents in TypeScript.
9
-
10
- - **Entry point:** `objectstack.config.ts` (uses `defineStack()`)
11
- - **Spec package:** `@objectstack/spec` (Zod-first schemas and types)
12
-
13
- ## Naming Conventions
14
-
15
- | Context | Convention | Example |
16
- |:--------|:-----------|:--------|
17
- | Config keys (TS props) | `camelCase` | `maxLength`, `defaultValue` |
18
- | Machine names (data values) | `snake_case` | `project_task`, `first_name` |
19
- | Metadata type names | singular | `'agent'`, `'view'`, `'flow'` |
20
- | File names | `{name}.{type}.ts` | `task.object.ts`, `main.app.ts` |
21
-
22
- ## Key Rules
23
-
24
- 1. **Zod First** — All schema definitions start with Zod. Types are derived via `z.infer<>`.
25
- 2. `defineStack()` is the single configuration entry point in `objectstack.config.ts`.
26
- 3. Use `Object.values()` barrel pattern for metadata arrays.
27
- 4. Import from `@objectstack/spec` — never use relative paths into the spec package.
28
-
29
- ## Project Structure
30
-
31
- ```
32
- {{PROJECT_NAME}}/
33
- ├── objectstack.config.ts # defineStack() — the single entry point
34
- ├── src/
35
- │ ├── objects/ # Business object definitions (snake_case names)
36
- │ ├── views/ # UI view definitions (list, form, kanban, calendar)
37
- │ ├── apps/ # App navigation & page structure
38
- │ ├── flows/ # Automation flows & workflows
39
- │ ├── actions/ # Custom actions (buttons, bulk ops)
40
- │ ├── dashboards/ # BI dashboards
41
- │ ├── reports/ # Analytics reports
42
- │ ├── agents/ # AI agent definitions
43
- │ ├── i18n/ # Translation bundles
44
- │ └── handlers/ # Runtime hook handlers
45
- ```
46
-
47
- ## AI Skills
48
-
49
- This project uses ObjectStack skills from `objectstack-ai/framework`.
50
- Install or update skills with the standard [skills CLI](https://skills.sh/):
51
-
52
- ```bash
53
- npx skills add objectstack-ai/framework
54
- ```
55
-
56
- Skills are triggered automatically based on task context:
57
-
58
- | Skill | Trigger Context |
59
- |:------|:----------------|
60
- | **objectstack-schema** | Define objects, fields, relationships, validations, indexes |
61
- | **objectstack-query** | Filters, sorting, pagination, aggregation, ObjectQL |
62
- | **objectstack-ui** | Views, dashboards, apps, reports, actions, navigation |
63
- | **objectstack-api** | REST endpoints, authentication, service contracts |
64
- | **objectstack-plugin** | Plugin lifecycle, DI, services, hooks, events |
65
- | **objectstack-automation** | Flows, workflows, triggers, approvals, state machines |
66
- | **objectstack-ai** | Agents, tools, skills, RAG pipelines, LLM config |
67
- | **objectstack-quickstart** | Project setup, defineStack(), driver selection |
68
- | **objectstack-i18n** | Translation bundles, locale config, coverage detection |
69
-
70
- ## Learn More
71
-
72
- - [ObjectStack Documentation](https://objectstack.com/docs)
73
- - [GitHub: objectstack-ai/framework](https://github.com/objectstack-ai/framework)
74
- - [Skills CLI](https://skills.sh/) — Manage AI skills across agents
package/tsconfig.json DELETED
@@ -1,23 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "NodeNext",
5
- "moduleResolution": "NodeNext",
6
- "lib": [
7
- "ES2022"
8
- ],
9
- "strict": true,
10
- "esModuleInterop": true,
11
- "skipLibCheck": true,
12
- "forceConsistentCasingInFileNames": true,
13
- "outDir": "dist",
14
- "rootDir": "src",
15
- "types": [
16
- "node"
17
- ],
18
- "ignoreDeprecations": "6.0"
19
- },
20
- "include": [
21
- "src"
22
- ]
23
- }
package/tsup.config.ts DELETED
@@ -1,15 +0,0 @@
1
- // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
-
3
- import { defineConfig } from 'tsup';
4
- import { cpSync } from 'fs';
5
-
6
- export default defineConfig({
7
- entry: ['src/index.ts'],
8
- format: ['esm'],
9
- clean: true,
10
- shims: true,
11
- onSuccess: async () => {
12
- // Copy template files to dist/ so they sit alongside the bundled JS
13
- cpSync('src/templates', 'dist/templates', { recursive: true });
14
- },
15
- });