@fougere/calls 0.8.4-alpha.0 → 0.9.0-alpha.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/dist/KeepHandler.d.ts +23 -0
- package/dist/KeepHandler.d.ts.map +1 -0
- package/dist/KeepHandler.js +28 -0
- package/dist/KeepHandler.js.map +1 -0
- package/dist/index.d.ts +0 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +27 -10
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
- package/src/KeepHandler.ts +26 -0
- package/src/index.ts +28 -11
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Fact, LogLine } from '@fougere/core';
|
|
2
|
+
import { LogRing, ErrorRing } from './rings.js';
|
|
3
|
+
/**
|
|
4
|
+
* Every line this process logged, kept for the panel.
|
|
5
|
+
*
|
|
6
|
+
* A handler and not an `onLog` sink: accepting the fact IS the subscription, so the two
|
|
7
|
+
* rings are filled by the same door every other reader goes through — with a validator,
|
|
8
|
+
* and with whatever middleware the app declared.
|
|
9
|
+
*
|
|
10
|
+
* The rings come from the container: the extension's `up` put them there, and this
|
|
11
|
+
* resolves at the first call, which is after.
|
|
12
|
+
*
|
|
13
|
+
* In `src/` and not under `fronds/`: that directory is what a SCAN reads, and this frond
|
|
14
|
+
* is stated (`frond('calls', …)`) because a published package is read by no scanner.
|
|
15
|
+
*/
|
|
16
|
+
export default class KeepHandler {
|
|
17
|
+
private lines;
|
|
18
|
+
private errors;
|
|
19
|
+
constructor(lines: LogRing, errors: ErrorRing);
|
|
20
|
+
/** Keep one line, and group it as a refusal when that is what it says. */
|
|
21
|
+
record(line: Fact<LogLine>): Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=KeepHandler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KeepHandler.d.ts","sourceRoot":"","sources":["../src/KeepHandler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEhD;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,OAAO,OAAO,WAAW;IAClB,OAAO,CAAC,KAAK;IAAW,OAAO,CAAC,MAAM;IAAlD,YAAoB,KAAK,EAAE,OAAO,EAAU,MAAM,EAAE,SAAS,EAAI;IAEjE,0EAA0E;IACpE,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAI/C;CACF"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every line this process logged, kept for the panel.
|
|
3
|
+
*
|
|
4
|
+
* A handler and not an `onLog` sink: accepting the fact IS the subscription, so the two
|
|
5
|
+
* rings are filled by the same door every other reader goes through — with a validator,
|
|
6
|
+
* and with whatever middleware the app declared.
|
|
7
|
+
*
|
|
8
|
+
* The rings come from the container: the extension's `up` put them there, and this
|
|
9
|
+
* resolves at the first call, which is after.
|
|
10
|
+
*
|
|
11
|
+
* In `src/` and not under `fronds/`: that directory is what a SCAN reads, and this frond
|
|
12
|
+
* is stated (`frond('calls', …)`) because a published package is read by no scanner.
|
|
13
|
+
*/
|
|
14
|
+
export default class KeepHandler {
|
|
15
|
+
lines;
|
|
16
|
+
errors;
|
|
17
|
+
constructor(lines, errors) {
|
|
18
|
+
this.lines = lines;
|
|
19
|
+
this.errors = errors;
|
|
20
|
+
}
|
|
21
|
+
/** Keep one line, and group it as a refusal when that is what it says. */
|
|
22
|
+
async record(line) {
|
|
23
|
+
const record = { ...line, args: line.args ?? [], at: line.at.getTime() };
|
|
24
|
+
this.lines.record(record);
|
|
25
|
+
this.errors.fromLog(record);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=KeepHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KeepHandler.js","sourceRoot":"","sources":["../src/KeepHandler.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,OAAO,OAAO,WAAW;IACV,KAAK;IAAmB,MAAM;IAAlD,YAAoB,KAAc,EAAU,MAAiB;qBAAzC,KAAK;sBAAmB,MAAM;IAAc,CAAC;IAEjE,0EAA0E;IAC1E,KAAK,CAAC,MAAM,CAAC,IAAmB;QAC9B,MAAM,MAAM,GAAG,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC;QACzE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC1B,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;CACF"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { type Extension } from '@fougere/core';
|
|
2
2
|
import { type PanelOptions } from './panel.js';
|
|
3
3
|
export type { CallPage, CallRecord } from '@fougere/core';
|
|
4
|
-
export { CallRing } from './CallRing.js';
|
|
5
|
-
export { LogRing, QueryRing, ErrorRing } from './rings.js';
|
|
6
|
-
export type { LogLine, QueryLine, ErrorGroup } from './rings.js';
|
|
7
|
-
export { servePanel, type PanelOptions } from './panel.js';
|
|
8
4
|
/** The rpc operation this extension answers under. */
|
|
9
5
|
export declare const CALLS_OP = "calls";
|
|
10
6
|
export interface CallsOptions {
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0C,KAAK,SAAS,EAA0B,MAAM,eAAe,CAAC;AAI/G,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAE3D,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE1D,sDAAsD;AACtD,eAAO,MAAM,QAAQ,UAAU,CAAC;AAEhC,MAAM,WAAW,YAAY;IAC3B,oFAAoF;IACpF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,YAAY,CAAC;CACzC;AAsFD,2FAA2F;AAC3F,wBAAgB,KAAK,CAAC,OAAO,GAAE,YAAiB,GAAG,SAAS,CA+E3D"}
|
package/dist/index.js
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CARRIES_LINE, frond, LogLine } from '@fougere/core';
|
|
2
|
+
import KeepHandler from './KeepHandler.js';
|
|
2
3
|
import { CallRing } from './CallRing.js';
|
|
3
4
|
import { ErrorRing, LogRing, QueryRing } from './rings.js';
|
|
4
5
|
import { servePanel } from './panel.js';
|
|
5
|
-
export { CallRing } from './CallRing.js';
|
|
6
|
-
export { LogRing, QueryRing, ErrorRing } from './rings.js';
|
|
7
|
-
export { servePanel } from './panel.js';
|
|
8
6
|
/** The rpc operation this extension answers under. */
|
|
9
7
|
export const CALLS_OP = 'calls';
|
|
10
8
|
/** What this process serves, read from the app itself. */
|
|
11
9
|
function servedModel(app) {
|
|
12
10
|
return {
|
|
13
|
-
fronds: app.fronds.map((frond) => ({
|
|
11
|
+
fronds: app.fronds.filter((frond) => !frond.brought).map((frond) => ({
|
|
14
12
|
name: frond.name,
|
|
15
13
|
// What the config SAYS. What the runtime saw is in the ring, under `route` — and the
|
|
16
14
|
// two disagree exactly when something is misconfigured, which is the whole point of
|
|
@@ -93,21 +91,39 @@ export function calls(options = {}) {
|
|
|
93
91
|
const stopping = new WeakMap();
|
|
94
92
|
return {
|
|
95
93
|
name: 'calls',
|
|
94
|
+
// What it needs a SIGNATURE for: every line this process logs. Stated rather than
|
|
95
|
+
// scanned, because a published package is read by no scanner.
|
|
96
|
+
fronds: [frond('calls', {
|
|
97
|
+
handlers: [{
|
|
98
|
+
ctor: KeepHandler,
|
|
99
|
+
deps: ['LogRing', 'ErrorRing'],
|
|
100
|
+
operations: {
|
|
101
|
+
record: {
|
|
102
|
+
input: LogLine,
|
|
103
|
+
binding: [{ name: 'line', optional: false, source: { kind: 'fact', factName: 'logLine' } }],
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
}],
|
|
107
|
+
})],
|
|
96
108
|
async up(app) {
|
|
97
109
|
const ring = new CallRing(options.max ?? 500, frondIndex(app));
|
|
98
110
|
const logs = new LogRing();
|
|
99
111
|
const errors = new ErrorRing();
|
|
100
112
|
const queries = new QueryRing();
|
|
113
|
+
// The rings the frond's handler asks for. Registered here and resolved at its first
|
|
114
|
+
// call, which is after this ascent — so a signature replaces the `onLog` sink.
|
|
115
|
+
app.container.registerValue('LogRing', logs);
|
|
116
|
+
app.container.registerValue('ErrorRing', errors);
|
|
101
117
|
const undo = [
|
|
102
118
|
app.observe((event) => {
|
|
119
|
+
// Not its own: keeping a line is a DISPATCH, so the ring would fill with the
|
|
120
|
+
// writes that fill it — the same shape as a logger that logs its own carrying.
|
|
121
|
+
if (CARRIES_LINE.has(event.call.address.entity))
|
|
122
|
+
return;
|
|
103
123
|
ring.record(event);
|
|
104
124
|
if (event.stage === 'failed')
|
|
105
125
|
errors.fromDispatch(event);
|
|
106
126
|
}),
|
|
107
|
-
onLog((line) => {
|
|
108
|
-
logs.record(line);
|
|
109
|
-
errors.fromLog(line);
|
|
110
|
-
}),
|
|
111
127
|
// `@fougere/adapter-sql` is optional — an app on another storage, or none, simply
|
|
112
128
|
// never resolves it, and the Queries tab says there is none rather than staying
|
|
113
129
|
// blank. Dynamic on purpose: this package declares no dependency on it.
|
|
@@ -126,7 +142,8 @@ export function calls(options = {}) {
|
|
|
126
142
|
...asked,
|
|
127
143
|
...(port !== undefined ? { port } : {}),
|
|
128
144
|
title: asked.title ?? app.fronds[0]?.name ?? 'fougere',
|
|
129
|
-
|
|
145
|
+
// What this app SERVES: a frond an extension brought is instrumentation.
|
|
146
|
+
fronds: app.fronds.filter((frond) => !frond.brought).map((frond) => frond.name),
|
|
130
147
|
model: servedModel(app),
|
|
131
148
|
logs: (cursor) => logs.since(cursor),
|
|
132
149
|
errors: (cursor) => errors.since(cursor),
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fougere/calls",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0-alpha.1",
|
|
4
4
|
"description": "Optional call log for Fougere: a bounded ring of every dispatch, served as an rpc operation. Read it with `fougere devtools`.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"fougere",
|
|
@@ -30,17 +30,17 @@
|
|
|
30
30
|
"src"
|
|
31
31
|
],
|
|
32
32
|
"peerDependencies": {
|
|
33
|
-
"@fougere/core": "^0.
|
|
34
|
-
"@fougere/adapter-sql": "^0.
|
|
33
|
+
"@fougere/core": "^0.9.0-alpha.1",
|
|
34
|
+
"@fougere/adapter-sql": "^0.9.0-alpha.1"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"vitest": "^4.1.0",
|
|
38
|
-
"@fougere/
|
|
39
|
-
"@fougere/
|
|
40
|
-
"@fougere/
|
|
41
|
-
"@fougere/
|
|
42
|
-
"@fougere/
|
|
43
|
-
"@fougere/
|
|
38
|
+
"@fougere/adapter-sql": "0.9.0-alpha.1",
|
|
39
|
+
"@fougere/container": "0.9.0-alpha.1",
|
|
40
|
+
"@fougere/core": "0.9.0-alpha.1",
|
|
41
|
+
"@fougere/compiler": "0.9.0-alpha.1",
|
|
42
|
+
"@fougere/schema": "0.9.0-alpha.1",
|
|
43
|
+
"@fougere/transport-http": "0.9.0-alpha.1"
|
|
44
44
|
},
|
|
45
45
|
"publishConfig": {
|
|
46
46
|
"access": "public"
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Fact, LogLine } from '@fougere/core';
|
|
2
|
+
import { LogRing, ErrorRing } from './rings.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Every line this process logged, kept for the panel.
|
|
6
|
+
*
|
|
7
|
+
* A handler and not an `onLog` sink: accepting the fact IS the subscription, so the two
|
|
8
|
+
* rings are filled by the same door every other reader goes through — with a validator,
|
|
9
|
+
* and with whatever middleware the app declared.
|
|
10
|
+
*
|
|
11
|
+
* The rings come from the container: the extension's `up` put them there, and this
|
|
12
|
+
* resolves at the first call, which is after.
|
|
13
|
+
*
|
|
14
|
+
* In `src/` and not under `fronds/`: that directory is what a SCAN reads, and this frond
|
|
15
|
+
* is stated (`frond('calls', …)`) because a published package is read by no scanner.
|
|
16
|
+
*/
|
|
17
|
+
export default class KeepHandler {
|
|
18
|
+
constructor(private lines: LogRing, private errors: ErrorRing) {}
|
|
19
|
+
|
|
20
|
+
/** Keep one line, and group it as a refusal when that is what it says. */
|
|
21
|
+
async record(line: Fact<LogLine>): Promise<void> {
|
|
22
|
+
const record = { ...line, args: line.args ?? [], at: line.at.getTime() };
|
|
23
|
+
this.lines.record(record);
|
|
24
|
+
this.errors.fromLog(record);
|
|
25
|
+
}
|
|
26
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CARRIES_LINE, frond, LogLine, type App, type Extension, type InvocationContext } from '@fougere/core';
|
|
2
|
+
import KeepHandler from './KeepHandler.js';
|
|
2
3
|
import { CallRing } from './CallRing.js';
|
|
3
4
|
import { ErrorRing, LogRing, QueryRing } from './rings.js';
|
|
4
5
|
import { servePanel, type PanelOptions } from './panel.js';
|
|
5
6
|
|
|
6
7
|
export type { CallPage, CallRecord } from '@fougere/core';
|
|
7
|
-
export { CallRing } from './CallRing.js';
|
|
8
|
-
export { LogRing, QueryRing, ErrorRing } from './rings.js';
|
|
9
|
-
export type { LogLine, QueryLine, ErrorGroup } from './rings.js';
|
|
10
|
-
export { servePanel, type PanelOptions } from './panel.js';
|
|
11
8
|
|
|
12
9
|
/** The rpc operation this extension answers under. */
|
|
13
10
|
export const CALLS_OP = 'calls';
|
|
@@ -22,7 +19,7 @@ export interface CallsOptions {
|
|
|
22
19
|
/** What this process serves, read from the app itself. */
|
|
23
20
|
function servedModel(app: App): unknown {
|
|
24
21
|
return {
|
|
25
|
-
fronds: app.fronds.map((frond) => ({
|
|
22
|
+
fronds: app.fronds.filter((frond) => !frond.brought).map((frond) => ({
|
|
26
23
|
name: frond.name,
|
|
27
24
|
// What the config SAYS. What the runtime saw is in the ring, under `route` — and the
|
|
28
25
|
// two disagree exactly when something is misconfigured, which is the whole point of
|
|
@@ -111,21 +108,40 @@ export function calls(options: CallsOptions = {}): Extension {
|
|
|
111
108
|
return {
|
|
112
109
|
name: 'calls',
|
|
113
110
|
|
|
111
|
+
// What it needs a SIGNATURE for: every line this process logs. Stated rather than
|
|
112
|
+
// scanned, because a published package is read by no scanner.
|
|
113
|
+
fronds: [frond('calls', {
|
|
114
|
+
handlers: [{
|
|
115
|
+
ctor: KeepHandler,
|
|
116
|
+
deps: ['LogRing', 'ErrorRing'],
|
|
117
|
+
operations: {
|
|
118
|
+
record: {
|
|
119
|
+
input: LogLine,
|
|
120
|
+
binding: [{ name: 'line', optional: false, source: { kind: 'fact', factName: 'logLine' } }],
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
}],
|
|
124
|
+
})],
|
|
125
|
+
|
|
114
126
|
async up(app: App) {
|
|
115
127
|
const ring = new CallRing(options.max ?? 500, frondIndex(app));
|
|
116
128
|
const logs = new LogRing();
|
|
117
129
|
const errors = new ErrorRing();
|
|
118
130
|
const queries = new QueryRing();
|
|
119
131
|
|
|
132
|
+
// The rings the frond's handler asks for. Registered here and resolved at its first
|
|
133
|
+
// call, which is after this ascent — so a signature replaces the `onLog` sink.
|
|
134
|
+
app.container.registerValue('LogRing', logs);
|
|
135
|
+
app.container.registerValue('ErrorRing', errors);
|
|
136
|
+
|
|
120
137
|
const undo = [
|
|
121
138
|
app.observe((event) => {
|
|
139
|
+
// Not its own: keeping a line is a DISPATCH, so the ring would fill with the
|
|
140
|
+
// writes that fill it — the same shape as a logger that logs its own carrying.
|
|
141
|
+
if (CARRIES_LINE.has(event.call.address.entity)) return;
|
|
122
142
|
ring.record(event);
|
|
123
143
|
if (event.stage === 'failed') errors.fromDispatch(event);
|
|
124
144
|
}),
|
|
125
|
-
onLog((line) => {
|
|
126
|
-
logs.record(line);
|
|
127
|
-
errors.fromLog(line);
|
|
128
|
-
}),
|
|
129
145
|
// `@fougere/adapter-sql` is optional — an app on another storage, or none, simply
|
|
130
146
|
// never resolves it, and the Queries tab says there is none rather than staying
|
|
131
147
|
// blank. Dynamic on purpose: this package declares no dependency on it.
|
|
@@ -146,7 +162,8 @@ export function calls(options: CallsOptions = {}): Extension {
|
|
|
146
162
|
...asked,
|
|
147
163
|
...(port !== undefined ? { port } : {}),
|
|
148
164
|
title: asked.title ?? app.fronds[0]?.name ?? 'fougere',
|
|
149
|
-
|
|
165
|
+
// What this app SERVES: a frond an extension brought is instrumentation.
|
|
166
|
+
fronds: app.fronds.filter((frond) => !frond.brought).map((frond) => frond.name),
|
|
150
167
|
model: servedModel(app),
|
|
151
168
|
logs: (cursor) => logs.since(cursor),
|
|
152
169
|
errors: (cursor) => errors.since(cursor),
|