@objectql/cli 1.6.1 → 1.7.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/CHANGELOG.md +11 -0
- package/IMPLEMENTATION_SUMMARY.md +437 -0
- package/README.md +385 -7
- package/USAGE_EXAMPLES.md +804 -0
- package/__tests__/commands.test.ts +153 -0
- package/dist/commands/i18n.d.ts +27 -0
- package/dist/commands/i18n.js +280 -0
- package/dist/commands/i18n.js.map +1 -0
- package/dist/commands/init.d.ts +9 -0
- package/dist/commands/init.js +202 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/migrate.d.ts +26 -0
- package/dist/commands/migrate.js +301 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/new.d.ts +7 -0
- package/dist/commands/new.js +279 -0
- package/dist/commands/new.js.map +1 -0
- package/dist/commands/studio.js +70 -9
- package/dist/commands/studio.js.map +1 -1
- package/dist/index.js +130 -2
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
- package/src/commands/i18n.ts +303 -0
- package/src/commands/init.ts +191 -0
- package/src/commands/migrate.ts +314 -0
- package/src/commands/new.ts +268 -0
- package/src/commands/studio.ts +75 -10
- package/src/index.ts +131 -2
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,804 @@
|
|
|
1
|
+
# ObjectQL CLI - Usage Examples
|
|
2
|
+
|
|
3
|
+
This guide provides practical examples for all ObjectQL CLI commands.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Project Initialization](#project-initialization)
|
|
8
|
+
- [Metadata Generation](#metadata-generation)
|
|
9
|
+
- [TypeScript Code Generation](#typescript-code-generation)
|
|
10
|
+
- [Internationalization (i18n)](#internationalization-i18n)
|
|
11
|
+
- [Database Migrations](#database-migrations)
|
|
12
|
+
- [Development Tools](#development-tools)
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Project Initialization
|
|
17
|
+
|
|
18
|
+
### Creating a New Project
|
|
19
|
+
|
|
20
|
+
#### Basic Project
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# Create a minimal project with basic examples
|
|
24
|
+
objectql init --template basic --name my-project
|
|
25
|
+
|
|
26
|
+
# Navigate and start working
|
|
27
|
+
cd my-project
|
|
28
|
+
pnpm install
|
|
29
|
+
pnpm run build
|
|
30
|
+
objectql repl
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
#### Express API Project
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# Create a project with Express server setup
|
|
37
|
+
objectql init -t express-api -n my-api
|
|
38
|
+
|
|
39
|
+
cd my-api
|
|
40
|
+
pnpm install
|
|
41
|
+
pnpm start
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
#### Enterprise Project
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# Create a full-featured enterprise structure
|
|
48
|
+
objectql init -t enterprise -n my-enterprise-app
|
|
49
|
+
|
|
50
|
+
cd my-enterprise-app
|
|
51
|
+
pnpm install
|
|
52
|
+
objectql studio
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
#### Advanced Options
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Skip dependency installation (install manually later)
|
|
59
|
+
objectql init -n my-project --skip-install
|
|
60
|
+
|
|
61
|
+
# Skip git initialization
|
|
62
|
+
objectql init -n my-project --skip-git
|
|
63
|
+
|
|
64
|
+
# Custom directory
|
|
65
|
+
objectql init -n my-project --dir /path/to/projects
|
|
66
|
+
|
|
67
|
+
# Combine options
|
|
68
|
+
objectql init -t express-api -n my-api --skip-install --skip-git
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Metadata Generation
|
|
74
|
+
|
|
75
|
+
### Creating Objects
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# Create a simple object
|
|
79
|
+
objectql new object users
|
|
80
|
+
|
|
81
|
+
# Create in specific directory
|
|
82
|
+
objectql new object products --dir ./src/catalog
|
|
83
|
+
|
|
84
|
+
# Create with module structure
|
|
85
|
+
objectql new object crm_contacts --dir ./src/modules/crm
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Generated `users.object.yml`:
|
|
89
|
+
```yaml
|
|
90
|
+
label: Users
|
|
91
|
+
fields:
|
|
92
|
+
name:
|
|
93
|
+
type: text
|
|
94
|
+
label: Name
|
|
95
|
+
required: true
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Creating Views
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
objectql new view user_list
|
|
102
|
+
|
|
103
|
+
# Creates user_list.view.yml with default columns
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Creating Forms
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
objectql new form user_edit
|
|
110
|
+
|
|
111
|
+
# Creates user_edit.form.yml with basic layout
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Creating Actions
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
objectql new action approve_request
|
|
118
|
+
|
|
119
|
+
# Creates TWO files:
|
|
120
|
+
# 1. approve_request.action.yml - metadata
|
|
121
|
+
# 2. approve_request.action.ts - implementation
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Edit the generated `approve_request.action.ts`:
|
|
125
|
+
```typescript
|
|
126
|
+
import { ActionContext } from '@objectql/types';
|
|
127
|
+
|
|
128
|
+
export async function action_approve_request(context: ActionContext) {
|
|
129
|
+
const { record, user } = context;
|
|
130
|
+
|
|
131
|
+
// Your business logic here
|
|
132
|
+
await context.object('requests').update(record._id, {
|
|
133
|
+
status: 'approved',
|
|
134
|
+
approved_by: user._id,
|
|
135
|
+
approved_at: new Date()
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
success: true,
|
|
140
|
+
message: 'Request approved successfully'
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Creating Hooks
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
objectql new hook users
|
|
149
|
+
|
|
150
|
+
# Creates TWO files:
|
|
151
|
+
# 1. users.hook.yml - metadata
|
|
152
|
+
# 2. users.hook.ts - implementation
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Creating Permissions
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
objectql new permission users
|
|
159
|
+
|
|
160
|
+
# Creates users.permission.yml with admin/user profiles
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Creating Validation Rules
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
objectql new validation users
|
|
167
|
+
|
|
168
|
+
# Creates users.validation.yml with sample rules
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Creating Workflows
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
objectql new workflow order_processing
|
|
175
|
+
|
|
176
|
+
# Creates order_processing.workflow.yml
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Creating Reports
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
objectql new report sales_summary
|
|
183
|
+
|
|
184
|
+
# Creates sales_summary.report.yml
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### All Supported Types
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
objectql new object <name> # Object/Entity definition
|
|
191
|
+
objectql new view <name> # Data view
|
|
192
|
+
objectql new form <name> # Form layout
|
|
193
|
+
objectql new page <name> # Page definition
|
|
194
|
+
objectql new action <name> # Custom action
|
|
195
|
+
objectql new hook <name> # Lifecycle hook
|
|
196
|
+
objectql new permission <name> # Permission rules
|
|
197
|
+
objectql new validation <name> # Validation rules
|
|
198
|
+
objectql new workflow <name> # Workflow automation
|
|
199
|
+
objectql new report <name> # Report definition
|
|
200
|
+
objectql new menu <name> # Menu configuration
|
|
201
|
+
objectql new data <name> # Sample data
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## TypeScript Code Generation
|
|
207
|
+
|
|
208
|
+
### Basic Usage
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
# Generate types from current directory
|
|
212
|
+
objectql generate
|
|
213
|
+
|
|
214
|
+
# Generates TypeScript interfaces in ./src/generated/
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Custom Paths
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
# Custom source and output
|
|
221
|
+
objectql generate -s ./metadata -o ./types
|
|
222
|
+
|
|
223
|
+
# From specific module
|
|
224
|
+
objectql generate -s ./src/modules/crm -o ./src/modules/crm/types
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Integration with Build Process
|
|
228
|
+
|
|
229
|
+
In `package.json`:
|
|
230
|
+
```json
|
|
231
|
+
{
|
|
232
|
+
"scripts": {
|
|
233
|
+
"codegen": "objectql generate -s src -o src/types",
|
|
234
|
+
"prebuild": "npm run codegen",
|
|
235
|
+
"build": "tsc"
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Using Generated Types
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
import { User, Project, Task } from './generated';
|
|
244
|
+
|
|
245
|
+
const user: User = {
|
|
246
|
+
_id: '123',
|
|
247
|
+
name: 'John Doe',
|
|
248
|
+
email: 'john@example.com'
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
const project: Project = {
|
|
252
|
+
_id: '456',
|
|
253
|
+
name: 'My Project',
|
|
254
|
+
owner: user._id,
|
|
255
|
+
status: 'active'
|
|
256
|
+
};
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## Internationalization (i18n)
|
|
262
|
+
|
|
263
|
+
### Setting Up i18n
|
|
264
|
+
|
|
265
|
+
#### 1. Extract Translatable Strings
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
# Extract for English (default)
|
|
269
|
+
objectql i18n extract
|
|
270
|
+
|
|
271
|
+
# Extract for specific language
|
|
272
|
+
objectql i18n extract --lang zh-CN
|
|
273
|
+
|
|
274
|
+
# Custom paths
|
|
275
|
+
objectql i18n extract -s ./src -o ./translations --lang en
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
This creates JSON files like `src/i18n/en/users.json`:
|
|
279
|
+
```json
|
|
280
|
+
{
|
|
281
|
+
"label": "Users",
|
|
282
|
+
"fields": {
|
|
283
|
+
"name": { "label": "Name" },
|
|
284
|
+
"email": { "label": "Email" },
|
|
285
|
+
"status": {
|
|
286
|
+
"label": "Status",
|
|
287
|
+
"options": {
|
|
288
|
+
"active": "Active",
|
|
289
|
+
"inactive": "Inactive"
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
},
|
|
293
|
+
"actions": {
|
|
294
|
+
"approve": {
|
|
295
|
+
"label": "Approve User",
|
|
296
|
+
"confirm_text": "Are you sure you want to approve this user?"
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
#### 2. Initialize New Language
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
# Initialize Chinese (Simplified)
|
|
306
|
+
objectql i18n init zh-CN
|
|
307
|
+
|
|
308
|
+
# Initialize French
|
|
309
|
+
objectql i18n init fr
|
|
310
|
+
|
|
311
|
+
# Initialize Spanish
|
|
312
|
+
objectql i18n init es
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
#### 3. Extract for New Language
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
# Extract all translatable strings for Chinese
|
|
319
|
+
objectql i18n extract --lang zh-CN
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
#### 4. Translate the JSON Files
|
|
323
|
+
|
|
324
|
+
Edit `src/i18n/zh-CN/users.json`:
|
|
325
|
+
```json
|
|
326
|
+
{
|
|
327
|
+
"label": "用户",
|
|
328
|
+
"fields": {
|
|
329
|
+
"name": { "label": "姓名" },
|
|
330
|
+
"email": { "label": "邮箱" },
|
|
331
|
+
"status": {
|
|
332
|
+
"label": "状态",
|
|
333
|
+
"options": {
|
|
334
|
+
"active": "活跃",
|
|
335
|
+
"inactive": "未激活"
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
},
|
|
339
|
+
"actions": {
|
|
340
|
+
"approve": {
|
|
341
|
+
"label": "批准用户",
|
|
342
|
+
"confirm_text": "确定要批准此用户吗?"
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
#### 5. Validate Completeness
|
|
349
|
+
|
|
350
|
+
```bash
|
|
351
|
+
# Check if all English strings are translated to Chinese
|
|
352
|
+
objectql i18n validate zh-CN
|
|
353
|
+
|
|
354
|
+
# Use custom base language
|
|
355
|
+
objectql i18n validate fr --base-lang en
|
|
356
|
+
|
|
357
|
+
# Custom directory
|
|
358
|
+
objectql i18n validate es --base-dir ./translations
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
Output:
|
|
362
|
+
```
|
|
363
|
+
🌐 Validating translations for zh-CN against en...
|
|
364
|
+
|
|
365
|
+
✓ users.json - Complete
|
|
366
|
+
⚠ projects.json - 3 missing keys:
|
|
367
|
+
- fields.budget.label
|
|
368
|
+
- fields.deadline.description
|
|
369
|
+
- actions.export.label
|
|
370
|
+
|
|
371
|
+
📊 Summary:
|
|
372
|
+
Total files: 5
|
|
373
|
+
Missing translations: 3
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### Complete i18n Workflow
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
# 1. Start with English (extract from metadata)
|
|
380
|
+
objectql i18n extract --lang en
|
|
381
|
+
|
|
382
|
+
# 2. Add Chinese support
|
|
383
|
+
objectql i18n init zh-CN
|
|
384
|
+
objectql i18n extract --lang zh-CN
|
|
385
|
+
|
|
386
|
+
# 3. Add French support
|
|
387
|
+
objectql i18n init fr
|
|
388
|
+
objectql i18n extract --lang fr
|
|
389
|
+
|
|
390
|
+
# 4. Translate the JSON files manually
|
|
391
|
+
# ... edit files in src/i18n/zh-CN/ and src/i18n/fr/
|
|
392
|
+
|
|
393
|
+
# 5. Validate translations
|
|
394
|
+
objectql i18n validate zh-CN
|
|
395
|
+
objectql i18n validate fr
|
|
396
|
+
|
|
397
|
+
# 6. When you add new fields, re-extract
|
|
398
|
+
objectql i18n extract --lang zh-CN
|
|
399
|
+
objectql i18n extract --lang fr
|
|
400
|
+
|
|
401
|
+
# 7. Re-validate
|
|
402
|
+
objectql i18n validate zh-CN
|
|
403
|
+
objectql i18n validate fr
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
---
|
|
407
|
+
|
|
408
|
+
## Database Migrations
|
|
409
|
+
|
|
410
|
+
### Creating Migrations
|
|
411
|
+
|
|
412
|
+
```bash
|
|
413
|
+
# Create a new migration
|
|
414
|
+
objectql migrate create add_status_field
|
|
415
|
+
|
|
416
|
+
# Creates: migrations/20260112120000_add_status_field.ts
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
### Editing Migration
|
|
420
|
+
|
|
421
|
+
Edit `migrations/20260112120000_add_status_field.ts`:
|
|
422
|
+
```typescript
|
|
423
|
+
import { ObjectQL } from '@objectql/core';
|
|
424
|
+
|
|
425
|
+
export async function up(app: ObjectQL) {
|
|
426
|
+
console.log('Adding status field to users');
|
|
427
|
+
|
|
428
|
+
const users = app.getObject('users');
|
|
429
|
+
await users.updateSchema({
|
|
430
|
+
fields: {
|
|
431
|
+
status: {
|
|
432
|
+
type: 'select',
|
|
433
|
+
label: 'Status',
|
|
434
|
+
options: [
|
|
435
|
+
{ label: 'Active', value: 'active' },
|
|
436
|
+
{ label: 'Inactive', value: 'inactive' }
|
|
437
|
+
]
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
export async function down(app: ObjectQL) {
|
|
444
|
+
console.log('Removing status field from users');
|
|
445
|
+
|
|
446
|
+
const users = app.getObject('users');
|
|
447
|
+
await users.updateSchema({
|
|
448
|
+
fields: {
|
|
449
|
+
status: undefined
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
### Running Migrations
|
|
456
|
+
|
|
457
|
+
```bash
|
|
458
|
+
# Check migration status
|
|
459
|
+
objectql migrate status
|
|
460
|
+
|
|
461
|
+
# Run all pending migrations
|
|
462
|
+
objectql migrate
|
|
463
|
+
|
|
464
|
+
# With custom config
|
|
465
|
+
objectql migrate --config ./config/objectql.config.ts
|
|
466
|
+
|
|
467
|
+
# Custom migrations directory
|
|
468
|
+
objectql migrate --dir ./db/migrations
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
### Migration Examples
|
|
472
|
+
|
|
473
|
+
#### Adding a Field
|
|
474
|
+
|
|
475
|
+
```typescript
|
|
476
|
+
export async function up(app: ObjectQL) {
|
|
477
|
+
const tasks = app.getObject('tasks');
|
|
478
|
+
await tasks.updateSchema({
|
|
479
|
+
fields: {
|
|
480
|
+
priority: {
|
|
481
|
+
type: 'select',
|
|
482
|
+
label: 'Priority',
|
|
483
|
+
options: ['low', 'medium', 'high']
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
#### Adding an Index
|
|
491
|
+
|
|
492
|
+
```typescript
|
|
493
|
+
export async function up(app: ObjectQL) {
|
|
494
|
+
const users = app.getObject('users');
|
|
495
|
+
await users.addIndex('email', { unique: true });
|
|
496
|
+
}
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
#### Data Migration
|
|
500
|
+
|
|
501
|
+
```typescript
|
|
502
|
+
export async function up(app: ObjectQL) {
|
|
503
|
+
const tasks = app.getObject('tasks');
|
|
504
|
+
|
|
505
|
+
// Update all tasks without priority
|
|
506
|
+
const result = await tasks.find({
|
|
507
|
+
filters: [['priority', '=', null]]
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
for (const task of result.records) {
|
|
511
|
+
await tasks.update(task._id, {
|
|
512
|
+
priority: 'medium'
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
console.log(`Updated ${result.records.length} tasks`);
|
|
517
|
+
}
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
---
|
|
521
|
+
|
|
522
|
+
## Development Tools
|
|
523
|
+
|
|
524
|
+
### REPL (Interactive Shell)
|
|
525
|
+
|
|
526
|
+
```bash
|
|
527
|
+
# Start REPL
|
|
528
|
+
objectql repl
|
|
529
|
+
|
|
530
|
+
# With custom config
|
|
531
|
+
objectql repl --config ./objectql.config.ts
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
In the REPL:
|
|
535
|
+
```javascript
|
|
536
|
+
objectql> await tasks.find()
|
|
537
|
+
objectql> await tasks.insert({ name: 'New Task', status: 'open' })
|
|
538
|
+
objectql> await tasks.update('123', { status: 'completed' })
|
|
539
|
+
objectql> await tasks.delete('123')
|
|
540
|
+
|
|
541
|
+
// Access specific object
|
|
542
|
+
objectql> const users = app.getObject('users')
|
|
543
|
+
objectql> await users.count()
|
|
544
|
+
|
|
545
|
+
// Run queries
|
|
546
|
+
objectql> await tasks.find({
|
|
547
|
+
... filters: [['status', '=', 'open']],
|
|
548
|
+
... sort: [['created_at', 'desc']]
|
|
549
|
+
... })
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
### Serve (Development Server)
|
|
553
|
+
|
|
554
|
+
```bash
|
|
555
|
+
# Start server on default port (3000)
|
|
556
|
+
objectql serve
|
|
557
|
+
|
|
558
|
+
# Custom port
|
|
559
|
+
objectql serve --port 8080
|
|
560
|
+
|
|
561
|
+
# Custom schema directory
|
|
562
|
+
objectql serve --dir ./src/metadata
|
|
563
|
+
|
|
564
|
+
# Full example
|
|
565
|
+
objectql serve --port 4000 --dir ./src
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
Access:
|
|
569
|
+
- Swagger UI: `http://localhost:3000/swagger`
|
|
570
|
+
- API: `http://localhost:3000/` (POST)
|
|
571
|
+
- OpenAPI: `http://localhost:3000/openapi.json` (GET)
|
|
572
|
+
|
|
573
|
+
### Studio (Web Admin)
|
|
574
|
+
|
|
575
|
+
```bash
|
|
576
|
+
# Start studio
|
|
577
|
+
objectql studio
|
|
578
|
+
|
|
579
|
+
# Custom port
|
|
580
|
+
objectql studio --port 8080
|
|
581
|
+
|
|
582
|
+
# Don't open browser
|
|
583
|
+
objectql studio --no-open
|
|
584
|
+
|
|
585
|
+
# Full example
|
|
586
|
+
objectql studio --port 4000 --dir ./src --no-open
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
Access the UI at: `http://localhost:3000/studio`
|
|
590
|
+
|
|
591
|
+
---
|
|
592
|
+
|
|
593
|
+
## Complete Workflow Examples
|
|
594
|
+
|
|
595
|
+
### Starting a New Project
|
|
596
|
+
|
|
597
|
+
```bash
|
|
598
|
+
# 1. Initialize project
|
|
599
|
+
objectql init -t basic -n my-crm
|
|
600
|
+
|
|
601
|
+
# 2. Navigate to project
|
|
602
|
+
cd my-crm
|
|
603
|
+
pnpm install
|
|
604
|
+
|
|
605
|
+
# 3. Create your first object
|
|
606
|
+
objectql new object contacts
|
|
607
|
+
|
|
608
|
+
# 4. Edit contacts.object.yml
|
|
609
|
+
# ... add fields
|
|
610
|
+
|
|
611
|
+
# 5. Generate TypeScript types
|
|
612
|
+
objectql generate
|
|
613
|
+
|
|
614
|
+
# 6. Start development
|
|
615
|
+
objectql studio
|
|
616
|
+
|
|
617
|
+
# 7. Build for production
|
|
618
|
+
pnpm run build
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
### Adding a New Feature Module
|
|
622
|
+
|
|
623
|
+
```bash
|
|
624
|
+
# 1. Create object
|
|
625
|
+
objectql new object crm_leads --dir ./src/modules/crm
|
|
626
|
+
|
|
627
|
+
# 2. Create view
|
|
628
|
+
objectql new view crm_lead_list --dir ./src/modules/crm
|
|
629
|
+
|
|
630
|
+
# 3. Create form
|
|
631
|
+
objectql new form crm_lead_edit --dir ./src/modules/crm
|
|
632
|
+
|
|
633
|
+
# 4. Create action
|
|
634
|
+
objectql new action crm_convert_lead --dir ./src/modules/crm
|
|
635
|
+
|
|
636
|
+
# 5. Add permissions
|
|
637
|
+
objectql new permission crm_leads --dir ./src/modules/crm
|
|
638
|
+
|
|
639
|
+
# 6. Generate types
|
|
640
|
+
objectql generate
|
|
641
|
+
|
|
642
|
+
# 7. Test in REPL
|
|
643
|
+
objectql repl
|
|
644
|
+
```
|
|
645
|
+
|
|
646
|
+
### Internationalization Workflow
|
|
647
|
+
|
|
648
|
+
```bash
|
|
649
|
+
# 1. Extract English strings
|
|
650
|
+
objectql i18n extract --lang en
|
|
651
|
+
|
|
652
|
+
# 2. Add Chinese support
|
|
653
|
+
objectql i18n init zh-CN
|
|
654
|
+
objectql i18n extract --lang zh-CN
|
|
655
|
+
|
|
656
|
+
# 3. Translate files in src/i18n/zh-CN/
|
|
657
|
+
|
|
658
|
+
# 4. Validate
|
|
659
|
+
objectql i18n validate zh-CN
|
|
660
|
+
|
|
661
|
+
# 5. When metadata changes, re-extract
|
|
662
|
+
objectql i18n extract --lang en
|
|
663
|
+
objectql i18n extract --lang zh-CN
|
|
664
|
+
|
|
665
|
+
# 6. Re-validate
|
|
666
|
+
objectql i18n validate zh-CN
|
|
667
|
+
```
|
|
668
|
+
|
|
669
|
+
### Database Migration Workflow
|
|
670
|
+
|
|
671
|
+
```bash
|
|
672
|
+
# 1. Create migration
|
|
673
|
+
objectql migrate create add_user_roles
|
|
674
|
+
|
|
675
|
+
# 2. Edit migration file in migrations/
|
|
676
|
+
|
|
677
|
+
# 3. Check status
|
|
678
|
+
objectql migrate status
|
|
679
|
+
|
|
680
|
+
# 4. Run migration
|
|
681
|
+
objectql migrate
|
|
682
|
+
|
|
683
|
+
# 5. Verify in REPL
|
|
684
|
+
objectql repl
|
|
685
|
+
> await users.findOne()
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
---
|
|
689
|
+
|
|
690
|
+
## Tips and Best Practices
|
|
691
|
+
|
|
692
|
+
### Project Structure
|
|
693
|
+
|
|
694
|
+
```
|
|
695
|
+
my-project/
|
|
696
|
+
├── src/
|
|
697
|
+
│ ├── modules/
|
|
698
|
+
│ │ ├── crm/
|
|
699
|
+
│ │ │ ├── contacts.object.yml
|
|
700
|
+
│ │ │ ├── contacts.view.yml
|
|
701
|
+
│ │ │ ├── contacts.form.yml
|
|
702
|
+
│ │ │ └── contacts.permission.yml
|
|
703
|
+
│ │ └── sales/
|
|
704
|
+
│ │ ├── orders.object.yml
|
|
705
|
+
│ │ └── ...
|
|
706
|
+
│ ├── i18n/
|
|
707
|
+
│ │ ├── en/
|
|
708
|
+
│ │ ├── zh-CN/
|
|
709
|
+
│ │ └── fr/
|
|
710
|
+
│ └── types/ # Generated
|
|
711
|
+
├── migrations/
|
|
712
|
+
├── objectql.config.ts
|
|
713
|
+
└── package.json
|
|
714
|
+
```
|
|
715
|
+
|
|
716
|
+
### Naming Conventions
|
|
717
|
+
|
|
718
|
+
- Objects: `snake_case` (e.g., `crm_contacts`, `sales_orders`)
|
|
719
|
+
- Actions/Hooks: `snake_case` (e.g., `approve_order`, `send_email`)
|
|
720
|
+
- Fields: `snake_case` (e.g., `first_name`, `email_address`)
|
|
721
|
+
|
|
722
|
+
### Git Integration
|
|
723
|
+
|
|
724
|
+
Add to `.gitignore`:
|
|
725
|
+
```
|
|
726
|
+
node_modules/
|
|
727
|
+
dist/
|
|
728
|
+
*.log
|
|
729
|
+
.DS_Store
|
|
730
|
+
*.sqlite3
|
|
731
|
+
.env
|
|
732
|
+
.env.local
|
|
733
|
+
|
|
734
|
+
# Keep migrations
|
|
735
|
+
!migrations/
|
|
736
|
+
```
|
|
737
|
+
|
|
738
|
+
### Automation Scripts
|
|
739
|
+
|
|
740
|
+
In `package.json`:
|
|
741
|
+
```json
|
|
742
|
+
{
|
|
743
|
+
"scripts": {
|
|
744
|
+
"codegen": "objectql generate -s src -o src/types",
|
|
745
|
+
"i18n:extract": "objectql i18n extract --lang en && objectql i18n extract --lang zh-CN",
|
|
746
|
+
"i18n:validate": "objectql i18n validate zh-CN",
|
|
747
|
+
"migrate": "objectql migrate",
|
|
748
|
+
"dev": "objectql studio",
|
|
749
|
+
"prebuild": "npm run codegen",
|
|
750
|
+
"build": "tsc"
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
```
|
|
754
|
+
|
|
755
|
+
---
|
|
756
|
+
|
|
757
|
+
## Troubleshooting
|
|
758
|
+
|
|
759
|
+
### Common Issues
|
|
760
|
+
|
|
761
|
+
**Issue**: `Cannot find module '@objectql/core'`
|
|
762
|
+
```bash
|
|
763
|
+
# Solution: Install dependencies first
|
|
764
|
+
pnpm install
|
|
765
|
+
```
|
|
766
|
+
|
|
767
|
+
**Issue**: Migration fails
|
|
768
|
+
```bash
|
|
769
|
+
# Solution: Check migration status
|
|
770
|
+
objectql migrate status
|
|
771
|
+
|
|
772
|
+
# Review config file
|
|
773
|
+
cat objectql.config.ts
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
**Issue**: Types not updating
|
|
777
|
+
```bash
|
|
778
|
+
# Solution: Re-generate types
|
|
779
|
+
objectql generate -s src -o src/types
|
|
780
|
+
```
|
|
781
|
+
|
|
782
|
+
**Issue**: i18n validation shows missing keys
|
|
783
|
+
```bash
|
|
784
|
+
# Solution: Re-extract and translate
|
|
785
|
+
objectql i18n extract --lang zh-CN
|
|
786
|
+
# Then edit the JSON files
|
|
787
|
+
```
|
|
788
|
+
|
|
789
|
+
---
|
|
790
|
+
|
|
791
|
+
## Getting Help
|
|
792
|
+
|
|
793
|
+
```bash
|
|
794
|
+
# General help
|
|
795
|
+
objectql --help
|
|
796
|
+
|
|
797
|
+
# Command-specific help
|
|
798
|
+
objectql init --help
|
|
799
|
+
objectql new --help
|
|
800
|
+
objectql i18n --help
|
|
801
|
+
objectql migrate --help
|
|
802
|
+
```
|
|
803
|
+
|
|
804
|
+
For more information, visit: https://github.com/objectql/objectql
|