@fedify/adonisjs 2.4.0-dev.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/LICENSE +20 -0
- package/README.md +420 -0
- package/dist/configure.cjs +108 -0
- package/dist/configure.cjs.map +1 -0
- package/dist/configure.d.cts +14 -0
- package/dist/configure.d.ts +14 -0
- package/dist/configure.js +107 -0
- package/dist/configure.js.map +1 -0
- package/dist/index.cjs +19 -0
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +8 -0
- package/dist/package.cjs +121 -0
- package/dist/package.cjs.map +1 -0
- package/dist/package.js +115 -0
- package/dist/package.js.map +1 -0
- package/dist/providers/fedify_provider.cjs +270 -0
- package/dist/providers/fedify_provider.cjs.map +1 -0
- package/dist/providers/fedify_provider.d.cts +54 -0
- package/dist/providers/fedify_provider.d.ts +55 -0
- package/dist/providers/fedify_provider.js +269 -0
- package/dist/providers/fedify_provider.js.map +1 -0
- package/dist/services/builder.cjs +9 -0
- package/dist/services/builder.cjs.map +1 -0
- package/dist/services/builder.d.cts +7 -0
- package/dist/services/builder.d.ts +8 -0
- package/dist/services/builder.js +8 -0
- package/dist/services/builder.js.map +1 -0
- package/dist/src/builder.cjs +55 -0
- package/dist/src/builder.cjs.map +1 -0
- package/dist/src/builder.d.cts +14 -0
- package/dist/src/builder.d.ts +14 -0
- package/dist/src/builder.js +54 -0
- package/dist/src/builder.js.map +1 -0
- package/dist/src/define_config.cjs +114 -0
- package/dist/src/define_config.cjs.map +1 -0
- package/dist/src/define_config.d.cts +30 -0
- package/dist/src/define_config.d.ts +30 -0
- package/dist/src/define_config.js +113 -0
- package/dist/src/define_config.js.map +1 -0
- package/dist/src/errors.cjs +77 -0
- package/dist/src/errors.cjs.map +1 -0
- package/dist/src/errors.d.cts +56 -0
- package/dist/src/errors.d.ts +56 -0
- package/dist/src/errors.js +73 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/fedify_middleware.cjs +507 -0
- package/dist/src/fedify_middleware.cjs.map +1 -0
- package/dist/src/fedify_middleware.d.cts +85 -0
- package/dist/src/fedify_middleware.d.ts +85 -0
- package/dist/src/fedify_middleware.js +505 -0
- package/dist/src/fedify_middleware.js.map +1 -0
- package/dist/src/http_context.cjs +79 -0
- package/dist/src/http_context.cjs.map +1 -0
- package/dist/src/http_context.d.cts +31 -0
- package/dist/src/http_context.d.ts +31 -0
- package/dist/src/http_context.js +76 -0
- package/dist/src/http_context.js.map +1 -0
- package/dist/src/logging.cjs +106 -0
- package/dist/src/logging.cjs.map +1 -0
- package/dist/src/logging.d.cts +45 -0
- package/dist/src/logging.d.ts +45 -0
- package/dist/src/logging.js +106 -0
- package/dist/src/logging.js.map +1 -0
- package/dist/src/types.cjs +1 -0
- package/dist/src/types.d.cts +269 -0
- package/dist/src/types.d.ts +269 -0
- package/dist/src/types.js +1 -0
- package/dist/src/unusable_authority.cjs +79 -0
- package/dist/src/unusable_authority.cjs.map +1 -0
- package/dist/src/unusable_authority.js +76 -0
- package/dist/src/unusable_authority.js.map +1 -0
- package/dist/stubs/config/fedify.stub +105 -0
- package/dist/stubs/federation/main.stub +64 -0
- package/dist/stubs/main.cjs +16 -0
- package/dist/stubs/main.cjs.map +1 -0
- package/dist/stubs/main.d.cts +11 -0
- package/dist/stubs/main.d.ts +11 -0
- package/dist/stubs/main.js +15 -0
- package/dist/stubs/main.js.map +1 -0
- package/dist/stubs/start/federation.stub +20 -0
- package/package.json +124 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
const require_src_errors = require('./errors.cjs');
|
|
3
|
+
let _adonisjs_core_http = require("@adonisjs/core/http");
|
|
4
|
+
|
|
5
|
+
//#region src/http_context.ts
|
|
6
|
+
/**
|
|
7
|
+
* The `ctx.federation` accessor: a Macroable getter on `HttpContext` (like
|
|
8
|
+
* `ctx.view`) that reads a per-request factory the middleware stores on the
|
|
9
|
+
* instance, and memoises the result.
|
|
10
|
+
*
|
|
11
|
+
* @module
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* The per-request slot holding the factory for `ctx.federation`. A
|
|
15
|
+
* registered symbol so the ESM and CommonJS builds share it, keyed by major
|
|
16
|
+
* version so another major in the same process gets its own.
|
|
17
|
+
*/
|
|
18
|
+
const FACTORY = Symbol.for("@fedify/adonisjs@2/federation-factory");
|
|
19
|
+
/**
|
|
20
|
+
* The accessors this module has installed, so a `federation` member defined
|
|
21
|
+
* by somebody else can be told apart from ours. `Macroable.getter()` wraps
|
|
22
|
+
* the function it is given, hence a registry rather than a marker; it lives on
|
|
23
|
+
* `globalThis` for the same reasons as {@link FACTORY}.
|
|
24
|
+
*/
|
|
25
|
+
const INSTALLED = Symbol.for("@fedify/adonisjs@2/federation-getters");
|
|
26
|
+
const registry = globalThis;
|
|
27
|
+
const installedGetters = registry[INSTALLED] ??= new WeakSet();
|
|
28
|
+
/**
|
|
29
|
+
* Records how to create the `RequestContext` for `ctx`; the getter runs
|
|
30
|
+
* `create` on first access.
|
|
31
|
+
*/
|
|
32
|
+
function setFederationContextFactory(ctx, create) {
|
|
33
|
+
Object.defineProperty(ctx, FACTORY, {
|
|
34
|
+
value: create,
|
|
35
|
+
configurable: true,
|
|
36
|
+
enumerable: false,
|
|
37
|
+
writable: true
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Installs the `federation` getter on a context class, once per class. The
|
|
42
|
+
* middleware also calls this on `ctx.constructor`, which covers an
|
|
43
|
+
* application with its own copy of `@adonisjs/core`. Macroable's
|
|
44
|
+
* `singleton` flag memoises the value on the instance.
|
|
45
|
+
*
|
|
46
|
+
* @returns `false` when a `federation` member somebody else defined is in the
|
|
47
|
+
* way; nothing is changed then, and the caller decides how to report it.
|
|
48
|
+
*/
|
|
49
|
+
function ensureFederationGetter(target = _adonisjs_core_http.HttpContext) {
|
|
50
|
+
const existing = Object.getOwnPropertyDescriptor(target.prototype, "federation");
|
|
51
|
+
if (existing !== undefined) return isOwnGetter(existing.get);
|
|
52
|
+
target.getter("federation", function() {
|
|
53
|
+
const create = this[FACTORY];
|
|
54
|
+
if (create === undefined) {
|
|
55
|
+
throw new require_src_errors.E_FEDIFY_CONTEXT_UNAVAILABLE(this.request.url());
|
|
56
|
+
}
|
|
57
|
+
return create();
|
|
58
|
+
}, true);
|
|
59
|
+
const installed = Object.getOwnPropertyDescriptor(target.prototype, "federation")?.get;
|
|
60
|
+
if (installed !== undefined) installedGetters.add(installed);
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* {@link ensureFederationGetter}, but a conflict throws. Called from the
|
|
65
|
+
* provider's `boot()`.
|
|
66
|
+
*/
|
|
67
|
+
function installFederationGetter(target = _adonisjs_core_http.HttpContext) {
|
|
68
|
+
if (ensureFederationGetter(target)) return;
|
|
69
|
+
throw new Error("Cannot install \"ctx.federation\": the HttpContext class already has a " + "\"federation\" member that @fedify/adonisjs did not define. Remove the " + "conflicting macro or getter, or rename it");
|
|
70
|
+
}
|
|
71
|
+
function isOwnGetter(fn) {
|
|
72
|
+
return typeof fn === "function" && installedGetters.has(fn);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
//#endregion
|
|
76
|
+
exports.ensureFederationGetter = ensureFederationGetter;
|
|
77
|
+
exports.installFederationGetter = installFederationGetter;
|
|
78
|
+
exports.setFederationContextFactory = setFederationContextFactory;
|
|
79
|
+
//# sourceMappingURL=http_context.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http_context.cjs","names":["HttpContext","E_FEDIFY_CONTEXT_UNAVAILABLE"],"sources":["../../src/http_context.ts"],"sourcesContent":["/**\n * The `ctx.federation` accessor: a Macroable getter on `HttpContext` (like\n * `ctx.view`) that reads a per-request factory the middleware stores on the\n * instance, and memoises the result.\n *\n * @module\n */\nimport { HttpContext } from \"@adonisjs/core/http\";\nimport type { RequestContext } from \"@fedify/fedify\";\n\nimport { E_FEDIFY_CONTEXT_UNAVAILABLE } from \"./errors.ts\";\n\n/**\n * The per-request slot holding the factory for `ctx.federation`. A\n * registered symbol so the ESM and CommonJS builds share it, keyed by major\n * version so another major in the same process gets its own.\n */\nconst FACTORY: unique symbol = Symbol.for(\n \"@fedify/adonisjs@2/federation-factory\",\n);\n\n/**\n * The accessors this module has installed, so a `federation` member defined\n * by somebody else can be told apart from ours. `Macroable.getter()` wraps\n * the function it is given, hence a registry rather than a marker; it lives on\n * `globalThis` for the same reasons as {@link FACTORY}.\n */\nconst INSTALLED: unique symbol = Symbol.for(\n \"@fedify/adonisjs@2/federation-getters\",\n);\n\nconst registry = globalThis as { [INSTALLED]?: WeakSet<object> };\n\nconst installedGetters: WeakSet<object> = registry[INSTALLED] ??= new WeakSet();\n\n/**\n * The shape of a context that carries the {@link FACTORY} slot.\n */\ntype FactoryCarrier = {\n [FACTORY]?: () => RequestContext<unknown>;\n};\n\n/**\n * A context class the getter can be installed on.\n */\nexport type HttpContextClass = typeof HttpContext;\n\n/**\n * Records how to create the `RequestContext` for `ctx`; the getter runs\n * `create` on first access.\n */\nexport function setFederationContextFactory<TContextData>(\n ctx: HttpContext,\n create: () => RequestContext<TContextData>,\n): void {\n Object.defineProperty(ctx, FACTORY, {\n value: create,\n configurable: true,\n enumerable: false,\n writable: true,\n });\n}\n\n/**\n * Installs the `federation` getter on a context class, once per class. The\n * middleware also calls this on `ctx.constructor`, which covers an\n * application with its own copy of `@adonisjs/core`. Macroable's\n * `singleton` flag memoises the value on the instance.\n *\n * @returns `false` when a `federation` member somebody else defined is in the\n * way; nothing is changed then, and the caller decides how to report it.\n */\nexport function ensureFederationGetter(\n target: HttpContextClass = HttpContext,\n): boolean {\n const existing = Object.getOwnPropertyDescriptor(\n target.prototype,\n \"federation\",\n );\n if (existing !== undefined) return isOwnGetter(existing.get);\n\n target.getter(\"federation\", function (this: HttpContext) {\n const create = (this as HttpContext & FactoryCarrier)[FACTORY];\n if (create === undefined) {\n throw new E_FEDIFY_CONTEXT_UNAVAILABLE(this.request.url());\n }\n return create() as HttpContext[\"federation\"];\n }, true);\n\n // Record the wrapper Macroable actually installed.\n const installed = Object.getOwnPropertyDescriptor(\n target.prototype,\n \"federation\",\n )?.get;\n if (installed !== undefined) installedGetters.add(installed);\n\n return true;\n}\n\n/**\n * {@link ensureFederationGetter}, but a conflict throws. Called from the\n * provider's `boot()`.\n */\nexport function installFederationGetter(\n target: HttpContextClass = HttpContext,\n): void {\n if (ensureFederationGetter(target)) return;\n\n throw new Error(\n 'Cannot install \"ctx.federation\": the HttpContext class already has a ' +\n '\"federation\" member that @fedify/adonisjs did not define. Remove the ' +\n \"conflicting macro or getter, or rename it\",\n );\n}\n\nfunction isOwnGetter(fn: unknown): boolean {\n return typeof fn === \"function\" && installedGetters.has(fn);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAiBA,MAAM,UAAyB,OAAO,IACpC,uCACF;;;;;;;AAQA,MAAM,YAA2B,OAAO,IACtC,uCACF;AAEA,MAAM,WAAW;AAEjB,MAAM,mBAAoC,SAAS,eAAe,IAAI,QAAQ;;;;;AAkB9E,SAAgB,4BACd,KACA,QACM;CACN,OAAO,eAAe,KAAK,SAAS;EAClC,OAAO;EACP,cAAc;EACd,YAAY;EACZ,UAAU;CACZ,CAAC;AACH;;;;;;;;;;AAWA,SAAgB,uBACd,SAA2BA,iCAClB;CACT,MAAM,WAAW,OAAO,yBACtB,OAAO,WACP,YACF;CACA,IAAI,aAAa,WAAW,OAAO,YAAY,SAAS,GAAG;CAE3D,OAAO,OAAO,cAAc,WAA6B;EACvD,MAAM,SAAU,KAAsC;EACtD,IAAI,WAAW,WAAW;GACxB,MAAM,IAAIC,gDAA6B,KAAK,QAAQ,IAAI,CAAC;EAC3D;EACA,OAAO,OAAO;CAChB,GAAG,IAAI;CAGP,MAAM,YAAY,OAAO,yBACvB,OAAO,WACP,YACF,CAAC,EAAE;CACH,IAAI,cAAc,WAAW,iBAAiB,IAAI,SAAS;CAE3D,OAAO;AACT;;;;;AAMA,SAAgB,wBACd,SAA2BD,iCACrB;CACN,IAAI,uBAAuB,MAAM,GAAG;CAEpC,MAAM,IAAI,MACR,4EACE,4EACA,2CACJ;AACF;AAEA,SAAS,YAAY,IAAsB;CACzC,OAAO,OAAO,OAAO,cAAc,iBAAiB,IAAI,EAAE;AAC5D"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { HttpContext } from "@adonisjs/core/http";
|
|
2
|
+
import { RequestContext } from "@fedify/fedify";
|
|
3
|
+
|
|
4
|
+
//#region src/http_context.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* A context class the getter can be installed on.
|
|
7
|
+
*/
|
|
8
|
+
type HttpContextClass = typeof HttpContext;
|
|
9
|
+
/**
|
|
10
|
+
* Records how to create the `RequestContext` for `ctx`; the getter runs
|
|
11
|
+
* `create` on first access.
|
|
12
|
+
*/
|
|
13
|
+
declare function setFederationContextFactory<TContextData>(ctx: HttpContext, create: () => RequestContext<TContextData>): void;
|
|
14
|
+
/**
|
|
15
|
+
* Installs the `federation` getter on a context class, once per class. The
|
|
16
|
+
* middleware also calls this on `ctx.constructor`, which covers an
|
|
17
|
+
* application with its own copy of `@adonisjs/core`. Macroable's
|
|
18
|
+
* `singleton` flag memoises the value on the instance.
|
|
19
|
+
*
|
|
20
|
+
* @returns `false` when a `federation` member somebody else defined is in the
|
|
21
|
+
* way; nothing is changed then, and the caller decides how to report it.
|
|
22
|
+
*/
|
|
23
|
+
declare function ensureFederationGetter(target?: HttpContextClass): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* {@link ensureFederationGetter}, but a conflict throws. Called from the
|
|
26
|
+
* provider's `boot()`.
|
|
27
|
+
*/
|
|
28
|
+
declare function installFederationGetter(target?: HttpContextClass): void;
|
|
29
|
+
//#endregion
|
|
30
|
+
export { HttpContextClass, ensureFederationGetter, installFederationGetter, setFederationContextFactory };
|
|
31
|
+
//# sourceMappingURL=http_context.d.cts.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { HttpContext } from "@adonisjs/core/http";
|
|
2
|
+
import { RequestContext } from "@fedify/fedify";
|
|
3
|
+
|
|
4
|
+
//#region src/http_context.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* A context class the getter can be installed on.
|
|
7
|
+
*/
|
|
8
|
+
type HttpContextClass = typeof HttpContext;
|
|
9
|
+
/**
|
|
10
|
+
* Records how to create the `RequestContext` for `ctx`; the getter runs
|
|
11
|
+
* `create` on first access.
|
|
12
|
+
*/
|
|
13
|
+
declare function setFederationContextFactory<TContextData>(ctx: HttpContext, create: () => RequestContext<TContextData>): void;
|
|
14
|
+
/**
|
|
15
|
+
* Installs the `federation` getter on a context class, once per class. The
|
|
16
|
+
* middleware also calls this on `ctx.constructor`, which covers an
|
|
17
|
+
* application with its own copy of `@adonisjs/core`. Macroable's
|
|
18
|
+
* `singleton` flag memoises the value on the instance.
|
|
19
|
+
*
|
|
20
|
+
* @returns `false` when a `federation` member somebody else defined is in the
|
|
21
|
+
* way; nothing is changed then, and the caller decides how to report it.
|
|
22
|
+
*/
|
|
23
|
+
declare function ensureFederationGetter(target?: HttpContextClass): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* {@link ensureFederationGetter}, but a conflict throws. Called from the
|
|
26
|
+
* provider's `boot()`.
|
|
27
|
+
*/
|
|
28
|
+
declare function installFederationGetter(target?: HttpContextClass): void;
|
|
29
|
+
//#endregion
|
|
30
|
+
export { HttpContextClass, ensureFederationGetter, installFederationGetter, setFederationContextFactory };
|
|
31
|
+
//# sourceMappingURL=http_context.d.ts.map
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { E_FEDIFY_CONTEXT_UNAVAILABLE } from "./errors.js";
|
|
2
|
+
import { HttpContext } from "@adonisjs/core/http";
|
|
3
|
+
|
|
4
|
+
//#region src/http_context.ts
|
|
5
|
+
/**
|
|
6
|
+
* The `ctx.federation` accessor: a Macroable getter on `HttpContext` (like
|
|
7
|
+
* `ctx.view`) that reads a per-request factory the middleware stores on the
|
|
8
|
+
* instance, and memoises the result.
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* The per-request slot holding the factory for `ctx.federation`. A
|
|
14
|
+
* registered symbol so the ESM and CommonJS builds share it, keyed by major
|
|
15
|
+
* version so another major in the same process gets its own.
|
|
16
|
+
*/
|
|
17
|
+
const FACTORY = Symbol.for("@fedify/adonisjs@2/federation-factory");
|
|
18
|
+
/**
|
|
19
|
+
* The accessors this module has installed, so a `federation` member defined
|
|
20
|
+
* by somebody else can be told apart from ours. `Macroable.getter()` wraps
|
|
21
|
+
* the function it is given, hence a registry rather than a marker; it lives on
|
|
22
|
+
* `globalThis` for the same reasons as {@link FACTORY}.
|
|
23
|
+
*/
|
|
24
|
+
const INSTALLED = Symbol.for("@fedify/adonisjs@2/federation-getters");
|
|
25
|
+
const registry = globalThis;
|
|
26
|
+
const installedGetters = registry[INSTALLED] ??= new WeakSet();
|
|
27
|
+
/**
|
|
28
|
+
* Records how to create the `RequestContext` for `ctx`; the getter runs
|
|
29
|
+
* `create` on first access.
|
|
30
|
+
*/
|
|
31
|
+
function setFederationContextFactory(ctx, create) {
|
|
32
|
+
Object.defineProperty(ctx, FACTORY, {
|
|
33
|
+
value: create,
|
|
34
|
+
configurable: true,
|
|
35
|
+
enumerable: false,
|
|
36
|
+
writable: true
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Installs the `federation` getter on a context class, once per class. The
|
|
41
|
+
* middleware also calls this on `ctx.constructor`, which covers an
|
|
42
|
+
* application with its own copy of `@adonisjs/core`. Macroable's
|
|
43
|
+
* `singleton` flag memoises the value on the instance.
|
|
44
|
+
*
|
|
45
|
+
* @returns `false` when a `federation` member somebody else defined is in the
|
|
46
|
+
* way; nothing is changed then, and the caller decides how to report it.
|
|
47
|
+
*/
|
|
48
|
+
function ensureFederationGetter(target = HttpContext) {
|
|
49
|
+
const existing = Object.getOwnPropertyDescriptor(target.prototype, "federation");
|
|
50
|
+
if (existing !== undefined) return isOwnGetter(existing.get);
|
|
51
|
+
target.getter("federation", function() {
|
|
52
|
+
const create = this[FACTORY];
|
|
53
|
+
if (create === undefined) {
|
|
54
|
+
throw new E_FEDIFY_CONTEXT_UNAVAILABLE(this.request.url());
|
|
55
|
+
}
|
|
56
|
+
return create();
|
|
57
|
+
}, true);
|
|
58
|
+
const installed = Object.getOwnPropertyDescriptor(target.prototype, "federation")?.get;
|
|
59
|
+
if (installed !== undefined) installedGetters.add(installed);
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* {@link ensureFederationGetter}, but a conflict throws. Called from the
|
|
64
|
+
* provider's `boot()`.
|
|
65
|
+
*/
|
|
66
|
+
function installFederationGetter(target = HttpContext) {
|
|
67
|
+
if (ensureFederationGetter(target)) return;
|
|
68
|
+
throw new Error("Cannot install \"ctx.federation\": the HttpContext class already has a " + "\"federation\" member that @fedify/adonisjs did not define. Remove the " + "conflicting macro or getter, or rename it");
|
|
69
|
+
}
|
|
70
|
+
function isOwnGetter(fn) {
|
|
71
|
+
return typeof fn === "function" && installedGetters.has(fn);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
//#endregion
|
|
75
|
+
export { ensureFederationGetter, installFederationGetter, setFederationContextFactory };
|
|
76
|
+
//# sourceMappingURL=http_context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http_context.js","names":[],"sources":["../../src/http_context.ts"],"sourcesContent":["/**\n * The `ctx.federation` accessor: a Macroable getter on `HttpContext` (like\n * `ctx.view`) that reads a per-request factory the middleware stores on the\n * instance, and memoises the result.\n *\n * @module\n */\nimport { HttpContext } from \"@adonisjs/core/http\";\nimport type { RequestContext } from \"@fedify/fedify\";\n\nimport { E_FEDIFY_CONTEXT_UNAVAILABLE } from \"./errors.ts\";\n\n/**\n * The per-request slot holding the factory for `ctx.federation`. A\n * registered symbol so the ESM and CommonJS builds share it, keyed by major\n * version so another major in the same process gets its own.\n */\nconst FACTORY: unique symbol = Symbol.for(\n \"@fedify/adonisjs@2/federation-factory\",\n);\n\n/**\n * The accessors this module has installed, so a `federation` member defined\n * by somebody else can be told apart from ours. `Macroable.getter()` wraps\n * the function it is given, hence a registry rather than a marker; it lives on\n * `globalThis` for the same reasons as {@link FACTORY}.\n */\nconst INSTALLED: unique symbol = Symbol.for(\n \"@fedify/adonisjs@2/federation-getters\",\n);\n\nconst registry = globalThis as { [INSTALLED]?: WeakSet<object> };\n\nconst installedGetters: WeakSet<object> = registry[INSTALLED] ??= new WeakSet();\n\n/**\n * The shape of a context that carries the {@link FACTORY} slot.\n */\ntype FactoryCarrier = {\n [FACTORY]?: () => RequestContext<unknown>;\n};\n\n/**\n * A context class the getter can be installed on.\n */\nexport type HttpContextClass = typeof HttpContext;\n\n/**\n * Records how to create the `RequestContext` for `ctx`; the getter runs\n * `create` on first access.\n */\nexport function setFederationContextFactory<TContextData>(\n ctx: HttpContext,\n create: () => RequestContext<TContextData>,\n): void {\n Object.defineProperty(ctx, FACTORY, {\n value: create,\n configurable: true,\n enumerable: false,\n writable: true,\n });\n}\n\n/**\n * Installs the `federation` getter on a context class, once per class. The\n * middleware also calls this on `ctx.constructor`, which covers an\n * application with its own copy of `@adonisjs/core`. Macroable's\n * `singleton` flag memoises the value on the instance.\n *\n * @returns `false` when a `federation` member somebody else defined is in the\n * way; nothing is changed then, and the caller decides how to report it.\n */\nexport function ensureFederationGetter(\n target: HttpContextClass = HttpContext,\n): boolean {\n const existing = Object.getOwnPropertyDescriptor(\n target.prototype,\n \"federation\",\n );\n if (existing !== undefined) return isOwnGetter(existing.get);\n\n target.getter(\"federation\", function (this: HttpContext) {\n const create = (this as HttpContext & FactoryCarrier)[FACTORY];\n if (create === undefined) {\n throw new E_FEDIFY_CONTEXT_UNAVAILABLE(this.request.url());\n }\n return create() as HttpContext[\"federation\"];\n }, true);\n\n // Record the wrapper Macroable actually installed.\n const installed = Object.getOwnPropertyDescriptor(\n target.prototype,\n \"federation\",\n )?.get;\n if (installed !== undefined) installedGetters.add(installed);\n\n return true;\n}\n\n/**\n * {@link ensureFederationGetter}, but a conflict throws. Called from the\n * provider's `boot()`.\n */\nexport function installFederationGetter(\n target: HttpContextClass = HttpContext,\n): void {\n if (ensureFederationGetter(target)) return;\n\n throw new Error(\n 'Cannot install \"ctx.federation\": the HttpContext class already has a ' +\n '\"federation\" member that @fedify/adonisjs did not define. Remove the ' +\n \"conflicting macro or getter, or rename it\",\n );\n}\n\nfunction isOwnGetter(fn: unknown): boolean {\n return typeof fn === \"function\" && installedGetters.has(fn);\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAiBA,MAAM,UAAyB,OAAO,IACpC,uCACF;;;;;;;AAQA,MAAM,YAA2B,OAAO,IACtC,uCACF;AAEA,MAAM,WAAW;AAEjB,MAAM,mBAAoC,SAAS,eAAe,IAAI,QAAQ;;;;;AAkB9E,SAAgB,4BACd,KACA,QACM;CACN,OAAO,eAAe,KAAK,SAAS;EAClC,OAAO;EACP,cAAc;EACd,YAAY;EACZ,UAAU;CACZ,CAAC;AACH;;;;;;;;;;AAWA,SAAgB,uBACd,SAA2B,aAClB;CACT,MAAM,WAAW,OAAO,yBACtB,OAAO,WACP,YACF;CACA,IAAI,aAAa,WAAW,OAAO,YAAY,SAAS,GAAG;CAE3D,OAAO,OAAO,cAAc,WAA6B;EACvD,MAAM,SAAU,KAAsC;EACtD,IAAI,WAAW,WAAW;GACxB,MAAM,IAAI,6BAA6B,KAAK,QAAQ,IAAI,CAAC;EAC3D;EACA,OAAO,OAAO;CAChB,GAAG,IAAI;CAGP,MAAM,YAAY,OAAO,yBACvB,OAAO,WACP,YACF,CAAC,EAAE;CACH,IAAI,cAAc,WAAW,iBAAiB,IAAI,SAAS;CAE3D,OAAO;AACT;;;;;AAMA,SAAgB,wBACd,SAA2B,aACrB;CACN,IAAI,uBAAuB,MAAM,GAAG;CAEpC,MAAM,IAAI,MACR,4EACE,4EACA,2CACJ;AACF;AAEA,SAAS,YAAY,IAAsB;CACzC,OAAO,OAAO,OAAO,cAAc,iBAAiB,IAAI,EAAE;AAC5D"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
let node_async_hooks = require("node:async_hooks");
|
|
2
|
+
let _logtape_logtape = require("@logtape/logtape");
|
|
3
|
+
|
|
4
|
+
//#region src/logging.ts
|
|
5
|
+
/**
|
|
6
|
+
* Bridges Fedify's [LogTape] logs into the AdonisJS logger.
|
|
7
|
+
*
|
|
8
|
+
* Fedify reports signature verification, delivery attempts, WebFinger lookups,
|
|
9
|
+
* and document loading through LogTape, but none of it is visible unless
|
|
10
|
+
* LogTape is configured. This module routes those records into the
|
|
11
|
+
* application's Pino logger so they share its formatting and level filtering.
|
|
12
|
+
*
|
|
13
|
+
* [LogTape]: https://logtape.org/
|
|
14
|
+
*
|
|
15
|
+
* @module
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Maps a LogTape level onto the matching Pino method (`warning` becomes
|
|
19
|
+
* `warn`). The methods are wrapped rather than bound because `bind()` would
|
|
20
|
+
* pick the `(message, ...values)` overload instead of the merging-object one.
|
|
21
|
+
*/
|
|
22
|
+
function logWith(logger, level) {
|
|
23
|
+
switch (level) {
|
|
24
|
+
case "trace": return (properties, message) => logger.trace(properties, message);
|
|
25
|
+
case "debug": return (properties, message) => logger.debug(properties, message);
|
|
26
|
+
case "info": return (properties, message) => logger.info(properties, message);
|
|
27
|
+
case "warning": return (properties, message) => logger.warn(properties, message);
|
|
28
|
+
case "error": return (properties, message) => logger.error(properties, message);
|
|
29
|
+
case "fatal": return (properties, message) => logger.fatal(properties, message);
|
|
30
|
+
default: return undefined;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Turns a record's LogTape properties into Pino's merging object, so that
|
|
35
|
+
* `redact` paths, serializers, and log aggregators see them as fields rather
|
|
36
|
+
* than as text flattened into the message.
|
|
37
|
+
*
|
|
38
|
+
* An `error` property holding an `Error` is moved to `err`, the key Pino
|
|
39
|
+
* serialises errors under. It is moved rather than copied because the
|
|
40
|
+
* rendered message already carries the inspected value.
|
|
41
|
+
*/
|
|
42
|
+
function toLogFields(properties) {
|
|
43
|
+
const fields = { ...properties };
|
|
44
|
+
if (fields.error instanceof Error && fields.err === undefined) {
|
|
45
|
+
fields.err = fields.error;
|
|
46
|
+
delete fields.error;
|
|
47
|
+
}
|
|
48
|
+
return fields;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Configures LogTape so that Fedify's logs flow into the AdonisJS logger.
|
|
52
|
+
* The service provider calls this during `boot()` unless `config/fedify.ts`
|
|
53
|
+
* sets `logging: false`, the escape hatch for applications that configure
|
|
54
|
+
* LogTape themselves.
|
|
55
|
+
*
|
|
56
|
+
* LogTape is a process-global singleton and `configure()` throws when called
|
|
57
|
+
* twice. The usual causes (an application configuring LogTape itself without
|
|
58
|
+
* `logging: false`, or a test process booting several applications) should
|
|
59
|
+
* keep the existing configuration, so this function logs a debug message and
|
|
60
|
+
* returns instead of throwing.
|
|
61
|
+
*
|
|
62
|
+
* Timestamps and levels are stripped from the rendered message because the
|
|
63
|
+
* AdonisJS logger adds its own. Properties are also passed as Pino fields;
|
|
64
|
+
* see {@link toLogFields}.
|
|
65
|
+
*
|
|
66
|
+
* @returns Whether this call configured LogTape and should therefore undo it.
|
|
67
|
+
* The provider resets it in `shutdown()` so that a process booting a second
|
|
68
|
+
* application (the test runner, an in-process dev-server restart) does not
|
|
69
|
+
* keep logging into the old application's logger.
|
|
70
|
+
*/
|
|
71
|
+
async function configureFedifyLogging(options) {
|
|
72
|
+
const { logger } = options;
|
|
73
|
+
const categories = options.categories ?? [["logtape", "meta"], ["fedify"]];
|
|
74
|
+
if ((0, _logtape_logtape.getConfig)() != null) {
|
|
75
|
+
logger.debug("LogTape is already configured, so the Fedify logging bridge was left " + "alone. Set \"logging\" to false in config/fedify.ts to make that " + "explicit.");
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
const formatter = (0, _logtape_logtape.getTextFormatter)({
|
|
79
|
+
timestamp: "disabled",
|
|
80
|
+
level: () => ""
|
|
81
|
+
});
|
|
82
|
+
await (0, _logtape_logtape.configure)({
|
|
83
|
+
sinks: { adonisjs: (record) => {
|
|
84
|
+
const message = formatter(record).replace(/^\[\]\s+/, "").trimEnd();
|
|
85
|
+
const fields = toLogFields(record.properties);
|
|
86
|
+
const write = logWith(logger, record.level);
|
|
87
|
+
/* c8 ignore next 3 -- LogTape may add levels in a future release */
|
|
88
|
+
if (write === undefined) {
|
|
89
|
+
logger.info(fields, message);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
write(fields, message);
|
|
93
|
+
} },
|
|
94
|
+
filters: {},
|
|
95
|
+
loggers: categories.map((category) => ({
|
|
96
|
+
category,
|
|
97
|
+
sinks: ["adonisjs"]
|
|
98
|
+
})),
|
|
99
|
+
contextLocalStorage: new node_async_hooks.AsyncLocalStorage()
|
|
100
|
+
});
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
//#endregion
|
|
105
|
+
exports.configureFedifyLogging = configureFedifyLogging;
|
|
106
|
+
//# sourceMappingURL=logging.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logging.cjs","names":["AsyncLocalStorage"],"sources":["../../src/logging.ts"],"sourcesContent":["/**\n * Bridges Fedify's [LogTape] logs into the AdonisJS logger.\n *\n * Fedify reports signature verification, delivery attempts, WebFinger lookups,\n * and document loading through LogTape, but none of it is visible unless\n * LogTape is configured. This module routes those records into the\n * application's Pino logger so they share its formatting and level filtering.\n *\n * [LogTape]: https://logtape.org/\n *\n * @module\n */\nimport { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport type { Logger } from \"@adonisjs/core/logger\";\nimport {\n configure,\n getConfig,\n getTextFormatter,\n type LogLevel,\n type LogRecord,\n type TextFormatter,\n} from \"@logtape/logtape\";\n\n/**\n * Options for {@link configureFedifyLogging}.\n */\nexport interface FedifyLoggingOptions {\n /**\n * The AdonisJS logger to forward records to.\n */\n logger: Logger;\n\n /**\n * The LogTape categories to route into the AdonisJS logger. The default\n * covers Fedify's logs and LogTape's meta category, where LogTape reports\n * its own misconfiguration.\n *\n * @default `[['logtape', 'meta'], ['fedify']]`\n */\n categories?: (string | string[])[];\n}\n\n/**\n * A Pino log method in its `(mergingObject, message)` form.\n */\ntype LogMethod = (\n properties: Record<string, unknown>,\n message: string,\n) => void;\n\n/**\n * Maps a LogTape level onto the matching Pino method (`warning` becomes\n * `warn`). The methods are wrapped rather than bound because `bind()` would\n * pick the `(message, ...values)` overload instead of the merging-object one.\n */\nfunction logWith(logger: Logger, level: LogLevel): LogMethod | undefined {\n switch (level) {\n case \"trace\":\n return (properties, message) => logger.trace(properties, message);\n case \"debug\":\n return (properties, message) => logger.debug(properties, message);\n case \"info\":\n return (properties, message) => logger.info(properties, message);\n case \"warning\":\n return (properties, message) => logger.warn(properties, message);\n case \"error\":\n return (properties, message) => logger.error(properties, message);\n case \"fatal\":\n return (properties, message) => logger.fatal(properties, message);\n default:\n return undefined;\n }\n}\n\n/**\n * Turns a record's LogTape properties into Pino's merging object, so that\n * `redact` paths, serializers, and log aggregators see them as fields rather\n * than as text flattened into the message.\n *\n * An `error` property holding an `Error` is moved to `err`, the key Pino\n * serialises errors under. It is moved rather than copied because the\n * rendered message already carries the inspected value.\n */\nfunction toLogFields(\n properties: Record<string, unknown>,\n): Record<string, unknown> {\n const fields: Record<string, unknown> = { ...properties };\n\n if (fields.error instanceof Error && fields.err === undefined) {\n fields.err = fields.error;\n delete fields.error;\n }\n\n return fields;\n}\n\n/**\n * Configures LogTape so that Fedify's logs flow into the AdonisJS logger.\n * The service provider calls this during `boot()` unless `config/fedify.ts`\n * sets `logging: false`, the escape hatch for applications that configure\n * LogTape themselves.\n *\n * LogTape is a process-global singleton and `configure()` throws when called\n * twice. The usual causes (an application configuring LogTape itself without\n * `logging: false`, or a test process booting several applications) should\n * keep the existing configuration, so this function logs a debug message and\n * returns instead of throwing.\n *\n * Timestamps and levels are stripped from the rendered message because the\n * AdonisJS logger adds its own. Properties are also passed as Pino fields;\n * see {@link toLogFields}.\n *\n * @returns Whether this call configured LogTape and should therefore undo it.\n * The provider resets it in `shutdown()` so that a process booting a second\n * application (the test runner, an in-process dev-server restart) does not\n * keep logging into the old application's logger.\n */\nexport async function configureFedifyLogging(\n options: FedifyLoggingOptions,\n): Promise<boolean> {\n const { logger } = options;\n const categories = options.categories ?? [[\"logtape\", \"meta\"], [\"fedify\"]];\n\n if (getConfig() != null) {\n logger.debug(\n \"LogTape is already configured, so the Fedify logging bridge was left \" +\n 'alone. Set \"logging\" to false in config/fedify.ts to make that ' +\n \"explicit.\",\n );\n return false;\n }\n\n const formatter: TextFormatter = getTextFormatter({\n timestamp: \"disabled\",\n level: () => \"\",\n });\n\n await configure({\n sinks: {\n adonisjs: (record: LogRecord) => {\n // The formatter still emits an empty `[]` where the level would go.\n const message = formatter(record).replace(/^\\[\\]\\s+/, \"\").trimEnd();\n const fields = toLogFields(record.properties);\n\n const write = logWith(logger, record.level);\n /* c8 ignore next 3 -- LogTape may add levels in a future release */\n if (write === undefined) {\n logger.info(fields, message);\n return;\n }\n write(fields, message);\n },\n },\n filters: {},\n loggers: categories.map((category) => ({ category, sinks: [\"adonisjs\"] })),\n contextLocalStorage: new AsyncLocalStorage(),\n });\n\n return true;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAwDA,SAAS,QAAQ,QAAgB,OAAwC;CACvE,QAAQ,OAAR;EACE,KAAK,SACH,QAAQ,YAAY,YAAY,OAAO,MAAM,YAAY,OAAO;EAClE,KAAK,SACH,QAAQ,YAAY,YAAY,OAAO,MAAM,YAAY,OAAO;EAClE,KAAK,QACH,QAAQ,YAAY,YAAY,OAAO,KAAK,YAAY,OAAO;EACjE,KAAK,WACH,QAAQ,YAAY,YAAY,OAAO,KAAK,YAAY,OAAO;EACjE,KAAK,SACH,QAAQ,YAAY,YAAY,OAAO,MAAM,YAAY,OAAO;EAClE,KAAK,SACH,QAAQ,YAAY,YAAY,OAAO,MAAM,YAAY,OAAO;EAClE,SACE,OAAO;CACX;AACF;;;;;;;;;;AAWA,SAAS,YACP,YACyB;CACzB,MAAM,SAAkC,EAAE,GAAG,WAAW;CAExD,IAAI,OAAO,iBAAiB,SAAS,OAAO,QAAQ,WAAW;EAC7D,OAAO,MAAM,OAAO;EACpB,OAAO,OAAO;CAChB;CAEA,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;AAuBA,eAAsB,uBACpB,SACkB;CAClB,MAAM,EAAE,WAAW;CACnB,MAAM,aAAa,QAAQ,cAAc,CAAC,CAAC,WAAW,MAAM,GAAG,CAAC,QAAQ,CAAC;CAEzE,oCAAc,KAAK,MAAM;EACvB,OAAO,MACL,0EACE,sEACA,WACJ;EACA,OAAO;CACT;CAEA,MAAM,mDAA4C;EAChD,WAAW;EACX,aAAa;CACf,CAAC;CAED,sCAAgB;EACd,OAAO,EACL,WAAW,WAAsB;GAE/B,MAAM,UAAU,UAAU,MAAM,CAAC,CAAC,QAAQ,YAAY,EAAE,CAAC,CAAC,QAAQ;GAClE,MAAM,SAAS,YAAY,OAAO,UAAU;GAE5C,MAAM,QAAQ,QAAQ,QAAQ,OAAO,KAAK;;GAE1C,IAAI,UAAU,WAAW;IACvB,OAAO,KAAK,QAAQ,OAAO;IAC3B;GACF;GACA,MAAM,QAAQ,OAAO;EACvB,EACF;EACA,SAAS,CAAC;EACV,SAAS,WAAW,KAAK,cAAc;GAAE;GAAU,OAAO,CAAC,UAAU;EAAE,EAAE;EACzE,qBAAqB,IAAIA,mCAAkB;CAC7C,CAAC;CAED,OAAO;AACT"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Logger } from "@adonisjs/core/logger";
|
|
2
|
+
|
|
3
|
+
//#region src/logging.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Options for {@link configureFedifyLogging}.
|
|
6
|
+
*/
|
|
7
|
+
interface FedifyLoggingOptions {
|
|
8
|
+
/**
|
|
9
|
+
* The AdonisJS logger to forward records to.
|
|
10
|
+
*/
|
|
11
|
+
logger: Logger;
|
|
12
|
+
/**
|
|
13
|
+
* The LogTape categories to route into the AdonisJS logger. The default
|
|
14
|
+
* covers Fedify's logs and LogTape's meta category, where LogTape reports
|
|
15
|
+
* its own misconfiguration.
|
|
16
|
+
*
|
|
17
|
+
* @default `[['logtape', 'meta'], ['fedify']]`
|
|
18
|
+
*/
|
|
19
|
+
categories?: (string | string[])[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Configures LogTape so that Fedify's logs flow into the AdonisJS logger.
|
|
23
|
+
* The service provider calls this during `boot()` unless `config/fedify.ts`
|
|
24
|
+
* sets `logging: false`, the escape hatch for applications that configure
|
|
25
|
+
* LogTape themselves.
|
|
26
|
+
*
|
|
27
|
+
* LogTape is a process-global singleton and `configure()` throws when called
|
|
28
|
+
* twice. The usual causes (an application configuring LogTape itself without
|
|
29
|
+
* `logging: false`, or a test process booting several applications) should
|
|
30
|
+
* keep the existing configuration, so this function logs a debug message and
|
|
31
|
+
* returns instead of throwing.
|
|
32
|
+
*
|
|
33
|
+
* Timestamps and levels are stripped from the rendered message because the
|
|
34
|
+
* AdonisJS logger adds its own. Properties are also passed as Pino fields;
|
|
35
|
+
* see {@link toLogFields}.
|
|
36
|
+
*
|
|
37
|
+
* @returns Whether this call configured LogTape and should therefore undo it.
|
|
38
|
+
* The provider resets it in `shutdown()` so that a process booting a second
|
|
39
|
+
* application (the test runner, an in-process dev-server restart) does not
|
|
40
|
+
* keep logging into the old application's logger.
|
|
41
|
+
*/
|
|
42
|
+
declare function configureFedifyLogging(options: FedifyLoggingOptions): Promise<boolean>;
|
|
43
|
+
//#endregion
|
|
44
|
+
export { FedifyLoggingOptions, configureFedifyLogging };
|
|
45
|
+
//# sourceMappingURL=logging.d.cts.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Logger } from "@adonisjs/core/logger";
|
|
2
|
+
|
|
3
|
+
//#region src/logging.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Options for {@link configureFedifyLogging}.
|
|
6
|
+
*/
|
|
7
|
+
interface FedifyLoggingOptions {
|
|
8
|
+
/**
|
|
9
|
+
* The AdonisJS logger to forward records to.
|
|
10
|
+
*/
|
|
11
|
+
logger: Logger;
|
|
12
|
+
/**
|
|
13
|
+
* The LogTape categories to route into the AdonisJS logger. The default
|
|
14
|
+
* covers Fedify's logs and LogTape's meta category, where LogTape reports
|
|
15
|
+
* its own misconfiguration.
|
|
16
|
+
*
|
|
17
|
+
* @default `[['logtape', 'meta'], ['fedify']]`
|
|
18
|
+
*/
|
|
19
|
+
categories?: (string | string[])[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Configures LogTape so that Fedify's logs flow into the AdonisJS logger.
|
|
23
|
+
* The service provider calls this during `boot()` unless `config/fedify.ts`
|
|
24
|
+
* sets `logging: false`, the escape hatch for applications that configure
|
|
25
|
+
* LogTape themselves.
|
|
26
|
+
*
|
|
27
|
+
* LogTape is a process-global singleton and `configure()` throws when called
|
|
28
|
+
* twice. The usual causes (an application configuring LogTape itself without
|
|
29
|
+
* `logging: false`, or a test process booting several applications) should
|
|
30
|
+
* keep the existing configuration, so this function logs a debug message and
|
|
31
|
+
* returns instead of throwing.
|
|
32
|
+
*
|
|
33
|
+
* Timestamps and levels are stripped from the rendered message because the
|
|
34
|
+
* AdonisJS logger adds its own. Properties are also passed as Pino fields;
|
|
35
|
+
* see {@link toLogFields}.
|
|
36
|
+
*
|
|
37
|
+
* @returns Whether this call configured LogTape and should therefore undo it.
|
|
38
|
+
* The provider resets it in `shutdown()` so that a process booting a second
|
|
39
|
+
* application (the test runner, an in-process dev-server restart) does not
|
|
40
|
+
* keep logging into the old application's logger.
|
|
41
|
+
*/
|
|
42
|
+
declare function configureFedifyLogging(options: FedifyLoggingOptions): Promise<boolean>;
|
|
43
|
+
//#endregion
|
|
44
|
+
export { FedifyLoggingOptions, configureFedifyLogging };
|
|
45
|
+
//# sourceMappingURL=logging.d.ts.map
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
+
import { configure, getConfig, getTextFormatter } from "@logtape/logtape";
|
|
3
|
+
|
|
4
|
+
//#region src/logging.ts
|
|
5
|
+
/**
|
|
6
|
+
* Bridges Fedify's [LogTape] logs into the AdonisJS logger.
|
|
7
|
+
*
|
|
8
|
+
* Fedify reports signature verification, delivery attempts, WebFinger lookups,
|
|
9
|
+
* and document loading through LogTape, but none of it is visible unless
|
|
10
|
+
* LogTape is configured. This module routes those records into the
|
|
11
|
+
* application's Pino logger so they share its formatting and level filtering.
|
|
12
|
+
*
|
|
13
|
+
* [LogTape]: https://logtape.org/
|
|
14
|
+
*
|
|
15
|
+
* @module
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Maps a LogTape level onto the matching Pino method (`warning` becomes
|
|
19
|
+
* `warn`). The methods are wrapped rather than bound because `bind()` would
|
|
20
|
+
* pick the `(message, ...values)` overload instead of the merging-object one.
|
|
21
|
+
*/
|
|
22
|
+
function logWith(logger, level) {
|
|
23
|
+
switch (level) {
|
|
24
|
+
case "trace": return (properties, message) => logger.trace(properties, message);
|
|
25
|
+
case "debug": return (properties, message) => logger.debug(properties, message);
|
|
26
|
+
case "info": return (properties, message) => logger.info(properties, message);
|
|
27
|
+
case "warning": return (properties, message) => logger.warn(properties, message);
|
|
28
|
+
case "error": return (properties, message) => logger.error(properties, message);
|
|
29
|
+
case "fatal": return (properties, message) => logger.fatal(properties, message);
|
|
30
|
+
default: return undefined;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Turns a record's LogTape properties into Pino's merging object, so that
|
|
35
|
+
* `redact` paths, serializers, and log aggregators see them as fields rather
|
|
36
|
+
* than as text flattened into the message.
|
|
37
|
+
*
|
|
38
|
+
* An `error` property holding an `Error` is moved to `err`, the key Pino
|
|
39
|
+
* serialises errors under. It is moved rather than copied because the
|
|
40
|
+
* rendered message already carries the inspected value.
|
|
41
|
+
*/
|
|
42
|
+
function toLogFields(properties) {
|
|
43
|
+
const fields = { ...properties };
|
|
44
|
+
if (fields.error instanceof Error && fields.err === undefined) {
|
|
45
|
+
fields.err = fields.error;
|
|
46
|
+
delete fields.error;
|
|
47
|
+
}
|
|
48
|
+
return fields;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Configures LogTape so that Fedify's logs flow into the AdonisJS logger.
|
|
52
|
+
* The service provider calls this during `boot()` unless `config/fedify.ts`
|
|
53
|
+
* sets `logging: false`, the escape hatch for applications that configure
|
|
54
|
+
* LogTape themselves.
|
|
55
|
+
*
|
|
56
|
+
* LogTape is a process-global singleton and `configure()` throws when called
|
|
57
|
+
* twice. The usual causes (an application configuring LogTape itself without
|
|
58
|
+
* `logging: false`, or a test process booting several applications) should
|
|
59
|
+
* keep the existing configuration, so this function logs a debug message and
|
|
60
|
+
* returns instead of throwing.
|
|
61
|
+
*
|
|
62
|
+
* Timestamps and levels are stripped from the rendered message because the
|
|
63
|
+
* AdonisJS logger adds its own. Properties are also passed as Pino fields;
|
|
64
|
+
* see {@link toLogFields}.
|
|
65
|
+
*
|
|
66
|
+
* @returns Whether this call configured LogTape and should therefore undo it.
|
|
67
|
+
* The provider resets it in `shutdown()` so that a process booting a second
|
|
68
|
+
* application (the test runner, an in-process dev-server restart) does not
|
|
69
|
+
* keep logging into the old application's logger.
|
|
70
|
+
*/
|
|
71
|
+
async function configureFedifyLogging(options) {
|
|
72
|
+
const { logger } = options;
|
|
73
|
+
const categories = options.categories ?? [["logtape", "meta"], ["fedify"]];
|
|
74
|
+
if (getConfig() != null) {
|
|
75
|
+
logger.debug("LogTape is already configured, so the Fedify logging bridge was left " + "alone. Set \"logging\" to false in config/fedify.ts to make that " + "explicit.");
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
const formatter = getTextFormatter({
|
|
79
|
+
timestamp: "disabled",
|
|
80
|
+
level: () => ""
|
|
81
|
+
});
|
|
82
|
+
await configure({
|
|
83
|
+
sinks: { adonisjs: (record) => {
|
|
84
|
+
const message = formatter(record).replace(/^\[\]\s+/, "").trimEnd();
|
|
85
|
+
const fields = toLogFields(record.properties);
|
|
86
|
+
const write = logWith(logger, record.level);
|
|
87
|
+
/* c8 ignore next 3 -- LogTape may add levels in a future release */
|
|
88
|
+
if (write === undefined) {
|
|
89
|
+
logger.info(fields, message);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
write(fields, message);
|
|
93
|
+
} },
|
|
94
|
+
filters: {},
|
|
95
|
+
loggers: categories.map((category) => ({
|
|
96
|
+
category,
|
|
97
|
+
sinks: ["adonisjs"]
|
|
98
|
+
})),
|
|
99
|
+
contextLocalStorage: new AsyncLocalStorage()
|
|
100
|
+
});
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
//#endregion
|
|
105
|
+
export { configureFedifyLogging };
|
|
106
|
+
//# sourceMappingURL=logging.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logging.js","names":[],"sources":["../../src/logging.ts"],"sourcesContent":["/**\n * Bridges Fedify's [LogTape] logs into the AdonisJS logger.\n *\n * Fedify reports signature verification, delivery attempts, WebFinger lookups,\n * and document loading through LogTape, but none of it is visible unless\n * LogTape is configured. This module routes those records into the\n * application's Pino logger so they share its formatting and level filtering.\n *\n * [LogTape]: https://logtape.org/\n *\n * @module\n */\nimport { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport type { Logger } from \"@adonisjs/core/logger\";\nimport {\n configure,\n getConfig,\n getTextFormatter,\n type LogLevel,\n type LogRecord,\n type TextFormatter,\n} from \"@logtape/logtape\";\n\n/**\n * Options for {@link configureFedifyLogging}.\n */\nexport interface FedifyLoggingOptions {\n /**\n * The AdonisJS logger to forward records to.\n */\n logger: Logger;\n\n /**\n * The LogTape categories to route into the AdonisJS logger. The default\n * covers Fedify's logs and LogTape's meta category, where LogTape reports\n * its own misconfiguration.\n *\n * @default `[['logtape', 'meta'], ['fedify']]`\n */\n categories?: (string | string[])[];\n}\n\n/**\n * A Pino log method in its `(mergingObject, message)` form.\n */\ntype LogMethod = (\n properties: Record<string, unknown>,\n message: string,\n) => void;\n\n/**\n * Maps a LogTape level onto the matching Pino method (`warning` becomes\n * `warn`). The methods are wrapped rather than bound because `bind()` would\n * pick the `(message, ...values)` overload instead of the merging-object one.\n */\nfunction logWith(logger: Logger, level: LogLevel): LogMethod | undefined {\n switch (level) {\n case \"trace\":\n return (properties, message) => logger.trace(properties, message);\n case \"debug\":\n return (properties, message) => logger.debug(properties, message);\n case \"info\":\n return (properties, message) => logger.info(properties, message);\n case \"warning\":\n return (properties, message) => logger.warn(properties, message);\n case \"error\":\n return (properties, message) => logger.error(properties, message);\n case \"fatal\":\n return (properties, message) => logger.fatal(properties, message);\n default:\n return undefined;\n }\n}\n\n/**\n * Turns a record's LogTape properties into Pino's merging object, so that\n * `redact` paths, serializers, and log aggregators see them as fields rather\n * than as text flattened into the message.\n *\n * An `error` property holding an `Error` is moved to `err`, the key Pino\n * serialises errors under. It is moved rather than copied because the\n * rendered message already carries the inspected value.\n */\nfunction toLogFields(\n properties: Record<string, unknown>,\n): Record<string, unknown> {\n const fields: Record<string, unknown> = { ...properties };\n\n if (fields.error instanceof Error && fields.err === undefined) {\n fields.err = fields.error;\n delete fields.error;\n }\n\n return fields;\n}\n\n/**\n * Configures LogTape so that Fedify's logs flow into the AdonisJS logger.\n * The service provider calls this during `boot()` unless `config/fedify.ts`\n * sets `logging: false`, the escape hatch for applications that configure\n * LogTape themselves.\n *\n * LogTape is a process-global singleton and `configure()` throws when called\n * twice. The usual causes (an application configuring LogTape itself without\n * `logging: false`, or a test process booting several applications) should\n * keep the existing configuration, so this function logs a debug message and\n * returns instead of throwing.\n *\n * Timestamps and levels are stripped from the rendered message because the\n * AdonisJS logger adds its own. Properties are also passed as Pino fields;\n * see {@link toLogFields}.\n *\n * @returns Whether this call configured LogTape and should therefore undo it.\n * The provider resets it in `shutdown()` so that a process booting a second\n * application (the test runner, an in-process dev-server restart) does not\n * keep logging into the old application's logger.\n */\nexport async function configureFedifyLogging(\n options: FedifyLoggingOptions,\n): Promise<boolean> {\n const { logger } = options;\n const categories = options.categories ?? [[\"logtape\", \"meta\"], [\"fedify\"]];\n\n if (getConfig() != null) {\n logger.debug(\n \"LogTape is already configured, so the Fedify logging bridge was left \" +\n 'alone. Set \"logging\" to false in config/fedify.ts to make that ' +\n \"explicit.\",\n );\n return false;\n }\n\n const formatter: TextFormatter = getTextFormatter({\n timestamp: \"disabled\",\n level: () => \"\",\n });\n\n await configure({\n sinks: {\n adonisjs: (record: LogRecord) => {\n // The formatter still emits an empty `[]` where the level would go.\n const message = formatter(record).replace(/^\\[\\]\\s+/, \"\").trimEnd();\n const fields = toLogFields(record.properties);\n\n const write = logWith(logger, record.level);\n /* c8 ignore next 3 -- LogTape may add levels in a future release */\n if (write === undefined) {\n logger.info(fields, message);\n return;\n }\n write(fields, message);\n },\n },\n filters: {},\n loggers: categories.map((category) => ({ category, sinks: [\"adonisjs\"] })),\n contextLocalStorage: new AsyncLocalStorage(),\n });\n\n return true;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAwDA,SAAS,QAAQ,QAAgB,OAAwC;CACvE,QAAQ,OAAR;EACE,KAAK,SACH,QAAQ,YAAY,YAAY,OAAO,MAAM,YAAY,OAAO;EAClE,KAAK,SACH,QAAQ,YAAY,YAAY,OAAO,MAAM,YAAY,OAAO;EAClE,KAAK,QACH,QAAQ,YAAY,YAAY,OAAO,KAAK,YAAY,OAAO;EACjE,KAAK,WACH,QAAQ,YAAY,YAAY,OAAO,KAAK,YAAY,OAAO;EACjE,KAAK,SACH,QAAQ,YAAY,YAAY,OAAO,MAAM,YAAY,OAAO;EAClE,KAAK,SACH,QAAQ,YAAY,YAAY,OAAO,MAAM,YAAY,OAAO;EAClE,SACE,OAAO;CACX;AACF;;;;;;;;;;AAWA,SAAS,YACP,YACyB;CACzB,MAAM,SAAkC,EAAE,GAAG,WAAW;CAExD,IAAI,OAAO,iBAAiB,SAAS,OAAO,QAAQ,WAAW;EAC7D,OAAO,MAAM,OAAO;EACpB,OAAO,OAAO;CAChB;CAEA,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;AAuBA,eAAsB,uBACpB,SACkB;CAClB,MAAM,EAAE,WAAW;CACnB,MAAM,aAAa,QAAQ,cAAc,CAAC,CAAC,WAAW,MAAM,GAAG,CAAC,QAAQ,CAAC;CAEzE,IAAI,UAAU,KAAK,MAAM;EACvB,OAAO,MACL,0EACE,sEACA,WACJ;EACA,OAAO;CACT;CAEA,MAAM,YAA2B,iBAAiB;EAChD,WAAW;EACX,aAAa;CACf,CAAC;CAED,MAAM,UAAU;EACd,OAAO,EACL,WAAW,WAAsB;GAE/B,MAAM,UAAU,UAAU,MAAM,CAAC,CAAC,QAAQ,YAAY,EAAE,CAAC,CAAC,QAAQ;GAClE,MAAM,SAAS,YAAY,OAAO,UAAU;GAE5C,MAAM,QAAQ,QAAQ,QAAQ,OAAO,KAAK;;GAE1C,IAAI,UAAU,WAAW;IACvB,OAAO,KAAK,QAAQ,OAAO;IAC3B;GACF;GACA,MAAM,QAAQ,OAAO;EACvB,EACF;EACA,SAAS,CAAC;EACV,SAAS,WAAW,KAAK,cAAc;GAAE;GAAU,OAAO,CAAC,UAAU;EAAE,EAAE;EACzE,qBAAqB,IAAI,kBAAkB;CAC7C,CAAC;CAED,OAAO;AACT"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|