@logixjs/i18n 1.0.2-beta.0 → 1.0.2

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.
@@ -1,116 +0,0 @@
1
- // src/internal/token/token.ts
2
- var InvalidI18nMessageTokenError = class extends Error {
3
- constructor(reason, details, fix) {
4
- super(`[InvalidI18nMessageTokenError] reason=${reason}`);
5
- this.reason = reason;
6
- this.details = details;
7
- this.fix = fix;
8
- this.name = "InvalidI18nMessageTokenError";
9
- }
10
- };
11
- var TOKEN_BUDGET = {
12
- keyMaxLen: 96,
13
- optionKeyMaxCount: 8,
14
- optionValueStringMaxLen: 96
15
- };
16
- var LANGUAGE_FROZEN_KEYS = /* @__PURE__ */ new Set(["lng", "lngs"]);
17
- var DANGEROUS_OPTION_KEYS = /* @__PURE__ */ new Set(["__proto__", "prototype", "constructor"]);
18
- var isJsonPrimitive = (value) => value === null || typeof value === "boolean" || typeof value === "number" || typeof value === "string";
19
- var invalidToken = (reason, details, fix) => {
20
- throw new InvalidI18nMessageTokenError(reason, details, fix);
21
- };
22
- var canonicalizeTokenOptions = (options) => {
23
- if (!options) return void 0;
24
- if (typeof options !== "object" || options === null || Array.isArray(options)) {
25
- invalidToken("optionValueInvalid", { field: "options", actual: typeof options }, [
26
- "\u8BF7\u4F20\u5165 plain object \u4F5C\u4E3A options\uFF08Record<string, JsonPrimitive>\uFF09\u3002",
27
- "\u4E0D\u8981\u4F20\u5165\u6570\u7EC4/\u51FD\u6570/\u7C7B\u5B9E\u4F8B\u7B49\u4E0D\u53EF\u5E8F\u5217\u5316\u503C\u3002"
28
- ]);
29
- }
30
- const entries = Object.entries(options).filter((p) => p[1] !== void 0);
31
- if (entries.length === 0) return void 0;
32
- if (entries.length > TOKEN_BUDGET.optionKeyMaxCount) {
33
- invalidToken(
34
- "tooManyOptions",
35
- {
36
- field: "options",
37
- max: TOKEN_BUDGET.optionKeyMaxCount,
38
- actual: entries.length
39
- },
40
- [
41
- `\u51CF\u5C11 options \u952E\u6570\u91CF\uFF08\u5EFA\u8BAE \u2264 ${TOKEN_BUDGET.optionKeyMaxCount}\uFF09\u3002`,
42
- "\u628A\u8F83\u957F\u7684\u4FE1\u606F\u632A\u5230 key \u6216 defaultValue\uFF1B\u907F\u514D\u628A\u5927\u5BF9\u8C61\u585E\u8FDB token\u3002"
43
- ]
44
- );
45
- }
46
- for (const [k, v] of entries) {
47
- if (DANGEROUS_OPTION_KEYS.has(k) || k.length === 0) {
48
- invalidToken("optionKeyInvalid", { field: `options.${k}`, key: k }, [
49
- "\u8BF7\u4F7F\u7528\u666E\u901A\u5B57\u6BB5\u540D\u4F5C\u4E3A options key\uFF08\u907F\u514D __proto__/constructor/prototype \u7B49\u5371\u9669\u952E\uFF09\u3002",
50
- "\u5982\u9700\u4F20\u9012\u590D\u6742\u7ED3\u6784\uFF0C\u8BF7\u5148\u5728\u5C55\u793A\u8FB9\u754C\u8F6C\u6362\u4E3A\u5B57\u7B26\u4E32\u3002"
51
- ]);
52
- }
53
- if (LANGUAGE_FROZEN_KEYS.has(k)) {
54
- invalidToken("languageFrozen", { field: `options.${k}`, key: k }, [
55
- "\u4E0D\u8981\u5728 token options \u4E2D\u4F20\u5165 lng/lngs \u7B49\u8BED\u8A00\u51BB\u7ED3\u5B57\u6BB5\u3002",
56
- "\u8BED\u8A00\u7531\u5916\u90E8 i18n \u5B9E\u4F8B\u51B3\u5B9A\uFF1Btoken \u53EA\u8868\u8FBE\u201C\u8981\u7FFB\u8BD1\u4EC0\u4E48\u201D\u3002"
57
- ]);
58
- }
59
- if (!isJsonPrimitive(v)) {
60
- invalidToken("optionValueInvalid", { field: `options.${k}`, actual: typeof v }, [
61
- "options value \u53EA\u5141\u8BB8 JsonPrimitive\uFF08null/boolean/number/string\uFF09\u3002",
62
- "\u4E0D\u8981\u4F20\u5165\u5BF9\u8C61/\u6570\u7EC4/\u51FD\u6570\uFF1B\u9700\u8981\u65F6\u8BF7\u5728\u5C55\u793A\u8FB9\u754C\u5148\u683C\u5F0F\u5316\u6210\u5B57\u7B26\u4E32\u3002"
63
- ]);
64
- }
65
- if (typeof v === "number" && !Number.isFinite(v)) {
66
- invalidToken("numberNotJsonSafe", { field: `options.${k}`, value: String(v) }, [
67
- "\u4E0D\u8981\u5728 token options \u4E2D\u4F20\u5165 NaN/Infinity\u3002",
68
- "\u8BF7\u5148\u628A\u8BE5\u6570\u503C\u8F6C\u6362\u4E3A\u53EF JSON \u5316\u7684 number \u6216 string\u3002"
69
- ]);
70
- }
71
- if (typeof v === "string" && v.length > TOKEN_BUDGET.optionValueStringMaxLen) {
72
- invalidToken(
73
- "optionValueTooLong",
74
- {
75
- field: `options.${k}`,
76
- maxLen: TOKEN_BUDGET.optionValueStringMaxLen,
77
- actualLen: v.length
78
- },
79
- [
80
- `\u7F29\u77ED\u5B57\u7B26\u4E32\u503C\u957F\u5EA6\uFF08\u5EFA\u8BAE \u2264 ${TOKEN_BUDGET.optionValueStringMaxLen}\uFF09\u3002`,
81
- "\u628A\u957F\u6587\u672C\u79FB\u5230 defaultValue \u6216\u76F4\u63A5\u5728\u5C55\u793A\u8FB9\u754C\u751F\u6210\u6700\u7EC8\u5B57\u7B26\u4E32\u3002"
82
- ]
83
- );
84
- }
85
- }
86
- entries.sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
87
- const out = {};
88
- for (const [k, v] of entries) {
89
- out[k] = v;
90
- }
91
- return out;
92
- };
93
- var token = (key, options) => {
94
- if (key.length > TOKEN_BUDGET.keyMaxLen) {
95
- invalidToken("keyTooLong", { field: "key", maxLen: TOKEN_BUDGET.keyMaxLen, actualLen: key.length }, [
96
- `\u7F29\u77ED key\uFF08\u5EFA\u8BAE \u2264 ${TOKEN_BUDGET.keyMaxLen}\uFF09\u3002`,
97
- "\u5982\u679C key \u8FC7\u957F\uFF0C\u5EFA\u8BAE\u6539\u4E3A\u201C\u7A33\u5B9A key + \u53D8\u91CF options/defaultValue\u201D\u3002"
98
- ]);
99
- }
100
- const canon = canonicalizeTokenOptions(options);
101
- return canon ? {
102
- _tag: "i18n",
103
- key,
104
- options: canon
105
- } : {
106
- _tag: "i18n",
107
- key
108
- };
109
- };
110
-
111
- export {
112
- InvalidI18nMessageTokenError,
113
- canonicalizeTokenOptions,
114
- token
115
- };
116
- //# sourceMappingURL=chunk-NWWL4MNH.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/internal/token/token.ts"],"sourcesContent":["export type JsonPrimitive = null | boolean | number | string\n\nexport type I18nTokenOptions = Readonly<Record<string, JsonPrimitive>>\nexport type I18nTokenOptionsInput = Readonly<Record<string, JsonPrimitive | undefined>>\n\nexport type I18nMessageToken = {\n readonly _tag: 'i18n'\n readonly key: string\n readonly options?: I18nTokenOptions\n}\n\nexport type InvalidI18nMessageTokenReason =\n | 'keyTooLong'\n | 'tooManyOptions'\n | 'optionKeyInvalid'\n | 'optionValueInvalid'\n | 'optionValueTooLong'\n | 'numberNotJsonSafe'\n | 'languageFrozen'\n\nexport class InvalidI18nMessageTokenError extends Error {\n readonly name = 'InvalidI18nMessageTokenError'\n\n constructor(\n readonly reason: InvalidI18nMessageTokenReason,\n readonly details: unknown,\n readonly fix: ReadonlyArray<string>,\n ) {\n super(`[InvalidI18nMessageTokenError] reason=${reason}`)\n }\n}\n\nconst TOKEN_BUDGET = {\n keyMaxLen: 96,\n optionKeyMaxCount: 8,\n optionValueStringMaxLen: 96,\n} as const\n\nconst LANGUAGE_FROZEN_KEYS = new Set(['lng', 'lngs'])\nconst DANGEROUS_OPTION_KEYS = new Set(['__proto__', 'prototype', 'constructor'])\n\nconst isJsonPrimitive = (value: unknown): value is JsonPrimitive =>\n value === null || typeof value === 'boolean' || typeof value === 'number' || typeof value === 'string'\n\nconst invalidToken = (reason: InvalidI18nMessageTokenReason, details: unknown, fix: ReadonlyArray<string>): never => {\n throw new InvalidI18nMessageTokenError(reason, details, fix)\n}\n\nexport const canonicalizeTokenOptions = (options: I18nTokenOptionsInput | undefined): I18nTokenOptions | undefined => {\n if (!options) return undefined\n if (typeof options !== 'object' || options === null || Array.isArray(options)) {\n invalidToken('optionValueInvalid', { field: 'options', actual: typeof options }, [\n '请传入 plain object 作为 options(Record<string, JsonPrimitive>)。',\n '不要传入数组/函数/类实例等不可序列化值。',\n ])\n }\n\n const entries = Object.entries(options).filter((p): p is [string, JsonPrimitive] => p[1] !== undefined)\n\n if (entries.length === 0) return undefined\n\n if (entries.length > TOKEN_BUDGET.optionKeyMaxCount) {\n invalidToken(\n 'tooManyOptions',\n {\n field: 'options',\n max: TOKEN_BUDGET.optionKeyMaxCount,\n actual: entries.length,\n },\n [\n `减少 options 键数量(建议 ≤ ${TOKEN_BUDGET.optionKeyMaxCount})。`,\n '把较长的信息挪到 key 或 defaultValue;避免把大对象塞进 token。',\n ],\n )\n }\n\n for (const [k, v] of entries) {\n if (DANGEROUS_OPTION_KEYS.has(k) || k.length === 0) {\n invalidToken('optionKeyInvalid', { field: `options.${k}`, key: k }, [\n '请使用普通字段名作为 options key(避免 __proto__/constructor/prototype 等危险键)。',\n '如需传递复杂结构,请先在展示边界转换为字符串。',\n ])\n }\n\n if (LANGUAGE_FROZEN_KEYS.has(k)) {\n invalidToken('languageFrozen', { field: `options.${k}`, key: k }, [\n '不要在 token options 中传入 lng/lngs 等语言冻结字段。',\n '语言由外部 i18n 实例决定;token 只表达“要翻译什么”。',\n ])\n }\n\n if (!isJsonPrimitive(v)) {\n invalidToken('optionValueInvalid', { field: `options.${k}`, actual: typeof v }, [\n 'options value 只允许 JsonPrimitive(null/boolean/number/string)。',\n '不要传入对象/数组/函数;需要时请在展示边界先格式化成字符串。',\n ])\n }\n\n if (typeof v === 'number' && !Number.isFinite(v)) {\n invalidToken('numberNotJsonSafe', { field: `options.${k}`, value: String(v) }, [\n '不要在 token options 中传入 NaN/Infinity。',\n '请先把该数值转换为可 JSON 化的 number 或 string。',\n ])\n }\n\n if (typeof v === 'string' && v.length > TOKEN_BUDGET.optionValueStringMaxLen) {\n invalidToken(\n 'optionValueTooLong',\n {\n field: `options.${k}`,\n maxLen: TOKEN_BUDGET.optionValueStringMaxLen,\n actualLen: v.length,\n },\n [\n `缩短字符串值长度(建议 ≤ ${TOKEN_BUDGET.optionValueStringMaxLen})。`,\n '把长文本移到 defaultValue 或直接在展示边界生成最终字符串。',\n ],\n )\n }\n }\n\n entries.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n\n const out: Record<string, JsonPrimitive> = {}\n for (const [k, v] of entries) {\n out[k] = v\n }\n return out\n}\n\nexport const token = (key: string, options?: I18nTokenOptionsInput): I18nMessageToken => {\n if (key.length > TOKEN_BUDGET.keyMaxLen) {\n invalidToken('keyTooLong', { field: 'key', maxLen: TOKEN_BUDGET.keyMaxLen, actualLen: key.length }, [\n `缩短 key(建议 ≤ ${TOKEN_BUDGET.keyMaxLen})。`,\n '如果 key 过长,建议改为“稳定 key + 变量 options/defaultValue”。',\n ])\n }\n\n const canon = canonicalizeTokenOptions(options)\n return canon\n ? {\n _tag: 'i18n',\n key,\n options: canon,\n }\n : {\n _tag: 'i18n',\n key,\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,45 +0,0 @@
1
- import {
2
- I18nSnapshotSchema,
3
- I18nTag
4
- } from "./chunk-4NKGIEWG.js";
5
-
6
- // src/internal/module/i18nModule.ts
7
- import * as Logix from "@logixjs/core";
8
- import { Effect, Schema, SubscriptionRef } from "effect";
9
- var I18nModuleDef = Logix.Module.make("@logixjs/i18n/I18nModule", {
10
- state: Schema.Struct({ snapshot: I18nSnapshotSchema }),
11
- actions: {
12
- changeLanguage: Schema.String
13
- }
14
- });
15
- var I18nModuleLogic = I18nModuleDef.logic(($) => ({
16
- setup: $.lifecycle.onStart(
17
- Effect.gen(function* () {
18
- const i18n = yield* $.root.resolve(I18nTag);
19
- const snap = yield* SubscriptionRef.get(i18n.snapshot);
20
- yield* $.state.mutate((draft) => {
21
- ;
22
- draft.snapshot = snap;
23
- });
24
- })
25
- ),
26
- run: Effect.gen(function* () {
27
- const i18n = yield* $.root.resolve(I18nTag);
28
- yield* $.on(SubscriptionRef.changes(i18n.snapshot)).runFork(
29
- (snap) => $.state.mutate((draft) => {
30
- ;
31
- draft.snapshot = snap;
32
- })
33
- );
34
- yield* $.onAction("changeLanguage").runFork((action) => i18n.changeLanguage(action.payload));
35
- })
36
- }));
37
- var I18nModule = I18nModuleDef.implement({
38
- initial: { snapshot: { language: "unknown", init: "pending", seq: 0 } },
39
- logics: [I18nModuleLogic]
40
- });
41
-
42
- export {
43
- I18nModule
44
- };
45
- //# sourceMappingURL=chunk-X2U6SCIR.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/internal/module/i18nModule.ts"],"sourcesContent":["import * as Logix from '@logixjs/core'\nimport { Effect, Schema, SubscriptionRef } from 'effect'\n\nimport { I18nSnapshotSchema, I18nTag } from '../driver/i18n.js'\n\nconst I18nModuleDef = Logix.Module.make('@logixjs/i18n/I18nModule', {\n state: Schema.Struct({ snapshot: I18nSnapshotSchema }),\n actions: {\n changeLanguage: Schema.String,\n },\n})\n\nconst I18nModuleLogic = I18nModuleDef.logic(($) => ({\n setup: $.lifecycle.onStart(\n Effect.gen(function* () {\n const i18n = yield* $.root.resolve(I18nTag)\n const snap = yield* SubscriptionRef.get(i18n.snapshot)\n yield* $.state.mutate((draft) => {\n ;(draft as any).snapshot = snap\n })\n }),\n ),\n run: Effect.gen(function* () {\n const i18n = yield* $.root.resolve(I18nTag)\n\n yield* $.on(SubscriptionRef.changes(i18n.snapshot)).runFork((snap) =>\n $.state.mutate((draft) => {\n ;(draft as any).snapshot = snap\n }),\n )\n\n yield* $.onAction('changeLanguage').runFork((action) => i18n.changeLanguage(action.payload))\n }),\n}))\n\nexport const I18nModule: Logix.AnyModule = I18nModuleDef.implement({\n initial: { snapshot: { language: 'unknown', init: 'pending', seq: 0 } },\n logics: [I18nModuleLogic],\n})\n"],"mappings":";;;;;;AAAA,YAAY,WAAW;AACvB,SAAS,QAAQ,QAAQ,uBAAuB;AAIhD,IAAM,gBAAsB,aAAO,KAAK,4BAA4B;AAAA,EAClE,OAAO,OAAO,OAAO,EAAE,UAAU,mBAAmB,CAAC;AAAA,EACrD,SAAS;AAAA,IACP,gBAAgB,OAAO;AAAA,EACzB;AACF,CAAC;AAED,IAAM,kBAAkB,cAAc,MAAM,CAAC,OAAO;AAAA,EAClD,OAAO,EAAE,UAAU;AAAA,IACjB,OAAO,IAAI,aAAa;AACtB,YAAM,OAAO,OAAO,EAAE,KAAK,QAAQ,OAAO;AAC1C,YAAM,OAAO,OAAO,gBAAgB,IAAI,KAAK,QAAQ;AACrD,aAAO,EAAE,MAAM,OAAO,CAAC,UAAU;AAC/B;AAAC,QAAC,MAAc,WAAW;AAAA,MAC7B,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA,EACA,KAAK,OAAO,IAAI,aAAa;AAC3B,UAAM,OAAO,OAAO,EAAE,KAAK,QAAQ,OAAO;AAE1C,WAAO,EAAE,GAAG,gBAAgB,QAAQ,KAAK,QAAQ,CAAC,EAAE;AAAA,MAAQ,CAAC,SAC3D,EAAE,MAAM,OAAO,CAAC,UAAU;AACxB;AAAC,QAAC,MAAc,WAAW;AAAA,MAC7B,CAAC;AAAA,IACH;AAEA,WAAO,EAAE,SAAS,gBAAgB,EAAE,QAAQ,CAAC,WAAW,KAAK,eAAe,OAAO,OAAO,CAAC;AAAA,EAC7F,CAAC;AACH,EAAE;AAEK,IAAM,aAA8B,cAAc,UAAU;AAAA,EACjE,SAAS,EAAE,UAAU,EAAE,UAAU,WAAW,MAAM,WAAW,KAAK,EAAE,EAAE;AAAA,EACtE,QAAQ,CAAC,eAAe;AAC1B,CAAC;","names":[]}