@fougere/core 0.16.3-alpha.0 → 0.16.5-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/StatedModules.d.ts +2 -1
- package/dist/StatedModules.d.ts.map +1 -1
- package/dist/StatedModules.js +1 -2
- package/dist/StatedModules.js.map +1 -1
- package/dist/boot/ambient-port.d.ts +4 -0
- package/dist/boot/ambient-port.d.ts.map +1 -1
- package/dist/boot/ambient.als.d.ts.map +1 -1
- package/dist/boot/ambient.als.js +5 -0
- package/dist/boot/ambient.als.js.map +1 -1
- package/dist/boot/ambient.queue.d.ts.map +1 -1
- package/dist/boot/ambient.queue.js +4 -0
- package/dist/boot/ambient.queue.js.map +1 -1
- package/dist/boot/bootstrap.d.ts.map +1 -1
- package/dist/boot/bootstrap.js +2 -1
- package/dist/boot/bootstrap.js.map +1 -1
- package/dist/boot/install.d.ts.map +1 -1
- package/dist/boot/install.js +22 -16
- package/dist/boot/install.js.map +1 -1
- package/dist/builtin/LogLine.d.ts +3 -1
- package/dist/builtin/LogLine.d.ts.map +1 -1
- package/dist/builtin/LogLine.js +3 -1
- package/dist/builtin/LogLine.js.map +1 -1
- package/dist/builtin/LogRecord.d.ts +2 -0
- package/dist/builtin/LogRecord.d.ts.map +1 -1
- package/dist/builtin/Logger.d.ts +1 -0
- package/dist/builtin/Logger.d.ts.map +1 -1
- package/dist/builtin/Logger.js +12 -3
- package/dist/builtin/Logger.js.map +1 -1
- package/dist/builtin/LoggerOptions.d.ts +2 -0
- package/dist/builtin/LoggerOptions.d.ts.map +1 -1
- package/dist/builtin/OwnLoggers.d.ts +10 -0
- package/dist/builtin/OwnLoggers.d.ts.map +1 -0
- package/dist/builtin/OwnLoggers.js +15 -0
- package/dist/builtin/OwnLoggers.js.map +1 -0
- package/dist/builtin/Rendered.d.ts +1 -0
- package/dist/builtin/Rendered.d.ts.map +1 -1
- package/dist/dispatch/Facade.d.ts +5 -0
- package/dist/dispatch/Facade.d.ts.map +1 -1
- package/dist/dispatch/HandlerFacade.d.ts.map +1 -1
- package/dist/dispatch/HandlerFacade.js +5 -2
- package/dist/dispatch/HandlerFacade.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js.map +1 -1
- package/dist/wire/OperationContext.d.ts +2 -0
- package/dist/wire/OperationContext.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/StatedModules.ts +2 -2
- package/src/boot/ambient-port.ts +6 -0
- package/src/boot/ambient.als.ts +7 -0
- package/src/boot/ambient.queue.ts +6 -0
- package/src/boot/bootstrap.ts +2 -1
- package/src/boot/install.ts +23 -14
- package/src/builtin/LogLine.ts +3 -1
- package/src/builtin/LogRecord.ts +2 -0
- package/src/builtin/Logger.ts +12 -3
- package/src/builtin/LoggerOptions.ts +2 -0
- package/src/builtin/OwnLoggers.ts +21 -0
- package/src/builtin/Rendered.ts +1 -0
- package/src/dispatch/Facade.ts +5 -0
- package/src/dispatch/HandlerFacade.ts +7 -2
- package/src/index.ts +0 -1
- package/src/node.ts +1 -1
- package/src/wire/OperationContext.ts +2 -0
- package/dist/wire/loggerMiddleware.d.ts +0 -8
- package/dist/wire/loggerMiddleware.d.ts.map +0 -1
- package/dist/wire/loggerMiddleware.js +0 -25
- package/dist/wire/loggerMiddleware.js.map +0 -1
- package/src/wire/loggerMiddleware.ts +0 -30
package/src/builtin/LogRecord.ts
CHANGED
package/src/builtin/Logger.ts
CHANGED
|
@@ -73,16 +73,22 @@ export class Logger {
|
|
|
73
73
|
private name: string;
|
|
74
74
|
private color: boolean;
|
|
75
75
|
private carry?: Carry;
|
|
76
|
+
private during?: () => string | undefined;
|
|
76
77
|
|
|
77
78
|
constructor(prefix?: string, options?: Omit<LoggerOptions, 'name'>) {
|
|
78
79
|
this.name = prefix ?? 'app';
|
|
79
80
|
this.color = options?.color ?? supportsColor();
|
|
80
81
|
this.carry = options?.carry;
|
|
82
|
+
this.during = options?.during;
|
|
81
83
|
}
|
|
82
84
|
|
|
83
85
|
/** Create a child logger with a sub-name. It carries no level of its own either. */
|
|
84
86
|
child(name: string): Logger {
|
|
85
|
-
return new Logger(`${this.name}:${name}`, {
|
|
87
|
+
return new Logger(`${this.name}:${name}`, {
|
|
88
|
+
color: this.color,
|
|
89
|
+
...(this.carry ? { carry: this.carry } : {}),
|
|
90
|
+
...(this.during ? { during: this.during } : {}),
|
|
91
|
+
});
|
|
86
92
|
}
|
|
87
93
|
|
|
88
94
|
debug(msg: string, ...args: unknown[]) { this.log('debug', msg, args); }
|
|
@@ -92,8 +98,10 @@ export class Logger {
|
|
|
92
98
|
|
|
93
99
|
private log(level: string, msg: string, args: unknown[]) {
|
|
94
100
|
if (LEVELS[level as LogLevel] < threshold) return;
|
|
101
|
+
const during = this.during?.();
|
|
95
102
|
const record: LogRecord = {
|
|
96
103
|
level: level as LogRecord['level'], name: this.name, message: msg, args, at: Date.now(),
|
|
104
|
+
...(during ? { during } : {}),
|
|
97
105
|
};
|
|
98
106
|
|
|
99
107
|
this.carry?.push({ ...record, args: args.map(objectOf) });
|
|
@@ -118,13 +126,14 @@ export function formatted(
|
|
|
118
126
|
const style = LEVEL_STYLE[record.level];
|
|
119
127
|
const time = stamp(record.at);
|
|
120
128
|
const method = record.level;
|
|
129
|
+
const during = record.during ? ` (${record.during})` : '';
|
|
121
130
|
|
|
122
131
|
if (color) {
|
|
123
132
|
const c = COLORS[style.color];
|
|
124
|
-
const prefix = `${COLORS.dim}${time}${COLORS.reset} ${c}${COLORS.bold}${style.badge}${COLORS.reset} ${COLORS.magenta}${record.name}${COLORS.reset}`;
|
|
133
|
+
const prefix = `${COLORS.dim}${time}${COLORS.reset} ${c}${COLORS.bold}${style.badge}${COLORS.reset} ${COLORS.magenta}${record.name}${COLORS.reset}${COLORS.gray}${during}${COLORS.reset}`;
|
|
125
134
|
|
|
126
135
|
return { method, text: [prefix, record.message, ...(record.args ?? [])] };
|
|
127
136
|
}
|
|
128
137
|
|
|
129
|
-
return { method, text: [`${time} ${style.badge} [${record.name}]`, record.message, ...(record.args ?? [])] };
|
|
138
|
+
return { method, text: [`${time} ${style.badge} [${record.name}]${during}`, record.message, ...(record.args ?? [])] };
|
|
130
139
|
}
|
|
@@ -9,6 +9,8 @@ export interface LoggerOptions {
|
|
|
9
9
|
* first lines do and what an app declaring no destination does forever.
|
|
10
10
|
*/
|
|
11
11
|
carry?: Carry;
|
|
12
|
+
/** The operation a line is written inside, asked at each line — the boot hands it over. */
|
|
13
|
+
during?: () => string | undefined;
|
|
12
14
|
/** Force color on/off. Auto-detected by default. */
|
|
13
15
|
color?: boolean;
|
|
14
16
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Container } from '@fougere/container';
|
|
2
|
+
import type { Logger } from './Logger.js';
|
|
3
|
+
|
|
4
|
+
/** A class's deps, its `Logger` replaced by one named after it. */
|
|
5
|
+
export type OwnLogger = (className: string, deps: readonly string[]) => string[];
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A class asking for `Logger` gets one named after it — `app:blog:PricingService` — under a key of
|
|
9
|
+
* its own, so the container builds nothing new. A frond that `replaced` it with a class of its own
|
|
10
|
+
* keeps that class whole: `child()` hands back a bare `Logger`.
|
|
11
|
+
*/
|
|
12
|
+
export function ownLoggers(scope: Container, replaced: boolean): OwnLogger {
|
|
13
|
+
return (className, deps) => {
|
|
14
|
+
if (replaced || !deps.includes('Logger')) return [...deps];
|
|
15
|
+
|
|
16
|
+
const key = `Logger:${className}`;
|
|
17
|
+
scope.registerValue(key, scope.resolve<Logger>('Logger').child(className));
|
|
18
|
+
|
|
19
|
+
return deps.map((dep) => (dep === 'Logger' ? key : dep));
|
|
20
|
+
};
|
|
21
|
+
}
|
package/src/builtin/Rendered.ts
CHANGED
|
@@ -14,6 +14,7 @@ export interface Rendered {
|
|
|
14
14
|
level: Exclude<LogLevel, 'silent'>;
|
|
15
15
|
name: string;
|
|
16
16
|
message: string;
|
|
17
|
+
during?: string | null;
|
|
17
18
|
/** Absent on most lines: a message usually carries its own detail. */
|
|
18
19
|
args?: unknown[] | null;
|
|
19
20
|
/** Epoch milliseconds from a logger, a `Date` from an entity that stamped it. */
|
package/src/dispatch/Facade.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { EffectiveOperationsMap } from '../EffectiveOperationsMap.js';
|
|
|
4
4
|
import type { HandlerEntry } from '../descriptor/HandlerEntry.js';
|
|
5
5
|
import type { PresenterEntry } from '../descriptor/PresenterEntry.js';
|
|
6
6
|
import type { StateShape } from '../wire/StateShape.js';
|
|
7
|
+
import type { OwnLogger } from '../builtin/OwnLoggers.js';
|
|
7
8
|
|
|
8
9
|
/** What boot resolved around one handler, beyond the handler and the scope it resolves in. */
|
|
9
10
|
export interface Facade {
|
|
@@ -25,4 +26,8 @@ export interface Facade {
|
|
|
25
26
|
middlewares: () => AppMiddleware[];
|
|
26
27
|
/** What a call's `state` may hold in this process. */
|
|
27
28
|
state: StateShape;
|
|
29
|
+
/** Runs the handler as the operation a line written inside it names. */
|
|
30
|
+
enterOperation: <R>(label: string, fn: () => Promise<R>) => Promise<R>;
|
|
31
|
+
/** The handler's deps, its `Logger` named after it. */
|
|
32
|
+
ownLogger: OwnLogger;
|
|
28
33
|
}
|
|
@@ -92,16 +92,21 @@ export class HandlerFacade {
|
|
|
92
92
|
const state = received.crossed ? { ...received.state } : this.facade.state.judge(received.state, entity, op);
|
|
93
93
|
const invocation = received.withState(state);
|
|
94
94
|
const entered = { ...state };
|
|
95
|
+
const { className, method } = this.effectiveOperations.get(op)!.implementation;
|
|
95
96
|
const context: OperationContext = {
|
|
96
97
|
entity,
|
|
97
98
|
frond: this.facade.frond,
|
|
99
|
+
handler: className,
|
|
98
100
|
operation: op,
|
|
99
101
|
args: [],
|
|
100
102
|
state: invocation.state,
|
|
101
103
|
invocation,
|
|
102
104
|
};
|
|
103
105
|
|
|
104
|
-
|
|
106
|
+
const label = `${this.facade.frond}:${className}.${method}`;
|
|
107
|
+
|
|
108
|
+
return runMiddlewares(this.facade.middlewares(), context, () =>
|
|
109
|
+
this.facade.enterOperation(label, () => this.answer(op, contract, context, invocation, entered)));
|
|
105
110
|
}
|
|
106
111
|
|
|
107
112
|
/**
|
|
@@ -162,7 +167,7 @@ export class HandlerFacade {
|
|
|
162
167
|
|
|
163
168
|
private depsOf(handler: HandlerEntry): string[] {
|
|
164
169
|
const { deps } = handler;
|
|
165
|
-
if (deps.length > 0) return deps;
|
|
170
|
+
if (deps.length > 0) return this.facade.ownLogger(handler.ctor.name, deps);
|
|
166
171
|
|
|
167
172
|
return inheritsCrud(handler.ctor)
|
|
168
173
|
? [repositoryKeyOf(subjectOf(handler.ctor, handler.address))]
|
package/src/index.ts
CHANGED
|
@@ -110,7 +110,6 @@ export { type Pipe } from './wire/Pipe.js';
|
|
|
110
110
|
export { callValueOf } from './contract.js';
|
|
111
111
|
export { toHttpError } from './wire/http-error.js';
|
|
112
112
|
export { toPublicError } from './contract.js';
|
|
113
|
-
export { loggerMiddleware } from './wire/loggerMiddleware.js';
|
|
114
113
|
export { Carry } from './builtin/Carry.js';
|
|
115
114
|
export { Logger, envLevel, formatted, logLevel, setLogLevel } from './builtin/Logger.js';
|
|
116
115
|
export type { LogRecord } from './builtin/LogRecord.js';
|
package/src/node.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** What Fougere does with a filesystem, minus the scan — that is `@fougere/compiler`. */
|
|
2
|
-
export { setModuleLoader, getModuleLoader } from './loader.js';
|
|
2
|
+
export { setModuleLoader, getModuleLoader, type ModuleLoader } from './loader.js';
|
|
3
3
|
export { configFileIn, loadConfig, loadCascadedConfig, projectRootOf, remotesOf } from './FougereConfig.js';
|
|
4
4
|
export { statedModules } from './StatedModules.js';
|
|
5
5
|
export { defineFrond, loadFrondConfig } from './FrondConfig.js';
|
|
@@ -7,6 +7,8 @@ export interface OperationContext {
|
|
|
7
7
|
* one a reader groups by first. Absent only where no frond claims the call.
|
|
8
8
|
*/
|
|
9
9
|
frond?: string;
|
|
10
|
+
/** The class that answers, as the scan named it — `PostHandler`. */
|
|
11
|
+
handler?: string;
|
|
10
12
|
/** Operation name (e.g. 'create', 'findById', 'searchByTitle'). */
|
|
11
13
|
operation: string;
|
|
12
14
|
/** Arguments passed to the operation. */
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Logger middleware — logs every operation with timing.
|
|
3
|
-
*/
|
|
4
|
-
import type { AppMiddleware } from './AppMiddleware.js';
|
|
5
|
-
import type { Logger } from '../builtin/Logger.js';
|
|
6
|
-
/** Create a logger middleware that logs operation entry, exit, and errors. */
|
|
7
|
-
export declare function loggerMiddleware(logger: Logger): AppMiddleware;
|
|
8
|
-
//# sourceMappingURL=loggerMiddleware.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"loggerMiddleware.d.ts","sourceRoot":"","sources":["../../src/wire/loggerMiddleware.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAGnD,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAqB9D"}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { CARRIES_LINE } from '../builtin/LogLine.js';
|
|
2
|
-
/** Create a logger middleware that logs operation entry, exit, and errors. */
|
|
3
|
-
export function loggerMiddleware(logger) {
|
|
4
|
-
return async (ctx, next) => {
|
|
5
|
-
// An op that CARRIES a line writes none: it is dispatched, so logging it announces a
|
|
6
|
-
// line inside the announcement of one — `Emission cycle: logLine → logLine`, which is
|
|
7
|
-
// the emission catching what `onLog`'s try/catch used to swallow.
|
|
8
|
-
if (CARRIES_LINE.has(ctx.entity))
|
|
9
|
-
return next();
|
|
10
|
-
const start = performance.now();
|
|
11
|
-
logger.info(`${ctx.entity}.${ctx.operation}`);
|
|
12
|
-
try {
|
|
13
|
-
const result = await next();
|
|
14
|
-
const ms = (performance.now() - start).toFixed(1);
|
|
15
|
-
logger.info(`${ctx.entity}.${ctx.operation} (${ms}ms)`);
|
|
16
|
-
return result;
|
|
17
|
-
}
|
|
18
|
-
catch (err) {
|
|
19
|
-
const ms = (performance.now() - start).toFixed(1);
|
|
20
|
-
logger.error(`${ctx.entity}.${ctx.operation} (${ms}ms)`, err);
|
|
21
|
-
throw err;
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
//# sourceMappingURL=loggerMiddleware.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"loggerMiddleware.js","sourceRoot":"","sources":["../../src/wire/loggerMiddleware.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAErD,8EAA8E;AAC9E,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,OAAO,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACzB,qFAAqF;QACrF,sFAAsF;QACtF,kEAAkE;QAClE,IAAI,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,OAAO,IAAI,EAAE,CAAC;QAEhD,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAChC,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC;QAC9C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,EAAE,CAAC;YAC5B,MAAM,EAAE,GAAG,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YAClD,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,SAAS,KAAK,EAAE,KAAK,CAAC,CAAC;YAExD,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,EAAE,GAAG,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YAClD,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,SAAS,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;YAC9D,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Logger middleware — logs every operation with timing.
|
|
3
|
-
*/
|
|
4
|
-
import type { AppMiddleware } from './AppMiddleware.js';
|
|
5
|
-
import type { Logger } from '../builtin/Logger.js';
|
|
6
|
-
import { CARRIES_LINE } from '../builtin/LogLine.js';
|
|
7
|
-
|
|
8
|
-
/** Create a logger middleware that logs operation entry, exit, and errors. */
|
|
9
|
-
export function loggerMiddleware(logger: Logger): AppMiddleware {
|
|
10
|
-
return async (ctx, next) => {
|
|
11
|
-
// An op that CARRIES a line writes none: it is dispatched, so logging it announces a
|
|
12
|
-
// line inside the announcement of one — `Emission cycle: logLine → logLine`, which is
|
|
13
|
-
// the emission catching what `onLog`'s try/catch used to swallow.
|
|
14
|
-
if (CARRIES_LINE.has(ctx.entity)) return next();
|
|
15
|
-
|
|
16
|
-
const start = performance.now();
|
|
17
|
-
logger.info(`${ctx.entity}.${ctx.operation}`);
|
|
18
|
-
try {
|
|
19
|
-
const result = await next();
|
|
20
|
-
const ms = (performance.now() - start).toFixed(1);
|
|
21
|
-
logger.info(`${ctx.entity}.${ctx.operation} (${ms}ms)`);
|
|
22
|
-
|
|
23
|
-
return result;
|
|
24
|
-
} catch (err) {
|
|
25
|
-
const ms = (performance.now() - start).toFixed(1);
|
|
26
|
-
logger.error(`${ctx.entity}.${ctx.operation} (${ms}ms)`, err);
|
|
27
|
-
throw err;
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
}
|