@genesislcap/mock-server 15.51.1 → 15.53.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/README.md +408 -39
- package/dist/db/criteria.d.ts +13 -0
- package/dist/db/criteria.js +60 -21
- package/dist/db/identity.d.ts +11 -0
- package/dist/db/identity.js +46 -0
- package/dist/db/ordering.d.ts +8 -0
- package/dist/db/ordering.js +49 -0
- package/dist/db/schema.d.ts +62 -0
- package/dist/db/schema.js +490 -0
- package/dist/db/store.d.ts +20 -3
- package/dist/db/store.js +300 -50
- package/dist/handlers/commitEvent.js +47 -9
- package/dist/handlers/crudEvents.d.ts +2 -0
- package/dist/handlers/crudEvents.js +138 -0
- package/dist/handlers/dataLogon.js +105 -6
- package/dist/handlers/eventValidation.d.ts +5 -0
- package/dist/handlers/eventValidation.js +29 -0
- package/dist/handlers/jsonSchema.d.ts +4 -2
- package/dist/handlers/jsonSchema.js +222 -61
- package/dist/handlers/meta.d.ts +6 -1
- package/dist/handlers/meta.js +168 -21
- package/dist/handlers/requestReply.js +519 -30
- package/dist/handlers/resourceAuth.d.ts +1 -0
- package/dist/handlers/resourceAuth.js +14 -0
- package/dist/handlers/resources.js +3 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +2 -1
- package/dist/protocol/connection.d.ts +2 -0
- package/dist/protocol/errors.d.ts +100 -2
- package/dist/protocol/errors.js +300 -12
- package/dist/protocol/fieldTypes.d.ts +10 -0
- package/dist/protocol/fieldTypes.js +107 -0
- package/dist/protocol/gsfSchemas.d.ts +9 -0
- package/dist/protocol/gsfSchemas.js +423 -0
- package/dist/protocol/messageTypes.d.ts +1 -0
- package/dist/protocol/messageTypes.js +1 -0
- package/dist/protocol/msgNack.d.ts +2 -0
- package/dist/protocol/msgNack.js +10 -0
- package/dist/protocol/rowUpdate.d.ts +5 -3
- package/dist/protocol/rowUpdate.js +33 -15
- package/dist/protocol/schemaValidation.d.ts +11 -0
- package/dist/protocol/schemaValidation.js +186 -0
- package/dist/server.js +95 -29
- package/dist/types.d.ts +45 -0
- package/package.json +1 -1
- package/src/db/criteria.ts +72 -21
- package/src/db/identity.ts +53 -0
- package/src/db/ordering.ts +56 -0
- package/src/db/schema.ts +672 -0
- package/src/db/store.ts +343 -50
- package/src/handlers/commitEvent.ts +54 -10
- package/src/handlers/crudEvents.ts +181 -0
- package/src/handlers/dataLogon.ts +127 -7
- package/src/handlers/eventValidation.ts +43 -0
- package/src/handlers/jsonSchema.ts +302 -69
- package/src/handlers/meta.ts +227 -23
- package/src/handlers/requestReply.ts +626 -33
- package/src/handlers/resourceAuth.ts +18 -0
- package/src/handlers/resources.ts +3 -0
- package/src/index.ts +17 -1
- package/src/protocol/connection.ts +10 -2
- package/src/protocol/errors.ts +361 -13
- package/src/protocol/fieldTypes.ts +115 -0
- package/src/protocol/gsfSchemas.ts +505 -0
- package/src/protocol/messageTypes.ts +1 -0
- package/src/protocol/msgNack.ts +12 -0
- package/src/protocol/rowUpdate.ts +40 -20
- package/src/protocol/schemaValidation.ts +208 -0
- package/src/server.ts +106 -28
- package/src/types.ts +187 -5
package/dist/db/criteria.js
CHANGED
|
@@ -15,6 +15,17 @@
|
|
|
15
15
|
// Deliberately NOT eval()/new Function() — this parses a small typed grammar
|
|
16
16
|
// so a malformed or hostile criteria string can only fail to parse, never
|
|
17
17
|
// execute arbitrary JS.
|
|
18
|
+
// A criteria this grammar can't parse: unbalanced parentheses, a missing
|
|
19
|
+
// operand, text it can't tokenize. GSF fails to compile those too.
|
|
20
|
+
export class CriteriaSyntaxError extends Error {
|
|
21
|
+
name = 'CriteriaSyntaxError';
|
|
22
|
+
}
|
|
23
|
+
// A well-formed call to a function EXPR_FUNCTIONS doesn't have. It may well be
|
|
24
|
+
// valid Groovy, so callers that refuse malformed criteria still fail open on
|
|
25
|
+
// this one.
|
|
26
|
+
export class UnsupportedCriteriaError extends Error {
|
|
27
|
+
name = 'UnsupportedCriteriaError';
|
|
28
|
+
}
|
|
18
29
|
const TOKEN_RE = /\s*(&&|\|\||<=|>=|!=|<>|==|=|<|>|!|\(|\)|,|'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|-?\d+(?:\.\d+)?|[A-Za-z_][A-Za-z0-9_.]*)/g;
|
|
19
30
|
function tokenize(input) {
|
|
20
31
|
const tokens = [];
|
|
@@ -23,13 +34,13 @@ function tokenize(input) {
|
|
|
23
34
|
TOKEN_RE.lastIndex = 0;
|
|
24
35
|
while ((match = TOKEN_RE.exec(input))) {
|
|
25
36
|
if (match.index !== lastIndex) {
|
|
26
|
-
throw new
|
|
37
|
+
throw new CriteriaSyntaxError(`Unable to tokenize criteria near: ${input.slice(lastIndex)}`);
|
|
27
38
|
}
|
|
28
39
|
tokens.push(match[1]);
|
|
29
40
|
lastIndex = TOKEN_RE.lastIndex;
|
|
30
41
|
}
|
|
31
42
|
if (lastIndex !== input.length) {
|
|
32
|
-
throw new
|
|
43
|
+
throw new CriteriaSyntaxError(`Unable to tokenize criteria near: ${input.slice(lastIndex)}`);
|
|
33
44
|
}
|
|
34
45
|
return tokens;
|
|
35
46
|
}
|
|
@@ -53,7 +64,7 @@ const COMPARATORS = new Set(['==', '=', '!=', '<>', '<', '<=', '>', '>=']);
|
|
|
53
64
|
// them makes every Expr.dateTimeIs* comparison silently false (date-filtered
|
|
54
65
|
// grids render zero rows with no warning). Row values may already be epoch
|
|
55
66
|
// millis (number) or an ISO string. Returns null if unparseable.
|
|
56
|
-
function parseGenesisDateTime(value) {
|
|
67
|
+
export function parseGenesisDateTime(value) {
|
|
57
68
|
if (typeof value === 'number')
|
|
58
69
|
return value;
|
|
59
70
|
if (typeof value !== 'string')
|
|
@@ -154,6 +165,9 @@ function compareByTime(record, args, resolve, cmp) {
|
|
|
154
165
|
class Parser {
|
|
155
166
|
tokens;
|
|
156
167
|
pos = 0;
|
|
168
|
+
// Every field the expression reads: bare identifiers in comparisons, and
|
|
169
|
+
// function-call arguments and receivers.
|
|
170
|
+
fields = new Set();
|
|
157
171
|
constructor(tokens) {
|
|
158
172
|
this.tokens = tokens;
|
|
159
173
|
}
|
|
@@ -205,12 +219,12 @@ class Parser {
|
|
|
205
219
|
this.next();
|
|
206
220
|
const inner = this.parseExpression();
|
|
207
221
|
if (this.next() !== ')')
|
|
208
|
-
throw new
|
|
222
|
+
throw new CriteriaSyntaxError('Missing closing parenthesis in criteria');
|
|
209
223
|
return inner;
|
|
210
224
|
}
|
|
211
225
|
const leftToken = this.next();
|
|
212
226
|
if (leftToken === undefined) {
|
|
213
|
-
throw new
|
|
227
|
+
throw new CriteriaSyntaxError('Expected operand on the left side of comparison');
|
|
214
228
|
}
|
|
215
229
|
// Both function-call dialects arrive as one dotted token followed by '(':
|
|
216
230
|
// 'Expr.containsIgnoreCase' (foundation-criteria) or
|
|
@@ -220,13 +234,15 @@ class Parser {
|
|
|
220
234
|
}
|
|
221
235
|
const op = this.peek();
|
|
222
236
|
if (!op || !COMPARATORS.has(op)) {
|
|
223
|
-
throw new
|
|
237
|
+
throw new CriteriaSyntaxError(`Expected comparator, got: ${op}`);
|
|
224
238
|
}
|
|
225
239
|
this.next();
|
|
226
240
|
const rightToken = this.next();
|
|
227
241
|
if (rightToken === undefined) {
|
|
228
|
-
throw new
|
|
242
|
+
throw new CriteriaSyntaxError('Expected operand on the right side of comparison');
|
|
229
243
|
}
|
|
244
|
+
this.noteField(leftToken);
|
|
245
|
+
this.noteField(rightToken);
|
|
230
246
|
const resolveLeft = (record) => this.resolveValue(leftToken, record);
|
|
231
247
|
const resolveRight = (record) => this.resolveValue(rightToken, record);
|
|
232
248
|
return (record) => {
|
|
@@ -252,6 +268,10 @@ class Parser {
|
|
|
252
268
|
}
|
|
253
269
|
};
|
|
254
270
|
}
|
|
271
|
+
noteField(token) {
|
|
272
|
+
if (parseLiteral(token) === undefined)
|
|
273
|
+
this.fields.add(token);
|
|
274
|
+
}
|
|
255
275
|
resolveValue(token, record) {
|
|
256
276
|
const literal = parseLiteral(token);
|
|
257
277
|
if (literal !== undefined)
|
|
@@ -264,18 +284,18 @@ class Parser {
|
|
|
264
284
|
if (this.peek() !== ')') {
|
|
265
285
|
const arg = this.next();
|
|
266
286
|
if (arg === undefined)
|
|
267
|
-
throw new
|
|
287
|
+
throw new CriteriaSyntaxError(`Unterminated argument list in ${name}(...)`);
|
|
268
288
|
args.push(arg);
|
|
269
289
|
while (this.peek() === ',') {
|
|
270
290
|
this.next();
|
|
271
291
|
const nextArg = this.next();
|
|
272
292
|
if (nextArg === undefined)
|
|
273
|
-
throw new
|
|
293
|
+
throw new CriteriaSyntaxError(`Unterminated argument list in ${name}(...)`);
|
|
274
294
|
args.push(nextArg);
|
|
275
295
|
}
|
|
276
296
|
}
|
|
277
297
|
if (this.next() !== ')')
|
|
278
|
-
throw new
|
|
298
|
+
throw new CriteriaSyntaxError(`Missing closing parenthesis in ${name}(...)`);
|
|
279
299
|
// 'Expr.<fn>(field, value)' passes args through as-is; the method-call
|
|
280
300
|
// form '<FIELD>.<fn>(value)' makes the receiver field the implicit first
|
|
281
301
|
// argument, so both dialects share EXPR_FUNCTIONS.
|
|
@@ -284,36 +304,55 @@ class Parser {
|
|
|
284
304
|
const fnName = name.slice(dotIndex + 1);
|
|
285
305
|
const handler = EXPR_FUNCTIONS[fnName];
|
|
286
306
|
if (!handler)
|
|
287
|
-
throw new
|
|
307
|
+
throw new UnsupportedCriteriaError(`Unsupported criteria function: ${name}`);
|
|
288
308
|
const allArgs = receiver === 'Expr' ? args : [receiver, ...args];
|
|
309
|
+
for (const arg of allArgs)
|
|
310
|
+
this.noteField(arg);
|
|
289
311
|
const resolve = (token, record) => this.resolveValue(token, record);
|
|
290
312
|
return (record) => handler(record, allArgs, resolve);
|
|
291
313
|
}
|
|
292
314
|
}
|
|
293
|
-
|
|
294
|
-
|
|
315
|
+
// Parses a CRITERIA_MATCH without failing open: throws CriteriaSyntaxError for
|
|
316
|
+
// a malformed one and UnsupportedCriteriaError for a call to a function the
|
|
317
|
+
// grammar doesn't have. A blank criteria matches everything.
|
|
318
|
+
export function parseCriteria(criteria) {
|
|
295
319
|
if (!criteria || typeof criteria !== 'string' || criteria.trim() === '') {
|
|
296
|
-
return () => true;
|
|
320
|
+
return { predicate: () => true, fields: [] };
|
|
297
321
|
}
|
|
322
|
+
const tokens = tokenize(criteria.trim());
|
|
323
|
+
const parser = new Parser(tokens);
|
|
324
|
+
const predicate = parser.parseExpression();
|
|
325
|
+
if (parser.position !== tokens.length) {
|
|
326
|
+
throw new CriteriaSyntaxError(`Unexpected trailing tokens in criteria: ${criteria}`);
|
|
327
|
+
}
|
|
328
|
+
return { predicate, fields: [...parser.fields] };
|
|
329
|
+
}
|
|
330
|
+
/** Compiles a CRITERIA_MATCH string into a predicate function(record) => boolean. */
|
|
331
|
+
export function compileCriteria(criteria) {
|
|
298
332
|
// Real Genesis clients can emit CRITERIA_MATCH syntax this grammar doesn't
|
|
299
333
|
// cover yet (e.g. function-call criteria like Expr.dateTimeIsGreaterEqual(...)
|
|
300
334
|
// from date-range filters). Failing open — matching everything and logging —
|
|
301
335
|
// keeps DATA_LOGON/broadcast working (unfiltered) instead of crashing the
|
|
302
336
|
// handler and leaving the client's grid stuck on "Loading...".
|
|
303
337
|
try {
|
|
304
|
-
|
|
305
|
-
const parser = new Parser(tokens);
|
|
306
|
-
const predicate = parser.parseExpression();
|
|
307
|
-
if (parser.position !== tokens.length) {
|
|
308
|
-
throw new Error(`Unexpected trailing tokens in criteria: ${criteria}`);
|
|
309
|
-
}
|
|
310
|
-
return predicate;
|
|
338
|
+
return parseCriteria(criteria).predicate;
|
|
311
339
|
}
|
|
312
340
|
catch (error) {
|
|
313
341
|
console.warn(`[mock-server] Unsupported CRITERIA_MATCH syntax, ignoring filter: ${criteria}`, error);
|
|
314
342
|
return () => true;
|
|
315
343
|
}
|
|
316
344
|
}
|
|
345
|
+
// The fields a CRITERIA_MATCH reads, or undefined when it doesn't parse
|
|
346
|
+
// (compileCriteria then fails open). The real dataserver refuses a criteria
|
|
347
|
+
// naming a field its query doesn't expose (INVALID_CRITERIA).
|
|
348
|
+
export function criteriaFields(criteria) {
|
|
349
|
+
try {
|
|
350
|
+
return parseCriteria(criteria).fields;
|
|
351
|
+
}
|
|
352
|
+
catch {
|
|
353
|
+
return undefined;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
317
356
|
export function filterByCriteria(rows, criteria) {
|
|
318
357
|
const predicate = compileCriteria(criteria);
|
|
319
358
|
return rows.filter((row) => {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Row } from '../types.ts';
|
|
2
|
+
export declare const RECORD_ID = "RECORD_ID";
|
|
3
|
+
export declare const TIMESTAMP = "TIMESTAMP";
|
|
4
|
+
export declare const RECORD_FIELDS: readonly string[];
|
|
5
|
+
export declare class RecordClock {
|
|
6
|
+
private last;
|
|
7
|
+
next(): number;
|
|
8
|
+
observe(value: unknown): void;
|
|
9
|
+
}
|
|
10
|
+
export declare function withoutRecordFields(row: Row): Row;
|
|
11
|
+
export declare function recordKey(row: Row | undefined | null): string | undefined;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// Record identity: the RECORD_ID and TIMESTAMP every Genesis table row carries.
|
|
2
|
+
//
|
|
3
|
+
// GSF sets TIMESTAMP from a high-resolution clock on every write and
|
|
4
|
+
// RECORD_ID = TIMESTAMP on insert (genesis-db InsertOperation.kt); a modify
|
|
5
|
+
// moves TIMESTAMP on and keeps RECORD_ID. The real values are around 7.5e18:
|
|
6
|
+
// epoch millis shifted left 22 bits, plus a counter. That is far above 2^53,
|
|
7
|
+
// so a JavaScript client's JSON.parse rounds neighbouring rows onto the same
|
|
8
|
+
// number. The mock deliberately stays below that: its stamps are a counter
|
|
9
|
+
// seeded from epoch millis that only goes up, so they stay exact, strictly
|
|
10
|
+
// increasing safe integers, and a client that reads TIMESTAMP as a date (the
|
|
11
|
+
// AI assistant shows a NANO_TIMESTAMP as epoch millis) still gets roughly the
|
|
12
|
+
// write time. The same order, a different magnitude.
|
|
13
|
+
export const RECORD_ID = 'RECORD_ID';
|
|
14
|
+
export const TIMESTAMP = 'TIMESTAMP';
|
|
15
|
+
export const RECORD_FIELDS = [RECORD_ID, TIMESTAMP];
|
|
16
|
+
// Hands out RECORD_ID/TIMESTAMP values: the current epoch millis, or one more
|
|
17
|
+
// than the last value when that is not ahead of it (seeding a thousand rows
|
|
18
|
+
// runs the counter a second or so ahead of the clock).
|
|
19
|
+
export class RecordClock {
|
|
20
|
+
last = 0;
|
|
21
|
+
next() {
|
|
22
|
+
this.last = Math.max(Date.now(), this.last + 1);
|
|
23
|
+
return this.last;
|
|
24
|
+
}
|
|
25
|
+
// Keeps later stamps above a value a seed row brought with it.
|
|
26
|
+
observe(value) {
|
|
27
|
+
if (typeof value === 'number' && Number.isSafeInteger(value) && value > this.last) {
|
|
28
|
+
this.last = value;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// A row without its record identity — what a dataserver sends (the real
|
|
33
|
+
// dataserver never puts RECORD_ID or TIMESTAMP in a row, only
|
|
34
|
+
// DETAILS.ROW_REF) and what field metadata is derived from.
|
|
35
|
+
export function withoutRecordFields(row) {
|
|
36
|
+
if (!(RECORD_ID in row) && !(TIMESTAMP in row))
|
|
37
|
+
return row;
|
|
38
|
+
const { [RECORD_ID]: _recordId, [TIMESTAMP]: _timestamp, ...rest } = row;
|
|
39
|
+
return rest;
|
|
40
|
+
}
|
|
41
|
+
// The Map key a record is tracked under. RECORD_IDs are numbers here, but a
|
|
42
|
+
// seed may bring a recorded string, so they are compared as strings.
|
|
43
|
+
export function recordKey(row) {
|
|
44
|
+
const id = row?.[RECORD_ID];
|
|
45
|
+
return id === undefined || id === null ? undefined : String(id);
|
|
46
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Row } from '../types.ts';
|
|
2
|
+
export declare function compareValues(a: unknown, b: unknown): number;
|
|
3
|
+
export interface OrderedField {
|
|
4
|
+
field: string;
|
|
5
|
+
descending: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function rowComparator(fields: OrderedField[]): (a: Row, b: Row) => number;
|
|
8
|
+
export declare function parseOrderBy(orderBy: string): OrderedField[];
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// Row ordering shared by the dataserver (DATA_LOGON ORDER_BY, an index name)
|
|
2
|
+
// and request servers (REQ_ DETAILS.ORDER_BY, fields with a direction).
|
|
3
|
+
import { RECORD_ID } from "./identity.js";
|
|
4
|
+
// Nulls sort low (first ascending, last descending), as H2's default null
|
|
5
|
+
// ordering does; numbers numerically, booleans false before true, anything
|
|
6
|
+
// else by its string form (UTF-16 order, as Java's String.compareTo).
|
|
7
|
+
export function compareValues(a, b) {
|
|
8
|
+
if (a === b)
|
|
9
|
+
return 0;
|
|
10
|
+
if (a === undefined || a === null)
|
|
11
|
+
return -1;
|
|
12
|
+
if (b === undefined || b === null)
|
|
13
|
+
return 1;
|
|
14
|
+
if (typeof a === 'number' && typeof b === 'number')
|
|
15
|
+
return a - b;
|
|
16
|
+
if (typeof a === 'boolean' && typeof b === 'boolean')
|
|
17
|
+
return a ? 1 : -1;
|
|
18
|
+
const [left, right] = [String(a), String(b)];
|
|
19
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
20
|
+
}
|
|
21
|
+
// Sorts by the fields in turn, then by RECORD_ID ascending: the tie-breaker
|
|
22
|
+
// column GSF's SQL ordering always appends (GetByCriteriaOperation.kt,
|
|
23
|
+
// tieBreakerColumn = "RECORD_ID", v8.15.29), whatever the direction.
|
|
24
|
+
export function rowComparator(fields) {
|
|
25
|
+
return (a, b) => {
|
|
26
|
+
for (const { field, descending } of fields) {
|
|
27
|
+
const result = compareValues(a[field], b[field]);
|
|
28
|
+
if (result !== 0)
|
|
29
|
+
return descending ? -result : result;
|
|
30
|
+
}
|
|
31
|
+
return compareValues(a[RECORD_ID], b[RECORD_ID]);
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
const ORDER_SEPARATOR = /\s*,\s*/;
|
|
35
|
+
const ORDER_FIELD = /^([A-Za-z]\w+)(?:\s+(ASC|DESC))?$/i;
|
|
36
|
+
// DETAILS.ORDER_BY as a request server reads it (OrderSpec.kt OrderedString,
|
|
37
|
+
// GSF v8.15.29): comma-separated fields, each with an optional ASC or DESC in
|
|
38
|
+
// any case. Throws GSF's IllegalArgumentException text for anything else,
|
|
39
|
+
// which the request server answers as REQUEST_FAILED.
|
|
40
|
+
export function parseOrderBy(orderBy) {
|
|
41
|
+
return orderBy.split(ORDER_SEPARATOR).map((part) => {
|
|
42
|
+
const match = ORDER_FIELD.exec(part);
|
|
43
|
+
if (!match) {
|
|
44
|
+
throw new Error(`${orderBy} is not a valid ORDER string, Fields should be comma separated, with followed ` +
|
|
45
|
+
"by an optional ASC or DESC. E.g. 'TRADER, TRADE_DATE DESC'");
|
|
46
|
+
}
|
|
47
|
+
return { field: match[1], descending: match[2]?.toUpperCase() === 'DESC' };
|
|
48
|
+
});
|
|
49
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { CrudEventVerb, FieldDef, IndexDef, MockServerConfig, QueryDef, RequestReplyDef, Row, TableDef } from '../types.ts';
|
|
2
|
+
import type { Store } from './store.ts';
|
|
3
|
+
export interface ResolvedField {
|
|
4
|
+
name: string;
|
|
5
|
+
type: string;
|
|
6
|
+
nullable: boolean;
|
|
7
|
+
generated: boolean;
|
|
8
|
+
values?: string[];
|
|
9
|
+
default?: unknown;
|
|
10
|
+
maxSize?: number;
|
|
11
|
+
minLength?: number;
|
|
12
|
+
description?: string;
|
|
13
|
+
title?: string;
|
|
14
|
+
optional?: boolean;
|
|
15
|
+
table?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface ResolvedSchema {
|
|
18
|
+
fields: ResolvedField[];
|
|
19
|
+
declared: boolean;
|
|
20
|
+
}
|
|
21
|
+
export declare function pkFieldsOf(def: TableDef): string[];
|
|
22
|
+
export declare function generatedFieldsOf(def: TableDef): Set<string>;
|
|
23
|
+
export declare function generatedFieldList(def: TableDef): string[];
|
|
24
|
+
export declare function isDeclared(source: string, config: MockServerConfig, store: Store): boolean;
|
|
25
|
+
export declare function resolveSourceSchema(source: string, config: MockServerConfig, store: Store): ResolvedSchema;
|
|
26
|
+
export declare function withTypeOverrides(schema: ResolvedSchema, fieldTypes: Record<string, string> | undefined): ResolvedSchema;
|
|
27
|
+
export declare function projectSchema(schema: ResolvedSchema, names: string[] | undefined): ResolvedSchema;
|
|
28
|
+
export declare function querySchema(query: QueryDef, config: MockServerConfig, store: Store): ResolvedSchema;
|
|
29
|
+
export declare function requestReplySchema(requestReply: RequestReplyDef, config: MockServerConfig, store: Store): ResolvedSchema;
|
|
30
|
+
export declare const RECORD_IDENTITY_FIELDS: ResolvedField[];
|
|
31
|
+
export declare function requestReplySourceSchema(requestReply: RequestReplyDef, config: MockServerConfig, store: Store): ResolvedSchema;
|
|
32
|
+
export declare function requestReplyReplySchema(requestReply: RequestReplyDef, config: MockServerConfig, store: Store): ResolvedSchema;
|
|
33
|
+
export declare function requestReplyFieldNames(requestReply: RequestReplyDef, config: MockServerConfig, store: Store): string[] | undefined;
|
|
34
|
+
export declare function requestFieldsOf(requestReply: RequestReplyDef, store: Store): string[];
|
|
35
|
+
export declare function knownValues(field: ResolvedField): string[] | undefined;
|
|
36
|
+
export declare function eventDefaultOf(field: ResolvedField): unknown;
|
|
37
|
+
export declare function queryFieldNames(query: QueryDef | undefined, config: MockServerConfig, store: Store): string[] | undefined;
|
|
38
|
+
export declare function projectRow(row: Row, names: string[] | undefined): Row;
|
|
39
|
+
export declare function defaultIndexName(table: string, fields: string[]): string;
|
|
40
|
+
export declare function primaryKeyIndexName(table: string, def: TableDef): string;
|
|
41
|
+
export declare function secondaryUniqueIndexes(def: TableDef): IndexDef[];
|
|
42
|
+
export declare const CRUD_EVENT_VERBS: readonly CrudEventVerb[];
|
|
43
|
+
export declare function crudEventName(table: string, verb: CrudEventVerb): string;
|
|
44
|
+
export declare function crudEventOf(name: string | undefined, config: MockServerConfig): {
|
|
45
|
+
table: string;
|
|
46
|
+
verb: CrudEventVerb;
|
|
47
|
+
} | undefined;
|
|
48
|
+
export declare function crudEventNames(config: MockServerConfig): string[];
|
|
49
|
+
export declare function isDeleteEventName(name: string): boolean;
|
|
50
|
+
export declare function inferEventTable(eventName: string | undefined, tableNames: string[]): string | undefined;
|
|
51
|
+
export interface EventTarget {
|
|
52
|
+
kind: 'table' | 'byId' | 'dto';
|
|
53
|
+
table?: string;
|
|
54
|
+
className: string;
|
|
55
|
+
title?: string;
|
|
56
|
+
fieldTypes?: Record<string, string>;
|
|
57
|
+
fields?: FieldDef[];
|
|
58
|
+
}
|
|
59
|
+
export declare function resolveEventTarget(name: string | undefined, config: MockServerConfig, { bareTable }?: {
|
|
60
|
+
bareTable?: boolean;
|
|
61
|
+
}): EventTarget | undefined;
|
|
62
|
+
export declare function eventFields(target: EventTarget, config: MockServerConfig, store: Store): ResolvedField[];
|