moost 0.7.3 → 0.7.5
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/index.cjs +118 -25
- package/dist/index.d.ts +93 -12
- package/dist/index.mjs +118 -26
- package/package.json +6 -6
package/dist/index.cjs
CHANGED
|
@@ -48,7 +48,7 @@ let stamped = false;
|
|
|
48
48
|
if (stamped) return;
|
|
49
49
|
stamped = true;
|
|
50
50
|
stampModuleIdentity({
|
|
51
|
-
version: "0.7.
|
|
51
|
+
version: "0.7.5",
|
|
52
52
|
path: typeof __filename === "string" ? __filename : require("url").pathToFileURL(__filename).href
|
|
53
53
|
});
|
|
54
54
|
}
|
|
@@ -3182,11 +3182,44 @@ function _define_property(obj, key, value) {
|
|
|
3182
3182
|
return getHandlerPaths(moost, getController(), method ?? getMethod() ?? "", opts);
|
|
3183
3183
|
}
|
|
3184
3184
|
|
|
3185
|
+
//#endregion
|
|
3186
|
+
//#region packages/moost/src/wooks-owner.ts
|
|
3187
|
+
/** Per Wooks instance: the first claim of each adapter (by `name`) bound into it. */ const owners = /* @__PURE__ */ new WeakMap();
|
|
3188
|
+
/** Wooks instances already warned about: the warning is logged once per instance. */ const warned = /* @__PURE__ */ new WeakSet();
|
|
3189
|
+
/**
|
|
3190
|
+
* Records that `app` binds the handlers of its `adapter` (the adapter's `name`) into `wooks`
|
|
3191
|
+
* (the Wooks instance its routes go to: `wooksApp.getWooks()`). Adapters call it from `onInit`.
|
|
3192
|
+
*
|
|
3193
|
+
* Adapters created without a Wooks app of their own share the process-wide global Wooks, so two
|
|
3194
|
+
* apps in one process (typically in tests) route through one router. When another app already
|
|
3195
|
+
* bound handlers of the same adapter into `wooks`, and either adapter created its Wooks app
|
|
3196
|
+
* (`opts.created`), it warns — once per Wooks instance, with the app's logger. Apps that share
|
|
3197
|
+
* a Wooks app they pass in on purpose stay silent; re-initialising the same app does not warn.
|
|
3198
|
+
* A disposed app still counts: `dispose()` does not remove its routes.
|
|
3199
|
+
*/ function claimWooks(app, wooks, adapter, opts) {
|
|
3200
|
+
const created = opts?.created === true;
|
|
3201
|
+
let byAdapter = owners.get(wooks);
|
|
3202
|
+
if (!byAdapter) {
|
|
3203
|
+
byAdapter = /* @__PURE__ */ new Map();
|
|
3204
|
+
owners.set(wooks, byAdapter);
|
|
3205
|
+
}
|
|
3206
|
+
const owner = byAdapter.get(adapter);
|
|
3207
|
+
if (owner === void 0) byAdapter.set(adapter, {
|
|
3208
|
+
app,
|
|
3209
|
+
created
|
|
3210
|
+
});
|
|
3211
|
+
else if (owner.app !== app && (created || owner.created) && !warned.has(wooks)) {
|
|
3212
|
+
warned.add(wooks);
|
|
3213
|
+
app.getLogger().warn(`[moost] A second Moost app binds "${adapter}" handlers into the Wooks instance another app already uses (adapters created without their own Wooks app share the process-wide global one). Both apps' routes now live in one router: an event on a route both register runs the first app's handler chain, and when that throws, its error is swallowed and the next app's chain runs instead. Call clearGlobalWooks() before creating each app (e.g. in a test's beforeEach): the next adapter then gets a fresh Wooks. (Logged once per Wooks instance.)`);
|
|
3214
|
+
}
|
|
3215
|
+
}
|
|
3216
|
+
|
|
3185
3217
|
//#endregion
|
|
3186
3218
|
//#region packages/moost/src/i18n.ts
|
|
3187
3219
|
var _globalThis, _STATE, _state, _state1, _state2, _state3, _state4;
|
|
3188
3220
|
const STATE = Symbol.for("moost.i18n");
|
|
3189
3221
|
const NO_LOCALES = Object.freeze([]);
|
|
3222
|
+
/** Distinct scopes given memo keys per generation: keeps every memo keyed by `key` bounded. */ const MAX_SCOPES = 32;
|
|
3190
3223
|
const state = (_globalThis = globalThis)[_STATE = STATE] ?? (_globalThis[_STATE] = {});
|
|
3191
3224
|
(_state = state).locales ?? (_state.locales = NO_LOCALES);
|
|
3192
3225
|
(_state1 = state).generation ?? (_state1.generation = 0);
|
|
@@ -3216,9 +3249,15 @@ const state = (_globalThis = globalThis)[_STATE = STATE] ?? (_globalThis[_STATE]
|
|
|
3216
3249
|
*/ function setTranslator(translate, opts) {
|
|
3217
3250
|
const isMap = typeof translate === "object";
|
|
3218
3251
|
state.translate = isMap ? mapTranslator(translate) : translate;
|
|
3252
|
+
state.scoping = opts?.scope && {
|
|
3253
|
+
translate: state.translate,
|
|
3254
|
+
get: opts.scope
|
|
3255
|
+
};
|
|
3256
|
+
state.noPathPrefix = opts?.pathPrefix === false ? state.translate : void 0;
|
|
3219
3257
|
const locales = opts?.locales ?? (isMap ? Object.keys(translate) : void 0);
|
|
3220
3258
|
state.locales = translate && locales?.length ? Object.freeze([...locales]) : NO_LOCALES;
|
|
3221
3259
|
state.failureLogged = false;
|
|
3260
|
+
state.scopeFailureLogged = false;
|
|
3222
3261
|
newGeneration();
|
|
3223
3262
|
}
|
|
3224
3263
|
/** The registered translator (a map wrapped as a function), or `undefined`. */ function getTranslator() {
|
|
@@ -3244,7 +3283,7 @@ const state = (_globalThis = globalThis)[_STATE = STATE] ?? (_globalThis[_STATE]
|
|
|
3244
3283
|
}
|
|
3245
3284
|
if (changed) newGeneration();
|
|
3246
3285
|
}
|
|
3247
|
-
/**
|
|
3286
|
+
/** Drops everything derived from the translator and the templates. */ function newGeneration() {
|
|
3248
3287
|
state.generation++;
|
|
3249
3288
|
state.memo.clear();
|
|
3250
3289
|
}
|
|
@@ -3279,10 +3318,7 @@ const PLACEHOLDER = /\{(\w+)\}/g;
|
|
|
3279
3318
|
let translateCtx;
|
|
3280
3319
|
return (id, params, fallback) => {
|
|
3281
3320
|
const translate = state.translate;
|
|
3282
|
-
return (translate ? callTranslator(translate, id, params, translateCtx ?? (translateCtx =
|
|
3283
|
-
locale: (0, _wooksjs_event_core.useLocale)(event).get(),
|
|
3284
|
-
event
|
|
3285
|
-
})) : void 0) ?? untranslated(id, params, fallback);
|
|
3321
|
+
return (translate ? callTranslator(translate, id, params, translateCtx ?? (translateCtx = translateContext(event, (0, _wooksjs_event_core.useLocale)(event).get(), readScope(event)))) : void 0) ?? untranslated(id, params, fallback);
|
|
3286
3322
|
};
|
|
3287
3323
|
}
|
|
3288
3324
|
/** `t`'s text without a translation: `fallback` as is, else the filled template (or id). */ function untranslated(id, params, fallback) {
|
|
@@ -3298,12 +3334,11 @@ const PLACEHOLDER = /\{(\w+)\}/g;
|
|
|
3298
3334
|
const event = ctx ?? (0, _wooksjs_event_core.current)();
|
|
3299
3335
|
const locale = (0, _wooksjs_event_core.useLocale)(event).get();
|
|
3300
3336
|
if (locale === void 0) return;
|
|
3301
|
-
const
|
|
3302
|
-
|
|
3303
|
-
event
|
|
3304
|
-
};
|
|
3337
|
+
const scope = readScope(event);
|
|
3338
|
+
const translateCtx = translateContext(event, locale, scope);
|
|
3305
3339
|
const generation = state.generation;
|
|
3306
|
-
const
|
|
3340
|
+
const partition = typeof scope === "string" ? `${locale}:${scope}` : locale;
|
|
3341
|
+
const key = state.locales.includes(locale) && (scope === void 0 || scope !== null && admitted(scope)) ? `${generation}:${partition}` : void 0;
|
|
3307
3342
|
const t = (id, params, fallback) => callTranslator(translate, id, params, translateCtx) ?? untranslated(id, params, fallback);
|
|
3308
3343
|
const messages = () => {
|
|
3309
3344
|
if (key === void 0 || state.generation !== generation) return translateTemplates(translate, translateCtx);
|
|
@@ -3316,31 +3351,82 @@ const PLACEHOLDER = /\{(\w+)\}/g;
|
|
|
3316
3351
|
};
|
|
3317
3352
|
return {
|
|
3318
3353
|
locale,
|
|
3354
|
+
partition,
|
|
3319
3355
|
key,
|
|
3320
3356
|
t,
|
|
3321
3357
|
messages
|
|
3322
3358
|
};
|
|
3323
3359
|
}
|
|
3360
|
+
function translateContext(event, locale, scope) {
|
|
3361
|
+
return typeof scope === "string" ? {
|
|
3362
|
+
locale,
|
|
3363
|
+
scope,
|
|
3364
|
+
event
|
|
3365
|
+
} : {
|
|
3366
|
+
locale,
|
|
3367
|
+
event
|
|
3368
|
+
};
|
|
3369
|
+
}
|
|
3370
|
+
/**
|
|
3371
|
+
* The event's scope (`opts.scope`): `undefined` without one, `null` when the scope function
|
|
3372
|
+
* threw (logged once) — translated unscoped then, and not memoized.
|
|
3373
|
+
*/ function readScope(event) {
|
|
3374
|
+
const scoping = state.scoping;
|
|
3375
|
+
if (!scoping || scoping.translate !== state.translate) return;
|
|
3376
|
+
try {
|
|
3377
|
+
const { get } = scoping;
|
|
3378
|
+
const scope = (0, _wooksjs_event_core.tryGetCurrent)() === event ? get() : (0, _wooksjs_event_core.run)(event, get);
|
|
3379
|
+
return typeof scope === "string" ? scope : typeof scope === "number" && Number.isFinite(scope) ? String(scope) : void 0;
|
|
3380
|
+
} catch (error) {
|
|
3381
|
+
logOnce("scopeFailureLogged", event, "The translation scope threw — translating unscoped, without memoizing (logged once)", error);
|
|
3382
|
+
return null;
|
|
3383
|
+
}
|
|
3384
|
+
}
|
|
3385
|
+
/** Whether `scope` gets memo keys: one of the first {@link MAX_SCOPES} of the generation. */ function admitted(scope) {
|
|
3386
|
+
if (state.admittedScopes?.generation !== state.generation) state.admittedScopes = {
|
|
3387
|
+
generation: state.generation,
|
|
3388
|
+
names: /* @__PURE__ */ new Set()
|
|
3389
|
+
};
|
|
3390
|
+
const { names } = state.admittedScopes;
|
|
3391
|
+
if (names.size < MAX_SCOPES) names.add(scope);
|
|
3392
|
+
return names.has(scope);
|
|
3393
|
+
}
|
|
3394
|
+
/** Logs a failure of the translator or the scope function once per `setTranslator`. */ function logOnce(flag, event, message, error) {
|
|
3395
|
+
if (!state[flag]) {
|
|
3396
|
+
state[flag] = true;
|
|
3397
|
+
(0, _wooksjs_event_core.useLogger)("i18n", event).error(message, error);
|
|
3398
|
+
}
|
|
3399
|
+
}
|
|
3324
3400
|
/**
|
|
3325
3401
|
* Returns a translated copy of an error body (`{ message, code?, params?, errors? }`) in the
|
|
3326
3402
|
* event's locale — the body itself when there is no translation ({@link useTranslation}).
|
|
3327
3403
|
*
|
|
3328
3404
|
* - each entry of `errors` (and of its entries' `details`): by its `code` (unless `custom`),
|
|
3329
|
-
* else by its message text, its English `message` being the fallback;
|
|
3330
|
-
*
|
|
3331
|
-
*
|
|
3405
|
+
* else by its message text, its English `message` being the fallback; the translator gets the
|
|
3406
|
+
* entry's `path`, `code` and `custom` ({@link TTranslateContext});
|
|
3407
|
+
* - the top `message`: by `code` when the body has one (the translator gets that `code`); else,
|
|
3408
|
+
* when it is the first entry's message (`path: message`), the first entry's translation
|
|
3409
|
+
* (`path: ` dropped with `setTranslator(t, { pathPrefix: false })`); else by its text.
|
|
3332
3410
|
*
|
|
3333
3411
|
* `MoostHttp` applies it to every error body when it creates the HTTP app.
|
|
3334
3412
|
*/ function translateErrorBody(body, ctx) {
|
|
3335
|
-
const
|
|
3336
|
-
|
|
3337
|
-
const
|
|
3413
|
+
const event = ctx ?? (0, _wooksjs_event_core.current)();
|
|
3414
|
+
const translate = state.translate;
|
|
3415
|
+
const locale = (0, _wooksjs_event_core.useLocale)(event).get();
|
|
3416
|
+
if (!translate || locale === void 0) return body;
|
|
3417
|
+
const base = translateContext(event, locale, readScope(event));
|
|
3418
|
+
const t = (id, params, fallback, entry) => callTranslator(translate, id, params, entry ? entryContext(base, entry) : base) ?? untranslated(id, params, fallback);
|
|
3338
3419
|
const source = Array.isArray(body.errors) ? body.errors : void 0;
|
|
3339
3420
|
const errors = source && translateEntries(source, t);
|
|
3340
3421
|
let message;
|
|
3341
|
-
if (typeof body.code === "string" && body.code) message =
|
|
3342
|
-
|
|
3343
|
-
|
|
3422
|
+
if (typeof body.code === "string" && body.code) message = callTranslator(translate, body.code, body.params, {
|
|
3423
|
+
...base,
|
|
3424
|
+
code: body.code
|
|
3425
|
+
}) ?? untranslated(body.code, body.params, body.message);
|
|
3426
|
+
else if (source && errors && isEntry(source[0]) && body.message === topMessage(source[0])) {
|
|
3427
|
+
const first = errors[0];
|
|
3428
|
+
message = state.noPathPrefix === translate ? first.message : topMessage(first);
|
|
3429
|
+
} else message = t(body.message, body.params, body.message);
|
|
3344
3430
|
return errors ? {
|
|
3345
3431
|
...body,
|
|
3346
3432
|
message,
|
|
@@ -3361,10 +3447,7 @@ function mapTranslator(map) {
|
|
|
3361
3447
|
const out = translate(id, params, ctx);
|
|
3362
3448
|
return typeof out === "string" ? out : void 0;
|
|
3363
3449
|
} catch (error) {
|
|
3364
|
-
|
|
3365
|
-
state.failureLogged = true;
|
|
3366
|
-
(0, _wooksjs_event_core.useLogger)("i18n", ctx.event).error(`The translator threw for "${id}" — using the untranslated text (logged once)`, error);
|
|
3367
|
-
}
|
|
3450
|
+
logOnce("failureLogged", ctx.event, `The translator threw for "${id}" — using the untranslated text (logged once)`, error);
|
|
3368
3451
|
return;
|
|
3369
3452
|
}
|
|
3370
3453
|
}
|
|
@@ -3381,13 +3464,22 @@ function mapTranslator(map) {
|
|
|
3381
3464
|
function isEntry(value) {
|
|
3382
3465
|
return typeof value === "object" && value !== null && typeof value.message === "string";
|
|
3383
3466
|
}
|
|
3467
|
+
/** `base` with the entry's `path` and `code` (each only when a string) and `custom: true`. */ function entryContext(base, { path, code, custom }) {
|
|
3468
|
+
const hasCode = typeof code === "string" && code !== "";
|
|
3469
|
+
if (typeof path !== "string" && !hasCode && custom !== true) return base;
|
|
3470
|
+
const out = { ...base };
|
|
3471
|
+
if (typeof path === "string") out.path = path;
|
|
3472
|
+
if (hasCode) out.code = code;
|
|
3473
|
+
if (custom === true) out.custom = true;
|
|
3474
|
+
return out;
|
|
3475
|
+
}
|
|
3384
3476
|
function translateEntries(entries, t) {
|
|
3385
3477
|
return entries.map((entry) => {
|
|
3386
3478
|
if (!isEntry(entry)) return entry;
|
|
3387
3479
|
const id = typeof entry.code === "string" && entry.code && entry.custom !== true ? entry.code : entry.message;
|
|
3388
3480
|
const out = {
|
|
3389
3481
|
...entry,
|
|
3390
|
-
message: t(id, entry.params, entry.message)
|
|
3482
|
+
message: t(id, entry.params, entry.message, entry)
|
|
3391
3483
|
};
|
|
3392
3484
|
if (Array.isArray(entry.details)) out.details = translateEntries(entry.details, t);
|
|
3393
3485
|
return out;
|
|
@@ -3460,6 +3552,7 @@ Object.defineProperty(exports, 'cached', {
|
|
|
3460
3552
|
return _wooksjs_event_core.cached;
|
|
3461
3553
|
}
|
|
3462
3554
|
});
|
|
3555
|
+
exports.claimWooks = claimWooks;
|
|
3463
3556
|
Object.defineProperty(exports, 'clearGlobalWooks', {
|
|
3464
3557
|
enumerable: true,
|
|
3465
3558
|
get: function () {
|
package/dist/index.d.ts
CHANGED
|
@@ -1649,6 +1649,27 @@ declare function mergeSorted<T extends {
|
|
|
1649
1649
|
priority: number;
|
|
1650
1650
|
}>(...lists: (T[] | readonly T[] | undefined)[]): T[];
|
|
1651
1651
|
|
|
1652
|
+
/** The options of {@link claimWooks}. */
|
|
1653
|
+
interface TClaimWooksOptions {
|
|
1654
|
+
/**
|
|
1655
|
+
* The adapter created its Wooks app itself (none was passed in), so it routes through the
|
|
1656
|
+
* process-wide global Wooks. Default `false`: an app passed in — sharing it is deliberate.
|
|
1657
|
+
*/
|
|
1658
|
+
created?: boolean;
|
|
1659
|
+
}
|
|
1660
|
+
/**
|
|
1661
|
+
* Records that `app` binds the handlers of its `adapter` (the adapter's `name`) into `wooks`
|
|
1662
|
+
* (the Wooks instance its routes go to: `wooksApp.getWooks()`). Adapters call it from `onInit`.
|
|
1663
|
+
*
|
|
1664
|
+
* Adapters created without a Wooks app of their own share the process-wide global Wooks, so two
|
|
1665
|
+
* apps in one process (typically in tests) route through one router. When another app already
|
|
1666
|
+
* bound handlers of the same adapter into `wooks`, and either adapter created its Wooks app
|
|
1667
|
+
* (`opts.created`), it warns — once per Wooks instance, with the app's logger. Apps that share
|
|
1668
|
+
* a Wooks app they pass in on purpose stay silent; re-initialising the same app does not warn.
|
|
1669
|
+
* A disposed app still counts: `dispose()` does not remove its routes.
|
|
1670
|
+
*/
|
|
1671
|
+
declare function claimWooks(app: Moost, wooks: object, adapter: string, opts?: TClaimWooksOptions): void;
|
|
1672
|
+
|
|
1652
1673
|
/**
|
|
1653
1674
|
* Sets the controller context for the current event scope.
|
|
1654
1675
|
* Called internally by adapters when dispatching events to handlers.
|
|
@@ -1771,12 +1792,40 @@ declare function defineInterceptor(def: TInterceptorDef, priority?: TInterceptor
|
|
|
1771
1792
|
*/
|
|
1772
1793
|
declare function definePipeFn<T extends TObject = TEmpty>(fn: TPipeFn<T>, priority?: TPipePriority): TPipeFn<T>;
|
|
1773
1794
|
|
|
1774
|
-
/**
|
|
1795
|
+
/**
|
|
1796
|
+
* What a translator gets besides the text: the event's locale, its scope and the event itself —
|
|
1797
|
+
* plus, when an error body is translated ({@link translateErrorBody}), the entry's `path` and
|
|
1798
|
+
* `code`.
|
|
1799
|
+
*/
|
|
1775
1800
|
interface TTranslateContext {
|
|
1776
1801
|
/** `useLocale().get()` of the event the text is translated for. */
|
|
1777
1802
|
locale: string | undefined;
|
|
1803
|
+
/**
|
|
1804
|
+
* The event's translation scope ({@link TTranslatorOptions.scope}) — e.g. a tenant whose
|
|
1805
|
+
* wording differs. `undefined`: the shared wording.
|
|
1806
|
+
*/
|
|
1807
|
+
scope?: string;
|
|
1778
1808
|
/** The event context — read anything else your policy needs from it. */
|
|
1779
1809
|
event: EventContext;
|
|
1810
|
+
/**
|
|
1811
|
+
* The field path (`'items.0.name'`, `''` for the root) of the error entry being
|
|
1812
|
+
* translated — word a message per field. Only set by {@link translateErrorBody}, for its
|
|
1813
|
+
* `errors` entries (and their `details`); error bodies are never memoized, while the memoized
|
|
1814
|
+
* {@link TTranslation.messages} never carry a path.
|
|
1815
|
+
*/
|
|
1816
|
+
path?: string;
|
|
1817
|
+
/**
|
|
1818
|
+
* The code of the error entry (or error body) being translated — also when `text` is the
|
|
1819
|
+
* entry's own message (an entry marked `custom`, or one translated by its text). Only set by
|
|
1820
|
+
* {@link translateErrorBody}.
|
|
1821
|
+
*/
|
|
1822
|
+
code?: string;
|
|
1823
|
+
/**
|
|
1824
|
+
* `true` when the error entry carries the app's own message (`custom: true`, e.g. from
|
|
1825
|
+
* `@expect.message`): `text` is that message — keep it unless you translate it as text. Only
|
|
1826
|
+
* set by {@link translateErrorBody}.
|
|
1827
|
+
*/
|
|
1828
|
+
custom?: boolean;
|
|
1780
1829
|
}
|
|
1781
1830
|
/**
|
|
1782
1831
|
* The app's translator. `text` is a message id: an error/message code (`WF_EXPIRED`,
|
|
@@ -1792,6 +1841,30 @@ type TTranslate = (text: string, params: Record<string, unknown> | undefined, ct
|
|
|
1792
1841
|
* placeholders, filled with {@link formatMessage}.
|
|
1793
1842
|
*/
|
|
1794
1843
|
type TTranslations = Record<string, Record<string, string>>;
|
|
1844
|
+
/** The options of {@link setTranslator}. */
|
|
1845
|
+
interface TTranslatorOptions {
|
|
1846
|
+
/** The locales the app serves, the default first. For a map: its keys by default. */
|
|
1847
|
+
locales?: readonly string[];
|
|
1848
|
+
/**
|
|
1849
|
+
* The event's translation scope, for wording that differs by more than the locale (per
|
|
1850
|
+
* tenant, brand, user group, …). Called in the event's context each time a translation is
|
|
1851
|
+
* taken — keep it cheap. Its result is passed to the translator ({@link TTranslateContext.scope})
|
|
1852
|
+
* and partitions everything memoized per translation ({@link TTranslation.key}); a finite
|
|
1853
|
+
* number counts as its string, and `undefined` (or any other value) is the shared, unscoped
|
|
1854
|
+
* wording. The translator must return the same text for the same (id, params, locale, scope).
|
|
1855
|
+
*
|
|
1856
|
+
* Derive it from a validated value (the authenticated principal's tenant), never straight from
|
|
1857
|
+
* request input: only the first 32 scopes seen per generation get a {@link TTranslation.key}.
|
|
1858
|
+
*/
|
|
1859
|
+
scope?: () => string | number | undefined;
|
|
1860
|
+
/**
|
|
1861
|
+
* `false`: a translated error body's top `message` that repeats its first entry is just that
|
|
1862
|
+
* entry's text, without the `path: ` prefix ({@link translateErrorBody}) — also when the entry
|
|
1863
|
+
* has no translation (its English text). Bodies of events without a locale are not touched.
|
|
1864
|
+
* Default `true`: `path: <translated>`, like the untranslated message.
|
|
1865
|
+
*/
|
|
1866
|
+
pathPrefix?: boolean;
|
|
1867
|
+
}
|
|
1795
1868
|
/** `t(id, params?, fallback?)` — see {@link useTranslate}. */
|
|
1796
1869
|
type TTranslateFn = (id: string, params?: Record<string, unknown>, fallback?: string) => string;
|
|
1797
1870
|
/** The translation of one event's locale — see {@link useTranslation}. */
|
|
@@ -1799,9 +1872,17 @@ interface TTranslation {
|
|
|
1799
1872
|
/** The event's locale. */
|
|
1800
1873
|
locale: string;
|
|
1801
1874
|
/**
|
|
1802
|
-
*
|
|
1803
|
-
* {@link
|
|
1804
|
-
*
|
|
1875
|
+
* What to index memoized results by: the locale, plus the event's scope when it has one
|
|
1876
|
+
* ({@link TTranslatorOptions.scope}). Keep one entry per partition, replaced when
|
|
1877
|
+
* {@link TTranslation.key} changes.
|
|
1878
|
+
*/
|
|
1879
|
+
partition: string;
|
|
1880
|
+
/**
|
|
1881
|
+
* A memo key for anything derived from this translation: the locale, the scope (if any) and
|
|
1882
|
+
* the generation — changes with every {@link setTranslator} call and every
|
|
1883
|
+
* {@link registerMessages} call that adds or changes a template. `undefined` for a locale
|
|
1884
|
+
* outside the translator's `locales`, or a scope past the cap ({@link TTranslatorOptions.scope})
|
|
1885
|
+
* — don't memoize then.
|
|
1805
1886
|
*/
|
|
1806
1887
|
key: string | undefined;
|
|
1807
1888
|
/** {@link useTranslate}'s `t`, bound to this translation. */
|
|
@@ -1834,9 +1915,7 @@ interface TTranslation {
|
|
|
1834
1915
|
* )
|
|
1835
1916
|
* ```
|
|
1836
1917
|
*/
|
|
1837
|
-
declare function setTranslator(translate: TTranslate | TTranslations | undefined, opts?:
|
|
1838
|
-
locales?: readonly string[];
|
|
1839
|
-
}): void;
|
|
1918
|
+
declare function setTranslator(translate: TTranslate | TTranslations | undefined, opts?: TTranslatorOptions): void;
|
|
1840
1919
|
/** The registered translator (a map wrapped as a function), or `undefined`. */
|
|
1841
1920
|
declare function getTranslator(): TTranslate | undefined;
|
|
1842
1921
|
/** The locales of the registered translator, the default first (empty without a translator). */
|
|
@@ -1882,9 +1961,11 @@ declare function useTranslation(ctx?: EventContext): TTranslation | undefined;
|
|
|
1882
1961
|
* event's locale — the body itself when there is no translation ({@link useTranslation}).
|
|
1883
1962
|
*
|
|
1884
1963
|
* - each entry of `errors` (and of its entries' `details`): by its `code` (unless `custom`),
|
|
1885
|
-
* else by its message text, its English `message` being the fallback;
|
|
1886
|
-
*
|
|
1887
|
-
*
|
|
1964
|
+
* else by its message text, its English `message` being the fallback; the translator gets the
|
|
1965
|
+
* entry's `path`, `code` and `custom` ({@link TTranslateContext});
|
|
1966
|
+
* - the top `message`: by `code` when the body has one (the translator gets that `code`); else,
|
|
1967
|
+
* when it is the first entry's message (`path: message`), the first entry's translation
|
|
1968
|
+
* (`path: ` dropped with `setTranslator(t, { pathPrefix: false })`); else by its text.
|
|
1888
1969
|
*
|
|
1889
1970
|
* `MoostHttp` applies it to every error body when it creates the HTTP app.
|
|
1890
1971
|
*/
|
|
@@ -1900,5 +1981,5 @@ declare function createLogger(opts?: Partial<TProstoLoggerOptions>): ProstoLogge
|
|
|
1900
1981
|
/** Default colored console transport used by Moost loggers. */
|
|
1901
1982
|
declare const loggerConsoleTransport: _prostojs_logger.TProstoLoggerTransportFn<any>;
|
|
1902
1983
|
|
|
1903
|
-
export { After, ApplyDecorators, Before, Circular, Const, ConstFactory, Controller, Description, HandlerPaths, Id, ImportController, Inherit, Inject, InjectEventLogger, InjectFromScope, InjectMoost, InjectMoostLogger, InjectScopeVars, Injectable, Intercept, Interceptor, InterceptorHandler, Label, Locale, LoggerTopic, MOOST_ADAPTER_BRAND, MOOST_MODULE_IDENTITY_KEY, Moost, MoostDispose, MoostInit, OnError, Optional, Overtake, Param, Params, Pipe, Provide, Replace, Required, Resolve, Response, TInterceptorPriority, TPipePriority, Value, createLogger, defineAfterInterceptor, defineBeforeInterceptor, defineErrorInterceptor, defineInfactScope, defineInterceptor, defineMoostEventHandler, definePipeFn, detachedKind, disposeInstances, forkEventContext, formatMessage, getHandlerPaths, getInfactScopeVars, getInfactSingletonInstances, getInstanceOwnMethods, getInstanceOwnProps, getMoostInfact, getMoostMate, getNewMoostInfact, getTranslator, getTranslatorLocales, globalKey, isThenable, loggerConsoleTransport, mergeSorted, registerEventScope, registerMessages, resolvePipe, setControllerContext, setInfactLoggingOptions, setInterceptOriginal, setInterceptResult, setOvertake, setTranslator, stampModuleIdentity, stampOnce, translateErrorBody, useControllerContext, useHandlerPaths, useInterceptOriginal, useInterceptResult, useOvertake, useScopeId, useTranslate, useTranslation, withControllerContext };
|
|
1904
|
-
export type { TAny, TAnyFn, TClassConstructor, TContextInjectorHook, TControllerOverview, TControllerRegistration, TControllersGroup, TDisposeError, TDisposeOptions, TDisposeResult, TEmpty, TForkEventContextOptions, TFunction, TGetHandlerPathsOptions, TInjectableScope, TInterceptorAfterFn, TInterceptorBeforeFn, TInterceptorData, TInterceptorDef, TInterceptorDefFactory, TInterceptorEntry, TInterceptorErrorFn, TIsolatedSlot, TLogger, TMoostAdapter, TMoostAdapterOptions, TMoostEventHandlerHookOptions, TMoostEventHandlerOptions, TMoostHandler, TMoostMetadata, TMoostModuleIdentity, TMoostOptions, TMoostParamsMetadata, TObject, TOvertakeFn, TPipeData, TPipeFn, TPipeMetas, TPrimitives, TRegistryMergeOptions, TRunDetachedOptions, TTranslate, TTranslateContext, TTranslation, TTranslations, TWithControllerContextOptions };
|
|
1984
|
+
export { After, ApplyDecorators, Before, Circular, Const, ConstFactory, Controller, Description, HandlerPaths, Id, ImportController, Inherit, Inject, InjectEventLogger, InjectFromScope, InjectMoost, InjectMoostLogger, InjectScopeVars, Injectable, Intercept, Interceptor, InterceptorHandler, Label, Locale, LoggerTopic, MOOST_ADAPTER_BRAND, MOOST_MODULE_IDENTITY_KEY, Moost, MoostDispose, MoostInit, OnError, Optional, Overtake, Param, Params, Pipe, Provide, Replace, Required, Resolve, Response, TInterceptorPriority, TPipePriority, Value, claimWooks, createLogger, defineAfterInterceptor, defineBeforeInterceptor, defineErrorInterceptor, defineInfactScope, defineInterceptor, defineMoostEventHandler, definePipeFn, detachedKind, disposeInstances, forkEventContext, formatMessage, getHandlerPaths, getInfactScopeVars, getInfactSingletonInstances, getInstanceOwnMethods, getInstanceOwnProps, getMoostInfact, getMoostMate, getNewMoostInfact, getTranslator, getTranslatorLocales, globalKey, isThenable, loggerConsoleTransport, mergeSorted, registerEventScope, registerMessages, resolvePipe, setControllerContext, setInfactLoggingOptions, setInterceptOriginal, setInterceptResult, setOvertake, setTranslator, stampModuleIdentity, stampOnce, translateErrorBody, useControllerContext, useHandlerPaths, useInterceptOriginal, useInterceptResult, useOvertake, useScopeId, useTranslate, useTranslation, withControllerContext };
|
|
1985
|
+
export type { TAny, TAnyFn, TClaimWooksOptions, TClassConstructor, TContextInjectorHook, TControllerOverview, TControllerRegistration, TControllersGroup, TDisposeError, TDisposeOptions, TDisposeResult, TEmpty, TForkEventContextOptions, TFunction, TGetHandlerPathsOptions, TInjectableScope, TInterceptorAfterFn, TInterceptorBeforeFn, TInterceptorData, TInterceptorDef, TInterceptorDefFactory, TInterceptorEntry, TInterceptorErrorFn, TIsolatedSlot, TLogger, TMoostAdapter, TMoostAdapterOptions, TMoostEventHandlerHookOptions, TMoostEventHandlerOptions, TMoostHandler, TMoostMetadata, TMoostModuleIdentity, TMoostOptions, TMoostParamsMetadata, TObject, TOvertakeFn, TPipeData, TPipeFn, TPipeMetas, TPrimitives, TRegistryMergeOptions, TRunDetachedOptions, TTranslate, TTranslateContext, TTranslation, TTranslations, TTranslatorOptions, TWithControllerContextOptions };
|
package/dist/index.mjs
CHANGED
|
@@ -47,7 +47,7 @@ let stamped = false;
|
|
|
47
47
|
if (stamped) return;
|
|
48
48
|
stamped = true;
|
|
49
49
|
stampModuleIdentity({
|
|
50
|
-
version: "0.7.
|
|
50
|
+
version: "0.7.5",
|
|
51
51
|
path: typeof __filename === "string" ? __filename : import.meta.url
|
|
52
52
|
});
|
|
53
53
|
}
|
|
@@ -3181,11 +3181,44 @@ function _define_property(obj, key, value) {
|
|
|
3181
3181
|
return getHandlerPaths(moost, getController(), method ?? getMethod() ?? "", opts);
|
|
3182
3182
|
}
|
|
3183
3183
|
|
|
3184
|
+
//#endregion
|
|
3185
|
+
//#region packages/moost/src/wooks-owner.ts
|
|
3186
|
+
/** Per Wooks instance: the first claim of each adapter (by `name`) bound into it. */ const owners = /* @__PURE__ */ new WeakMap();
|
|
3187
|
+
/** Wooks instances already warned about: the warning is logged once per instance. */ const warned = /* @__PURE__ */ new WeakSet();
|
|
3188
|
+
/**
|
|
3189
|
+
* Records that `app` binds the handlers of its `adapter` (the adapter's `name`) into `wooks`
|
|
3190
|
+
* (the Wooks instance its routes go to: `wooksApp.getWooks()`). Adapters call it from `onInit`.
|
|
3191
|
+
*
|
|
3192
|
+
* Adapters created without a Wooks app of their own share the process-wide global Wooks, so two
|
|
3193
|
+
* apps in one process (typically in tests) route through one router. When another app already
|
|
3194
|
+
* bound handlers of the same adapter into `wooks`, and either adapter created its Wooks app
|
|
3195
|
+
* (`opts.created`), it warns — once per Wooks instance, with the app's logger. Apps that share
|
|
3196
|
+
* a Wooks app they pass in on purpose stay silent; re-initialising the same app does not warn.
|
|
3197
|
+
* A disposed app still counts: `dispose()` does not remove its routes.
|
|
3198
|
+
*/ function claimWooks(app, wooks, adapter, opts) {
|
|
3199
|
+
const created = opts?.created === true;
|
|
3200
|
+
let byAdapter = owners.get(wooks);
|
|
3201
|
+
if (!byAdapter) {
|
|
3202
|
+
byAdapter = /* @__PURE__ */ new Map();
|
|
3203
|
+
owners.set(wooks, byAdapter);
|
|
3204
|
+
}
|
|
3205
|
+
const owner = byAdapter.get(adapter);
|
|
3206
|
+
if (owner === void 0) byAdapter.set(adapter, {
|
|
3207
|
+
app,
|
|
3208
|
+
created
|
|
3209
|
+
});
|
|
3210
|
+
else if (owner.app !== app && (created || owner.created) && !warned.has(wooks)) {
|
|
3211
|
+
warned.add(wooks);
|
|
3212
|
+
app.getLogger().warn(`[moost] A second Moost app binds "${adapter}" handlers into the Wooks instance another app already uses (adapters created without their own Wooks app share the process-wide global one). Both apps' routes now live in one router: an event on a route both register runs the first app's handler chain, and when that throws, its error is swallowed and the next app's chain runs instead. Call clearGlobalWooks() before creating each app (e.g. in a test's beforeEach): the next adapter then gets a fresh Wooks. (Logged once per Wooks instance.)`);
|
|
3213
|
+
}
|
|
3214
|
+
}
|
|
3215
|
+
|
|
3184
3216
|
//#endregion
|
|
3185
3217
|
//#region packages/moost/src/i18n.ts
|
|
3186
3218
|
var _globalThis, _STATE, _state, _state1, _state2, _state3, _state4;
|
|
3187
3219
|
const STATE = Symbol.for("moost.i18n");
|
|
3188
3220
|
const NO_LOCALES = Object.freeze([]);
|
|
3221
|
+
/** Distinct scopes given memo keys per generation: keeps every memo keyed by `key` bounded. */ const MAX_SCOPES = 32;
|
|
3189
3222
|
const state = (_globalThis = globalThis)[_STATE = STATE] ?? (_globalThis[_STATE] = {});
|
|
3190
3223
|
(_state = state).locales ?? (_state.locales = NO_LOCALES);
|
|
3191
3224
|
(_state1 = state).generation ?? (_state1.generation = 0);
|
|
@@ -3215,9 +3248,15 @@ const state = (_globalThis = globalThis)[_STATE = STATE] ?? (_globalThis[_STATE]
|
|
|
3215
3248
|
*/ function setTranslator(translate, opts) {
|
|
3216
3249
|
const isMap = typeof translate === "object";
|
|
3217
3250
|
state.translate = isMap ? mapTranslator(translate) : translate;
|
|
3251
|
+
state.scoping = opts?.scope && {
|
|
3252
|
+
translate: state.translate,
|
|
3253
|
+
get: opts.scope
|
|
3254
|
+
};
|
|
3255
|
+
state.noPathPrefix = opts?.pathPrefix === false ? state.translate : void 0;
|
|
3218
3256
|
const locales = opts?.locales ?? (isMap ? Object.keys(translate) : void 0);
|
|
3219
3257
|
state.locales = translate && locales?.length ? Object.freeze([...locales]) : NO_LOCALES;
|
|
3220
3258
|
state.failureLogged = false;
|
|
3259
|
+
state.scopeFailureLogged = false;
|
|
3221
3260
|
newGeneration();
|
|
3222
3261
|
}
|
|
3223
3262
|
/** The registered translator (a map wrapped as a function), or `undefined`. */ function getTranslator() {
|
|
@@ -3243,7 +3282,7 @@ const state = (_globalThis = globalThis)[_STATE = STATE] ?? (_globalThis[_STATE]
|
|
|
3243
3282
|
}
|
|
3244
3283
|
if (changed) newGeneration();
|
|
3245
3284
|
}
|
|
3246
|
-
/**
|
|
3285
|
+
/** Drops everything derived from the translator and the templates. */ function newGeneration() {
|
|
3247
3286
|
state.generation++;
|
|
3248
3287
|
state.memo.clear();
|
|
3249
3288
|
}
|
|
@@ -3278,10 +3317,7 @@ const PLACEHOLDER = /\{(\w+)\}/g;
|
|
|
3278
3317
|
let translateCtx;
|
|
3279
3318
|
return (id, params, fallback) => {
|
|
3280
3319
|
const translate = state.translate;
|
|
3281
|
-
return (translate ? callTranslator(translate, id, params, translateCtx ?? (translateCtx =
|
|
3282
|
-
locale: useLocale$1(event).get(),
|
|
3283
|
-
event
|
|
3284
|
-
})) : void 0) ?? untranslated(id, params, fallback);
|
|
3320
|
+
return (translate ? callTranslator(translate, id, params, translateCtx ?? (translateCtx = translateContext(event, useLocale$1(event).get(), readScope(event)))) : void 0) ?? untranslated(id, params, fallback);
|
|
3285
3321
|
};
|
|
3286
3322
|
}
|
|
3287
3323
|
/** `t`'s text without a translation: `fallback` as is, else the filled template (or id). */ function untranslated(id, params, fallback) {
|
|
@@ -3297,12 +3333,11 @@ const PLACEHOLDER = /\{(\w+)\}/g;
|
|
|
3297
3333
|
const event = ctx ?? current$1();
|
|
3298
3334
|
const locale = useLocale$1(event).get();
|
|
3299
3335
|
if (locale === void 0) return;
|
|
3300
|
-
const
|
|
3301
|
-
|
|
3302
|
-
event
|
|
3303
|
-
};
|
|
3336
|
+
const scope = readScope(event);
|
|
3337
|
+
const translateCtx = translateContext(event, locale, scope);
|
|
3304
3338
|
const generation = state.generation;
|
|
3305
|
-
const
|
|
3339
|
+
const partition = typeof scope === "string" ? `${locale}:${scope}` : locale;
|
|
3340
|
+
const key = state.locales.includes(locale) && (scope === void 0 || scope !== null && admitted(scope)) ? `${generation}:${partition}` : void 0;
|
|
3306
3341
|
const t = (id, params, fallback) => callTranslator(translate, id, params, translateCtx) ?? untranslated(id, params, fallback);
|
|
3307
3342
|
const messages = () => {
|
|
3308
3343
|
if (key === void 0 || state.generation !== generation) return translateTemplates(translate, translateCtx);
|
|
@@ -3315,31 +3350,82 @@ const PLACEHOLDER = /\{(\w+)\}/g;
|
|
|
3315
3350
|
};
|
|
3316
3351
|
return {
|
|
3317
3352
|
locale,
|
|
3353
|
+
partition,
|
|
3318
3354
|
key,
|
|
3319
3355
|
t,
|
|
3320
3356
|
messages
|
|
3321
3357
|
};
|
|
3322
3358
|
}
|
|
3359
|
+
function translateContext(event, locale, scope) {
|
|
3360
|
+
return typeof scope === "string" ? {
|
|
3361
|
+
locale,
|
|
3362
|
+
scope,
|
|
3363
|
+
event
|
|
3364
|
+
} : {
|
|
3365
|
+
locale,
|
|
3366
|
+
event
|
|
3367
|
+
};
|
|
3368
|
+
}
|
|
3369
|
+
/**
|
|
3370
|
+
* The event's scope (`opts.scope`): `undefined` without one, `null` when the scope function
|
|
3371
|
+
* threw (logged once) — translated unscoped then, and not memoized.
|
|
3372
|
+
*/ function readScope(event) {
|
|
3373
|
+
const scoping = state.scoping;
|
|
3374
|
+
if (!scoping || scoping.translate !== state.translate) return;
|
|
3375
|
+
try {
|
|
3376
|
+
const { get } = scoping;
|
|
3377
|
+
const scope = tryGetCurrent() === event ? get() : run$1(event, get);
|
|
3378
|
+
return typeof scope === "string" ? scope : typeof scope === "number" && Number.isFinite(scope) ? String(scope) : void 0;
|
|
3379
|
+
} catch (error) {
|
|
3380
|
+
logOnce("scopeFailureLogged", event, "The translation scope threw — translating unscoped, without memoizing (logged once)", error);
|
|
3381
|
+
return null;
|
|
3382
|
+
}
|
|
3383
|
+
}
|
|
3384
|
+
/** Whether `scope` gets memo keys: one of the first {@link MAX_SCOPES} of the generation. */ function admitted(scope) {
|
|
3385
|
+
if (state.admittedScopes?.generation !== state.generation) state.admittedScopes = {
|
|
3386
|
+
generation: state.generation,
|
|
3387
|
+
names: /* @__PURE__ */ new Set()
|
|
3388
|
+
};
|
|
3389
|
+
const { names } = state.admittedScopes;
|
|
3390
|
+
if (names.size < MAX_SCOPES) names.add(scope);
|
|
3391
|
+
return names.has(scope);
|
|
3392
|
+
}
|
|
3393
|
+
/** Logs a failure of the translator or the scope function once per `setTranslator`. */ function logOnce(flag, event, message, error) {
|
|
3394
|
+
if (!state[flag]) {
|
|
3395
|
+
state[flag] = true;
|
|
3396
|
+
useLogger$1("i18n", event).error(message, error);
|
|
3397
|
+
}
|
|
3398
|
+
}
|
|
3323
3399
|
/**
|
|
3324
3400
|
* Returns a translated copy of an error body (`{ message, code?, params?, errors? }`) in the
|
|
3325
3401
|
* event's locale — the body itself when there is no translation ({@link useTranslation}).
|
|
3326
3402
|
*
|
|
3327
3403
|
* - each entry of `errors` (and of its entries' `details`): by its `code` (unless `custom`),
|
|
3328
|
-
* else by its message text, its English `message` being the fallback;
|
|
3329
|
-
*
|
|
3330
|
-
*
|
|
3404
|
+
* else by its message text, its English `message` being the fallback; the translator gets the
|
|
3405
|
+
* entry's `path`, `code` and `custom` ({@link TTranslateContext});
|
|
3406
|
+
* - the top `message`: by `code` when the body has one (the translator gets that `code`); else,
|
|
3407
|
+
* when it is the first entry's message (`path: message`), the first entry's translation
|
|
3408
|
+
* (`path: ` dropped with `setTranslator(t, { pathPrefix: false })`); else by its text.
|
|
3331
3409
|
*
|
|
3332
3410
|
* `MoostHttp` applies it to every error body when it creates the HTTP app.
|
|
3333
3411
|
*/ function translateErrorBody(body, ctx) {
|
|
3334
|
-
const
|
|
3335
|
-
|
|
3336
|
-
const
|
|
3412
|
+
const event = ctx ?? current$1();
|
|
3413
|
+
const translate = state.translate;
|
|
3414
|
+
const locale = useLocale$1(event).get();
|
|
3415
|
+
if (!translate || locale === void 0) return body;
|
|
3416
|
+
const base = translateContext(event, locale, readScope(event));
|
|
3417
|
+
const t = (id, params, fallback, entry) => callTranslator(translate, id, params, entry ? entryContext(base, entry) : base) ?? untranslated(id, params, fallback);
|
|
3337
3418
|
const source = Array.isArray(body.errors) ? body.errors : void 0;
|
|
3338
3419
|
const errors = source && translateEntries(source, t);
|
|
3339
3420
|
let message;
|
|
3340
|
-
if (typeof body.code === "string" && body.code) message =
|
|
3341
|
-
|
|
3342
|
-
|
|
3421
|
+
if (typeof body.code === "string" && body.code) message = callTranslator(translate, body.code, body.params, {
|
|
3422
|
+
...base,
|
|
3423
|
+
code: body.code
|
|
3424
|
+
}) ?? untranslated(body.code, body.params, body.message);
|
|
3425
|
+
else if (source && errors && isEntry(source[0]) && body.message === topMessage(source[0])) {
|
|
3426
|
+
const first = errors[0];
|
|
3427
|
+
message = state.noPathPrefix === translate ? first.message : topMessage(first);
|
|
3428
|
+
} else message = t(body.message, body.params, body.message);
|
|
3343
3429
|
return errors ? {
|
|
3344
3430
|
...body,
|
|
3345
3431
|
message,
|
|
@@ -3360,10 +3446,7 @@ function mapTranslator(map) {
|
|
|
3360
3446
|
const out = translate(id, params, ctx);
|
|
3361
3447
|
return typeof out === "string" ? out : void 0;
|
|
3362
3448
|
} catch (error) {
|
|
3363
|
-
|
|
3364
|
-
state.failureLogged = true;
|
|
3365
|
-
useLogger$1("i18n", ctx.event).error(`The translator threw for "${id}" — using the untranslated text (logged once)`, error);
|
|
3366
|
-
}
|
|
3449
|
+
logOnce("failureLogged", ctx.event, `The translator threw for "${id}" — using the untranslated text (logged once)`, error);
|
|
3367
3450
|
return;
|
|
3368
3451
|
}
|
|
3369
3452
|
}
|
|
@@ -3380,13 +3463,22 @@ function mapTranslator(map) {
|
|
|
3380
3463
|
function isEntry(value) {
|
|
3381
3464
|
return typeof value === "object" && value !== null && typeof value.message === "string";
|
|
3382
3465
|
}
|
|
3466
|
+
/** `base` with the entry's `path` and `code` (each only when a string) and `custom: true`. */ function entryContext(base, { path, code, custom }) {
|
|
3467
|
+
const hasCode = typeof code === "string" && code !== "";
|
|
3468
|
+
if (typeof path !== "string" && !hasCode && custom !== true) return base;
|
|
3469
|
+
const out = { ...base };
|
|
3470
|
+
if (typeof path === "string") out.path = path;
|
|
3471
|
+
if (hasCode) out.code = code;
|
|
3472
|
+
if (custom === true) out.custom = true;
|
|
3473
|
+
return out;
|
|
3474
|
+
}
|
|
3383
3475
|
function translateEntries(entries, t) {
|
|
3384
3476
|
return entries.map((entry) => {
|
|
3385
3477
|
if (!isEntry(entry)) return entry;
|
|
3386
3478
|
const id = typeof entry.code === "string" && entry.code && entry.custom !== true ? entry.code : entry.message;
|
|
3387
3479
|
const out = {
|
|
3388
3480
|
...entry,
|
|
3389
|
-
message: t(id, entry.params, entry.message)
|
|
3481
|
+
message: t(id, entry.params, entry.message, entry)
|
|
3390
3482
|
};
|
|
3391
3483
|
if (Array.isArray(entry.details)) out.details = translateEntries(entry.details, t);
|
|
3392
3484
|
return out;
|
|
@@ -3397,4 +3489,4 @@ function topMessage(entry) {
|
|
|
3397
3489
|
}
|
|
3398
3490
|
|
|
3399
3491
|
//#endregion
|
|
3400
|
-
export { After, ApplyDecorators, Before, Circular, Const, ConstFactory, ContextInjector, Controller, Description, HandlerPaths, Id, ImportController, Inherit, Inject, InjectEventLogger, InjectFromScope, InjectMoost, InjectMoostLogger, InjectScopeVars, Injectable, Intercept, Interceptor, InterceptorHandler, Label, Locale, LoggerTopic, MOOST_ADAPTER_BRAND, MOOST_MODULE_IDENTITY_KEY, Moost, MoostDispose, MoostInit, OnError, Optional, Overtake, Param, Params, Pipe, ProstoLogger, Provide, Replace, Required, Resolve, Response, TInterceptorPriority, TPipePriority, Value, cached, clearGlobalWooks, createEventContext, createLogger, createProvideRegistry, createReplaceRegistry, current, defineAfterInterceptor, defineBeforeInterceptor, defineErrorInterceptor, defineInfactScope, defineInterceptor, defineMoostEventHandler, definePipeFn, detachedKind, disposeInstances, eventTypeKey, forkEventContext, formatMessage, getClassKey, getConstructor, getContextInjector, getGlobalWooks, getHandlerPaths, getInfactScopeVars, getInfactSingletonInstances, getInstanceOwnMethods, getInstanceOwnProps, getMoostInfact, getMoostMate, getNewMoostInfact, getTranslator, getTranslatorLocales, globalKey, isConstructor, isThenable, key, loggerConsoleTransport, mergeSorted, registerEventScope, registerMessages, replaceContextInjector, resetContextInjector, resolvePipe, run, setControllerContext, setInfactLoggingOptions, setInterceptOriginal, setInterceptResult, setOvertake, setTranslator, stampModuleIdentity, stampOnce, translateErrorBody, useControllerContext, useHandlerPaths, useInterceptOriginal, useInterceptResult, useLocale, useLogger, useOvertake, useScopeId, useTranslate, useTranslation, withControllerContext };
|
|
3492
|
+
export { After, ApplyDecorators, Before, Circular, Const, ConstFactory, ContextInjector, Controller, Description, HandlerPaths, Id, ImportController, Inherit, Inject, InjectEventLogger, InjectFromScope, InjectMoost, InjectMoostLogger, InjectScopeVars, Injectable, Intercept, Interceptor, InterceptorHandler, Label, Locale, LoggerTopic, MOOST_ADAPTER_BRAND, MOOST_MODULE_IDENTITY_KEY, Moost, MoostDispose, MoostInit, OnError, Optional, Overtake, Param, Params, Pipe, ProstoLogger, Provide, Replace, Required, Resolve, Response, TInterceptorPriority, TPipePriority, Value, cached, claimWooks, clearGlobalWooks, createEventContext, createLogger, createProvideRegistry, createReplaceRegistry, current, defineAfterInterceptor, defineBeforeInterceptor, defineErrorInterceptor, defineInfactScope, defineInterceptor, defineMoostEventHandler, definePipeFn, detachedKind, disposeInstances, eventTypeKey, forkEventContext, formatMessage, getClassKey, getConstructor, getContextInjector, getGlobalWooks, getHandlerPaths, getInfactScopeVars, getInfactSingletonInstances, getInstanceOwnMethods, getInstanceOwnProps, getMoostInfact, getMoostMate, getNewMoostInfact, getTranslator, getTranslatorLocales, globalKey, isConstructor, isThenable, key, loggerConsoleTransport, mergeSorted, registerEventScope, registerMessages, replaceContextInjector, resetContextInjector, resolvePipe, run, setControllerContext, setInfactLoggingOptions, setInterceptOriginal, setInterceptResult, setOvertake, setTranslator, stampModuleIdentity, stampOnce, translateErrorBody, useControllerContext, useHandlerPaths, useInterceptOriginal, useInterceptResult, useLocale, useLogger, useOvertake, useScopeId, useTranslate, useTranslation, withControllerContext };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "moost",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.5",
|
|
4
4
|
"description": "moost",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"composables",
|
|
@@ -41,15 +41,15 @@
|
|
|
41
41
|
"@prostojs/infact": "^0.6.1",
|
|
42
42
|
"@prostojs/logger": "^0.4.3",
|
|
43
43
|
"@prostojs/mate": "^0.5.1",
|
|
44
|
-
"@wooksjs/event-core": "^0.8.
|
|
44
|
+
"@wooksjs/event-core": "^0.8.2",
|
|
45
45
|
"hookable": "^5.5.3",
|
|
46
|
-
"wooks": "^0.8.
|
|
46
|
+
"wooks": "^0.8.2"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@wooksjs/event-http": "^0.8.
|
|
50
|
-
"@wooksjs/http-body": "^0.8.
|
|
49
|
+
"@wooksjs/event-http": "^0.8.2",
|
|
50
|
+
"@wooksjs/http-body": "^0.8.2",
|
|
51
51
|
"vitest": "4.1.12",
|
|
52
|
-
"@moostjs/event-http": "^0.7.
|
|
52
|
+
"@moostjs/event-http": "^0.7.5"
|
|
53
53
|
},
|
|
54
54
|
"scripts": {
|
|
55
55
|
"pub": "pnpm publish --access public",
|