@objectstack/objectql 4.0.3 → 4.0.4
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 +9 -0
- package/dist/index.d.mts +34 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.js +94 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +94 -12
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
- package/src/datasource-mapping.test.ts +181 -0
- package/src/engine.test.ts +15 -1
- package/src/engine.ts +137 -17
- package/src/protocol.ts +8 -1
package/dist/index.mjs
CHANGED
|
@@ -696,7 +696,10 @@ var ObjectStackProtocolImplementation = class {
|
|
|
696
696
|
const services = this.getServicesRegistry?.();
|
|
697
697
|
const metadataService = services?.get("metadata");
|
|
698
698
|
if (metadataService && typeof metadataService.list === "function") {
|
|
699
|
-
|
|
699
|
+
let runtimeItems = await metadataService.list(request.type);
|
|
700
|
+
if (packageId && runtimeItems && runtimeItems.length > 0) {
|
|
701
|
+
runtimeItems = runtimeItems.filter((item) => item?._packageId === packageId);
|
|
702
|
+
}
|
|
700
703
|
if (runtimeItems && runtimeItems.length > 0) {
|
|
701
704
|
const itemMap = /* @__PURE__ */ new Map();
|
|
702
705
|
for (const item of items) {
|
|
@@ -1515,6 +1518,10 @@ var _ObjectQL = class _ObjectQL {
|
|
|
1515
1518
|
constructor(hostContext = {}) {
|
|
1516
1519
|
this.drivers = /* @__PURE__ */ new Map();
|
|
1517
1520
|
this.defaultDriver = null;
|
|
1521
|
+
// Datasource mapping rules (imported from defineStack)
|
|
1522
|
+
this.datasourceMapping = [];
|
|
1523
|
+
// Package manifests registry (for defaultDatasource lookup)
|
|
1524
|
+
this.manifests = /* @__PURE__ */ new Map();
|
|
1518
1525
|
// Per-object hooks with priority support
|
|
1519
1526
|
this.hooks = /* @__PURE__ */ new Map([
|
|
1520
1527
|
["beforeFind", []],
|
|
@@ -1712,6 +1719,9 @@ var _ObjectQL = class _ObjectQL {
|
|
|
1712
1719
|
const id = manifest.id || manifest.name;
|
|
1713
1720
|
const namespace = manifest.namespace;
|
|
1714
1721
|
this.logger.debug("Registering package manifest", { id, namespace });
|
|
1722
|
+
if (id) {
|
|
1723
|
+
this.manifests.set(id, manifest);
|
|
1724
|
+
}
|
|
1715
1725
|
SchemaRegistry.installPackage(manifest);
|
|
1716
1726
|
this.logger.debug("Installed Package", { id: manifest.id, name: manifest.name, namespace });
|
|
1717
1727
|
if (manifest.objects) {
|
|
@@ -1966,27 +1976,99 @@ var _ObjectQL = class _ObjectQL {
|
|
|
1966
1976
|
}
|
|
1967
1977
|
/**
|
|
1968
1978
|
* Helper to get the target driver
|
|
1979
|
+
*
|
|
1980
|
+
* Resolution priority (first match wins):
|
|
1981
|
+
* 1. Object's explicit `datasource` field (if not 'default')
|
|
1982
|
+
* 2. DatasourceMapping rules (namespace/package/pattern matching)
|
|
1983
|
+
* 3. Package's `defaultDatasource` from manifest
|
|
1984
|
+
* 4. Global default driver
|
|
1969
1985
|
*/
|
|
1970
1986
|
getDriver(objectName) {
|
|
1971
1987
|
const object = SchemaRegistry.getObject(objectName);
|
|
1972
|
-
if (object) {
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1988
|
+
if (object?.datasource && object.datasource !== "default") {
|
|
1989
|
+
if (this.drivers.has(object.datasource)) {
|
|
1990
|
+
return this.drivers.get(object.datasource);
|
|
1991
|
+
}
|
|
1992
|
+
throw new Error(`[ObjectQL] Datasource '${object.datasource}' configured for object '${objectName}' is not registered.`);
|
|
1993
|
+
}
|
|
1994
|
+
const mappedDatasource = this.resolveDatasourceFromMapping(objectName, object);
|
|
1995
|
+
if (mappedDatasource && this.drivers.has(mappedDatasource)) {
|
|
1996
|
+
this.logger.debug("Resolved datasource from mapping", {
|
|
1997
|
+
object: objectName,
|
|
1998
|
+
datasource: mappedDatasource
|
|
1999
|
+
});
|
|
2000
|
+
return this.drivers.get(mappedDatasource);
|
|
2001
|
+
}
|
|
2002
|
+
const fqn = object?.name || objectName;
|
|
2003
|
+
const owner = SchemaRegistry.getObjectOwner(fqn);
|
|
2004
|
+
if (owner?.packageId) {
|
|
2005
|
+
const manifest = this.manifests.get(owner.packageId);
|
|
2006
|
+
if (manifest?.defaultDatasource && manifest.defaultDatasource !== "default") {
|
|
2007
|
+
if (this.drivers.has(manifest.defaultDatasource)) {
|
|
2008
|
+
this.logger.debug("Resolved datasource from package manifest", {
|
|
2009
|
+
object: objectName,
|
|
2010
|
+
package: owner.packageId,
|
|
2011
|
+
datasource: manifest.defaultDatasource
|
|
2012
|
+
});
|
|
2013
|
+
return this.drivers.get(manifest.defaultDatasource);
|
|
1981
2014
|
}
|
|
1982
|
-
throw new Error(`[ObjectQL] Datasource '${datasourceName}' configured for object '${objectName}' is not registered.`);
|
|
1983
2015
|
}
|
|
1984
2016
|
}
|
|
1985
|
-
if (this.defaultDriver) {
|
|
2017
|
+
if (this.defaultDriver && this.drivers.has(this.defaultDriver)) {
|
|
1986
2018
|
return this.drivers.get(this.defaultDriver);
|
|
1987
2019
|
}
|
|
1988
2020
|
throw new Error(`[ObjectQL] No driver available for object '${objectName}'`);
|
|
1989
2021
|
}
|
|
2022
|
+
/**
|
|
2023
|
+
* Resolve datasource from mapping rules
|
|
2024
|
+
*
|
|
2025
|
+
* Rules are evaluated in order (or by priority if specified).
|
|
2026
|
+
* First matching rule wins.
|
|
2027
|
+
*/
|
|
2028
|
+
resolveDatasourceFromMapping(objectName, object) {
|
|
2029
|
+
if (!this.datasourceMapping || this.datasourceMapping.length === 0) {
|
|
2030
|
+
return null;
|
|
2031
|
+
}
|
|
2032
|
+
const sortedRules = [...this.datasourceMapping].sort((a, b) => {
|
|
2033
|
+
const aPriority = a.priority ?? 1e3;
|
|
2034
|
+
const bPriority = b.priority ?? 1e3;
|
|
2035
|
+
return aPriority - bPriority;
|
|
2036
|
+
});
|
|
2037
|
+
for (const rule of sortedRules) {
|
|
2038
|
+
if (rule.namespace && object?.namespace === rule.namespace) {
|
|
2039
|
+
return rule.datasource;
|
|
2040
|
+
}
|
|
2041
|
+
if (rule.package && object?.packageId === rule.package) {
|
|
2042
|
+
return rule.datasource;
|
|
2043
|
+
}
|
|
2044
|
+
if (rule.objectPattern && this.matchPattern(objectName, rule.objectPattern)) {
|
|
2045
|
+
return rule.datasource;
|
|
2046
|
+
}
|
|
2047
|
+
if (rule.default) {
|
|
2048
|
+
return rule.datasource;
|
|
2049
|
+
}
|
|
2050
|
+
}
|
|
2051
|
+
return null;
|
|
2052
|
+
}
|
|
2053
|
+
/**
|
|
2054
|
+
* Simple glob pattern matching
|
|
2055
|
+
* Supports * (any chars) and ? (single char)
|
|
2056
|
+
*/
|
|
2057
|
+
matchPattern(objectName, pattern) {
|
|
2058
|
+
const regexPattern = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
|
|
2059
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
2060
|
+
return regex.test(objectName);
|
|
2061
|
+
}
|
|
2062
|
+
/**
|
|
2063
|
+
* Set datasource mapping rules
|
|
2064
|
+
* Called by ObjectQLPlugin during bootstrap
|
|
2065
|
+
*/
|
|
2066
|
+
setDatasourceMapping(rules) {
|
|
2067
|
+
this.datasourceMapping = rules;
|
|
2068
|
+
this.logger.info("Datasource mapping rules configured", {
|
|
2069
|
+
ruleCount: rules.length
|
|
2070
|
+
});
|
|
2071
|
+
}
|
|
1990
2072
|
/**
|
|
1991
2073
|
* Initialize the engine and all registered drivers
|
|
1992
2074
|
*/
|