@_linked/core 2.36.1 → 2.36.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/CHANGELOG.md +24 -0
- package/README.md +19 -0
- package/lib/esm/collections/CoreSet.js +2 -0
- package/lib/esm/collections/CoreSet.js.map +1 -1
- package/lib/esm/collections/ShapeSet.js +2 -0
- package/lib/esm/collections/ShapeSet.js.map +1 -1
- package/lib/esm/expressions/Expr.js +3 -2
- package/lib/esm/expressions/Expr.js.map +1 -1
- package/lib/esm/expressions/ExpressionNode.js +10 -7
- package/lib/esm/expressions/ExpressionNode.js.map +1 -1
- package/lib/esm/index.d.ts +1 -1
- package/lib/esm/index.js +1 -1
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/queries/AskBuilder.js +5 -3
- package/lib/esm/queries/AskBuilder.js.map +1 -1
- package/lib/esm/queries/CountBuilder.js +4 -2
- package/lib/esm/queries/CountBuilder.js.map +1 -1
- package/lib/esm/queries/CreateBuilder.js +2 -0
- package/lib/esm/queries/CreateBuilder.js.map +1 -1
- package/lib/esm/queries/DeleteBuilder.js +3 -1
- package/lib/esm/queries/DeleteBuilder.js.map +1 -1
- package/lib/esm/queries/DslJsonExpression.js +7 -6
- package/lib/esm/queries/DslJsonExpression.js.map +1 -1
- package/lib/esm/queries/FieldSet.js +10 -8
- package/lib/esm/queries/FieldSet.js.map +1 -1
- package/lib/esm/queries/IRLower.js +2 -1
- package/lib/esm/queries/IRLower.js.map +1 -1
- package/lib/esm/queries/MutationSerialization.js +2 -1
- package/lib/esm/queries/MutationSerialization.js.map +1 -1
- package/lib/esm/queries/PropertyPath.js +2 -0
- package/lib/esm/queries/PropertyPath.js.map +1 -1
- package/lib/esm/queries/ProxiedPathBuilder.js +2 -1
- package/lib/esm/queries/ProxiedPathBuilder.js.map +1 -1
- package/lib/esm/queries/QueryBuilder.js +5 -4
- package/lib/esm/queries/QueryBuilder.js.map +1 -1
- package/lib/esm/queries/QueryContext.js +17 -6
- package/lib/esm/queries/QueryContext.js.map +1 -1
- package/lib/esm/queries/SelectQuery.js +18 -12
- package/lib/esm/queries/SelectQuery.js.map +1 -1
- package/lib/esm/queries/UpdateBuilder.js +3 -1
- package/lib/esm/queries/UpdateBuilder.js.map +1 -1
- package/lib/esm/queries/lower.js +5 -4
- package/lib/esm/queries/lower.js.map +1 -1
- package/lib/esm/shapes/SHACL.js +6 -3
- package/lib/esm/shapes/SHACL.js.map +1 -1
- package/lib/esm/shapes/Shape.d.ts +3 -1
- package/lib/esm/shapes/Shape.js +20 -2
- package/lib/esm/shapes/Shape.js.map +1 -1
- package/lib/esm/utils/LinkedErrorLogging.d.ts +2 -1
- package/lib/esm/utils/LinkedErrorLogging.js +11 -0
- package/lib/esm/utils/LinkedErrorLogging.js.map +1 -1
- package/lib/esm/utils/LinkedFileStorage.d.ts +6 -4
- package/lib/esm/utils/LinkedFileStorage.js +34 -4
- package/lib/esm/utils/LinkedFileStorage.js.map +1 -1
- package/lib/esm/utils/Package.d.ts +6 -0
- package/lib/esm/utils/Package.js +35 -7
- package/lib/esm/utils/Package.js.map +1 -1
- package/lib/esm/utils/Prefix.d.ts +4 -2
- package/lib/esm/utils/Prefix.js +18 -2
- package/lib/esm/utils/Prefix.js.map +1 -1
- package/lib/esm/utils/ShapeClass.js +11 -6
- package/lib/esm/utils/ShapeClass.js.map +1 -1
- package/lib/esm/utils/cached.js +2 -1
- package/lib/esm/utils/cached.js.map +1 -1
- package/lib/esm/utils/linkedError.d.ts +32 -0
- package/lib/esm/utils/linkedError.js +63 -0
- package/lib/esm/utils/linkedError.js.map +1 -1
- package/lib/esm/utils/unresolvedShape.d.ts +3 -1
- package/lib/esm/utils/unresolvedShape.js +5 -1
- package/lib/esm/utils/unresolvedShape.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueryContext.js","sourceRoot":"","sources":["../../../src/queries/QueryContext.ts"],"names":[],"mappings":"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","sourcesContent":["import {type QShape, QueryShape} from './SelectQuery.js';\nimport {Shape, createShapeTarget} from '../shapes/Shape.js';\nimport {brandLinkedError} from '../utils/linkedError.js';\n\nconst queryContext = new Map<string, QShape<any, any, any>>();\n\n/**\n * A live reference returned by getQueryContext when the context hasn't been set yet.\n * Its `id` getter resolves lazily from the global context map, so queries built with\n * a PendingQueryContext will pick up the value once it's set (e.g. after auth completes).\n */\nexport class PendingQueryContext {\n constructor(public readonly contextName: string) {}\n\n get id(): string | undefined {\n return queryContext.get(this.contextName)?.id;\n }\n}\n\n/**\n * Thrown when a query carrying a context reference is lowered but the context\n * isn't set in the current process. A context ref is carried in DSL-JSON and\n * resolves at lowering time against whatever context map is available (e.g.\n * server-side auth); if it can't resolve, lowering throws this rather than\n * silently producing a subject-less query.\n */\nexport class UnresolvedContextError extends Error {\n constructor(public readonly contextName: string) {\n super(\n `Query context \"${contextName}\" is not set and could not be resolved at lowering time.`,\n );\n this.name = 'UnresolvedContextError';\n }\n}\nbrandLinkedError(UnresolvedContextError, '@_linked/core', 'UnresolvedContextError');\n\n/** Listener notified (with the changed context name) whenever a context is set or cleared. */\nexport type QueryContextListener = (name: string) => void;\nconst contextListeners = new Set<QueryContextListener>();\n\n/**\n * Subscribe to query-context changes. Returns an unsubscribe function.\n *\n * This is the primitive that makes context resolution reactive: a consuming layer\n * (e.g. React components) subscribes and re-runs affected queries when the context\n * lands — so a query that resolved to `null` while the context was unset simply\n * re-runs and resolves once it's available (\"waiting\"), and re-runs again on any\n * later change (\"auto re-resolve\"). Core only emits the change; re-execution is the\n * consumer's responsibility.\n */\nexport function subscribeQueryContext(listener: QueryContextListener): () => void {\n contextListeners.add(listener);\n return () => contextListeners.delete(listener);\n}\n\nfunction notifyContextChange(name: string): void {\n // Snapshot so a listener that (un)subscribes or re-sets a context during\n // notification can't mutate the set mid-iteration.\n for (const listener of [...contextListeners]) {\n try {\n listener(name);\n } catch (err) {\n // A listener must never break setQueryContext for the others.\n console.error('[linked] query context listener failed', err);\n }\n }\n}\n\n/**\n * Normalize any query-context value to a {@link PendingQueryContext} carrying its name,\n * or return `undefined` if the value is not a context reference.\n *\n * A context appears in two runtime forms: a `PendingQueryContext` (the context was unset\n * when `getQueryContext()` was called) or a resolved `QueryShape` stamped with\n * `__queryContextName` (it was already set). Both must be treated as the same `{@ctx}`\n * reference wherever a node value/id is accepted (mutation field values, delete ids), so\n * that context-bound mutations behave identically whether the context is set or unset at\n * build time — resolution always happens at lowering.\n */\nexport function asContextRef(value: unknown): PendingQueryContext | undefined {\n if (value instanceof PendingQueryContext) return value;\n if (!value || typeof value !== 'object') return undefined;\n // A resolved context is a QueryShape proxy wrapping a Shape stamped with\n // `__queryContextName`. Read it via `originalValue` (a known QueryShape field)\n // so we don't trip the proxy's \"undecorated property\" guard (it now throws);\n // a bare Shape\n // carries the stamp directly.\n const v = value as {originalValue?: {__queryContextName?: unknown}; __queryContextName?: unknown};\n const source = v.originalValue ?? v;\n const name = (source as {__queryContextName?: unknown}).__queryContextName;\n if (typeof name === 'string') return new PendingQueryContext(name);\n return undefined;\n}\n\nexport function getQueryContext<T extends Shape>(name: string): QShape<T> {\n if (queryContext.has(name)) {\n return queryContext.get(name);\n }\n // Return a live reference that resolves lazily when the context is set.\n // This avoids the timing issue where module-level queries capture null\n // because the context hasn't been set yet (e.g. useEffect hasn't fired).\n return new PendingQueryContext(name) as any;\n}\n\nexport function setQueryContext(name: string, value: any, shapeType?) {\n // Clearing a context entry\n if (!value) {\n queryContext.delete(name);\n notifyContextChange(name);\n return;\n }\n\n // Already a QShape — stamp the underlying shape and store as-is. (Checked before\n // the plain-`{id}` branch below: a QueryShape's `.id` getter is also a string, so\n // testing for `{id}` first would wrongly require a shapeType and no-op.)\n if (value instanceof QueryShape) {\n const orig = (value as any).originalValue;\n if (orig) {\n orig.__queryContextName = name;\n if (typeof orig.id === 'string') orig.__queryContextId = orig.id;\n }\n queryContext.set(name, value as any);\n notifyContextChange(name);\n return;\n }\n\n // A Shape-shaped value (e.g. a `createShapeTarget` proxy target) — stamp it and\n // wrap as a QShape. Needs no shapeType (it already carries its shape class).\n if (value instanceof Shape) {\n value.__queryContextName = name;\n if (typeof value.id === 'string') value.__queryContextId = value.id;\n queryContext.set(name, new QueryShape(value) as any);\n notifyContextChange(name);\n return;\n }\n\n // A plain QResult `{id}` — materialize a shape (requires shapeType).\n if (typeof value.id === 'string') {\n if (!shapeType) {\n // A silent no-op here is a trap: the context never sets and the caller\n // gets no signal. A `{id}` value cannot be materialized without its shape.\n throw new Error(\n `setQueryContext('${name}'): a {id} value requires a shapeType so the shape can be materialized. Pass the Shape class as the third argument.`,\n );\n }\n const shape = createShapeTarget(shapeType as any, value.id);\n shape.__queryContextId = value.id;\n shape.__queryContextName = name;\n queryContext.set(name, QueryShape.create(shape) as any);\n notifyContextChange(name);\n return;\n }\n\n throw new Error(\n `setQueryContext('${name}'): value is not a QueryShape, Shape, or {id} result. Got ${typeof value}. Pass a Shape instance, a query-context shape, or a {id} result (with its shapeType).`,\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"QueryContext.js","sourceRoot":"","sources":["../../../src/queries/QueryContext.ts"],"names":[],"mappings":"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","sourcesContent":["import {type QShape, QueryShape} from './SelectQuery.js';\nimport {Shape, createShapeTarget} from '../shapes/Shape.js';\nimport {brandLinkedClass, brandLinkedError, isLinkedInstance} from '../utils/linkedError.js';\nimport {sharedState} from '../utils/sharedState.js';\n\n/**\n * The context map and its listeners, shared by every copy of core in the runtime: a context\n * the app sets through one copy must resolve for a query lowered by the other, and a React\n * layer subscribed through one copy must hear a change made through the other.\n */\nconst contextState = sharedState('@_linked/core', 'QueryContext', () => ({\n contexts: new Map<string, QShape<any, any, any>>(),\n listeners: new Set<QueryContextListener>(),\n}));\nconst queryContext = contextState.contexts;\n\n/**\n * A live reference returned by getQueryContext when the context hasn't been set yet.\n * Its `id` getter resolves lazily from the global context map, so queries built with\n * a PendingQueryContext will pick up the value once it's set (e.g. after auth completes).\n */\nexport class PendingQueryContext {\n constructor(public readonly contextName: string) {}\n\n get id(): string | undefined {\n return queryContext.get(this.contextName)?.id;\n }\n}\nbrandLinkedClass(PendingQueryContext, '@_linked/core', 'PendingQueryContext');\n\n\n/**\n * Thrown when a query carrying a context reference is lowered but the context\n * isn't set in the current process. A context ref is carried in DSL-JSON and\n * resolves at lowering time against whatever context map is available (e.g.\n * server-side auth); if it can't resolve, lowering throws this rather than\n * silently producing a subject-less query.\n */\nexport class UnresolvedContextError extends Error {\n constructor(public readonly contextName: string) {\n super(\n `Query context \"${contextName}\" is not set and could not be resolved at lowering time.`,\n );\n this.name = 'UnresolvedContextError';\n }\n}\nbrandLinkedError(UnresolvedContextError, '@_linked/core', 'UnresolvedContextError');\n\n/** Listener notified (with the changed context name) whenever a context is set or cleared. */\nexport type QueryContextListener = (name: string) => void;\nconst contextListeners = contextState.listeners;\n\n/**\n * Subscribe to query-context changes. Returns an unsubscribe function.\n *\n * This is the primitive that makes context resolution reactive: a consuming layer\n * (e.g. React components) subscribes and re-runs affected queries when the context\n * lands — so a query that resolved to `null` while the context was unset simply\n * re-runs and resolves once it's available (\"waiting\"), and re-runs again on any\n * later change (\"auto re-resolve\"). Core only emits the change; re-execution is the\n * consumer's responsibility.\n */\nexport function subscribeQueryContext(listener: QueryContextListener): () => void {\n contextListeners.add(listener);\n return () => contextListeners.delete(listener);\n}\n\nfunction notifyContextChange(name: string): void {\n // Snapshot so a listener that (un)subscribes or re-sets a context during\n // notification can't mutate the set mid-iteration.\n for (const listener of [...contextListeners]) {\n try {\n listener(name);\n } catch (err) {\n // A listener must never break setQueryContext for the others.\n console.error('[linked] query context listener failed', err);\n }\n }\n}\n\n/**\n * Normalize any query-context value to a {@link PendingQueryContext} carrying its name,\n * or return `undefined` if the value is not a context reference.\n *\n * A context appears in two runtime forms: a `PendingQueryContext` (the context was unset\n * when `getQueryContext()` was called) or a resolved `QueryShape` stamped with\n * `__queryContextName` (it was already set). Both must be treated as the same `{@ctx}`\n * reference wherever a node value/id is accepted (mutation field values, delete ids), so\n * that context-bound mutations behave identically whether the context is set or unset at\n * build time — resolution always happens at lowering.\n */\nexport function asContextRef(value: unknown): PendingQueryContext | undefined {\n if (isLinkedInstance(value, PendingQueryContext)) return value;\n if (!value || typeof value !== 'object') return undefined;\n // A resolved context is a QueryShape proxy wrapping a Shape stamped with\n // `__queryContextName`. Read it via `originalValue` (a known QueryShape field)\n // so we don't trip the proxy's \"undecorated property\" guard (it now throws);\n // a bare Shape\n // carries the stamp directly.\n const v = value as {originalValue?: {__queryContextName?: unknown}; __queryContextName?: unknown};\n const source = v.originalValue ?? v;\n const name = (source as {__queryContextName?: unknown}).__queryContextName;\n if (typeof name === 'string') return new PendingQueryContext(name);\n return undefined;\n}\n\nexport function getQueryContext<T extends Shape>(name: string): QShape<T> {\n if (queryContext.has(name)) {\n return queryContext.get(name);\n }\n // Return a live reference that resolves lazily when the context is set.\n // This avoids the timing issue where module-level queries capture null\n // because the context hasn't been set yet (e.g. useEffect hasn't fired).\n return new PendingQueryContext(name) as any;\n}\n\nexport function setQueryContext(name: string, value: any, shapeType?) {\n // Clearing a context entry\n if (!value) {\n queryContext.delete(name);\n notifyContextChange(name);\n return;\n }\n\n // Already a QShape — stamp the underlying shape and store as-is. (Checked before\n // the plain-`{id}` branch below: a QueryShape's `.id` getter is also a string, so\n // testing for `{id}` first would wrongly require a shapeType and no-op.)\n if (isLinkedInstance(value, QueryShape)) {\n const orig = (value as any).originalValue;\n if (orig) {\n orig.__queryContextName = name;\n if (typeof orig.id === 'string') orig.__queryContextId = orig.id;\n }\n queryContext.set(name, value as any);\n notifyContextChange(name);\n return;\n }\n\n // A Shape-shaped value (e.g. a `createShapeTarget` proxy target) — stamp it and\n // wrap as a QShape. Needs no shapeType (it already carries its shape class).\n if (isLinkedInstance(value, Shape)) {\n value.__queryContextName = name;\n if (typeof value.id === 'string') value.__queryContextId = value.id;\n queryContext.set(name, new QueryShape(value) as any);\n notifyContextChange(name);\n return;\n }\n\n // A plain QResult `{id}` — materialize a shape (requires shapeType).\n if (typeof value.id === 'string') {\n if (!shapeType) {\n // A silent no-op here is a trap: the context never sets and the caller\n // gets no signal. A `{id}` value cannot be materialized without its shape.\n throw new Error(\n `setQueryContext('${name}'): a {id} value requires a shapeType so the shape can be materialized. Pass the Shape class as the third argument.`,\n );\n }\n const shape = createShapeTarget(shapeType as any, value.id);\n shape.__queryContextId = value.id;\n shape.__queryContextName = name;\n queryContext.set(name, QueryShape.create(shape) as any);\n notifyContextChange(name);\n return;\n }\n\n throw new Error(\n `setQueryContext('${name}'): value is not a QueryShape, Shape, or {id} result. Got ${typeof value}. Pass a Shape instance, a query-context shape, or a {id} result (with its shapeType).`,\n );\n}\n"]}
|
|
@@ -11,6 +11,7 @@ import { PropertyPath } from './PropertyPath.js';
|
|
|
11
11
|
import { ExpressionNode, ExistsCondition, isExpressionNode, isExistsCondition, tracedPropertyExpression, tracedAliasExpression } from '../expressions/ExpressionNode.js';
|
|
12
12
|
import { PendingQueryContext } from './QueryContext.js';
|
|
13
13
|
import { unresolvedValueShapeError } from '../utils/unresolvedShape.js';
|
|
14
|
+
import { brandLinkedClass, isLinkedInstance } from '../utils/linkedError.js';
|
|
14
15
|
/**
|
|
15
16
|
* String keys the query-shape proxy must let through *without* treating them as
|
|
16
17
|
* a property access — promise-awaiting (`then`), React (`$$typeof`), and common
|
|
@@ -169,6 +170,7 @@ export class QueryBuilderObject {
|
|
|
169
170
|
return path;
|
|
170
171
|
}
|
|
171
172
|
}
|
|
173
|
+
brandLinkedClass(QueryBuilderObject, '@_linked/core', 'QueryBuilderObject');
|
|
172
174
|
export class BoundComponent extends QueryBuilderObject {
|
|
173
175
|
constructor(originalValue, source) {
|
|
174
176
|
super(null, null);
|
|
@@ -261,7 +263,7 @@ function findContextName(qbo) {
|
|
|
261
263
|
var _a;
|
|
262
264
|
let current = qbo;
|
|
263
265
|
while (current) {
|
|
264
|
-
if (current
|
|
266
|
+
if (isLinkedInstance(current, QueryShape) && ((_a = current.originalValue) === null || _a === void 0 ? void 0 : _a.__queryContextName)) {
|
|
265
267
|
return current.originalValue.__queryContextName;
|
|
266
268
|
}
|
|
267
269
|
current = current.subject;
|
|
@@ -303,7 +305,7 @@ function wrapWithExpressionProxy(qp) {
|
|
|
303
305
|
const baseNode = toExpressionNode(target);
|
|
304
306
|
return (...args) => {
|
|
305
307
|
// Convert QueryBuilderObject arguments to ExpressionNode
|
|
306
|
-
const convertedArgs = args.map((arg) => { var _a; return arg
|
|
308
|
+
const convertedArgs = args.map((arg) => { var _a; return isLinkedInstance(arg, QueryBuilderObject) ? ((_a = toExpressionNode(arg)) !== null && _a !== void 0 ? _a : arg) : arg; });
|
|
307
309
|
return baseNode[key](...convertedArgs);
|
|
308
310
|
};
|
|
309
311
|
}
|
|
@@ -321,12 +323,12 @@ export const evaluateSortCallback = (shape, sortFn, direction = 'ASC') => {
|
|
|
321
323
|
const response = sortFn(proxy);
|
|
322
324
|
const nodeShape = shape.shape;
|
|
323
325
|
const paths = [];
|
|
324
|
-
if (response
|
|
326
|
+
if (isLinkedInstance(response, QueryBuilderObject) || isLinkedInstance(response, QueryPrimitiveSet)) {
|
|
325
327
|
paths.push(new PropertyPath(nodeShape, FieldSet.collectPropertySegments(response)));
|
|
326
328
|
}
|
|
327
329
|
else if (Array.isArray(response)) {
|
|
328
330
|
for (const item of response) {
|
|
329
|
-
if (item
|
|
331
|
+
if (isLinkedInstance(item, QueryBuilderObject)) {
|
|
330
332
|
paths.push(new PropertyPath(nodeShape, FieldSet.collectPropertySegments(item)));
|
|
331
333
|
}
|
|
332
334
|
}
|
|
@@ -427,7 +429,7 @@ export class QueryShapeSet extends QueryBuilderObject {
|
|
|
427
429
|
}
|
|
428
430
|
concat(other) {
|
|
429
431
|
if (other) {
|
|
430
|
-
if (other
|
|
432
|
+
if (isLinkedInstance(other, QueryShapeSet)) {
|
|
431
433
|
other.queryShapes.forEach(this.queryShapes.add.bind(this.queryShapes));
|
|
432
434
|
}
|
|
433
435
|
else {
|
|
@@ -534,6 +536,7 @@ export class QueryShapeSet extends QueryBuilderObject {
|
|
|
534
536
|
throw new Error('Expected a callback or ExpressionNode for some/every/none');
|
|
535
537
|
}
|
|
536
538
|
}
|
|
539
|
+
brandLinkedClass(QueryShapeSet, '@_linked/core', 'QueryShapeSet');
|
|
537
540
|
export class QueryShape extends QueryBuilderObject {
|
|
538
541
|
constructor(originalValue, property, subject) {
|
|
539
542
|
super(property, subject);
|
|
@@ -597,23 +600,23 @@ export class QueryShape extends QueryBuilderObject {
|
|
|
597
600
|
const self = toExpressionNode(this);
|
|
598
601
|
// An unresolved query-context reference (`getQueryContext('user')` before it
|
|
599
602
|
// is set) carries no `.id` yet — keep it as a `{@ctx}` ref, resolved at lower.
|
|
600
|
-
if (otherValue
|
|
603
|
+
if (isLinkedInstance(otherValue, PendingQueryContext)) {
|
|
601
604
|
return self.eq(otherValue);
|
|
602
605
|
}
|
|
603
606
|
//validate the value is formed correctly
|
|
604
607
|
if (!otherValue.id) {
|
|
605
608
|
throw Error(`Invalid value for .equals(). ${JSON.stringify(otherValue)}`);
|
|
606
609
|
}
|
|
607
|
-
const arg = otherValue
|
|
610
|
+
const arg = isLinkedInstance(otherValue, QueryBuilderObject)
|
|
608
611
|
? toExpressionNode(otherValue)
|
|
609
612
|
: otherValue;
|
|
610
613
|
return self.eq(arg);
|
|
611
614
|
}
|
|
612
615
|
oneOf(values) {
|
|
613
|
-
return toExpressionNode(this).oneOf(values.map((v) => (v
|
|
616
|
+
return toExpressionNode(this).oneOf(values.map((v) => (isLinkedInstance(v, QueryBuilderObject) ? toExpressionNode(v) : v)));
|
|
614
617
|
}
|
|
615
618
|
notOneOf(values) {
|
|
616
|
-
return toExpressionNode(this).notOneOf(values.map((v) => (v
|
|
619
|
+
return toExpressionNode(this).notOneOf(values.map((v) => (isLinkedInstance(v, QueryBuilderObject) ? toExpressionNode(v) : v)));
|
|
617
620
|
}
|
|
618
621
|
select(subQueryFn) {
|
|
619
622
|
// A sub-select on a project-authored value shape has no authored class, so fall
|
|
@@ -640,6 +643,7 @@ export class QueryShape extends QueryBuilderObject {
|
|
|
640
643
|
return this.select((shape) => propertyLabels.map((label) => shape[label]));
|
|
641
644
|
}
|
|
642
645
|
}
|
|
646
|
+
brandLinkedClass(QueryShape, '@_linked/core', 'QueryShape');
|
|
643
647
|
/**
|
|
644
648
|
* Concrete query wrapper for JS primitive values (string, number, boolean, Date).
|
|
645
649
|
*
|
|
@@ -656,16 +660,16 @@ export class QueryPrimitive extends QueryBuilderObject {
|
|
|
656
660
|
}
|
|
657
661
|
equals(otherValue) {
|
|
658
662
|
const self = toExpressionNode(this);
|
|
659
|
-
const arg = otherValue
|
|
663
|
+
const arg = isLinkedInstance(otherValue, QueryBuilderObject)
|
|
660
664
|
? toExpressionNode(otherValue)
|
|
661
665
|
: otherValue;
|
|
662
666
|
return self.eq(arg);
|
|
663
667
|
}
|
|
664
668
|
oneOf(values) {
|
|
665
|
-
return toExpressionNode(this).oneOf(values.map((v) => (v
|
|
669
|
+
return toExpressionNode(this).oneOf(values.map((v) => (isLinkedInstance(v, QueryBuilderObject) ? toExpressionNode(v) : v)));
|
|
666
670
|
}
|
|
667
671
|
notOneOf(values) {
|
|
668
|
-
return toExpressionNode(this).notOneOf(values.map((v) => (v
|
|
672
|
+
return toExpressionNode(this).notOneOf(values.map((v) => (isLinkedInstance(v, QueryBuilderObject) ? toExpressionNode(v) : v)));
|
|
669
673
|
}
|
|
670
674
|
where(validation) {
|
|
671
675
|
// For inline where on a primitive (p.hobby.where(h => h.equals(...))),
|
|
@@ -677,6 +681,7 @@ export class QueryPrimitive extends QueryBuilderObject {
|
|
|
677
681
|
return this;
|
|
678
682
|
}
|
|
679
683
|
}
|
|
684
|
+
brandLinkedClass(QueryPrimitive, '@_linked/core', 'QueryPrimitive');
|
|
680
685
|
export class QueryPrimitiveSet extends QueryBuilderObject {
|
|
681
686
|
constructor(originalValue, property, subject, items) {
|
|
682
687
|
super(property, subject);
|
|
@@ -730,6 +735,7 @@ export class QueryPrimitiveSet extends QueryBuilderObject {
|
|
|
730
735
|
//countable, resultKey
|
|
731
736
|
}
|
|
732
737
|
}
|
|
738
|
+
brandLinkedClass(QueryPrimitiveSet, '@_linked/core', 'QueryPrimitiveSet');
|
|
733
739
|
export class SetSize extends QueryPrimitive {
|
|
734
740
|
constructor(subject, countable, label) {
|
|
735
741
|
super();
|