@suss/recognize 0.33.1 → 0.34.1
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 +7 -7
- package/dist/ast.d.cts +9 -9
- package/dist/ast.d.ts +9 -9
- package/dist/{chain-CVG6Jnr-.d.cts → chain-DYU9ZdzF.d.cts} +105 -106
- package/dist/{chain-CVG6Jnr-.d.ts → chain-DYU9ZdzF.d.ts} +105 -106
- package/dist/index.cjs +235 -60
- package/dist/index.d.cts +67 -69
- package/dist/index.d.ts +67 -69
- package/dist/index.js +235 -60
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -63,6 +63,7 @@ function opsIn(ctx) {
|
|
|
63
63
|
// src/compile.ts
|
|
64
64
|
var MAX_RECEIVER_HOPS = 8;
|
|
65
65
|
function compile(chain, recognition) {
|
|
66
|
+
const receiverMethods = methodsWhoseReceiversAreAsked(chain);
|
|
66
67
|
return (_call, ctx) => {
|
|
67
68
|
const ops = opsIn(ctx);
|
|
68
69
|
if (ops === null) {
|
|
@@ -83,6 +84,9 @@ function compile(chain, recognition) {
|
|
|
83
84
|
if (methods === null) {
|
|
84
85
|
return null;
|
|
85
86
|
}
|
|
87
|
+
if (receiverMethods !== null) {
|
|
88
|
+
ops.readingReceivers?.(receiverMethods);
|
|
89
|
+
}
|
|
86
90
|
for (const subject of subjectsOf(chain, ops)) {
|
|
87
91
|
const method = operationOf(subject);
|
|
88
92
|
const meaning = method === null ? null : listed(methods, method);
|
|
@@ -101,6 +105,14 @@ function compile(chain, recognition) {
|
|
|
101
105
|
return null;
|
|
102
106
|
};
|
|
103
107
|
}
|
|
108
|
+
function methodsWhoseReceiversAreAsked(chain) {
|
|
109
|
+
const start = linkIn(chain, "start");
|
|
110
|
+
const table = methodsIn(chain);
|
|
111
|
+
if (start === null || start.at.starts !== "receiver" || start.at.origin.origin !== "constructed" || linkIn(chain, "subject") !== null || table === null || table.ignoringCase) {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
return new Set(Object.keys(table.table));
|
|
115
|
+
}
|
|
104
116
|
function linkIn(chain, asks) {
|
|
105
117
|
const link = chain.links.find((candidate) => candidate.asks === asks);
|
|
106
118
|
return link ?? null;
|
|
@@ -134,7 +146,23 @@ function listed(link, method) {
|
|
|
134
146
|
}
|
|
135
147
|
function subjectsOf(chain, ops) {
|
|
136
148
|
const link = linkIn(chain, "subject");
|
|
137
|
-
|
|
149
|
+
if (link === null) {
|
|
150
|
+
return [ops];
|
|
151
|
+
}
|
|
152
|
+
announceArgumentReads(link.of, ops);
|
|
153
|
+
return walk([ops], link.of);
|
|
154
|
+
}
|
|
155
|
+
function announceArgumentReads(steps, ops) {
|
|
156
|
+
const first = steps[0];
|
|
157
|
+
if (first === void 0 || first.to !== "argument") {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
const at = first.at;
|
|
161
|
+
if (typeof at === "number") {
|
|
162
|
+
ops.readingArguments?.(at, at);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
ops.readingArguments?.(at.from);
|
|
138
166
|
}
|
|
139
167
|
var STEP = {
|
|
140
168
|
receiver: (step, ops) => receiversOf(ops, step.method),
|
|
@@ -216,9 +244,24 @@ function accessEffect(matched, access) {
|
|
|
216
244
|
const ending = chain.ending;
|
|
217
245
|
const { input, kind, reached, unsettled } = access;
|
|
218
246
|
const stated = { input, entry: reached.entry, kind };
|
|
219
|
-
const
|
|
220
|
-
const
|
|
221
|
-
|
|
247
|
+
const listening = ops.statesSlots !== void 0;
|
|
248
|
+
const selectorRead = listening ? /* @__PURE__ */ new Map() : null;
|
|
249
|
+
const fieldsRead = listening ? /* @__PURE__ */ new Map() : null;
|
|
250
|
+
const selector = namesFor(
|
|
251
|
+
meaning.selector,
|
|
252
|
+
subject,
|
|
253
|
+
stated,
|
|
254
|
+
unsettled,
|
|
255
|
+
selectorRead
|
|
256
|
+
);
|
|
257
|
+
const fields = namesFor(
|
|
258
|
+
meaning.fields,
|
|
259
|
+
subject,
|
|
260
|
+
stated,
|
|
261
|
+
unsettled,
|
|
262
|
+
fieldsRead
|
|
263
|
+
);
|
|
264
|
+
const effect = {
|
|
222
265
|
type: "interaction",
|
|
223
266
|
binding: (0, import_behavioral_ir.storageBinding)({
|
|
224
267
|
recognition,
|
|
@@ -237,6 +280,69 @@ function accessEffect(matched, access) {
|
|
|
237
280
|
...selector.length > 0 ? { selector } : {}
|
|
238
281
|
}
|
|
239
282
|
};
|
|
283
|
+
const slots = [
|
|
284
|
+
...slotsRead("selector", selector, selectorRead),
|
|
285
|
+
...slotsRead("field", fields, fieldsRead)
|
|
286
|
+
];
|
|
287
|
+
if (slots.length > 0) {
|
|
288
|
+
ops.statesSlots?.(effect, slots);
|
|
289
|
+
}
|
|
290
|
+
return effect;
|
|
291
|
+
}
|
|
292
|
+
function slotsRead(slot, names, read) {
|
|
293
|
+
if (read === null) {
|
|
294
|
+
return [];
|
|
295
|
+
}
|
|
296
|
+
return [...new Set(names)].flatMap(
|
|
297
|
+
(name) => (read.get(name) ?? []).map((value) => ({ slot, name, value }))
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
function noteRead(read, name, value) {
|
|
301
|
+
const already = read.get(name);
|
|
302
|
+
if (already === void 0) {
|
|
303
|
+
read.set(name, [value]);
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
if (!already.includes(value)) {
|
|
307
|
+
already.push(value);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
function recording(value, read) {
|
|
311
|
+
return {
|
|
312
|
+
text: () => value.text(),
|
|
313
|
+
name: (unsettled) => value.name(unsettled),
|
|
314
|
+
...value.names === void 0 ? {} : { names: (cap) => value.names?.(cap) ?? null },
|
|
315
|
+
flag: () => value.flag(),
|
|
316
|
+
entries: (unsettled) => value.entries(unsettled).map((entry) => {
|
|
317
|
+
if (entry.key !== null) {
|
|
318
|
+
noteRead(read, entry.key, entry.value);
|
|
319
|
+
}
|
|
320
|
+
return { key: entry.key, value: recording(entry.value, read) };
|
|
321
|
+
}),
|
|
322
|
+
items: () => value.items().map((item) => recording(item, read)),
|
|
323
|
+
property: (name) => {
|
|
324
|
+
const inside = value.property(name);
|
|
325
|
+
if (inside === null) {
|
|
326
|
+
return null;
|
|
327
|
+
}
|
|
328
|
+
noteRead(read, name, inside);
|
|
329
|
+
return recording(inside, read);
|
|
330
|
+
},
|
|
331
|
+
asArg: () => value.asArg(),
|
|
332
|
+
parts: () => value.parts(),
|
|
333
|
+
holes: () => value.holes(),
|
|
334
|
+
...value.interpolated === void 0 ? {} : { interpolated: () => value.interpolated?.() ?? [] }
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
function watched(inputs, read) {
|
|
338
|
+
if (read === null) {
|
|
339
|
+
return inputs;
|
|
340
|
+
}
|
|
341
|
+
return {
|
|
342
|
+
...inputs,
|
|
343
|
+
input: recording(inputs.input, read),
|
|
344
|
+
entry: inputs.entry === null ? null : recording(inputs.entry, read)
|
|
345
|
+
};
|
|
240
346
|
}
|
|
241
347
|
function reachedBy(chain, subject, unsettled) {
|
|
242
348
|
const link = linkIn(chain, "containers");
|
|
@@ -315,7 +421,7 @@ var NOTHING_STATED = {
|
|
|
315
421
|
parts: () => null,
|
|
316
422
|
holes: () => []
|
|
317
423
|
};
|
|
318
|
-
function namesFor(says, subject, stated, unsettled) {
|
|
424
|
+
function namesFor(says, subject, stated, unsettled, read = null) {
|
|
319
425
|
if (says === void 0) {
|
|
320
426
|
return [];
|
|
321
427
|
}
|
|
@@ -324,7 +430,7 @@ function namesFor(says, subject, stated, unsettled) {
|
|
|
324
430
|
}
|
|
325
431
|
if (typeof says === "function") {
|
|
326
432
|
const input2 = stated.input;
|
|
327
|
-
return input2 === null ? [] : [...says({ ...stated, input: input2 })];
|
|
433
|
+
return input2 === null ? [] : [...says(watched({ ...stated, input: input2 }, read))];
|
|
328
434
|
}
|
|
329
435
|
if ("selectorParam" in says) {
|
|
330
436
|
return [...subject.parameterReadsAt?.(says.selectorParam) ?? []];
|
|
@@ -334,7 +440,7 @@ function namesFor(says, subject, stated, unsettled) {
|
|
|
334
440
|
return namesAt(subject, pointed, unsettled);
|
|
335
441
|
}
|
|
336
442
|
const input = statedValue(subject, pointed.of) ?? NOTHING_STATED;
|
|
337
|
-
return [...pointed.by({ ...stated, input })];
|
|
443
|
+
return [...pointed.by(watched({ ...stated, input }, read))];
|
|
338
444
|
}
|
|
339
445
|
function namesAt(subject, pick, unsettled) {
|
|
340
446
|
if (pick === void 0) {
|
|
@@ -375,20 +481,27 @@ function messageSend(matched) {
|
|
|
375
481
|
}
|
|
376
482
|
const messages = messagesIn(input, ending.messages);
|
|
377
483
|
const sent = messages.length === 0 ? [NOTHING_STATED] : messages;
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
484
|
+
const effects = [];
|
|
485
|
+
for (const message of sent) {
|
|
486
|
+
const channels = channelsOf({ message, input, ending });
|
|
487
|
+
for (const channel of channels) {
|
|
488
|
+
effects.push({
|
|
489
|
+
type: "interaction",
|
|
490
|
+
binding: (0, import_behavioral_ir.messageBusBinding)({
|
|
491
|
+
recognition,
|
|
492
|
+
messageBus: ending.wire,
|
|
493
|
+
channel
|
|
494
|
+
}),
|
|
495
|
+
callee: ops.calleeText(),
|
|
496
|
+
interaction: {
|
|
497
|
+
class: "message-send",
|
|
498
|
+
...bodyOf(message, ending),
|
|
499
|
+
...routingKeyOf(message, ending)
|
|
500
|
+
}
|
|
501
|
+
});
|
|
390
502
|
}
|
|
391
|
-
}
|
|
503
|
+
}
|
|
504
|
+
return effects;
|
|
392
505
|
}
|
|
393
506
|
function messagesIn(input, location) {
|
|
394
507
|
if (location.each === "theInput") {
|
|
@@ -397,25 +510,47 @@ function messagesIn(input, location) {
|
|
|
397
510
|
const collection = input.property(location.property);
|
|
398
511
|
return collection === null ? [] : collection.items();
|
|
399
512
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
513
|
+
var CHANNEL_CAP = 16;
|
|
514
|
+
function oneName(written, unsettled) {
|
|
515
|
+
const stated = written.name(unsettled);
|
|
516
|
+
return stated === null || stated === "" ? null : [stated];
|
|
517
|
+
}
|
|
518
|
+
function everyString(written, unsettled) {
|
|
519
|
+
const each = written.names?.(CHANNEL_CAP) ?? null;
|
|
520
|
+
if (each === null || each.length < 2 || each.includes("")) {
|
|
521
|
+
return oneName(written, unsettled);
|
|
522
|
+
}
|
|
523
|
+
return each;
|
|
524
|
+
}
|
|
525
|
+
function channelsOf(sending) {
|
|
526
|
+
const each = channelsRead(sending, "everyString");
|
|
527
|
+
return each.length > CHANNEL_CAP ? channelsRead(sending, "oneName") : each;
|
|
528
|
+
}
|
|
529
|
+
function channelsRead(sending, read) {
|
|
530
|
+
const separator = sending.ending.channelSeparator ?? "#";
|
|
531
|
+
let channels = null;
|
|
532
|
+
for (const part of sending.ending.channel) {
|
|
533
|
+
const values = partValues(part, sending, read);
|
|
534
|
+
if (values === null) {
|
|
535
|
+
return [null];
|
|
415
536
|
}
|
|
416
|
-
|
|
537
|
+
channels = channels === null ? values : crossed(channels, values, separator);
|
|
417
538
|
}
|
|
418
|
-
return
|
|
539
|
+
return channels ?? [""];
|
|
540
|
+
}
|
|
541
|
+
function crossed(heads, values, separator) {
|
|
542
|
+
return heads.flatMap(
|
|
543
|
+
(head) => values.map((value) => `${head}${separator}${value}`)
|
|
544
|
+
);
|
|
545
|
+
}
|
|
546
|
+
function partValues(part, sending, read) {
|
|
547
|
+
const holder = part.on === "theInput" ? sending.input : sending.message;
|
|
548
|
+
const written = firstWritten(holder, part.property);
|
|
549
|
+
if (written === null) {
|
|
550
|
+
return part.whenAbsent === void 0 ? null : [part.whenAbsent];
|
|
551
|
+
}
|
|
552
|
+
const unsettled = part.unsettled ?? sending.ending.unsettledName;
|
|
553
|
+
return read === "everyString" ? everyString(written, unsettled) : oneName(written, unsettled);
|
|
419
554
|
}
|
|
420
555
|
function firstWritten(holder, properties) {
|
|
421
556
|
for (const property of properties) {
|
|
@@ -498,28 +633,68 @@ function sqlAccess(matched) {
|
|
|
498
633
|
namesInHoles(chain, stated.value),
|
|
499
634
|
settledHoles(stated.value)
|
|
500
635
|
);
|
|
501
|
-
const accesses = (0, import_sql.readSqlAccess)(statement, {
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
636
|
+
const accesses = (0, import_sql.readSqlAccess)(statement, {
|
|
637
|
+
dialect: ending.dialect,
|
|
638
|
+
placeholders: ops.statesSlots !== void 0
|
|
639
|
+
});
|
|
640
|
+
if (accesses.length === 0) {
|
|
641
|
+
return null;
|
|
642
|
+
}
|
|
643
|
+
const values = placeholderValues(
|
|
644
|
+
stated,
|
|
645
|
+
subject,
|
|
646
|
+
matched.meaning.parameters
|
|
647
|
+
);
|
|
648
|
+
return accesses.map((access) => {
|
|
649
|
+
const effect = {
|
|
650
|
+
type: "interaction",
|
|
651
|
+
binding: (0, import_behavioral_ir.storageBinding)({
|
|
652
|
+
recognition,
|
|
653
|
+
storageSystem: ending.system,
|
|
654
|
+
...ending.transport === void 0 ? {} : { transport: ending.transport },
|
|
655
|
+
// A statement that qualifies its table says which namespace
|
|
656
|
+
// the access is in, and the pack's own scope is the fallback
|
|
657
|
+
// for a statement that leaves it out.
|
|
658
|
+
scope: access.qualifier[access.qualifier.length - 1] ?? ending.scope,
|
|
659
|
+
container: access.table
|
|
660
|
+
}),
|
|
661
|
+
callee: ops.calleeText(),
|
|
662
|
+
interaction: {
|
|
663
|
+
class: "storage-access",
|
|
664
|
+
kind: access.kind,
|
|
665
|
+
fields: access.fields,
|
|
666
|
+
...access.selector.length > 0 ? { selector: access.selector } : {},
|
|
667
|
+
operation: method
|
|
668
|
+
}
|
|
669
|
+
};
|
|
670
|
+
const slots = (access.placeholders ?? []).flatMap((one) => {
|
|
671
|
+
const value = placeholderValue(values, one.placeholder);
|
|
672
|
+
return value === null ? [] : [{ slot: SLOT_OF[one.clause], name: one.field, value }];
|
|
673
|
+
});
|
|
674
|
+
if (slots.length > 0) {
|
|
675
|
+
ops.statesSlots?.(effect, slots);
|
|
521
676
|
}
|
|
522
|
-
|
|
677
|
+
return effect;
|
|
678
|
+
});
|
|
679
|
+
}
|
|
680
|
+
var SLOT_OF = {
|
|
681
|
+
fields: "field",
|
|
682
|
+
selector: "selector"
|
|
683
|
+
};
|
|
684
|
+
function placeholderValues(stated, subject, says) {
|
|
685
|
+
const writesItsOwn = stated.parts.some((part) => /\$\d/.test(part));
|
|
686
|
+
if (stated.parts.length > 1 && !writesItsOwn) {
|
|
687
|
+
return { numbered: stated.value.interpolated?.() ?? [], named: null };
|
|
688
|
+
}
|
|
689
|
+
const picks = says === void 0 ? [] : Array.isArray(says) ? says : [says];
|
|
690
|
+
const given = picks.map((pick) => statedValue(subject, pick)).find((value) => value !== null);
|
|
691
|
+
return given === void 0 ? { numbered: [], named: null } : { numbered: given.items(), named: given };
|
|
692
|
+
}
|
|
693
|
+
function placeholderValue(values, placeholder) {
|
|
694
|
+
if (typeof placeholder === "number") {
|
|
695
|
+
return values.numbered[placeholder - 1] ?? null;
|
|
696
|
+
}
|
|
697
|
+
return values.named?.property(placeholder) ?? null;
|
|
523
698
|
}
|
|
524
699
|
function statementIn(subject, says) {
|
|
525
700
|
const picks = Array.isArray(says) ? says : [says];
|
|
@@ -711,8 +886,8 @@ function describe(chain) {
|
|
|
711
886
|
];
|
|
712
887
|
return {
|
|
713
888
|
name: declaredName(chain.ending),
|
|
714
|
-
// A method table with a rule inside
|
|
715
|
-
//
|
|
889
|
+
// A method table with a rule inside still counts as a data link. The
|
|
890
|
+
// rule is counted on its own, as a function link.
|
|
716
891
|
dataLinks: chain.links.length - links.length,
|
|
717
892
|
functionLinks: written.map((rule) => rule.asks),
|
|
718
893
|
astLinks: written.filter((rule) => rule.reachesAst).map((rule) => rule.asks),
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ConstructedFrom, DeclaredBy, CallOps, InvocationRecognizer, PatternPack, UnsettledName, ReceiverOrigin, ProjectHelpers, PackDeclarations } from '@suss/extractor';
|
|
2
|
-
export { CallOps, ConstructedFrom, DeclaredBy, DeclaredMatch, HelperDeclarations, HelperSink, HelperValue, OpsCarrier, PackDeclarations, PatternPack, ProjectHelper, ProjectHelpers, ReceiverOrigin, UnsettledName, ValueEntry, ValueOps } from '@suss/extractor';
|
|
3
|
-
import { C as Chain, M as MethodMeaning, a as MessageSendMethod, b as MessageLocation, c as ChannelPart, S as SqlMethod, I as InterpolatesLink, d as CallStep, e as StorageMethod, A as ArgumentPick, L as LinkFunction, O as OneArgument, U as UnitInvokeMethod } from './chain-
|
|
4
|
-
export { f as AccessKind, g as AccessPathLink, h as ArgumentsFrom, i as CallsLink, j as ContainerArgument, k as ContainerLink, l as ContainerRule, m as ContainersLink, E as Ending, F as FromReceiver, n as InputLink, o as InputRule, K as KindAsAsked, p as Link, q as ManyIn, r as MatchStart, s as MessageSendEnding, t as MethodsLink, u as OneMessage, v as ScopeLink, w as SelectorParamPick, x as SqlEnding, y as StartLink, z as StatedInputs, B as StatedRule, D as StorageEnding, G as SubjectLink, T as ToArgument, H as ToReceiver, J as UnitInvokeEnding } from './chain-
|
|
2
|
+
export { CallOps, ClassOps, ConstructedFrom, DeclaredBy, DeclaredMatch, HelperDeclarations, HelperSink, HelperValue, OpsCarrier, PackDeclarations, PatternPack, ProjectHelper, ProjectHelpers, ReceiverOrigin, UnsettledName, ValueEntry, ValueOps } from '@suss/extractor';
|
|
3
|
+
import { C as Chain, M as MethodMeaning, a as MessageSendMethod, b as MessageLocation, c as ChannelPart, S as SqlMethod, I as InterpolatesLink, d as CallStep, e as StorageMethod, A as ArgumentPick, L as LinkFunction, O as OneArgument, U as UnitInvokeMethod } from './chain-DYU9ZdzF.cjs';
|
|
4
|
+
export { f as AccessKind, g as AccessPathLink, h as ArgumentsFrom, i as CallsLink, j as ContainerArgument, k as ContainerLink, l as ContainerRule, m as ContainersLink, E as Ending, F as FromReceiver, n as InputLink, o as InputRule, K as KindAsAsked, p as Link, q as ManyIn, r as MatchStart, s as MessageSendEnding, t as MethodsLink, u as OneMessage, v as ScopeLink, w as SelectorParamPick, x as SqlEnding, y as StartLink, z as StatedInputs, B as StatedRule, D as StorageEnding, G as SubjectLink, T as ToArgument, H as ToReceiver, J as UnitInvokeEnding } from './chain-DYU9ZdzF.cjs';
|
|
5
5
|
import { Effect, MessageBusSemantics, DeployableUnit } from '@suss/behavioral-ir';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -15,8 +15,8 @@ import { Effect, MessageBusSemantics, DeployableUnit } from '@suss/behavioral-ir
|
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* A receiver whose method one of these modules declared. Pass every
|
|
18
|
-
* module that ships the same client,
|
|
19
|
-
* one wire protocol.
|
|
18
|
+
* module that ships the same client, for example several packages that
|
|
19
|
+
* implement one wire protocol.
|
|
20
20
|
*/
|
|
21
21
|
declare function declaredBy(...importedFrom: readonly string[]): DeclaredBy;
|
|
22
22
|
/** A client made from one of these modules' exports. */
|
|
@@ -30,18 +30,18 @@ declare function constructedFrom(spec: {
|
|
|
30
30
|
declare function opsIn(ctx: unknown): CallOps | null;
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
|
-
*
|
|
33
|
+
* Turns a chain into the recognizer hook the adapters already call.
|
|
34
34
|
*
|
|
35
|
-
*
|
|
36
|
-
* first
|
|
37
|
-
* a receiver to the library that made it walks declarations.
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
35
|
+
* Every link is a guard, and the compiled hook checks the cheapest one
|
|
36
|
+
* first. Looking a method up in a table costs nothing, while following
|
|
37
|
+
* a receiver to the library that made it walks declarations. So the
|
|
38
|
+
* hook ignores the order the pack declared its links in. A link that
|
|
39
|
+
* changes what the receiver is, as a Prisma model property would, needs
|
|
40
|
+
* declared order back, and that change goes here.
|
|
41
41
|
*
|
|
42
42
|
* A chain that states a subject asks its questions of a call next to
|
|
43
|
-
* the one in hand,
|
|
44
|
-
*
|
|
43
|
+
* the one in hand, and the walk to that call is also here. DESIGN.md
|
|
44
|
+
* describes what each step reaches and why the walk is bounded.
|
|
45
45
|
*/
|
|
46
46
|
|
|
47
47
|
/** A chain, as the hook the adapter dispatches to on every call. */
|
|
@@ -71,28 +71,27 @@ interface RanExample {
|
|
|
71
71
|
/** How a pack's test compiles one line and runs the pack over it. */
|
|
72
72
|
type RunOverCode = (code: string) => Effect[];
|
|
73
73
|
/**
|
|
74
|
-
*
|
|
75
|
-
*
|
|
74
|
+
* Runs every example a pack declares. A declaration with no example is
|
|
75
|
+
* skipped here; `examplesMissing` lists those, and the pack health
|
|
76
|
+
* check reports them.
|
|
76
77
|
*/
|
|
77
78
|
declare function runExamples(pack: PatternPack, run: RunOverCode): RanExample[];
|
|
78
79
|
/** The declarations a pack shipped without a line of code to run. */
|
|
79
80
|
declare function examplesMissing(pack: PatternPack): string[];
|
|
80
81
|
|
|
81
82
|
/**
|
|
82
|
-
*
|
|
83
|
-
* wire.
|
|
83
|
+
* A pack that recognizes a call putting a message on a wire.
|
|
84
84
|
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
85
|
+
* It was written against the AWS SDK. There an operation is a command
|
|
86
|
+
* class and its arguments are one object, so the pack says which
|
|
87
|
+
* command, where the message is inside it, and which of the message's
|
|
88
|
+
* properties make up the channel:
|
|
89
89
|
*
|
|
90
90
|
* client.send(new SendMessageCommand({ QueueUrl, MessageBody }))
|
|
91
91
|
* client.send(new PutEventsCommand({ Entries: [{ EventBusName, DetailType }] }))
|
|
92
92
|
*
|
|
93
|
-
* A library
|
|
94
|
-
*
|
|
95
|
-
* belongs to the command rather than to a setting on one declaration.
|
|
93
|
+
* A library that sends one message and a batch through separate
|
|
94
|
+
* commands gets two declarations, one per command.
|
|
96
95
|
*/
|
|
97
96
|
|
|
98
97
|
interface MessageSendsSpec {
|
|
@@ -102,19 +101,19 @@ interface MessageSendsSpec {
|
|
|
102
101
|
messages: MessageLocation;
|
|
103
102
|
/** The parts of the channel, joined in the order they are written. */
|
|
104
103
|
channel: readonly ChannelPart[];
|
|
105
|
-
/** What joins the parts. Defaults to "#",
|
|
104
|
+
/** What joins the parts. Defaults to "#", as used between a bus and a subject. */
|
|
106
105
|
channelSeparator?: string;
|
|
107
106
|
/** The property a message states its body on. */
|
|
108
107
|
body?: string;
|
|
109
108
|
/**
|
|
110
|
-
* The property whose literal value
|
|
111
|
-
*
|
|
109
|
+
* The property whose literal value is recorded as the routing key. A
|
|
110
|
+
* reader can filter on it, and it stays out of the channel name.
|
|
112
111
|
*/
|
|
113
112
|
routingKey?: string;
|
|
114
113
|
/**
|
|
115
114
|
* What a reader gives back for a channel nothing in the source
|
|
116
|
-
* settles. Defaults to keeping the reference,
|
|
117
|
-
*
|
|
115
|
+
* settles. Defaults to keeping the reference, because most queues get
|
|
116
|
+
* their name at deploy time.
|
|
118
117
|
*/
|
|
119
118
|
unsettledName?: UnsettledName;
|
|
120
119
|
/** How the pack pins down the client its calls are on. */
|
|
@@ -146,15 +145,15 @@ declare function messageSends(spec: MessageSendsSpec): MessageSends;
|
|
|
146
145
|
*/
|
|
147
146
|
|
|
148
147
|
/**
|
|
149
|
-
* One thing a pack matches, as
|
|
150
|
-
*
|
|
148
|
+
* One thing a pack matches, as an entry point returns it. `storageCalls`
|
|
149
|
+
* and `sqlStatements` both return this.
|
|
151
150
|
*/
|
|
152
151
|
interface Match {
|
|
153
152
|
readonly declared: Chain<MethodMeaning>;
|
|
154
153
|
}
|
|
155
154
|
/** What a pack says about itself, beyond the calls it matches. */
|
|
156
155
|
interface PackSpec {
|
|
157
|
-
/** The languages the pack runs on, as the adapters
|
|
156
|
+
/** The languages the pack runs on, spelled as the adapters spell them. */
|
|
158
157
|
languages: string[];
|
|
159
158
|
/**
|
|
160
159
|
* The name effects from this pack are recorded under, which is the
|
|
@@ -168,24 +167,23 @@ interface PackSpec {
|
|
|
168
167
|
*/
|
|
169
168
|
version?: string;
|
|
170
169
|
/**
|
|
171
|
-
*
|
|
172
|
-
* record. An S3
|
|
173
|
-
*
|
|
170
|
+
* The pack's own protocol, when it differs from the wire its accesses
|
|
171
|
+
* record. An S3 pack records the AWS SDK as the wire on every effect,
|
|
172
|
+
* and its protocol is S3.
|
|
174
173
|
*/
|
|
175
174
|
protocol?: string;
|
|
176
175
|
/**
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
180
|
-
* imports gives it something.
|
|
176
|
+
* More modules that make a file worth reading, beyond the ones the
|
|
177
|
+
* chains match on. A helper imported by a relative path does not open
|
|
178
|
+
* the import gate, so the pack lists the library the helper imports.
|
|
181
179
|
*/
|
|
182
180
|
requiresImport?: string[];
|
|
183
181
|
/**
|
|
184
182
|
* Recognizers written against the adapter directly, run alongside the
|
|
185
|
-
* declared chains. A pack
|
|
186
|
-
* not declared yet here, and a
|
|
187
|
-
*
|
|
188
|
-
* function links, so
|
|
183
|
+
* declared chains. A pack moving to chains one call at a time keeps
|
|
184
|
+
* the calls it has not declared yet here, and a call no ending can
|
|
185
|
+
* describe stays here for good. The pack health report counts these
|
|
186
|
+
* as function links, so a reader sees how many are left.
|
|
189
187
|
*/
|
|
190
188
|
recognizers?: InvocationRecognizer[];
|
|
191
189
|
/**
|
|
@@ -198,9 +196,10 @@ interface PackSpec {
|
|
|
198
196
|
/** A pack, assembled from the calls it says it matches. */
|
|
199
197
|
declare function pack(name: string, matches: readonly Match[], spec: PackSpec): PatternPack;
|
|
200
198
|
/**
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
199
|
+
* Describes a set of chains for the pack health report, for a pack that
|
|
200
|
+
* builds its `PatternPack` by hand. A pack partway through moving to
|
|
201
|
+
* declared chains keeps hand-written recognizers beside them, and this
|
|
202
|
+
* reports on the part that has moved.
|
|
204
203
|
*/
|
|
205
204
|
declare function declarationsIn(matches: readonly Match[]): PackDeclarations;
|
|
206
205
|
|
|
@@ -208,13 +207,13 @@ declare function declarationsIn(matches: readonly Match[]): PackDeclarations;
|
|
|
208
207
|
* The entry point for a pack whose calls hand the store a statement
|
|
209
208
|
* written as SQL.
|
|
210
209
|
*
|
|
211
|
-
*
|
|
212
|
-
*
|
|
213
|
-
*
|
|
214
|
-
* the kind, the fields and the selector of every table the
|
|
215
|
-
* touches.
|
|
216
|
-
*
|
|
217
|
-
*
|
|
210
|
+
* With a typed client, the call's arguments show which table it
|
|
211
|
+
* reached. With a raw statement that information is in the SQL text,
|
|
212
|
+
* so the chain passes the text to `@suss/sql`. The parse gives the
|
|
213
|
+
* container, the kind, the fields and the selector of every table the
|
|
214
|
+
* statement touches. Every link before that point is one any other
|
|
215
|
+
* chain uses too, so SQL is a chain ending and needs no separate
|
|
216
|
+
* grammar.
|
|
218
217
|
*/
|
|
219
218
|
|
|
220
219
|
/** What a pack says about the store its statements reach. */
|
|
@@ -255,10 +254,10 @@ declare function sqlStatements(spec: SqlStatementsSpec): SqlStatements;
|
|
|
255
254
|
* The entry point for a pack that recognizes storage calls, and the
|
|
256
255
|
* chain it builds.
|
|
257
256
|
*
|
|
258
|
-
*
|
|
259
|
-
*
|
|
260
|
-
*
|
|
261
|
-
*
|
|
257
|
+
* A pack author writes `storageCalls` and never builds an `Effect` by
|
|
258
|
+
* hand. Each method on the returned value adds one link and returns a
|
|
259
|
+
* new chain, so by the time `pack` receives a chain it is plain data
|
|
260
|
+
* that nothing changes afterwards.
|
|
262
261
|
*/
|
|
263
262
|
|
|
264
263
|
/** What a pack says about the store its calls reach. */
|
|
@@ -271,8 +270,8 @@ interface StorageCallsSpec {
|
|
|
271
270
|
scope?: string;
|
|
272
271
|
/**
|
|
273
272
|
* How the pack pins down the client its calls are on. A pack that
|
|
274
|
-
* matches a helper a project
|
|
275
|
-
* because the name
|
|
273
|
+
* matches a helper listed in a project's own config leaves this out,
|
|
274
|
+
* because the helper's name is the only thing it has to match on.
|
|
276
275
|
*/
|
|
277
276
|
client?: ReceiverOrigin;
|
|
278
277
|
/**
|
|
@@ -294,9 +293,9 @@ interface StorageCalls {
|
|
|
294
293
|
ignoringCase?: boolean;
|
|
295
294
|
}): StorageCalls;
|
|
296
295
|
/**
|
|
297
|
-
* What a bare call of the client itself does. A store hook
|
|
298
|
-
*
|
|
299
|
-
*
|
|
296
|
+
* What a bare call of the client itself does. A store hook such as
|
|
297
|
+
* `useAppStore((s) => s.bears)` calls no method, so this meaning
|
|
298
|
+
* applies to every call.
|
|
300
299
|
*/
|
|
301
300
|
calls(meaning: StorageMethod): StorageCalls;
|
|
302
301
|
/**
|
|
@@ -336,13 +335,12 @@ interface StorageCalls {
|
|
|
336
335
|
declare function storageCalls(spec: StorageCallsSpec): StorageCalls;
|
|
337
336
|
|
|
338
337
|
/**
|
|
339
|
-
*
|
|
340
|
-
* unit by name.
|
|
338
|
+
* A pack that recognizes a call invoking one deployed unit by name.
|
|
341
339
|
*
|
|
342
|
-
*
|
|
343
|
-
*
|
|
344
|
-
*
|
|
345
|
-
*
|
|
340
|
+
* It was written against the AWS SDK, where an invoke looks like a
|
|
341
|
+
* message send: an operation is a command class and its arguments are
|
|
342
|
+
* one object. The pack says which command, and which of its properties
|
|
343
|
+
* identifies the unit the call reaches.
|
|
346
344
|
*
|
|
347
345
|
* client.send(new InvokeCommand({ FunctionName, Payload }))
|
|
348
346
|
*/
|