@objectstack/metadata 0.9.0 → 0.9.2

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 (3) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +257 -0
  3. package/package.json +4 -4
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @objectstack/metadata
2
2
 
3
+ ## 0.9.2
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+ - @objectstack/spec@0.9.2
9
+ - @objectstack/core@0.9.2
10
+ - @objectstack/types@0.9.2
11
+
12
+ ## 0.9.1
13
+
14
+ ### Patch Changes
15
+
16
+ - Patch release for maintenance and stability improvements. All packages updated with unified versioning.
17
+ - Updated dependencies
18
+ - @objectstack/spec@0.9.1
19
+ - @objectstack/core@0.9.1
20
+ - @objectstack/types@0.9.1
21
+
3
22
  ## 0.8.2
4
23
 
5
24
  ### Patch Changes
package/README.md CHANGED
@@ -12,6 +12,13 @@ The `@objectstack/metadata` package provides a unified interface for managing me
12
12
  - **Caching** - ETag-based caching for performance optimization
13
13
  - **File Watching** - Development mode with automatic reload on file changes
14
14
 
15
+ ## 🤖 AI Development Context
16
+
17
+ **Role**: Metadata IO & Persistence
18
+ **Usage**:
19
+ - Use `MetadataManager` to read/write `.object.ts`, `.view.yaml` files.
20
+ - Handles format loading (TS, JSON, YAML).
21
+
15
22
  ## Installation
16
23
 
17
24
  ```bash
@@ -196,6 +203,256 @@ The metadata package is designed as a Layer 3 package in the ObjectStack archite
196
203
  └── @objectstack/objectql (registry persistence)
197
204
  ```
198
205
 
206
+ ## Common Workflows
207
+
208
+ ### Development Workflow with File Watching
209
+
210
+ ```typescript
211
+ import { MetadataManager } from '@objectstack/metadata';
212
+
213
+ const manager = new MetadataManager({
214
+ rootDir: './metadata',
215
+ watch: true, // Enable file watching
216
+ cache: { enabled: true, ttl: 3600 }
217
+ });
218
+
219
+ // Watch for changes and reload
220
+ manager.watch('object', async (event) => {
221
+ if (event.type === 'modified' || event.type === 'added') {
222
+ console.log(`Reloading object: ${event.name}`);
223
+ const updated = await manager.load('object', event.name);
224
+
225
+ // Notify the system to reload
226
+ await objectQL.reloadObject(event.name, updated);
227
+ }
228
+ });
229
+
230
+ // Hot module replacement for development
231
+ console.log('Watching metadata files for changes...');
232
+ ```
233
+
234
+ ### Metadata Migration Workflow
235
+
236
+ ```typescript
237
+ import { MetadataManager } from '@objectstack/metadata';
238
+
239
+ async function migrateMetadata() {
240
+ const manager = new MetadataManager({
241
+ rootDir: './metadata'
242
+ });
243
+
244
+ // 1. Load all existing objects
245
+ const objects = await manager.loadMany('object');
246
+
247
+ // 2. Transform metadata (e.g., rename field)
248
+ const transformed = objects.map(obj => ({
249
+ ...obj,
250
+ fields: Object.entries(obj.fields).reduce((acc, [key, field]) => {
251
+ // Rename 'description' to 'notes'
252
+ const newKey = key === 'description' ? 'notes' : key;
253
+ acc[newKey] = field;
254
+ return acc;
255
+ }, {})
256
+ }));
257
+
258
+ // 3. Save with backup
259
+ for (const obj of transformed) {
260
+ await manager.save('object', obj.name, obj, {
261
+ format: 'typescript',
262
+ backup: true, // Create .bak file
263
+ prettify: true
264
+ });
265
+ }
266
+
267
+ console.log(`Migrated ${objects.length} objects`);
268
+ }
269
+ ```
270
+
271
+ ### Multi-Format Support Workflow
272
+
273
+ ```typescript
274
+ import { MetadataManager } from '@objectstack/metadata';
275
+
276
+ const manager = new MetadataManager({
277
+ rootDir: './metadata',
278
+ formats: ['typescript', 'json', 'yaml']
279
+ });
280
+
281
+ // Load from any format - manager auto-detects
282
+ const customer = await manager.load('object', 'customer');
283
+ // Tries: customer.object.ts, customer.object.json, customer.object.yaml
284
+
285
+ // Save in preferred format
286
+ await manager.save('object', 'customer', customer, {
287
+ format: 'typescript' // Convert to TypeScript
288
+ });
289
+
290
+ // Generate documentation from metadata
291
+ const allObjects = await manager.loadMany('object');
292
+ const docs = allObjects.map(obj => `
293
+ ## ${obj.label}
294
+
295
+ **Name:** ${obj.name}
296
+
297
+ **Fields:**
298
+ ${Object.entries(obj.fields).map(([name, field]) =>
299
+ `- **${field.label}** (\`${name}\`): ${field.type}`
300
+ ).join('\n')}
301
+ `).join('\n\n');
302
+
303
+ fs.writeFileSync('docs/objects.md', docs);
304
+ ```
305
+
306
+ ### Validation and Testing Workflow
307
+
308
+ ```typescript
309
+ import { MetadataManager } from '@objectstack/metadata';
310
+ import { ObjectSchema } from '@objectstack/spec/data';
311
+
312
+ async function validateAllMetadata() {
313
+ const manager = new MetadataManager({
314
+ rootDir: './metadata'
315
+ });
316
+
317
+ const objects = await manager.loadMany('object');
318
+ const errors = [];
319
+
320
+ for (const obj of objects) {
321
+ const result = ObjectSchema.safeParse(obj);
322
+
323
+ if (!result.success) {
324
+ errors.push({
325
+ name: obj.name,
326
+ issues: result.error.issues
327
+ });
328
+ }
329
+ }
330
+
331
+ if (errors.length > 0) {
332
+ console.error('Validation errors found:');
333
+ errors.forEach(({ name, issues }) => {
334
+ console.error(`\n${name}:`);
335
+ issues.forEach(issue => {
336
+ console.error(` - ${issue.path.join('.')}: ${issue.message}`);
337
+ });
338
+ });
339
+ process.exit(1);
340
+ }
341
+
342
+ console.log(`✅ All ${objects.length} objects validated successfully`);
343
+ }
344
+ ```
345
+
346
+ ### Metadata Versioning Workflow
347
+
348
+ ```typescript
349
+ import { MetadataManager } from '@objectstack/metadata';
350
+ import { execSync } from 'child_process';
351
+
352
+ async function versionMetadata() {
353
+ const manager = new MetadataManager({
354
+ rootDir: './metadata'
355
+ });
356
+
357
+ const objects = await manager.loadMany('object');
358
+
359
+ // Get git user name safely
360
+ let modifiedBy = 'unknown';
361
+ try {
362
+ modifiedBy = execSync('git config user.name', { encoding: 'utf-8' }).trim();
363
+ } catch (error) {
364
+ console.warn('Could not get git user name, using "unknown"');
365
+ }
366
+
367
+ // Add version metadata
368
+ const versioned = objects.map(obj => ({
369
+ ...obj,
370
+ metadata: {
371
+ ...obj.metadata,
372
+ version: '2.0.0',
373
+ lastModified: new Date().toISOString(),
374
+ modifiedBy
375
+ }
376
+ }));
377
+
378
+ // Save versioned metadata
379
+ for (const obj of versioned) {
380
+ await manager.save('object', obj.name, obj, {
381
+ format: 'typescript',
382
+ prettify: true
383
+ });
384
+ }
385
+
386
+ // Commit to version control (if git is available)
387
+ try {
388
+ execSync('git add metadata/', { stdio: 'inherit' });
389
+ execSync('git commit -m "Version bump to 2.0.0"', { stdio: 'inherit' });
390
+ } catch (error) {
391
+ console.warn('Git commit failed, changes are staged but not committed');
392
+ }
393
+ }
394
+ ```
395
+
396
+ ### Import/Export Workflow
397
+
398
+ ```typescript
399
+ import { MetadataManager } from '@objectstack/metadata';
400
+
401
+ async function exportToJSON() {
402
+ const manager = new MetadataManager({
403
+ rootDir: './metadata'
404
+ });
405
+
406
+ // Load all metadata
407
+ const [objects, views, apps] = await Promise.all([
408
+ manager.loadMany('object'),
409
+ manager.loadMany('view'),
410
+ manager.loadMany('app')
411
+ ]);
412
+
413
+ // Create unified export
414
+ const exportData = {
415
+ version: '1.0.0',
416
+ exported: new Date().toISOString(),
417
+ objects,
418
+ views,
419
+ apps
420
+ };
421
+
422
+ // Save as single JSON file
423
+ fs.writeFileSync(
424
+ 'export/metadata-export.json',
425
+ JSON.stringify(exportData, null, 2)
426
+ );
427
+
428
+ console.log('Export complete!');
429
+ }
430
+
431
+ async function importFromJSON(filePath: string) {
432
+ const manager = new MetadataManager({
433
+ rootDir: './metadata'
434
+ });
435
+
436
+ const importData = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
437
+
438
+ // Import objects
439
+ for (const obj of importData.objects) {
440
+ await manager.save('object', obj.name, obj, {
441
+ format: 'typescript'
442
+ });
443
+ }
444
+
445
+ // Import views
446
+ for (const view of importData.views) {
447
+ await manager.save('view', view.name, view, {
448
+ format: 'typescript'
449
+ });
450
+ }
451
+
452
+ console.log('Import complete!');
453
+ }
454
+ ```
455
+
199
456
  ## License
200
457
 
201
458
  MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@objectstack/metadata",
3
- "version": "0.9.0",
3
+ "version": "0.9.2",
4
4
  "description": "Metadata loading, saving, and persistence for ObjectStack",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -16,9 +16,9 @@
16
16
  "js-yaml": "^4.1.0",
17
17
  "chokidar": "^3.5.3",
18
18
  "zod": "^4.3.6",
19
- "@objectstack/core": "0.9.0",
20
- "@objectstack/spec": "0.9.0",
21
- "@objectstack/types": "0.9.0"
19
+ "@objectstack/core": "0.9.2",
20
+ "@objectstack/spec": "0.9.2",
21
+ "@objectstack/types": "0.9.2"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@types/js-yaml": "^4.0.9",