@objectstack/objectql 3.2.8 → 3.3.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/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +20 -0
- package/dist/index.d.mts +30 -2
- package/dist/index.d.ts +30 -2
- package/dist/index.js +83 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +83 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
- package/src/engine.test.ts +5 -5
- package/src/engine.ts +25 -4
- package/src/plugin.integration.test.ts +311 -0
- package/src/plugin.ts +66 -0
- package/src/registry.test.ts +25 -0
- package/src/registry.ts +17 -2
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @objectstack/objectql@3.
|
|
2
|
+
> @objectstack/objectql@3.3.0 build /home/runner/work/spec/spec/packages/objectql
|
|
3
3
|
> tsup --config ../../tsup.config.ts
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.ts
|
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
[34mCLI[39m Cleaning output folder
|
|
11
11
|
[34mESM[39m Build start
|
|
12
12
|
[34mCJS[39m Build start
|
|
13
|
-
[
|
|
14
|
-
[
|
|
15
|
-
[
|
|
16
|
-
[
|
|
17
|
-
[
|
|
18
|
-
[
|
|
13
|
+
[32mCJS[39m [1mdist/index.js [22m[32m98.69 KB[39m
|
|
14
|
+
[32mCJS[39m [1mdist/index.js.map [22m[32m199.38 KB[39m
|
|
15
|
+
[32mCJS[39m ⚡️ Build success in 147ms
|
|
16
|
+
[32mESM[39m [1mdist/index.mjs [22m[32m96.95 KB[39m
|
|
17
|
+
[32mESM[39m [1mdist/index.mjs.map [22m[32m198.08 KB[39m
|
|
18
|
+
[32mESM[39m ⚡️ Build success in 148ms
|
|
19
19
|
[34mDTS[39m Build start
|
|
20
|
-
[32mDTS[39m ⚡️ Build success in
|
|
21
|
-
[32mDTS[39m [1mdist/index.d.mts [22m[
|
|
22
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[
|
|
20
|
+
[32mDTS[39m ⚡️ Build success in 25675ms
|
|
21
|
+
[32mDTS[39m [1mdist/index.d.mts [22m[32m78.59 KB[39m
|
|
22
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m78.59 KB[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,29 @@
|
|
|
1
1
|
# @objectstack/objectql
|
|
2
2
|
|
|
3
|
+
## 3.3.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- @objectstack/spec@3.3.0
|
|
8
|
+
- @objectstack/core@3.3.0
|
|
9
|
+
- @objectstack/types@3.3.0
|
|
10
|
+
|
|
11
|
+
## 3.2.9
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- c3065dd: fix turso 2
|
|
16
|
+
- @objectstack/spec@3.2.9
|
|
17
|
+
- @objectstack/core@3.2.9
|
|
18
|
+
- @objectstack/types@3.2.9
|
|
19
|
+
|
|
3
20
|
## 3.2.8
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
|
6
23
|
|
|
24
|
+
- Auto-sync all registered object schemas to database on startup: `ObjectQLPlugin.start()` now iterates every object in `SchemaRegistry` and calls `driver.syncSchema()` after driver connections are established. This ensures tables for plugin-registered objects (e.g. `sys_user` from plugin-auth) are created or updated automatically.
|
|
25
|
+
- Added `getDriverForObject(objectName)` public method to `ObjectQL` engine for resolving the responsible driver for a given object.
|
|
26
|
+
- Added optional `syncSchema` method to `DriverInterface` contract, aligning it with the full `IDataDriver` protocol.
|
|
7
27
|
- @objectstack/spec@3.2.8
|
|
8
28
|
- @objectstack/core@3.2.8
|
|
9
29
|
- @objectstack/types@3.2.8
|
package/dist/index.d.mts
CHANGED
|
@@ -167,8 +167,14 @@ declare class SchemaRegistry {
|
|
|
167
167
|
*/
|
|
168
168
|
static resolveObject(fqn: string): ServiceObject | undefined;
|
|
169
169
|
/**
|
|
170
|
-
* Get object by name (FQN
|
|
171
|
-
*
|
|
170
|
+
* Get object by name (FQN, short name, or physical table name).
|
|
171
|
+
*
|
|
172
|
+
* Resolution order:
|
|
173
|
+
* 1. Exact FQN match (e.g., 'crm__account')
|
|
174
|
+
* 2. Short name fallback (e.g., 'account' → 'crm__account')
|
|
175
|
+
* 3. Physical table name match (e.g., 'sys_user' → 'sys__user')
|
|
176
|
+
* ObjectSchema.create() auto-derives tableName as {namespace}_{name},
|
|
177
|
+
* which uses a single underscore — different from the FQN double underscore.
|
|
172
178
|
*/
|
|
173
179
|
static getObject(name: string): ServiceObject | undefined;
|
|
174
180
|
/**
|
|
@@ -1683,6 +1689,17 @@ declare class ObjectQL implements IDataEngine {
|
|
|
1683
1689
|
* this method directly looks up a driver by its registered name.
|
|
1684
1690
|
*/
|
|
1685
1691
|
getDriverByName(name: string): DriverInterface | undefined;
|
|
1692
|
+
/**
|
|
1693
|
+
* Get the driver responsible for the given object.
|
|
1694
|
+
*
|
|
1695
|
+
* Resolves datasource binding from the object's schema definition,
|
|
1696
|
+
* falling back to the default driver. This is a public version of
|
|
1697
|
+
* the internal getDriver() used by CRUD operations.
|
|
1698
|
+
*
|
|
1699
|
+
* @param objectName - FQN or short name of the registered object.
|
|
1700
|
+
* @returns The resolved DriverInterface, or undefined if no driver is available.
|
|
1701
|
+
*/
|
|
1702
|
+
getDriverForObject(objectName: string): DriverInterface | undefined;
|
|
1686
1703
|
/**
|
|
1687
1704
|
* Get a registered driver by datasource name.
|
|
1688
1705
|
* Alias matching @objectql/core datasource() API.
|
|
@@ -1877,6 +1894,17 @@ declare class ObjectQLPlugin implements Plugin {
|
|
|
1877
1894
|
* for multi-tenant operations.
|
|
1878
1895
|
*/
|
|
1879
1896
|
private registerTenantMiddleware;
|
|
1897
|
+
/**
|
|
1898
|
+
* Synchronize all registered object schemas to the database.
|
|
1899
|
+
*
|
|
1900
|
+
* Iterates every object in the SchemaRegistry and calls the
|
|
1901
|
+
* responsible driver's `syncSchema()` for each one. This is
|
|
1902
|
+
* idempotent — drivers must tolerate repeated calls without
|
|
1903
|
+
* duplicating tables or erroring out.
|
|
1904
|
+
*
|
|
1905
|
+
* Drivers that do not implement `syncSchema` are silently skipped.
|
|
1906
|
+
*/
|
|
1907
|
+
private syncRegisteredSchemas;
|
|
1880
1908
|
/**
|
|
1881
1909
|
* Load metadata from external metadata service into ObjectQL registry
|
|
1882
1910
|
* This enables ObjectQL to use file-based or remote metadata
|
package/dist/index.d.ts
CHANGED
|
@@ -167,8 +167,14 @@ declare class SchemaRegistry {
|
|
|
167
167
|
*/
|
|
168
168
|
static resolveObject(fqn: string): ServiceObject | undefined;
|
|
169
169
|
/**
|
|
170
|
-
* Get object by name (FQN
|
|
171
|
-
*
|
|
170
|
+
* Get object by name (FQN, short name, or physical table name).
|
|
171
|
+
*
|
|
172
|
+
* Resolution order:
|
|
173
|
+
* 1. Exact FQN match (e.g., 'crm__account')
|
|
174
|
+
* 2. Short name fallback (e.g., 'account' → 'crm__account')
|
|
175
|
+
* 3. Physical table name match (e.g., 'sys_user' → 'sys__user')
|
|
176
|
+
* ObjectSchema.create() auto-derives tableName as {namespace}_{name},
|
|
177
|
+
* which uses a single underscore — different from the FQN double underscore.
|
|
172
178
|
*/
|
|
173
179
|
static getObject(name: string): ServiceObject | undefined;
|
|
174
180
|
/**
|
|
@@ -1683,6 +1689,17 @@ declare class ObjectQL implements IDataEngine {
|
|
|
1683
1689
|
* this method directly looks up a driver by its registered name.
|
|
1684
1690
|
*/
|
|
1685
1691
|
getDriverByName(name: string): DriverInterface | undefined;
|
|
1692
|
+
/**
|
|
1693
|
+
* Get the driver responsible for the given object.
|
|
1694
|
+
*
|
|
1695
|
+
* Resolves datasource binding from the object's schema definition,
|
|
1696
|
+
* falling back to the default driver. This is a public version of
|
|
1697
|
+
* the internal getDriver() used by CRUD operations.
|
|
1698
|
+
*
|
|
1699
|
+
* @param objectName - FQN or short name of the registered object.
|
|
1700
|
+
* @returns The resolved DriverInterface, or undefined if no driver is available.
|
|
1701
|
+
*/
|
|
1702
|
+
getDriverForObject(objectName: string): DriverInterface | undefined;
|
|
1686
1703
|
/**
|
|
1687
1704
|
* Get a registered driver by datasource name.
|
|
1688
1705
|
* Alias matching @objectql/core datasource() API.
|
|
@@ -1877,6 +1894,17 @@ declare class ObjectQLPlugin implements Plugin {
|
|
|
1877
1894
|
* for multi-tenant operations.
|
|
1878
1895
|
*/
|
|
1879
1896
|
private registerTenantMiddleware;
|
|
1897
|
+
/**
|
|
1898
|
+
* Synchronize all registered object schemas to the database.
|
|
1899
|
+
*
|
|
1900
|
+
* Iterates every object in the SchemaRegistry and calls the
|
|
1901
|
+
* responsible driver's `syncSchema()` for each one. This is
|
|
1902
|
+
* idempotent — drivers must tolerate repeated calls without
|
|
1903
|
+
* duplicating tables or erroring out.
|
|
1904
|
+
*
|
|
1905
|
+
* Drivers that do not implement `syncSchema` are silently skipped.
|
|
1906
|
+
*/
|
|
1907
|
+
private syncRegisteredSchemas;
|
|
1880
1908
|
/**
|
|
1881
1909
|
* Load metadata from external metadata service into ObjectQL registry
|
|
1882
1910
|
* This enables ObjectQL to use file-based or remote metadata
|
package/dist/index.js
CHANGED
|
@@ -207,8 +207,14 @@ var SchemaRegistry = class {
|
|
|
207
207
|
return merged;
|
|
208
208
|
}
|
|
209
209
|
/**
|
|
210
|
-
* Get object by name (FQN
|
|
211
|
-
*
|
|
210
|
+
* Get object by name (FQN, short name, or physical table name).
|
|
211
|
+
*
|
|
212
|
+
* Resolution order:
|
|
213
|
+
* 1. Exact FQN match (e.g., 'crm__account')
|
|
214
|
+
* 2. Short name fallback (e.g., 'account' → 'crm__account')
|
|
215
|
+
* 3. Physical table name match (e.g., 'sys_user' → 'sys__user')
|
|
216
|
+
* ObjectSchema.create() auto-derives tableName as {namespace}_{name},
|
|
217
|
+
* which uses a single underscore — different from the FQN double underscore.
|
|
212
218
|
*/
|
|
213
219
|
static getObject(name) {
|
|
214
220
|
const direct = this.resolveObject(name);
|
|
@@ -219,6 +225,12 @@ var SchemaRegistry = class {
|
|
|
219
225
|
return this.resolveObject(fqn);
|
|
220
226
|
}
|
|
221
227
|
}
|
|
228
|
+
for (const fqn of this.objectContributors.keys()) {
|
|
229
|
+
const resolved = this.resolveObject(fqn);
|
|
230
|
+
if (resolved?.tableName === name) {
|
|
231
|
+
return resolved;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
222
234
|
return void 0;
|
|
223
235
|
}
|
|
224
236
|
/**
|
|
@@ -1760,7 +1772,7 @@ var _ObjectQL = class _ObjectQL {
|
|
|
1760
1772
|
resolveObjectName(name) {
|
|
1761
1773
|
const schema = SchemaRegistry.getObject(name);
|
|
1762
1774
|
if (schema) {
|
|
1763
|
-
return schema.name;
|
|
1775
|
+
return schema.tableName || schema.name;
|
|
1764
1776
|
}
|
|
1765
1777
|
return name;
|
|
1766
1778
|
}
|
|
@@ -2246,6 +2258,23 @@ var _ObjectQL = class _ObjectQL {
|
|
|
2246
2258
|
getDriverByName(name) {
|
|
2247
2259
|
return this.drivers.get(name);
|
|
2248
2260
|
}
|
|
2261
|
+
/**
|
|
2262
|
+
* Get the driver responsible for the given object.
|
|
2263
|
+
*
|
|
2264
|
+
* Resolves datasource binding from the object's schema definition,
|
|
2265
|
+
* falling back to the default driver. This is a public version of
|
|
2266
|
+
* the internal getDriver() used by CRUD operations.
|
|
2267
|
+
*
|
|
2268
|
+
* @param objectName - FQN or short name of the registered object.
|
|
2269
|
+
* @returns The resolved DriverInterface, or undefined if no driver is available.
|
|
2270
|
+
*/
|
|
2271
|
+
getDriverForObject(objectName) {
|
|
2272
|
+
try {
|
|
2273
|
+
return this.getDriver(objectName);
|
|
2274
|
+
} catch {
|
|
2275
|
+
return void 0;
|
|
2276
|
+
}
|
|
2277
|
+
}
|
|
2249
2278
|
/**
|
|
2250
2279
|
* Get a registered driver by datasource name.
|
|
2251
2280
|
* Alias matching @objectql/core datasource() API.
|
|
@@ -2643,6 +2672,7 @@ var ObjectQLPlugin = class {
|
|
|
2643
2672
|
}
|
|
2644
2673
|
}
|
|
2645
2674
|
await this.ql?.init();
|
|
2675
|
+
await this.syncRegisteredSchemas(ctx);
|
|
2646
2676
|
this.registerAuditHooks(ctx);
|
|
2647
2677
|
this.registerTenantMiddleware(ctx);
|
|
2648
2678
|
ctx.logger.info("ObjectQL engine started", {
|
|
@@ -2737,6 +2767,56 @@ var ObjectQLPlugin = class {
|
|
|
2737
2767
|
});
|
|
2738
2768
|
ctx.logger.debug("Tenant isolation middleware registered");
|
|
2739
2769
|
}
|
|
2770
|
+
/**
|
|
2771
|
+
* Synchronize all registered object schemas to the database.
|
|
2772
|
+
*
|
|
2773
|
+
* Iterates every object in the SchemaRegistry and calls the
|
|
2774
|
+
* responsible driver's `syncSchema()` for each one. This is
|
|
2775
|
+
* idempotent — drivers must tolerate repeated calls without
|
|
2776
|
+
* duplicating tables or erroring out.
|
|
2777
|
+
*
|
|
2778
|
+
* Drivers that do not implement `syncSchema` are silently skipped.
|
|
2779
|
+
*/
|
|
2780
|
+
async syncRegisteredSchemas(ctx) {
|
|
2781
|
+
if (!this.ql) return;
|
|
2782
|
+
const allObjects = this.ql.registry?.getAllObjects?.() ?? [];
|
|
2783
|
+
if (allObjects.length === 0) return;
|
|
2784
|
+
let synced = 0;
|
|
2785
|
+
let skipped = 0;
|
|
2786
|
+
for (const obj of allObjects) {
|
|
2787
|
+
const driver = this.ql.getDriverForObject(obj.name);
|
|
2788
|
+
if (!driver) {
|
|
2789
|
+
ctx.logger.debug("No driver available for object, skipping schema sync", {
|
|
2790
|
+
object: obj.name
|
|
2791
|
+
});
|
|
2792
|
+
skipped++;
|
|
2793
|
+
continue;
|
|
2794
|
+
}
|
|
2795
|
+
if (typeof driver.syncSchema !== "function") {
|
|
2796
|
+
ctx.logger.debug("Driver does not support syncSchema, skipping", {
|
|
2797
|
+
object: obj.name,
|
|
2798
|
+
driver: driver.name
|
|
2799
|
+
});
|
|
2800
|
+
skipped++;
|
|
2801
|
+
continue;
|
|
2802
|
+
}
|
|
2803
|
+
const tableName = obj.tableName || obj.name;
|
|
2804
|
+
try {
|
|
2805
|
+
await driver.syncSchema(tableName, obj);
|
|
2806
|
+
synced++;
|
|
2807
|
+
} catch (e) {
|
|
2808
|
+
ctx.logger.warn("Failed to sync schema for object", {
|
|
2809
|
+
object: obj.name,
|
|
2810
|
+
tableName,
|
|
2811
|
+
driver: driver.name,
|
|
2812
|
+
error: e instanceof Error ? e.message : String(e)
|
|
2813
|
+
});
|
|
2814
|
+
}
|
|
2815
|
+
}
|
|
2816
|
+
if (synced > 0 || skipped > 0) {
|
|
2817
|
+
ctx.logger.info("Schema sync complete", { synced, skipped, total: allObjects.length });
|
|
2818
|
+
}
|
|
2819
|
+
}
|
|
2740
2820
|
/**
|
|
2741
2821
|
* Load metadata from external metadata service into ObjectQL registry
|
|
2742
2822
|
* This enables ObjectQL to use file-based or remote metadata
|