@objectstack/metadata 3.0.1 → 3.0.3
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/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +19 -0
- package/README.md +238 -6
- package/ROADMAP.md +223 -0
- package/dist/index.d.mts +22 -1
- package/dist/index.d.ts +22 -1
- package/dist/index.js +45 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +45 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
- package/src/metadata-manager.ts +62 -5
- package/src/metadata-service.test.ts +85 -0
|
@@ -143,6 +143,53 @@ describe('MetadataManager — IMetadataService Contract', () => {
|
|
|
143
143
|
});
|
|
144
144
|
});
|
|
145
145
|
|
|
146
|
+
// ==========================================
|
|
147
|
+
// UI Convenience Methods
|
|
148
|
+
// ==========================================
|
|
149
|
+
|
|
150
|
+
describe('UI convenience methods', () => {
|
|
151
|
+
it('should get a view via getView()', async () => {
|
|
152
|
+
const viewDef = { name: 'account_list', object: 'account', type: 'grid' };
|
|
153
|
+
await manager.register('view', 'account_list', viewDef);
|
|
154
|
+
|
|
155
|
+
const result = await manager.getView('account_list');
|
|
156
|
+
expect(result).toEqual(viewDef);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('should list views via listViews()', async () => {
|
|
160
|
+
await manager.register('view', 'account_list', { name: 'account_list', object: 'account' });
|
|
161
|
+
await manager.register('view', 'contact_list', { name: 'contact_list', object: 'contact' });
|
|
162
|
+
|
|
163
|
+
const allViews = await manager.listViews();
|
|
164
|
+
expect(allViews).toHaveLength(2);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('should filter views by object via listViews(object)', async () => {
|
|
168
|
+
await manager.register('view', 'account_list', { name: 'account_list', object: 'account' });
|
|
169
|
+
await manager.register('view', 'contact_list', { name: 'contact_list', object: 'contact' });
|
|
170
|
+
|
|
171
|
+
const accountViews = await manager.listViews('account');
|
|
172
|
+
expect(accountViews).toHaveLength(1);
|
|
173
|
+
expect((accountViews[0] as any).name).toBe('account_list');
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it('should get a dashboard via getDashboard()', async () => {
|
|
177
|
+
const dashDef = { name: 'sales', label: 'Sales Overview' };
|
|
178
|
+
await manager.register('dashboard', 'sales', dashDef);
|
|
179
|
+
|
|
180
|
+
const result = await manager.getDashboard('sales');
|
|
181
|
+
expect(result).toEqual(dashDef);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('should list dashboards via listDashboards()', async () => {
|
|
185
|
+
await manager.register('dashboard', 'sales', { name: 'sales' });
|
|
186
|
+
await manager.register('dashboard', 'ops', { name: 'ops' });
|
|
187
|
+
|
|
188
|
+
const dashboards = await manager.listDashboards();
|
|
189
|
+
expect(dashboards).toHaveLength(2);
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
|
|
146
193
|
// ==========================================
|
|
147
194
|
// Package Management
|
|
148
195
|
// ==========================================
|
|
@@ -328,6 +375,44 @@ describe('MetadataManager — IMetadataService Contract', () => {
|
|
|
328
375
|
const effective = await manager.getEffective('object', 'account') as any;
|
|
329
376
|
expect(effective.label).toBe('Original');
|
|
330
377
|
});
|
|
378
|
+
|
|
379
|
+
it('should apply user overlay scoped to specific userId via getEffective context', async () => {
|
|
380
|
+
await manager.register('view', 'account_list', {
|
|
381
|
+
name: 'account_list',
|
|
382
|
+
columns: ['name', 'email', 'status']
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
// Platform overlay
|
|
386
|
+
await manager.saveOverlay({
|
|
387
|
+
id: 'platform-view-1',
|
|
388
|
+
baseType: 'view',
|
|
389
|
+
baseName: 'account_list',
|
|
390
|
+
scope: 'platform',
|
|
391
|
+
patch: { columns: ['name', 'email', 'status', 'created_at'] },
|
|
392
|
+
active: true,
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
// User-specific overlay
|
|
396
|
+
await manager.saveOverlay({
|
|
397
|
+
id: 'user-view-1',
|
|
398
|
+
baseType: 'view',
|
|
399
|
+
baseName: 'account_list',
|
|
400
|
+
scope: 'user',
|
|
401
|
+
owner: 'user-456',
|
|
402
|
+
patch: { columns: ['name', 'status'] },
|
|
403
|
+
active: true,
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
// Without context — should apply platform but not user overlay (no owner match)
|
|
407
|
+
const general = await manager.getEffective('view', 'account_list') as any;
|
|
408
|
+
expect(general.columns).toEqual(['name', 'email', 'status', 'created_at']);
|
|
409
|
+
|
|
410
|
+
// With userId context — should apply user overlay
|
|
411
|
+
const forUser = await manager.getEffective('view', 'account_list', {
|
|
412
|
+
userId: 'user-456'
|
|
413
|
+
}) as any;
|
|
414
|
+
expect(forUser.columns).toEqual(['name', 'status']);
|
|
415
|
+
});
|
|
331
416
|
});
|
|
332
417
|
|
|
333
418
|
// ==========================================
|