@agentshouse/mdruntime 0.1.0-alpha.24 → 0.1.0-alpha.25
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/AGENTS.md +36 -0
- package/dist/change-set.d.ts +4 -11
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +8 -16
- package/dist/change-set.js.map +1 -1
- package/dist/client.d.ts +7 -3
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +2 -2
- package/dist/client.js.map +1 -1
- package/dist/collection.d.ts +0 -2
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +0 -5
- package/dist/collection.js.map +1 -1
- package/dist/connection.d.ts +7 -5
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +52 -68
- package/dist/connection.js.map +1 -1
- package/dist/conversation.d.ts +4 -4
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +12 -6
- package/dist/conversation.js.map +1 -1
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/paths.d.ts +1 -0
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +8 -0
- package/dist/paths.js.map +1 -1
- package/dist/query.d.ts +199 -10
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +450 -14
- package/dist/query.js.map +1 -1
- package/dist/read-side.d.ts +10 -0
- package/dist/read-side.d.ts.map +1 -0
- package/dist/read-side.js +374 -0
- package/dist/read-side.js.map +1 -0
- package/dist/rows.d.ts +39 -0
- package/dist/rows.d.ts.map +1 -0
- package/dist/rows.js +85 -0
- package/dist/rows.js.map +1 -0
- package/dist/wire.d.ts +1 -1
- package/dist/wire.js +1 -1
- package/dist/wire.js.map +1 -1
- package/package.json +2 -2
package/dist/query.d.ts
CHANGED
|
@@ -1,13 +1,202 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import type { Definition } from '@agentshouse/mdmodel';
|
|
2
|
+
export type Value = string | number | boolean | null;
|
|
3
|
+
export type Predicate = Value | {
|
|
4
|
+
$eq: Value;
|
|
5
|
+
} | {
|
|
6
|
+
$ne: Value;
|
|
7
|
+
} | {
|
|
8
|
+
$in: readonly Value[];
|
|
9
|
+
} | {
|
|
10
|
+
$nin: readonly Value[];
|
|
11
|
+
} | {
|
|
12
|
+
$gt?: Value;
|
|
13
|
+
$gte?: Value;
|
|
14
|
+
$lt?: Value;
|
|
15
|
+
$lte?: Value;
|
|
16
|
+
} | {
|
|
17
|
+
$all: readonly Value[];
|
|
18
|
+
} | {
|
|
19
|
+
$size: number;
|
|
20
|
+
} | {
|
|
21
|
+
$exists: boolean;
|
|
22
|
+
};
|
|
23
|
+
export type Where = {
|
|
24
|
+
$and?: readonly Where[];
|
|
25
|
+
$or?: readonly Where[];
|
|
26
|
+
[field: string]: Predicate | readonly Where[] | undefined;
|
|
27
|
+
};
|
|
28
|
+
export type Related = {
|
|
29
|
+
types?: readonly string[];
|
|
30
|
+
where?: Where;
|
|
31
|
+
pathPrefix?: string;
|
|
32
|
+
};
|
|
33
|
+
export type Filter = {
|
|
34
|
+
rooms?: readonly string[];
|
|
35
|
+
types?: readonly string[];
|
|
36
|
+
where?: Where;
|
|
37
|
+
pathPrefix?: string;
|
|
38
|
+
hop?: Related & {
|
|
39
|
+
field: string;
|
|
40
|
+
};
|
|
41
|
+
backlinks?: Related & {
|
|
42
|
+
field?: string;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
export type Key = 'room' | 'path' | 'type' | {
|
|
46
|
+
field: string;
|
|
47
|
+
};
|
|
48
|
+
export type Select = 'all' | {
|
|
49
|
+
fields?: 'all' | readonly string[];
|
|
50
|
+
sections?: 'all' | readonly string[];
|
|
51
|
+
preamble?: true;
|
|
52
|
+
markdown?: true;
|
|
53
|
+
backlinks?: true;
|
|
54
|
+
};
|
|
55
|
+
export type OrderOptions = {
|
|
56
|
+
nulls?: 'first' | 'last';
|
|
57
|
+
stringSort?: 'lexical' | 'locale';
|
|
58
|
+
locale?: string;
|
|
59
|
+
localeOptions?: Readonly<Record<string, unknown>>;
|
|
60
|
+
};
|
|
61
|
+
export type Direction = 'asc' | 'desc';
|
|
62
|
+
export type DocumentQuery = Filter & {
|
|
63
|
+
select: Select;
|
|
64
|
+
orderBy?: readonly ({
|
|
65
|
+
by: Key;
|
|
66
|
+
direction?: Direction;
|
|
67
|
+
} & OrderOptions)[];
|
|
68
|
+
limit?: number;
|
|
69
|
+
};
|
|
70
|
+
export type GroupQuery = Filter & {
|
|
71
|
+
groupBy: readonly Exclude<Key, 'path'>[];
|
|
72
|
+
orderBy?: readonly {
|
|
73
|
+
by: 'count' | Exclude<Key, 'path'>;
|
|
74
|
+
direction?: Direction;
|
|
75
|
+
}[];
|
|
76
|
+
limit?: number;
|
|
77
|
+
};
|
|
78
|
+
export type LocalQuery = DocumentQuery | GroupQuery;
|
|
79
|
+
export type Backlink = {
|
|
80
|
+
path: string;
|
|
81
|
+
type: string;
|
|
82
|
+
field: string;
|
|
83
|
+
};
|
|
84
|
+
export type QueryDocument = {
|
|
5
85
|
room: string;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
86
|
+
path: string;
|
|
87
|
+
type: string;
|
|
88
|
+
fields?: Readonly<Record<string, unknown>>;
|
|
89
|
+
sections?: Readonly<Record<string, string>>;
|
|
90
|
+
preamble?: string;
|
|
91
|
+
markdown?: string;
|
|
92
|
+
backlinks?: readonly Backlink[];
|
|
93
|
+
};
|
|
94
|
+
export type QueryGroup = {
|
|
95
|
+
key: readonly unknown[];
|
|
96
|
+
count: number;
|
|
97
|
+
};
|
|
98
|
+
export type DocumentResult = {
|
|
99
|
+
documents: readonly QueryDocument[];
|
|
100
|
+
};
|
|
101
|
+
export type GroupResult = {
|
|
102
|
+
groups: readonly QueryGroup[];
|
|
103
|
+
};
|
|
104
|
+
export type QueryResult = DocumentResult | GroupResult;
|
|
105
|
+
export type QueryErrorCode = 'invalid-query' | 'unknown-type' | 'unknown-field' | 'wrong-kind';
|
|
106
|
+
export type RoomFacts = {
|
|
107
|
+
locator: string;
|
|
108
|
+
available: boolean;
|
|
109
|
+
types: readonly Definition[];
|
|
110
|
+
};
|
|
111
|
+
export type HeldRooms = {
|
|
112
|
+
listed: boolean;
|
|
113
|
+
rooms: readonly RoomFacts[];
|
|
114
|
+
};
|
|
115
|
+
export type Test = {
|
|
116
|
+
op: 'eq';
|
|
117
|
+
value: Value;
|
|
118
|
+
} | {
|
|
119
|
+
op: 'ne';
|
|
120
|
+
value: Value;
|
|
121
|
+
} | {
|
|
122
|
+
op: 'in';
|
|
123
|
+
values: readonly Value[];
|
|
124
|
+
} | {
|
|
125
|
+
op: 'nin';
|
|
126
|
+
values: readonly Value[];
|
|
127
|
+
} | {
|
|
128
|
+
op: 'range';
|
|
129
|
+
bounds: readonly (readonly ['gt' | 'gte' | 'lt' | 'lte', Value])[];
|
|
130
|
+
} | {
|
|
131
|
+
op: 'all';
|
|
132
|
+
values: readonly Value[];
|
|
133
|
+
} | {
|
|
134
|
+
op: 'size';
|
|
135
|
+
size: number;
|
|
136
|
+
} | {
|
|
137
|
+
op: 'exists';
|
|
138
|
+
exists: boolean;
|
|
139
|
+
};
|
|
140
|
+
export type Condition = {
|
|
141
|
+
every: readonly Condition[];
|
|
142
|
+
} | {
|
|
143
|
+
some: readonly Condition[];
|
|
144
|
+
} | {
|
|
145
|
+
field: string;
|
|
146
|
+
test: Test;
|
|
147
|
+
};
|
|
148
|
+
export type Scope = {
|
|
149
|
+
types: readonly string[] | null;
|
|
150
|
+
where: Condition | null;
|
|
151
|
+
pathPrefix: string | null;
|
|
152
|
+
};
|
|
153
|
+
export type KeyPlan = {
|
|
154
|
+
of: 'room';
|
|
155
|
+
} | {
|
|
156
|
+
of: 'path';
|
|
157
|
+
} | {
|
|
158
|
+
of: 'type';
|
|
159
|
+
} | {
|
|
160
|
+
of: 'field';
|
|
161
|
+
field: string;
|
|
162
|
+
};
|
|
163
|
+
export type DocumentShape = {
|
|
164
|
+
kind: 'documents';
|
|
165
|
+
fields: 'all' | readonly string[] | null;
|
|
166
|
+
sections: 'all' | readonly string[] | null;
|
|
167
|
+
preamble: boolean;
|
|
168
|
+
markdown: boolean;
|
|
169
|
+
backlinks: boolean;
|
|
170
|
+
orderBy: readonly {
|
|
171
|
+
key: KeyPlan;
|
|
172
|
+
options: OrderOptions & {
|
|
173
|
+
direction: Direction;
|
|
174
|
+
};
|
|
175
|
+
}[];
|
|
176
|
+
};
|
|
177
|
+
export type GroupShape = {
|
|
178
|
+
kind: 'groups';
|
|
179
|
+
groupBy: readonly KeyPlan[];
|
|
180
|
+
orderBy: readonly {
|
|
181
|
+
by: 'count' | number;
|
|
182
|
+
direction: Direction;
|
|
183
|
+
}[];
|
|
184
|
+
};
|
|
185
|
+
export type Plan = {
|
|
186
|
+
rooms: readonly string[] | null;
|
|
187
|
+
root: Scope;
|
|
188
|
+
hop: (Scope & {
|
|
189
|
+
field: string;
|
|
190
|
+
}) | null;
|
|
191
|
+
backlinks: (Scope & {
|
|
192
|
+
field: string | null;
|
|
193
|
+
}) | null;
|
|
194
|
+
shape: DocumentShape | GroupShape;
|
|
195
|
+
limit: number | null;
|
|
10
196
|
};
|
|
11
|
-
export
|
|
12
|
-
|
|
197
|
+
export declare class QueryError extends Error {
|
|
198
|
+
constructor(code: QueryErrorCode, at: string, problem: string);
|
|
199
|
+
}
|
|
200
|
+
export declare function planOf(input: unknown, facts: HeldRooms): Plan;
|
|
201
|
+
export declare function identityOf(plan: Plan): string;
|
|
13
202
|
//# sourceMappingURL=query.d.ts.map
|
package/dist/query.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"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"}
|
package/dist/query.js
CHANGED
|
@@ -1,18 +1,454 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
import { normalize } from './paths.js';
|
|
2
|
+
export class QueryError extends Error {
|
|
3
|
+
constructor(code, at, problem){
|
|
4
|
+
super(`${code} at ${at}: ${problem}`);
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
const RANGE = [
|
|
8
|
+
'$gt',
|
|
9
|
+
'$gte',
|
|
10
|
+
'$lt',
|
|
11
|
+
'$lte'
|
|
12
|
+
];
|
|
13
|
+
const SINGLE = [
|
|
14
|
+
'$eq',
|
|
15
|
+
'$ne',
|
|
16
|
+
'$in',
|
|
17
|
+
'$nin',
|
|
18
|
+
'$all',
|
|
19
|
+
'$size',
|
|
20
|
+
'$exists'
|
|
21
|
+
];
|
|
22
|
+
const FILTER = [
|
|
23
|
+
'rooms',
|
|
24
|
+
'types',
|
|
25
|
+
'where',
|
|
26
|
+
'pathPrefix',
|
|
27
|
+
'hop',
|
|
28
|
+
'backlinks',
|
|
29
|
+
'orderBy',
|
|
30
|
+
'limit'
|
|
31
|
+
];
|
|
32
|
+
const RELATED = [
|
|
33
|
+
'types',
|
|
34
|
+
'where',
|
|
35
|
+
'pathPrefix',
|
|
36
|
+
'field'
|
|
37
|
+
];
|
|
38
|
+
const PARTS = [
|
|
39
|
+
'fields',
|
|
40
|
+
'sections',
|
|
41
|
+
'preamble',
|
|
42
|
+
'markdown',
|
|
43
|
+
'backlinks'
|
|
44
|
+
];
|
|
45
|
+
const ORDER = [
|
|
46
|
+
'by',
|
|
47
|
+
'direction',
|
|
48
|
+
'nulls',
|
|
49
|
+
'stringSort',
|
|
50
|
+
'locale',
|
|
51
|
+
'localeOptions'
|
|
52
|
+
];
|
|
53
|
+
const CALENDAR_DATE = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
54
|
+
function invalid(at, problem) {
|
|
55
|
+
throw new QueryError('invalid-query', at, problem);
|
|
56
|
+
}
|
|
57
|
+
function place(at, name) {
|
|
58
|
+
return at === '' ? name : `${at}.${name}`;
|
|
59
|
+
}
|
|
60
|
+
function plain(value) {
|
|
61
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
|
|
62
|
+
}
|
|
63
|
+
function known(value, allowed, at) {
|
|
64
|
+
for (const name of Object.keys(value)){
|
|
65
|
+
if (!allowed.includes(name)) invalid(place(at, name), 'unknown part');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function list(input, at) {
|
|
69
|
+
if (!Array.isArray(input)) invalid(at, 'expects a list');
|
|
70
|
+
return input;
|
|
71
|
+
}
|
|
72
|
+
function value(input, at) {
|
|
73
|
+
if (Array.isArray(input)) invalid(at, 'a list is not a value');
|
|
74
|
+
if (input !== null && typeof input !== 'string' && typeof input !== 'boolean' && !(typeof input === 'number' && Number.isFinite(input))) {
|
|
75
|
+
invalid(at, 'not a value');
|
|
76
|
+
}
|
|
77
|
+
return input;
|
|
78
|
+
}
|
|
79
|
+
function values(input, at) {
|
|
80
|
+
return list(input, at).map((item, index)=>value(item, `${at}[${index}]`));
|
|
81
|
+
}
|
|
82
|
+
function names(input, at) {
|
|
83
|
+
const listed = list(input, at);
|
|
84
|
+
if (listed.some((item)=>typeof item !== 'string')) invalid(at, 'expects a list of names');
|
|
85
|
+
return [
|
|
86
|
+
...new Set(listed)
|
|
87
|
+
].sort();
|
|
88
|
+
}
|
|
89
|
+
function directory(input, at) {
|
|
90
|
+
if (typeof input !== 'string' || normalize(input) !== input) {
|
|
91
|
+
invalid(at, 'expects a normalized directory');
|
|
92
|
+
}
|
|
93
|
+
return input;
|
|
94
|
+
}
|
|
95
|
+
function calendarDate(value) {
|
|
96
|
+
const match = CALENDAR_DATE.exec(value);
|
|
97
|
+
if (match === null) return false;
|
|
98
|
+
const [year, month, day] = match.slice(1).map(Number);
|
|
99
|
+
const date = new Date(Date.UTC(year, month - 1, day));
|
|
100
|
+
return date.getUTCFullYear() === year && date.getUTCMonth() === month - 1 && date.getUTCDate() === day;
|
|
101
|
+
}
|
|
102
|
+
function fits(spec, value) {
|
|
103
|
+
const item = spec.kind === 'list' ? spec.of : spec;
|
|
104
|
+
if (item.kind === 'number') return typeof value === 'number';
|
|
105
|
+
if (typeof value !== 'string') return false;
|
|
106
|
+
if (item.kind === 'enum') return item.values.includes(value);
|
|
107
|
+
if (item.kind === 'date') return calendarDate(value);
|
|
108
|
+
if (item.kind === 'reference') return value !== '' && normalize(value) === value;
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
function reference(spec) {
|
|
112
|
+
return spec.kind === 'reference' || spec.kind === 'list' && spec.of.kind === 'reference';
|
|
113
|
+
}
|
|
114
|
+
function typing(facts, rooms, types, at) {
|
|
115
|
+
const read = rooms === null ? facts.rooms : facts.rooms.filter((room)=>rooms.includes(room.locator));
|
|
116
|
+
const acquiring = !facts.listed && (rooms === null || rooms.some((locator)=>!facts.rooms.some((room)=>room.locator === locator)));
|
|
117
|
+
const available = !acquiring && read.every((room)=>room.available);
|
|
118
|
+
const declared = read.flatMap((room)=>room.types);
|
|
119
|
+
for (const name of types ?? []){
|
|
120
|
+
if (name === 'any' || !available || declared.some((type)=>type.name === name)) continue;
|
|
121
|
+
throw new QueryError('unknown-type', place(at, 'types'), `no model it reads declares ${name}`);
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
untyped: types === null || types.includes('any') || !available,
|
|
125
|
+
types: types === null ? declared : declared.filter((type)=>types.includes(type.name))
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
function specs(typed, field, at) {
|
|
129
|
+
const declared = typed.types.flatMap((type)=>Object.hasOwn(type.fields, field) ? [
|
|
130
|
+
type.fields[field]
|
|
131
|
+
] : []);
|
|
132
|
+
if (declared.length === 0 && !typed.untyped) {
|
|
133
|
+
throw new QueryError('unknown-field', at, `no MD Type it reads declares ${field}`);
|
|
134
|
+
}
|
|
135
|
+
return declared;
|
|
136
|
+
}
|
|
137
|
+
function kind(declared, checked, at) {
|
|
138
|
+
if (checked === null || declared.length === 0 || declared.some((spec)=>fits(spec, checked))) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
throw new QueryError('wrong-kind', at, `${JSON.stringify(checked)} is not of its field's kind`);
|
|
142
|
+
}
|
|
143
|
+
function listed(declared, list) {
|
|
144
|
+
return declared.length > 0 && declared.every((spec)=>spec.kind === 'list' === list);
|
|
145
|
+
}
|
|
146
|
+
function test(declared, input, at) {
|
|
147
|
+
if (!plain(input)) {
|
|
148
|
+
const equal = value(input, at);
|
|
149
|
+
kind(declared, equal, at);
|
|
150
|
+
return {
|
|
151
|
+
op: 'eq',
|
|
152
|
+
value: equal
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
const operators = Object.keys(input);
|
|
156
|
+
if (operators.length === 0) invalid(at, 'names no operator');
|
|
157
|
+
if (operators.some((operator)=>RANGE.includes(operator))) {
|
|
158
|
+
const stray = operators.find((operator)=>!RANGE.includes(operator));
|
|
159
|
+
if (stray !== undefined) invalid(place(at, stray), 'cannot join a range');
|
|
160
|
+
if (listed(declared, true)) invalid(at, 'a range on a list');
|
|
161
|
+
return {
|
|
162
|
+
op: 'range',
|
|
163
|
+
bounds: RANGE.filter((operator)=>operators.includes(operator)).map((operator)=>{
|
|
164
|
+
const bound = value(input[operator], place(at, operator));
|
|
165
|
+
if (bound === null) invalid(place(at, operator), 'a range bound is never null');
|
|
166
|
+
kind(declared, bound, place(at, operator));
|
|
167
|
+
return [
|
|
168
|
+
operator.slice(1),
|
|
169
|
+
bound
|
|
170
|
+
];
|
|
171
|
+
})
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
if (operators.length > 1) invalid(place(at, operators[1]), 'names a second operator');
|
|
175
|
+
const [operator] = operators;
|
|
176
|
+
const where = place(at, operator);
|
|
177
|
+
if (!SINGLE.includes(operator)) invalid(where, 'unknown operator');
|
|
178
|
+
const operand = input[operator];
|
|
179
|
+
if (operator === '$eq' || operator === '$ne') {
|
|
180
|
+
const compared = value(operand, where);
|
|
181
|
+
kind(declared, compared, where);
|
|
182
|
+
return operator === '$eq' ? {
|
|
183
|
+
op: 'eq',
|
|
184
|
+
value: compared
|
|
185
|
+
} : {
|
|
186
|
+
op: 'ne',
|
|
187
|
+
value: compared
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
if (operator === '$in' || operator === '$nin' || operator === '$all') {
|
|
191
|
+
const compared = values(operand, where);
|
|
192
|
+
compared.forEach((item, index)=>kind(declared, item, `${where}[${index}]`));
|
|
193
|
+
if (operator === '$in') return {
|
|
194
|
+
op: 'in',
|
|
195
|
+
values: compared
|
|
196
|
+
};
|
|
197
|
+
if (operator === '$nin') return {
|
|
198
|
+
op: 'nin',
|
|
199
|
+
values: compared
|
|
200
|
+
};
|
|
201
|
+
if (compared.includes(null)) invalid(where, 'a list holds no null');
|
|
202
|
+
if (listed(declared, false)) invalid(where, 'the field is not a list');
|
|
203
|
+
return {
|
|
204
|
+
op: 'all',
|
|
205
|
+
values: compared
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
if (operator === '$size') {
|
|
209
|
+
if (!Number.isSafeInteger(operand) || operand < 0) {
|
|
210
|
+
invalid(where, 'expects a nonnegative integer');
|
|
211
|
+
}
|
|
212
|
+
if (listed(declared, false)) invalid(where, 'the field is not a list');
|
|
213
|
+
return {
|
|
214
|
+
op: 'size',
|
|
215
|
+
size: operand
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
if (typeof operand !== 'boolean') invalid(where, 'expects true or false');
|
|
219
|
+
return {
|
|
220
|
+
op: 'exists',
|
|
221
|
+
exists: operand
|
|
15
222
|
};
|
|
16
223
|
}
|
|
224
|
+
function condition(typed, input, at) {
|
|
225
|
+
if (!plain(input)) invalid(at, 'expects an object of field predicates');
|
|
226
|
+
const conditions = [];
|
|
227
|
+
for (const name of Object.keys(input).sort()){
|
|
228
|
+
const where = place(at, name);
|
|
229
|
+
const entry = input[name];
|
|
230
|
+
if (name === '$and' || name === '$or') {
|
|
231
|
+
const nested = list(entry, where).map((item, index)=>condition(typed, item, `${where}[${index}]`));
|
|
232
|
+
if (nested.length === 0) invalid(where, 'expects a nonempty list');
|
|
233
|
+
conditions.push(name === '$and' ? {
|
|
234
|
+
every: nested
|
|
235
|
+
} : {
|
|
236
|
+
some: nested
|
|
237
|
+
});
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
if (name.startsWith('$')) invalid(where, 'unknown operator');
|
|
241
|
+
conditions.push({
|
|
242
|
+
field: name,
|
|
243
|
+
test: test(specs(typed, name, where), entry, where)
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
if (conditions.length === 0) invalid(at, 'names no field');
|
|
247
|
+
return conditions.length === 1 ? conditions[0] : {
|
|
248
|
+
every: conditions
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
function scope(facts, rooms, input, at) {
|
|
252
|
+
const types = input.types === undefined ? null : names(input.types, place(at, 'types'));
|
|
253
|
+
const typed = typing(facts, rooms, types, at);
|
|
254
|
+
return {
|
|
255
|
+
typed,
|
|
256
|
+
types,
|
|
257
|
+
where: input.where === undefined || plain(input.where) && Object.keys(input.where).length === 0 ? null : condition(typed, input.where, place(at, 'where')),
|
|
258
|
+
pathPrefix: input.pathPrefix === undefined ? null : directory(input.pathPrefix, place(at, 'pathPrefix'))
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
function referenceField(typed, field, at) {
|
|
262
|
+
if (typeof field !== 'string') invalid(at, 'expects a field name');
|
|
263
|
+
const declared = specs(typed, field, at);
|
|
264
|
+
if (declared.length > 0 && !declared.some(reference)) invalid(at, 'not a reference field');
|
|
265
|
+
return field;
|
|
266
|
+
}
|
|
267
|
+
function hopOf(facts, rooms, root, input) {
|
|
268
|
+
if (!plain(input)) invalid('hop', 'expects an object');
|
|
269
|
+
known(input, RELATED, 'hop');
|
|
270
|
+
const field = referenceField(root, input.field, 'hop.field');
|
|
271
|
+
const { types, where, pathPrefix } = scope(facts, rooms, input, 'hop');
|
|
272
|
+
return {
|
|
273
|
+
types,
|
|
274
|
+
where,
|
|
275
|
+
pathPrefix,
|
|
276
|
+
field
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
function backlinksOf(facts, rooms, input) {
|
|
280
|
+
if (!plain(input)) invalid('backlinks', 'expects an object');
|
|
281
|
+
known(input, RELATED, 'backlinks');
|
|
282
|
+
const { typed, types, where, pathPrefix } = scope(facts, rooms, input, 'backlinks');
|
|
283
|
+
const field = input.field === undefined ? null : referenceField(typed, input.field, 'backlinks.field');
|
|
284
|
+
return {
|
|
285
|
+
types,
|
|
286
|
+
where,
|
|
287
|
+
pathPrefix,
|
|
288
|
+
field
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
function keyPlan(typed, input, at, path) {
|
|
292
|
+
if (input === 'room' || input === 'type' || path && input === 'path') return {
|
|
293
|
+
of: input
|
|
294
|
+
};
|
|
295
|
+
if (plain(input) && typeof input.field === 'string' && Object.keys(input).length === 1) {
|
|
296
|
+
specs(typed, input.field, place(at, 'field'));
|
|
297
|
+
return {
|
|
298
|
+
of: 'field',
|
|
299
|
+
field: input.field
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
return invalid(at, path ? 'expects room, path, type or a field' : 'expects room, type or a field');
|
|
303
|
+
}
|
|
304
|
+
function direction(input, at) {
|
|
305
|
+
if (input === undefined) return 'asc';
|
|
306
|
+
if (input !== 'asc' && input !== 'desc') invalid(at, 'expects asc or desc');
|
|
307
|
+
return input;
|
|
308
|
+
}
|
|
309
|
+
function orderOptions(input, at) {
|
|
310
|
+
const options = {
|
|
311
|
+
direction: direction(input.direction, place(at, 'direction'))
|
|
312
|
+
};
|
|
313
|
+
if (input.nulls !== undefined) {
|
|
314
|
+
if (input.nulls !== 'first' && input.nulls !== 'last') {
|
|
315
|
+
invalid(place(at, 'nulls'), 'expects first or last');
|
|
316
|
+
}
|
|
317
|
+
options.nulls = input.nulls;
|
|
318
|
+
}
|
|
319
|
+
if (input.stringSort !== undefined) {
|
|
320
|
+
if (input.stringSort !== 'lexical' && input.stringSort !== 'locale') {
|
|
321
|
+
invalid(place(at, 'stringSort'), 'expects lexical or locale');
|
|
322
|
+
}
|
|
323
|
+
options.stringSort = input.stringSort;
|
|
324
|
+
}
|
|
325
|
+
if (input.locale !== undefined) {
|
|
326
|
+
if (typeof input.locale !== 'string' || !collates(input.locale, undefined)) {
|
|
327
|
+
invalid(place(at, 'locale'), 'expects a locale name');
|
|
328
|
+
}
|
|
329
|
+
options.locale = input.locale;
|
|
330
|
+
}
|
|
331
|
+
if (input.localeOptions !== undefined) {
|
|
332
|
+
if (!plain(input.localeOptions) || !collates(options.locale, input.localeOptions)) {
|
|
333
|
+
invalid(place(at, 'localeOptions'), 'expects collation options');
|
|
334
|
+
}
|
|
335
|
+
options.localeOptions = input.localeOptions;
|
|
336
|
+
}
|
|
337
|
+
return options;
|
|
338
|
+
}
|
|
339
|
+
function collates(locale, options) {
|
|
340
|
+
try {
|
|
341
|
+
''.localeCompare('', locale, options);
|
|
342
|
+
return true;
|
|
343
|
+
} catch {
|
|
344
|
+
return false;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
function parts(typed, input, at, fields) {
|
|
348
|
+
if (input === undefined) return null;
|
|
349
|
+
if (input === 'all') return 'all';
|
|
350
|
+
const named = list(input, at);
|
|
351
|
+
named.forEach((name, index)=>{
|
|
352
|
+
if (typeof name !== 'string') invalid(`${at}[${index}]`, 'expects a name');
|
|
353
|
+
if (fields) specs(typed, name, `${at}[${index}]`);
|
|
354
|
+
});
|
|
355
|
+
return named;
|
|
356
|
+
}
|
|
357
|
+
function flag(input, at) {
|
|
358
|
+
if (input === undefined) return false;
|
|
359
|
+
if (input !== true) invalid(at, 'expects true');
|
|
360
|
+
return true;
|
|
361
|
+
}
|
|
362
|
+
function documentShape(typed, input) {
|
|
363
|
+
const orderBy = (input.orderBy === undefined ? [] : list(input.orderBy, 'orderBy')).map((clause, index)=>{
|
|
364
|
+
const at = `orderBy[${index}]`;
|
|
365
|
+
if (!plain(clause)) invalid(at, 'expects an order clause');
|
|
366
|
+
known(clause, ORDER, at);
|
|
367
|
+
return {
|
|
368
|
+
key: keyPlan(typed, clause.by, place(at, 'by'), true),
|
|
369
|
+
options: orderOptions(clause, at)
|
|
370
|
+
};
|
|
371
|
+
});
|
|
372
|
+
const select = input.select;
|
|
373
|
+
if (select === 'all') {
|
|
374
|
+
return {
|
|
375
|
+
kind: 'documents',
|
|
376
|
+
fields: 'all',
|
|
377
|
+
sections: 'all',
|
|
378
|
+
preamble: true,
|
|
379
|
+
markdown: true,
|
|
380
|
+
backlinks: true,
|
|
381
|
+
orderBy
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
if (!plain(select)) invalid('select', "expects 'all' or the parts to return");
|
|
385
|
+
known(select, PARTS, 'select');
|
|
386
|
+
return {
|
|
387
|
+
kind: 'documents',
|
|
388
|
+
fields: parts(typed, select.fields, 'select.fields', true),
|
|
389
|
+
sections: parts(typed, select.sections, 'select.sections', false),
|
|
390
|
+
preamble: flag(select.preamble, 'select.preamble'),
|
|
391
|
+
markdown: flag(select.markdown, 'select.markdown'),
|
|
392
|
+
backlinks: flag(select.backlinks, 'select.backlinks'),
|
|
393
|
+
orderBy
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
function groupShape(typed, input) {
|
|
397
|
+
const groupBy = list(input.groupBy, 'groupBy').map((key, index)=>keyPlan(typed, key, `groupBy[${index}]`, false));
|
|
398
|
+
if (groupBy.length === 0) invalid('groupBy', 'names no key');
|
|
399
|
+
const grouped = groupBy.map((key)=>JSON.stringify(key));
|
|
400
|
+
const orderBy = (input.orderBy === undefined ? [] : list(input.orderBy, 'orderBy')).map((clause, index)=>{
|
|
401
|
+
const at = `orderBy[${index}]`;
|
|
402
|
+
if (!plain(clause)) invalid(at, 'expects an order clause');
|
|
403
|
+
known(clause, [
|
|
404
|
+
'by',
|
|
405
|
+
'direction'
|
|
406
|
+
], at);
|
|
407
|
+
const by = clause.by === 'count' ? 'count' : grouped.indexOf(JSON.stringify(keyPlan(typed, clause.by, place(at, 'by'), false)));
|
|
408
|
+
if (by === -1) invalid(place(at, 'by'), 'orders by a key the query does not group by');
|
|
409
|
+
return {
|
|
410
|
+
by,
|
|
411
|
+
direction: direction(clause.direction, place(at, 'direction'))
|
|
412
|
+
};
|
|
413
|
+
});
|
|
414
|
+
return {
|
|
415
|
+
kind: 'groups',
|
|
416
|
+
groupBy,
|
|
417
|
+
orderBy
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
export function planOf(input, facts) {
|
|
421
|
+
if (!plain(input)) invalid('query', 'expects a query object');
|
|
422
|
+
const grouped = input.groupBy !== undefined;
|
|
423
|
+
if (grouped && input.select !== undefined) invalid('select', 'a grouped query selects nothing');
|
|
424
|
+
if (!grouped && input.select === undefined) invalid('select', 'a Document query must select');
|
|
425
|
+
known(input, [
|
|
426
|
+
...FILTER,
|
|
427
|
+
grouped ? 'groupBy' : 'select'
|
|
428
|
+
], '');
|
|
429
|
+
if (input.limit !== undefined && (!Number.isSafeInteger(input.limit) || input.limit < 0)) {
|
|
430
|
+
invalid('limit', 'expects a nonnegative integer');
|
|
431
|
+
}
|
|
432
|
+
const rooms = input.rooms === undefined ? null : names(input.rooms, 'rooms');
|
|
433
|
+
const { typed, ...root } = scope(facts, rooms, input, '');
|
|
434
|
+
return {
|
|
435
|
+
rooms,
|
|
436
|
+
root,
|
|
437
|
+
hop: input.hop === undefined ? null : hopOf(facts, rooms, typed, input.hop),
|
|
438
|
+
backlinks: input.backlinks === undefined ? null : backlinksOf(facts, rooms, input.backlinks),
|
|
439
|
+
shape: grouped ? groupShape(typed, input) : documentShape(typed, input),
|
|
440
|
+
limit: input.limit ?? null
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
function canonical(value) {
|
|
444
|
+
if (Array.isArray(value)) return `[${value.map(canonical).join(',')}]`;
|
|
445
|
+
if (typeof value === 'object' && value !== null) {
|
|
446
|
+
return `{${Object.keys(value).sort().map((name)=>`${JSON.stringify(name)}:${canonical(value[name])}`).join(',')}}`;
|
|
447
|
+
}
|
|
448
|
+
return JSON.stringify(value);
|
|
449
|
+
}
|
|
450
|
+
export function identityOf(plan) {
|
|
451
|
+
return canonical(plan);
|
|
452
|
+
}
|
|
17
453
|
|
|
18
454
|
//# sourceMappingURL=query.js.map
|