@fougere/core 0.9.0-alpha.1 → 0.9.3-alpha.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/dist/boot/AppLifecycle.d.ts +5 -1
- package/dist/boot/AppLifecycle.d.ts.map +1 -1
- package/dist/boot/AppLifecycle.js.map +1 -1
- package/dist/boot/apply.d.ts +5 -1
- package/dist/boot/apply.d.ts.map +1 -1
- package/dist/boot/apply.js +5 -1
- package/dist/boot/apply.js.map +1 -1
- package/dist/boot/declared.d.ts +29 -0
- package/dist/boot/declared.d.ts.map +1 -0
- package/dist/boot/declared.js +67 -0
- package/dist/boot/declared.js.map +1 -0
- package/dist/boot/install.d.ts.map +1 -1
- package/dist/boot/install.js +20 -3
- package/dist/boot/install.js.map +1 -1
- package/dist/boot/ownership.d.ts +2 -0
- package/dist/boot/ownership.d.ts.map +1 -1
- package/dist/boot/ownership.js +17 -0
- package/dist/boot/ownership.js.map +1 -1
- package/dist/boot/ports.d.ts +23 -0
- package/dist/boot/ports.d.ts.map +1 -1
- package/dist/boot/ports.js +49 -0
- package/dist/boot/ports.js.map +1 -1
- package/dist/boot/remote.d.ts +5 -1
- package/dist/boot/remote.d.ts.map +1 -1
- package/dist/boot/remote.js.map +1 -1
- package/dist/boot/seed.d.ts +5 -1
- package/dist/boot/seed.d.ts.map +1 -1
- package/dist/boot/seed.js +5 -1
- package/dist/boot/seed.js.map +1 -1
- package/dist/boot/together.d.ts.map +1 -1
- package/dist/boot/together.js +5 -1
- package/dist/boot/together.js.map +1 -1
- package/dist/boot/types.d.ts +1 -1
- package/dist/boot/types.d.ts.map +1 -1
- package/dist/builtin/logger.d.ts +1 -2
- package/dist/builtin/logger.d.ts.map +1 -1
- package/dist/builtin/logger.js +0 -19
- package/dist/builtin/logger.js.map +1 -1
- package/dist/config-loader.d.ts +0 -1
- package/dist/config-loader.d.ts.map +1 -1
- package/dist/config-loader.js.map +1 -1
- package/dist/contract.d.ts +1 -1
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js.map +1 -1
- package/dist/descriptor/frond.d.ts +5 -1
- package/dist/descriptor/frond.d.ts.map +1 -1
- package/dist/descriptor/frond.js.map +1 -1
- package/dist/effective-operation.d.ts +20 -0
- package/dist/effective-operation.d.ts.map +1 -1
- package/dist/effective-operation.js +17 -0
- package/dist/effective-operation.js.map +1 -1
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +5 -1
- package/dist/identity.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/prefab/collector.d.ts +5 -1
- package/dist/prefab/collector.d.ts.map +1 -1
- package/dist/prefab/collector.js +5 -1
- package/dist/prefab/collector.js.map +1 -1
- package/dist/prefab/crud.d.ts +9 -5
- package/dist/prefab/crud.d.ts.map +1 -1
- package/dist/prefab/crud.js +14 -7
- package/dist/prefab/crud.js.map +1 -1
- package/dist/prefab/mirror.d.ts +5 -1
- package/dist/prefab/mirror.d.ts.map +1 -1
- package/dist/prefab/mirror.js.map +1 -1
- package/dist/prefab/presenter.d.ts +6 -2
- package/dist/prefab/presenter.d.ts.map +1 -1
- package/dist/prefab/presenter.js +6 -2
- package/dist/prefab/presenter.js.map +1 -1
- package/dist/prefab/repository.d.ts +5 -1
- package/dist/prefab/repository.d.ts.map +1 -1
- package/dist/prefab/repository.js.map +1 -1
- package/dist/scan.d.ts +1 -1
- package/dist/scan.d.ts.map +1 -1
- package/dist/source.d.ts +5 -1
- package/dist/source.d.ts.map +1 -1
- package/dist/source.js.map +1 -1
- package/dist/storage/port.d.ts +27 -1
- package/dist/storage/port.d.ts.map +1 -1
- package/dist/storage/port.js +70 -0
- package/dist/storage/port.js.map +1 -1
- package/dist/wire/call.d.ts +26 -1
- package/dist/wire/call.d.ts.map +1 -1
- package/dist/wire/call.js +1 -1
- package/dist/wire/call.js.map +1 -1
- package/dist/wire/emit.d.ts.map +1 -1
- package/dist/wire/emit.js +5 -1
- package/dist/wire/emit.js.map +1 -1
- package/dist/wire/errors.d.ts +5 -1
- package/dist/wire/errors.d.ts.map +1 -1
- package/dist/wire/errors.js +5 -1
- package/dist/wire/errors.js.map +1 -1
- package/dist/wire/signature.d.ts +1 -2
- package/dist/wire/signature.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/boot/AppLifecycle.ts +5 -1
- package/src/boot/apply.ts +5 -1
- package/src/boot/declared.ts +88 -0
- package/src/boot/install.ts +20 -4
- package/src/boot/ownership.ts +21 -0
- package/src/boot/ports.ts +63 -0
- package/src/boot/remote.ts +5 -1
- package/src/boot/seed.ts +5 -1
- package/src/boot/together.ts +5 -1
- package/src/boot/types.ts +1 -1
- package/src/builtin/logger.ts +1 -20
- package/src/config-loader.ts +0 -1
- package/src/contract.ts +4 -1
- package/src/descriptor/frond.ts +5 -1
- package/src/effective-operation.ts +41 -0
- package/src/identity.ts +5 -1
- package/src/index.ts +10 -3
- package/src/prefab/collector.ts +5 -1
- package/src/prefab/crud.ts +14 -7
- package/src/prefab/mirror.ts +5 -1
- package/src/prefab/presenter.ts +6 -2
- package/src/prefab/repository.ts +5 -1
- package/src/scan.ts +1 -1
- package/src/source.ts +5 -1
- package/src/storage/port.ts +74 -1
- package/src/wire/call.ts +29 -1
- package/src/wire/emit.ts +5 -1
- package/src/wire/errors.ts +5 -1
- package/src/wire/signature.ts +1 -2
package/src/prefab/crud.ts
CHANGED
|
@@ -4,8 +4,8 @@ import type { OperationContract } from '../wire/operation.js';
|
|
|
4
4
|
import { targetOf } from './prefab.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
8
|
-
* FR :
|
|
7
|
+
* A class is recognized by what it ANSWERS — the mixin leaves no other trace.
|
|
8
|
+
* FR : une classe se reconnaît à ce qu'elle répond, le mixin ne laissant rien d'autre.
|
|
9
9
|
* `inheritsCrud(class PostHandler extends Crud(Post) {})` → `true`
|
|
10
10
|
*/
|
|
11
11
|
export function inheritsCrud(ctor: unknown): boolean {
|
|
@@ -15,8 +15,8 @@ export function inheritsCrud(ctor: unknown): boolean {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
19
|
-
* FR :
|
|
18
|
+
* Storage follows the shape the handler was built on, which may differ from its address.
|
|
19
|
+
* FR : le stockage suit la forme sur laquelle le handler est bâti, pas son adresse.
|
|
20
20
|
* `subjectOf(class Draft extends Crud(Post) {}, 'draft')` → `'post'`
|
|
21
21
|
*/
|
|
22
22
|
export function subjectOf(ctor: unknown, address: string): string {
|
|
@@ -35,8 +35,11 @@ const inputParam = (entity: string) => ({ name: 'input', type: { raw: `Partial<$
|
|
|
35
35
|
const returns = (raw: string, name: string, extra?: { array?: boolean; nullable?: boolean }) =>
|
|
36
36
|
({ raw, name, ...extra });
|
|
37
37
|
|
|
38
|
-
/**
|
|
39
|
-
|
|
38
|
+
/**
|
|
39
|
+
* The five ops a Crud handler brings, declared rather than discovered.
|
|
40
|
+
*
|
|
41
|
+
* `output` says the entity, and saying it costs nothing at runtime.
|
|
42
|
+
*/
|
|
40
43
|
function crudOps(entity: SchemaView & { partial?: () => SchemaView }): Record<string, OperationContract> {
|
|
41
44
|
const name = (entity as { name?: string }).name ?? 'Entity';
|
|
42
45
|
const input = inputParam(name);
|
|
@@ -112,7 +115,11 @@ export interface CrudConstructor<T, V = {}> {
|
|
|
112
115
|
readonly __ops: Record<string, OperationContract>;
|
|
113
116
|
}
|
|
114
117
|
|
|
115
|
-
/**
|
|
118
|
+
/**
|
|
119
|
+
* Mixin — extends Crud(Entity) to get all 5 typed CRUD methods.
|
|
120
|
+
*
|
|
121
|
+
* Documented: [handlers](https://fougere.dev/docs/business/handlers).
|
|
122
|
+
*/
|
|
116
123
|
export function Crud<E extends EntityConstructor, V extends CrudViews | EntityConstructor = {}>(
|
|
117
124
|
entity: E,
|
|
118
125
|
output?: V,
|
package/src/prefab/mirror.ts
CHANGED
|
@@ -11,7 +11,11 @@ export interface Refreshed {
|
|
|
11
11
|
ms: number;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
/**
|
|
14
|
+
/**
|
|
15
|
+
* A paginated local copy of a source that cannot be queried directly.
|
|
16
|
+
*
|
|
17
|
+
* Documented: [the base](https://fougere.dev/docs/concepts/the-base).
|
|
18
|
+
*/
|
|
15
19
|
export interface MirrorOf<T> {
|
|
16
20
|
/** The copy's own storage — where a page lands. */
|
|
17
21
|
storage: Storage<T>;
|
package/src/prefab/presenter.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* Presenter(Entity) — enriches an entity's output with computed fields.
|
|
3
|
+
*
|
|
4
|
+
* Documented: [presenters](https://fougere.dev/docs/business/presenters).
|
|
5
|
+
*/
|
|
2
6
|
|
|
3
7
|
import { upperFirst, type EntityConstructor } from '@fougere/schema';
|
|
4
8
|
|
|
@@ -8,7 +12,7 @@ import { upperFirst, type EntityConstructor } from '@fougere/schema';
|
|
|
8
12
|
*/
|
|
9
13
|
export type PresenterViews = Record<string, EntityConstructor | [EntityConstructor]>;
|
|
10
14
|
|
|
11
|
-
/** `Presenter(Order, { items. */
|
|
15
|
+
/** `Presenter(Order, { items: [OrderItemView] })` — the views its computed fields emit. */
|
|
12
16
|
export function Presenter<E extends EntityConstructor>(entity: E, views?: PresenterViews) {
|
|
13
17
|
class PresenterBase {
|
|
14
18
|
static readonly __entity = entity;
|
package/src/prefab/repository.ts
CHANGED
|
@@ -2,7 +2,11 @@ import { upperFirst, type EntityConstructor } from '@fougere/schema';
|
|
|
2
2
|
import type { Storage, ListOptions, ListResult, SelectOption } from '../storage/port.js';
|
|
3
3
|
import type { SchemaView } from '@fougere/schema';
|
|
4
4
|
|
|
5
|
-
/**
|
|
5
|
+
/**
|
|
6
|
+
* Repository(…entities) — who owns an entity's storage, and where its questions are named.
|
|
7
|
+
*
|
|
8
|
+
* Documented: [repositories](https://fougere.dev/docs/business/repositories).
|
|
9
|
+
*/
|
|
6
10
|
|
|
7
11
|
/**
|
|
8
12
|
* The shape a repository of ONE entity has — the port itself, plus whatever the subclass names on
|
package/src/scan.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { Fronds } from './descriptor/Fronds.js';
|
|
2
2
|
|
|
3
|
-
/** Result of scanning a project directory. */
|
|
4
3
|
/** Something the scan could NOT do — recorded instead of swallowed. */
|
|
5
4
|
export interface ScanDiagnostic {
|
|
6
5
|
/**
|
|
@@ -22,6 +21,7 @@ export interface ScanDiagnostic {
|
|
|
22
21
|
cause?: unknown;
|
|
23
22
|
}
|
|
24
23
|
|
|
24
|
+
/** Result of scanning a project directory. */
|
|
25
25
|
export interface ScanResult {
|
|
26
26
|
fronds: Fronds;
|
|
27
27
|
/** What the scan could not do. Empty is a claim, not a default — see {@link ScanDiagnostic}. */
|
package/src/source.ts
CHANGED
|
@@ -12,7 +12,11 @@ export function declares(schema: SchemaView, constraint: Constraint): boolean {
|
|
|
12
12
|
return Object.values(schema.getFields()).some((field) => Role.of(field).isUnique);
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* A place rows live, whatever realizes it.
|
|
17
|
+
*
|
|
18
|
+
* Documented: [sources](https://fougere.dev/docs/infra/sources).
|
|
19
|
+
*/
|
|
16
20
|
export interface Source {
|
|
17
21
|
storageFactory: StorageFactory;
|
|
18
22
|
/**
|
package/src/storage/port.ts
CHANGED
|
@@ -102,8 +102,81 @@ export interface Storage<T = Record<string, unknown>> {
|
|
|
102
102
|
delete(id: string): Promise<boolean>;
|
|
103
103
|
/** Returns a scoped storage that restricts all read results to the fields of the given schema. */
|
|
104
104
|
output(schema: SchemaView): Storage<T>;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* What each link of a chain stands in front of.
|
|
109
|
+
*
|
|
110
|
+
* A SYMBOL on the instance, set through a cast so it joins no declaration: `Storage` is an
|
|
111
|
+
* interface as well as a class, and the realizations satisfy it structurally —
|
|
112
|
+
* `storageOver` returns an object literal, and one more member would stop it being a
|
|
113
|
+
* storage. A `#private` field says the same thing and makes the class NOMINAL, which
|
|
114
|
+
* refuses every realization at once.
|
|
115
|
+
*
|
|
116
|
+
* On the instance and not in a `WeakMap` beside it, because `StorageGuard.guard` hands out
|
|
117
|
+
* `Object.create(storage)` — a new object whose prototype is the link. A symbol is found
|
|
118
|
+
* through that chain; a map keyed on the link is not, and the guarded object read
|
|
119
|
+
* `undefined`.
|
|
120
|
+
*/
|
|
121
|
+
const BEHIND = Symbol('fougere.storage.behind');
|
|
122
|
+
|
|
123
|
+
const behind = <T>(link: object): Storage<T> =>
|
|
124
|
+
(link as Record<symbol, unknown>)[BEHIND] as Storage<T>;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* A storage that stands in front of another — the base a wrapper extends, and the only
|
|
128
|
+
* thing that makes `Storage` a seam rather than a shape.
|
|
129
|
+
*
|
|
130
|
+
* Merged with the interface above, so the class carries the thirteen gestures as a TYPE
|
|
131
|
+
* while its prototype carries them as a FORWARD. A wrapper writes what it changes and
|
|
132
|
+
* nothing else:
|
|
133
|
+
*
|
|
134
|
+
* ```ts
|
|
135
|
+
* class Audit extends Storage {
|
|
136
|
+
* constructor(private inner: Storage) { super(inner); }
|
|
137
|
+
* async create(row) { await say(row); return this.inner.create(row); }
|
|
138
|
+
* }
|
|
139
|
+
* ```
|
|
140
|
+
*
|
|
141
|
+
* `ports: { Storage: ['Audit'] }` orders the chain when a frond declares two, which is the
|
|
142
|
+
* same key, the same order and the same refusals a port gets. A realization does not extend
|
|
143
|
+
* this: it is handed in by `storageFactory` and is the last link, so what a wrapper does not
|
|
144
|
+
* override reaches it through these forwards.
|
|
145
|
+
*
|
|
146
|
+
* Documented: [storage](https://fougere.dev/docs/business/storage) and
|
|
147
|
+
* [ports](https://fougere.dev/docs/business/ports).
|
|
148
|
+
*/
|
|
149
|
+
export abstract class Storage<T = Record<string, unknown>> {
|
|
150
|
+
constructor(inner: Storage<T>) {
|
|
151
|
+
(this as Record<symbol, unknown>)[BEHIND] = inner;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
list(options?: ListOptions & SelectOption): Promise<ListResult<T>> { return behind<T>(this).list(options); }
|
|
155
|
+
findById(id: string, options?: SelectOption): Promise<T | undefined> { return behind<T>(this).findById(id, options); }
|
|
156
|
+
findBy(criteria: Partial<T> | Record<string, unknown>, options?: SelectOption): Promise<T | undefined> {
|
|
157
|
+
return behind<T>(this).findBy(criteria, options);
|
|
158
|
+
}
|
|
159
|
+
findAllBy(criteria: Partial<T> | Record<string, unknown>, options?: SelectOption): Promise<T[]> {
|
|
160
|
+
return behind<T>(this).findAllBy(criteria, options);
|
|
161
|
+
}
|
|
162
|
+
findByKeys(ids: readonly string[], options?: SelectOption): Promise<Map<string, T>> {
|
|
163
|
+
return behind<T>(this).findByKeys(ids, options);
|
|
164
|
+
}
|
|
165
|
+
findAllByKeys(field: string, keys: readonly string[], options?: SelectOption): Promise<Map<string, T[]>> {
|
|
166
|
+
return behind<T>(this).findAllByKeys(field, keys, options);
|
|
167
|
+
}
|
|
168
|
+
create(input: Partial<T>, options?: SelectOption): Promise<T> { return behind<T>(this).create(input, options); }
|
|
169
|
+
upsert(input: Partial<T>, options?: SelectOption): Promise<T> { return behind<T>(this).upsert(input, options); }
|
|
170
|
+
upsertAll(inputs: readonly Partial<T>[], options?: SelectOption): Promise<number> {
|
|
171
|
+
return behind<T>(this).upsertAll(inputs, options);
|
|
172
|
+
}
|
|
173
|
+
update(id: string, input: Partial<T>, options?: SelectOption): Promise<T> {
|
|
174
|
+
return behind<T>(this).update(id, input, options);
|
|
175
|
+
}
|
|
176
|
+
delete(id: string): Promise<boolean> { return behind<T>(this).delete(id); }
|
|
177
|
+
output(schema: SchemaView): Storage<T> { return behind<T>(this).output(schema); }
|
|
105
178
|
/** What this storage wraps — the Kysely instance for the SQL one, something else elsewhere. */
|
|
106
|
-
|
|
179
|
+
get client(): unknown { return behind<T>(this).client; }
|
|
107
180
|
}
|
|
108
181
|
|
|
109
182
|
/**
|
package/src/wire/call.ts
CHANGED
|
@@ -30,10 +30,10 @@ export interface FrondCall {
|
|
|
30
30
|
/** A transport executes a call somewhere else. Failures surface as thrown FougereError. */
|
|
31
31
|
export type Transport = (call: FrondCall, invocation: InvocationContext) => Promise<unknown>;
|
|
32
32
|
|
|
33
|
-
/** Reserved namespace — calls the runner answers itself, never a façade. */
|
|
34
33
|
/** What a receiver accepts before it stops reading an input. */
|
|
35
34
|
export const MAX_BODY_BYTES = 1024 * 1024;
|
|
36
35
|
|
|
36
|
+
/** Reserved namespace — calls the runner answers itself, never a façade. */
|
|
37
37
|
export const RPC_ENTITY = 'rpc';
|
|
38
38
|
|
|
39
39
|
/** What an `rpc` op answers — the door for what the app says about ITSELF, never about a row. */
|
|
@@ -98,6 +98,33 @@ export interface Edge {
|
|
|
98
98
|
errors: number;
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
/** A frond the config knows of, and where it says to reach it. */
|
|
102
|
+
export interface DeclaredFrond {
|
|
103
|
+
frond: string;
|
|
104
|
+
placement: 'local' | 'remote';
|
|
105
|
+
/**
|
|
106
|
+
* Host and port of the address `remotes:` names, absent when the frond runs here. Never the
|
|
107
|
+
* whole address: a declared one may carry credentials, and this answer leaves the process.
|
|
108
|
+
*/
|
|
109
|
+
at?: string;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** One frond reaching another, read from a handler's dependencies rather than from a call. */
|
|
113
|
+
export interface DeclaredEdge {
|
|
114
|
+
from: string;
|
|
115
|
+
to: string;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* What the config SAYS, beside what the runtime SAW. The two disagree exactly when something
|
|
120
|
+
* is misconfigured, and a frond that never answered is absent from the observed half — so
|
|
121
|
+
* without this one, nothing tells a silent dependency from an absent one.
|
|
122
|
+
*/
|
|
123
|
+
export interface DeclaredTopology {
|
|
124
|
+
fronds: DeclaredFrond[];
|
|
125
|
+
edges: DeclaredEdge[];
|
|
126
|
+
}
|
|
127
|
+
|
|
101
128
|
/** The shape of the system as ONE process discovered it — the answer to `rpc.topology`. */
|
|
102
129
|
export interface TopologyReport {
|
|
103
130
|
/** When this process started counting — an edge count is read against it. */
|
|
@@ -106,6 +133,7 @@ export interface TopologyReport {
|
|
|
106
133
|
active: number;
|
|
107
134
|
fronds: FrondPlacement[];
|
|
108
135
|
edges: Edge[];
|
|
136
|
+
declared: DeclaredTopology;
|
|
109
137
|
}
|
|
110
138
|
|
|
111
139
|
/** The shape a card must have to be walked — `fronds`, and each frond's `doors`. */
|
package/src/wire/emit.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* Announcing a fact — the half of the topology `remotes:` never covered.
|
|
3
|
+
*
|
|
4
|
+
* Documented: [facts](https://fougere.dev/docs/business/facts).
|
|
5
|
+
*/
|
|
2
6
|
import { lowerFirst } from '@fougere/schema';
|
|
3
7
|
|
|
4
8
|
/**
|
package/src/wire/errors.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* The error vocabulary — what a refusal IS, independently of who hears it.
|
|
3
|
+
*
|
|
4
|
+
* Documented: [errors](https://fougere.dev/docs/business/errors).
|
|
5
|
+
*/
|
|
2
6
|
|
|
3
7
|
import type { ValidationError } from '@fougere/schema';
|
|
4
8
|
|
package/src/wire/signature.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/** A method's signature, as a contract is built from it — the shape, never the reading. */
|
|
2
1
|
/** A type reference — primitives, entities, arrays, generics. */
|
|
3
2
|
export interface TypeRef {
|
|
4
3
|
/** Raw type text as written in source (e.g. 'Pagination<Post>'). */
|
|
@@ -26,7 +25,7 @@ export interface Param {
|
|
|
26
25
|
optional?: boolean;
|
|
27
26
|
}
|
|
28
27
|
|
|
29
|
-
/** A method signature. */
|
|
28
|
+
/** A method's signature, as a contract is built from it — the shape, never the reading. */
|
|
30
29
|
export interface Signature {
|
|
31
30
|
name: string;
|
|
32
31
|
params: Param[];
|