@objectstack/objectql 1.1.0 → 2.0.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/src/engine.ts CHANGED
@@ -1,3 +1,5 @@
1
+ // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
+
1
3
  import { QueryAST, HookContext } from '@objectstack/spec/data';
2
4
  import {
3
5
  DataEngineQueryOptions,
@@ -219,8 +221,20 @@ export class ObjectQL implements IDataEngine {
219
221
 
220
222
  // 5. Register all other metadata types generically
221
223
  const metadataArrayKeys = [
222
- 'actions', 'dashboards', 'reports', 'flows', 'agents',
223
- 'apis', 'ragPipelines', 'profiles', 'sharingRules'
224
+ // UI Protocol
225
+ 'actions', 'views', 'pages', 'dashboards', 'reports', 'themes',
226
+ // Automation Protocol
227
+ 'flows', 'workflows', 'approvals', 'webhooks',
228
+ // Security Protocol
229
+ 'roles', 'permissions', 'profiles', 'sharingRules', 'policies',
230
+ // AI Protocol
231
+ 'agents', 'ragPipelines',
232
+ // API Protocol
233
+ 'apis',
234
+ // Data Extensions
235
+ 'hooks', 'mappings', 'analyticsCubes',
236
+ // Integration Protocol
237
+ 'connectors',
224
238
  ];
225
239
  for (const key of metadataArrayKeys) {
226
240
  const items = (manifest as any)[key];
@@ -425,13 +439,13 @@ export class ObjectQL implements IDataEngine {
425
439
  await this.triggerHooks('beforeFind', hookContext);
426
440
 
427
441
  try {
428
- const result = await driver.find(object, hookContext.input.ast, hookContext.input.options);
442
+ const result = await driver.find(object, hookContext.input.ast as QueryAST, hookContext.input.options as any);
429
443
 
430
444
  hookContext.event = 'afterFind';
431
445
  hookContext.result = result;
432
446
  await this.triggerHooks('afterFind', hookContext);
433
447
 
434
- return hookContext.result;
448
+ return hookContext.result as any[];
435
449
  } catch (e) {
436
450
  this.logger.error('Find operation failed', e as Error, { object });
437
451
  throw e;
@@ -468,13 +482,13 @@ export class ObjectQL implements IDataEngine {
468
482
  if (Array.isArray(hookContext.input.data)) {
469
483
  // Bulk Create
470
484
  if (driver.bulkCreate) {
471
- result = await driver.bulkCreate(object, hookContext.input.data, hookContext.input.options);
485
+ result = await driver.bulkCreate(object, hookContext.input.data as any[], hookContext.input.options as any);
472
486
  } else {
473
487
  // Fallback loop
474
- result = await Promise.all(hookContext.input.data.map((item: any) => driver.create(object, item, hookContext.input.options)));
488
+ result = await Promise.all((hookContext.input.data as any[]).map((item: any) => driver.create(object, item, hookContext.input.options as any)));
475
489
  }
476
490
  } else {
477
- result = await driver.create(object, hookContext.input.data, hookContext.input.options);
491
+ result = await driver.create(object, hookContext.input.data, hookContext.input.options as any);
478
492
  }
479
493
 
480
494
  hookContext.event = 'afterInsert';
@@ -517,11 +531,11 @@ export class ObjectQL implements IDataEngine {
517
531
  let result;
518
532
  if (hookContext.input.id) {
519
533
  // Single update by ID
520
- result = await driver.update(object, hookContext.input.id, hookContext.input.data, hookContext.input.options);
534
+ result = await driver.update(object, hookContext.input.id as string, hookContext.input.data, hookContext.input.options as any);
521
535
  } else if (options?.multi && driver.updateMany) {
522
536
  // Bulk update by Query
523
537
  const ast = this.toQueryAST(object, { filter: options.filter });
524
- result = await driver.updateMany(object, ast, hookContext.input.data, hookContext.input.options);
538
+ result = await driver.updateMany(object, ast, hookContext.input.data, hookContext.input.options as any);
525
539
  } else {
526
540
  throw new Error('Update requires an ID or options.multi=true');
527
541
  }
@@ -560,10 +574,10 @@ export class ObjectQL implements IDataEngine {
560
574
  try {
561
575
  let result;
562
576
  if (hookContext.input.id) {
563
- result = await driver.delete(object, hookContext.input.id, hookContext.input.options);
577
+ result = await driver.delete(object, hookContext.input.id as string, hookContext.input.options as any);
564
578
  } else if (options?.multi && driver.deleteMany) {
565
579
  const ast = this.toQueryAST(object, { filter: options.filter });
566
- result = await driver.deleteMany(object, ast, hookContext.input.options);
580
+ result = await driver.deleteMany(object, ast, hookContext.input.options as any);
567
581
  } else {
568
582
  throw new Error('Delete requires an ID or options.multi=true');
569
583
  }
package/src/index.ts CHANGED
@@ -1,3 +1,5 @@
1
+ // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
+
1
3
  // Export Registry
2
4
  export {
3
5
  SchemaRegistry,
package/src/plugin.ts CHANGED
@@ -1,3 +1,5 @@
1
+ // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
+
1
3
  import { ObjectQL } from './engine.js';
2
4
  import { ObjectStackProtocolImplementation } from './protocol.js';
3
5
  import { Plugin, PluginContext } from '@objectstack/core';
package/src/protocol.ts CHANGED
@@ -1,3 +1,5 @@
1
+ // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
+
1
3
  import { ObjectStackProtocol } from '@objectstack/spec/api';
2
4
  import { IDataEngine } from '@objectstack/core';
3
5
  import type {
@@ -32,7 +34,7 @@ export class ObjectStackProtocolImplementation implements ObjectStackProtocol {
32
34
  this.engine = engine;
33
35
  }
34
36
 
35
- async getDiscovery(_request: {}) {
37
+ async getDiscovery() {
36
38
  return {
37
39
  version: '1.0',
38
40
  apiName: 'ObjectStack API',
@@ -42,7 +44,11 @@ export class ObjectStackProtocolImplementation implements ObjectStackProtocol {
42
44
  websockets: false,
43
45
  files: true,
44
46
  analytics: false,
45
- hub: false
47
+ hub: false,
48
+ ai: false,
49
+ workflow: false,
50
+ notifications: false,
51
+ i18n: false,
46
52
  },
47
53
  endpoints: {
48
54
  data: '/api/data',
@@ -52,24 +58,36 @@ export class ObjectStackProtocolImplementation implements ObjectStackProtocol {
52
58
  };
53
59
  }
54
60
 
55
- async getMetaTypes(_request: {}) {
61
+ async getMetaTypes() {
56
62
  return {
57
63
  types: SchemaRegistry.getRegisteredTypes()
58
64
  };
59
65
  }
60
66
 
61
- async getMetaItems(request: { type: string; packageId?: string }) {
67
+ async getMetaItems(request: { type: string }) {
68
+ let items = SchemaRegistry.listItems(request.type);
69
+ // Normalize singular/plural: REST uses singular ('app') but registry may store as plural ('apps')
70
+ if (items.length === 0) {
71
+ const alt = request.type.endsWith('s') ? request.type.slice(0, -1) : request.type + 's';
72
+ items = SchemaRegistry.listItems(alt);
73
+ }
62
74
  return {
63
75
  type: request.type,
64
- items: SchemaRegistry.listItems(request.type, request.packageId)
76
+ items
65
77
  };
66
78
  }
67
79
 
68
80
  async getMetaItem(request: { type: string, name: string }) {
81
+ let item = SchemaRegistry.getItem(request.type, request.name);
82
+ // Normalize singular/plural
83
+ if (item === undefined) {
84
+ const alt = request.type.endsWith('s') ? request.type.slice(0, -1) : request.type + 's';
85
+ item = SchemaRegistry.getItem(alt, request.name);
86
+ }
69
87
  return {
70
88
  type: request.type,
71
89
  name: request.name,
72
- item: SchemaRegistry.getItem(request.type, request.name)
90
+ item
73
91
  };
74
92
  }
75
93
 
package/src/registry.ts CHANGED
@@ -1,3 +1,5 @@
1
+ // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
+
1
3
  import { ServiceObject, ObjectSchema, ObjectOwnership } from '@objectstack/spec/data';
2
4
  import { ObjectStackManifest, ManifestSchema, InstalledPackage, InstalledPackageSchema } from '@objectstack/spec/kernel';
3
5
  import { AppSchema } from '@objectstack/spec/ui';