@logixjs/i18n 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/I18n.cjs +267 -0
- package/dist/I18n.cjs.map +1 -0
- package/dist/I18n.d.cts +38 -0
- package/dist/I18n.d.ts +38 -0
- package/dist/I18n.js +13 -0
- package/dist/I18n.js.map +1 -0
- package/dist/I18nModule.cjs +88 -0
- package/dist/I18nModule.cjs.map +1 -0
- package/dist/I18nModule.d.cts +5 -0
- package/dist/I18nModule.d.ts +5 -0
- package/dist/I18nModule.js +9 -0
- package/dist/I18nModule.js.map +1 -0
- package/dist/Token.cjs +144 -0
- package/dist/Token.cjs.map +1 -0
- package/dist/Token.d.cts +20 -0
- package/dist/Token.d.ts +20 -0
- package/dist/Token.js +12 -0
- package/dist/Token.js.map +1 -0
- package/dist/chunk-7ZGW2A7L.js +143 -0
- package/dist/chunk-7ZGW2A7L.js.map +1 -0
- package/dist/chunk-B5AXXW7R.js +45 -0
- package/dist/chunk-B5AXXW7R.js.map +1 -0
- package/dist/chunk-FDPDEDU7.js +1 -0
- package/dist/chunk-FDPDEDU7.js.map +1 -0
- package/dist/chunk-LW6LHDDL.js +1 -0
- package/dist/chunk-LW6LHDDL.js.map +1 -0
- package/dist/chunk-NWWL4MNH.js +116 -0
- package/dist/chunk-NWWL4MNH.js.map +1 -0
- package/dist/index.cjs +321 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/package.json +53 -0
package/dist/Token.cjs
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/Token.ts
|
|
21
|
+
var Token_exports = {};
|
|
22
|
+
__export(Token_exports, {
|
|
23
|
+
InvalidI18nMessageTokenError: () => InvalidI18nMessageTokenError,
|
|
24
|
+
canonicalizeTokenOptions: () => canonicalizeTokenOptions,
|
|
25
|
+
token: () => token
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(Token_exports);
|
|
28
|
+
|
|
29
|
+
// src/internal/token/token.ts
|
|
30
|
+
var InvalidI18nMessageTokenError = class extends Error {
|
|
31
|
+
constructor(reason, details, fix) {
|
|
32
|
+
super(`[InvalidI18nMessageTokenError] reason=${reason}`);
|
|
33
|
+
this.reason = reason;
|
|
34
|
+
this.details = details;
|
|
35
|
+
this.fix = fix;
|
|
36
|
+
this.name = "InvalidI18nMessageTokenError";
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
var TOKEN_BUDGET = {
|
|
40
|
+
keyMaxLen: 96,
|
|
41
|
+
optionKeyMaxCount: 8,
|
|
42
|
+
optionValueStringMaxLen: 96
|
|
43
|
+
};
|
|
44
|
+
var LANGUAGE_FROZEN_KEYS = /* @__PURE__ */ new Set(["lng", "lngs"]);
|
|
45
|
+
var DANGEROUS_OPTION_KEYS = /* @__PURE__ */ new Set(["__proto__", "prototype", "constructor"]);
|
|
46
|
+
var isJsonPrimitive = (value) => value === null || typeof value === "boolean" || typeof value === "number" || typeof value === "string";
|
|
47
|
+
var invalidToken = (reason, details, fix) => {
|
|
48
|
+
throw new InvalidI18nMessageTokenError(reason, details, fix);
|
|
49
|
+
};
|
|
50
|
+
var canonicalizeTokenOptions = (options) => {
|
|
51
|
+
if (!options) return void 0;
|
|
52
|
+
if (typeof options !== "object" || options === null || Array.isArray(options)) {
|
|
53
|
+
invalidToken("optionValueInvalid", { field: "options", actual: typeof options }, [
|
|
54
|
+
"\u8BF7\u4F20\u5165 plain object \u4F5C\u4E3A options\uFF08Record<string, JsonPrimitive>\uFF09\u3002",
|
|
55
|
+
"\u4E0D\u8981\u4F20\u5165\u6570\u7EC4/\u51FD\u6570/\u7C7B\u5B9E\u4F8B\u7B49\u4E0D\u53EF\u5E8F\u5217\u5316\u503C\u3002"
|
|
56
|
+
]);
|
|
57
|
+
}
|
|
58
|
+
const entries = Object.entries(options).filter((p) => p[1] !== void 0);
|
|
59
|
+
if (entries.length === 0) return void 0;
|
|
60
|
+
if (entries.length > TOKEN_BUDGET.optionKeyMaxCount) {
|
|
61
|
+
invalidToken(
|
|
62
|
+
"tooManyOptions",
|
|
63
|
+
{
|
|
64
|
+
field: "options",
|
|
65
|
+
max: TOKEN_BUDGET.optionKeyMaxCount,
|
|
66
|
+
actual: entries.length
|
|
67
|
+
},
|
|
68
|
+
[
|
|
69
|
+
`\u51CF\u5C11 options \u952E\u6570\u91CF\uFF08\u5EFA\u8BAE \u2264 ${TOKEN_BUDGET.optionKeyMaxCount}\uFF09\u3002`,
|
|
70
|
+
"\u628A\u8F83\u957F\u7684\u4FE1\u606F\u632A\u5230 key \u6216 defaultValue\uFF1B\u907F\u514D\u628A\u5927\u5BF9\u8C61\u585E\u8FDB token\u3002"
|
|
71
|
+
]
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
for (const [k, v] of entries) {
|
|
75
|
+
if (DANGEROUS_OPTION_KEYS.has(k) || k.length === 0) {
|
|
76
|
+
invalidToken("optionKeyInvalid", { field: `options.${k}`, key: k }, [
|
|
77
|
+
"\u8BF7\u4F7F\u7528\u666E\u901A\u5B57\u6BB5\u540D\u4F5C\u4E3A options key\uFF08\u907F\u514D __proto__/constructor/prototype \u7B49\u5371\u9669\u952E\uFF09\u3002",
|
|
78
|
+
"\u5982\u9700\u4F20\u9012\u590D\u6742\u7ED3\u6784\uFF0C\u8BF7\u5148\u5728\u5C55\u793A\u8FB9\u754C\u8F6C\u6362\u4E3A\u5B57\u7B26\u4E32\u3002"
|
|
79
|
+
]);
|
|
80
|
+
}
|
|
81
|
+
if (LANGUAGE_FROZEN_KEYS.has(k)) {
|
|
82
|
+
invalidToken("languageFrozen", { field: `options.${k}`, key: k }, [
|
|
83
|
+
"\u4E0D\u8981\u5728 token options \u4E2D\u4F20\u5165 lng/lngs \u7B49\u8BED\u8A00\u51BB\u7ED3\u5B57\u6BB5\u3002",
|
|
84
|
+
"\u8BED\u8A00\u7531\u5916\u90E8 i18n \u5B9E\u4F8B\u51B3\u5B9A\uFF1Btoken \u53EA\u8868\u8FBE\u201C\u8981\u7FFB\u8BD1\u4EC0\u4E48\u201D\u3002"
|
|
85
|
+
]);
|
|
86
|
+
}
|
|
87
|
+
if (!isJsonPrimitive(v)) {
|
|
88
|
+
invalidToken("optionValueInvalid", { field: `options.${k}`, actual: typeof v }, [
|
|
89
|
+
"options value \u53EA\u5141\u8BB8 JsonPrimitive\uFF08null/boolean/number/string\uFF09\u3002",
|
|
90
|
+
"\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"
|
|
91
|
+
]);
|
|
92
|
+
}
|
|
93
|
+
if (typeof v === "number" && !Number.isFinite(v)) {
|
|
94
|
+
invalidToken("numberNotJsonSafe", { field: `options.${k}`, value: String(v) }, [
|
|
95
|
+
"\u4E0D\u8981\u5728 token options \u4E2D\u4F20\u5165 NaN/Infinity\u3002",
|
|
96
|
+
"\u8BF7\u5148\u628A\u8BE5\u6570\u503C\u8F6C\u6362\u4E3A\u53EF JSON \u5316\u7684 number \u6216 string\u3002"
|
|
97
|
+
]);
|
|
98
|
+
}
|
|
99
|
+
if (typeof v === "string" && v.length > TOKEN_BUDGET.optionValueStringMaxLen) {
|
|
100
|
+
invalidToken(
|
|
101
|
+
"optionValueTooLong",
|
|
102
|
+
{
|
|
103
|
+
field: `options.${k}`,
|
|
104
|
+
maxLen: TOKEN_BUDGET.optionValueStringMaxLen,
|
|
105
|
+
actualLen: v.length
|
|
106
|
+
},
|
|
107
|
+
[
|
|
108
|
+
`\u7F29\u77ED\u5B57\u7B26\u4E32\u503C\u957F\u5EA6\uFF08\u5EFA\u8BAE \u2264 ${TOKEN_BUDGET.optionValueStringMaxLen}\uFF09\u3002`,
|
|
109
|
+
"\u628A\u957F\u6587\u672C\u79FB\u5230 defaultValue \u6216\u76F4\u63A5\u5728\u5C55\u793A\u8FB9\u754C\u751F\u6210\u6700\u7EC8\u5B57\u7B26\u4E32\u3002"
|
|
110
|
+
]
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
entries.sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
|
|
115
|
+
const out = {};
|
|
116
|
+
for (const [k, v] of entries) {
|
|
117
|
+
out[k] = v;
|
|
118
|
+
}
|
|
119
|
+
return out;
|
|
120
|
+
};
|
|
121
|
+
var token = (key, options) => {
|
|
122
|
+
if (key.length > TOKEN_BUDGET.keyMaxLen) {
|
|
123
|
+
invalidToken("keyTooLong", { field: "key", maxLen: TOKEN_BUDGET.keyMaxLen, actualLen: key.length }, [
|
|
124
|
+
`\u7F29\u77ED key\uFF08\u5EFA\u8BAE \u2264 ${TOKEN_BUDGET.keyMaxLen}\uFF09\u3002`,
|
|
125
|
+
"\u5982\u679C key \u8FC7\u957F\uFF0C\u5EFA\u8BAE\u6539\u4E3A\u201C\u7A33\u5B9A key + \u53D8\u91CF options/defaultValue\u201D\u3002"
|
|
126
|
+
]);
|
|
127
|
+
}
|
|
128
|
+
const canon = canonicalizeTokenOptions(options);
|
|
129
|
+
return canon ? {
|
|
130
|
+
_tag: "i18n",
|
|
131
|
+
key,
|
|
132
|
+
options: canon
|
|
133
|
+
} : {
|
|
134
|
+
_tag: "i18n",
|
|
135
|
+
key
|
|
136
|
+
};
|
|
137
|
+
};
|
|
138
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
139
|
+
0 && (module.exports = {
|
|
140
|
+
InvalidI18nMessageTokenError,
|
|
141
|
+
canonicalizeTokenOptions,
|
|
142
|
+
token
|
|
143
|
+
});
|
|
144
|
+
//# sourceMappingURL=Token.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/Token.ts","../src/internal/token/token.ts"],"sourcesContent":["export type {\n I18nMessageToken,\n I18nTokenOptions,\n I18nTokenOptionsInput,\n InvalidI18nMessageTokenReason,\n JsonPrimitive,\n} from './internal/token/token.js'\nexport { InvalidI18nMessageTokenError, canonicalizeTokenOptions, token } from './internal/token/token.js'\n","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":[]}
|
package/dist/Token.d.cts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
type JsonPrimitive = null | boolean | number | string;
|
|
2
|
+
type I18nTokenOptions = Readonly<Record<string, JsonPrimitive>>;
|
|
3
|
+
type I18nTokenOptionsInput = Readonly<Record<string, JsonPrimitive | undefined>>;
|
|
4
|
+
type I18nMessageToken = {
|
|
5
|
+
readonly _tag: 'i18n';
|
|
6
|
+
readonly key: string;
|
|
7
|
+
readonly options?: I18nTokenOptions;
|
|
8
|
+
};
|
|
9
|
+
type InvalidI18nMessageTokenReason = 'keyTooLong' | 'tooManyOptions' | 'optionKeyInvalid' | 'optionValueInvalid' | 'optionValueTooLong' | 'numberNotJsonSafe' | 'languageFrozen';
|
|
10
|
+
declare class InvalidI18nMessageTokenError extends Error {
|
|
11
|
+
readonly reason: InvalidI18nMessageTokenReason;
|
|
12
|
+
readonly details: unknown;
|
|
13
|
+
readonly fix: ReadonlyArray<string>;
|
|
14
|
+
readonly name = "InvalidI18nMessageTokenError";
|
|
15
|
+
constructor(reason: InvalidI18nMessageTokenReason, details: unknown, fix: ReadonlyArray<string>);
|
|
16
|
+
}
|
|
17
|
+
declare const canonicalizeTokenOptions: (options: I18nTokenOptionsInput | undefined) => I18nTokenOptions | undefined;
|
|
18
|
+
declare const token: (key: string, options?: I18nTokenOptionsInput) => I18nMessageToken;
|
|
19
|
+
|
|
20
|
+
export { type I18nMessageToken, type I18nTokenOptions, type I18nTokenOptionsInput, InvalidI18nMessageTokenError, type InvalidI18nMessageTokenReason, type JsonPrimitive, canonicalizeTokenOptions, token };
|
package/dist/Token.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
type JsonPrimitive = null | boolean | number | string;
|
|
2
|
+
type I18nTokenOptions = Readonly<Record<string, JsonPrimitive>>;
|
|
3
|
+
type I18nTokenOptionsInput = Readonly<Record<string, JsonPrimitive | undefined>>;
|
|
4
|
+
type I18nMessageToken = {
|
|
5
|
+
readonly _tag: 'i18n';
|
|
6
|
+
readonly key: string;
|
|
7
|
+
readonly options?: I18nTokenOptions;
|
|
8
|
+
};
|
|
9
|
+
type InvalidI18nMessageTokenReason = 'keyTooLong' | 'tooManyOptions' | 'optionKeyInvalid' | 'optionValueInvalid' | 'optionValueTooLong' | 'numberNotJsonSafe' | 'languageFrozen';
|
|
10
|
+
declare class InvalidI18nMessageTokenError extends Error {
|
|
11
|
+
readonly reason: InvalidI18nMessageTokenReason;
|
|
12
|
+
readonly details: unknown;
|
|
13
|
+
readonly fix: ReadonlyArray<string>;
|
|
14
|
+
readonly name = "InvalidI18nMessageTokenError";
|
|
15
|
+
constructor(reason: InvalidI18nMessageTokenReason, details: unknown, fix: ReadonlyArray<string>);
|
|
16
|
+
}
|
|
17
|
+
declare const canonicalizeTokenOptions: (options: I18nTokenOptionsInput | undefined) => I18nTokenOptions | undefined;
|
|
18
|
+
declare const token: (key: string, options?: I18nTokenOptionsInput) => I18nMessageToken;
|
|
19
|
+
|
|
20
|
+
export { type I18nMessageToken, type I18nTokenOptions, type I18nTokenOptionsInput, InvalidI18nMessageTokenError, type InvalidI18nMessageTokenReason, type JsonPrimitive, canonicalizeTokenOptions, token };
|
package/dist/Token.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import "./chunk-LW6LHDDL.js";
|
|
2
|
+
import {
|
|
3
|
+
InvalidI18nMessageTokenError,
|
|
4
|
+
canonicalizeTokenOptions,
|
|
5
|
+
token
|
|
6
|
+
} from "./chunk-NWWL4MNH.js";
|
|
7
|
+
export {
|
|
8
|
+
InvalidI18nMessageTokenError,
|
|
9
|
+
canonicalizeTokenOptions,
|
|
10
|
+
token
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=Token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import {
|
|
2
|
+
token
|
|
3
|
+
} from "./chunk-NWWL4MNH.js";
|
|
4
|
+
|
|
5
|
+
// src/internal/driver/i18n.ts
|
|
6
|
+
import {
|
|
7
|
+
Context,
|
|
8
|
+
Duration,
|
|
9
|
+
Effect,
|
|
10
|
+
Fiber,
|
|
11
|
+
Layer,
|
|
12
|
+
Option,
|
|
13
|
+
Runtime,
|
|
14
|
+
Scope,
|
|
15
|
+
Schema,
|
|
16
|
+
Stream,
|
|
17
|
+
SubscriptionRef
|
|
18
|
+
} from "effect";
|
|
19
|
+
var I18nSnapshotSchema = Schema.Struct({
|
|
20
|
+
language: Schema.String,
|
|
21
|
+
init: Schema.Literal("pending", "ready", "failed"),
|
|
22
|
+
seq: Schema.Number
|
|
23
|
+
});
|
|
24
|
+
var I18nTag = class extends Context.Tag("@logixjs/i18n/I18n")() {
|
|
25
|
+
};
|
|
26
|
+
var asNonEmptyString = (value) => typeof value === "string" && value.length > 0 ? value : void 0;
|
|
27
|
+
var makeI18nService = (driver) => Effect.gen(function* () {
|
|
28
|
+
const runtime = yield* Effect.runtime();
|
|
29
|
+
const init = driver.isInitialized ? "ready" : "pending";
|
|
30
|
+
let currentSnapshot = {
|
|
31
|
+
language: driver.language,
|
|
32
|
+
init,
|
|
33
|
+
seq: 0
|
|
34
|
+
};
|
|
35
|
+
const snapshotRef = yield* SubscriptionRef.make(currentSnapshot);
|
|
36
|
+
const update = (patch) => SubscriptionRef.update(snapshotRef, (prev) => {
|
|
37
|
+
const next = {
|
|
38
|
+
language: patch.language ?? prev.language,
|
|
39
|
+
init: patch.init ?? prev.init,
|
|
40
|
+
seq: prev.seq + 1
|
|
41
|
+
};
|
|
42
|
+
currentSnapshot = next;
|
|
43
|
+
return next;
|
|
44
|
+
});
|
|
45
|
+
const pushSnapshot = (patch) => {
|
|
46
|
+
const next = {
|
|
47
|
+
language: patch.language ?? currentSnapshot.language,
|
|
48
|
+
init: patch.init ?? currentSnapshot.init,
|
|
49
|
+
seq: currentSnapshot.seq + 1
|
|
50
|
+
};
|
|
51
|
+
currentSnapshot = next;
|
|
52
|
+
Runtime.runFork(runtime, SubscriptionRef.set(snapshotRef, next).pipe(Effect.catchAllCause(() => Effect.void)));
|
|
53
|
+
};
|
|
54
|
+
const onInitialized = () => {
|
|
55
|
+
pushSnapshot({ init: "ready", language: driver.language });
|
|
56
|
+
};
|
|
57
|
+
const onLanguageChanged = (lang) => {
|
|
58
|
+
pushSnapshot({
|
|
59
|
+
init: "ready",
|
|
60
|
+
language: asNonEmptyString(lang) ?? driver.language
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
yield* Effect.sync(() => {
|
|
64
|
+
driver.on("initialized", onInitialized);
|
|
65
|
+
driver.on("languageChanged", onLanguageChanged);
|
|
66
|
+
});
|
|
67
|
+
const scope = yield* Effect.scope;
|
|
68
|
+
yield* Scope.addFinalizer(
|
|
69
|
+
scope,
|
|
70
|
+
Effect.sync(() => {
|
|
71
|
+
driver.off("initialized", onInitialized);
|
|
72
|
+
driver.off("languageChanged", onLanguageChanged);
|
|
73
|
+
})
|
|
74
|
+
);
|
|
75
|
+
const changeLanguage = (language) => Effect.gen(function* () {
|
|
76
|
+
yield* update({ language, init: "pending" });
|
|
77
|
+
const exit = yield* Effect.exit(
|
|
78
|
+
Effect.tryPromise({
|
|
79
|
+
try: () => Promise.resolve(driver.changeLanguage(language)),
|
|
80
|
+
catch: () => void 0
|
|
81
|
+
})
|
|
82
|
+
);
|
|
83
|
+
if (exit._tag === "Failure") {
|
|
84
|
+
yield* update({ init: "failed" });
|
|
85
|
+
} else {
|
|
86
|
+
yield* update({ init: "ready", language });
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
const fallback = (key, options) => typeof options?.defaultValue === "string" ? options.defaultValue : key;
|
|
90
|
+
const t = (key, options) => {
|
|
91
|
+
if (currentSnapshot.init !== "ready") {
|
|
92
|
+
return fallback(key, options);
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
return driver.t(key, options);
|
|
96
|
+
} catch {
|
|
97
|
+
return fallback(key, options);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
const tReady = (key, options, timeoutMs) => Effect.gen(function* () {
|
|
101
|
+
const cap = timeoutMs ?? 5e3;
|
|
102
|
+
const snap0 = yield* SubscriptionRef.get(snapshotRef);
|
|
103
|
+
if (snap0.init === "ready") return t(key, options);
|
|
104
|
+
if (snap0.init === "failed") return fallback(key, options);
|
|
105
|
+
const wait = Stream.filter(snapshotRef.changes, (s) => s.init !== "pending").pipe(
|
|
106
|
+
Stream.runHead,
|
|
107
|
+
Effect.timeoutFail({
|
|
108
|
+
duration: Duration.millis(cap),
|
|
109
|
+
onTimeout: () => void 0
|
|
110
|
+
}),
|
|
111
|
+
Effect.catchAll(() => Effect.succeed(Option.none()))
|
|
112
|
+
);
|
|
113
|
+
const fiber = yield* Effect.fork(wait);
|
|
114
|
+
const snap1 = yield* SubscriptionRef.get(snapshotRef);
|
|
115
|
+
if (snap1.init !== "pending") {
|
|
116
|
+
yield* Fiber.interruptFork(fiber);
|
|
117
|
+
return snap1.init === "ready" ? t(key, options) : fallback(key, options);
|
|
118
|
+
}
|
|
119
|
+
const outcome = yield* Fiber.join(fiber);
|
|
120
|
+
return Option.match(outcome, {
|
|
121
|
+
onNone: () => fallback(key, options),
|
|
122
|
+
onSome: (snap) => snap.init === "ready" ? t(key, options) : fallback(key, options)
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
return {
|
|
126
|
+
instance: driver,
|
|
127
|
+
snapshot: snapshotRef,
|
|
128
|
+
token,
|
|
129
|
+
changeLanguage,
|
|
130
|
+
t,
|
|
131
|
+
tReady
|
|
132
|
+
};
|
|
133
|
+
});
|
|
134
|
+
var I18n = {
|
|
135
|
+
layer: (driver) => Layer.scoped(I18nTag, makeI18nService(driver))
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
export {
|
|
139
|
+
I18nSnapshotSchema,
|
|
140
|
+
I18nTag,
|
|
141
|
+
I18n
|
|
142
|
+
};
|
|
143
|
+
//# sourceMappingURL=chunk-7ZGW2A7L.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/internal/driver/i18n.ts"],"sourcesContent":["import {\n Context,\n Duration,\n Effect,\n Fiber,\n Layer,\n Option,\n Runtime,\n Scope,\n Schema,\n Stream,\n SubscriptionRef,\n} from 'effect'\n\nimport type { I18nMessageToken, I18nTokenOptionsInput } from '../token/token.js'\nimport { token } from '../token/token.js'\n\nexport type { I18nTokenOptionsInput } from '../token/token.js'\n\nexport type I18nDriver = {\n readonly language: string\n readonly isInitialized?: boolean\n readonly t: (key: string, options?: unknown) => string\n readonly changeLanguage: (language: string) => Promise<unknown> | unknown\n readonly on: (event: 'initialized' | 'languageChanged', handler: (...args: any[]) => void) => unknown\n readonly off: (event: 'initialized' | 'languageChanged', handler: (...args: any[]) => void) => unknown\n}\n\nexport type I18nInitState = 'pending' | 'ready' | 'failed'\n\nexport type I18nSnapshot = {\n readonly language: string\n readonly init: I18nInitState\n readonly seq: number\n}\n\nexport const I18nSnapshotSchema = Schema.Struct({\n language: Schema.String,\n init: Schema.Literal('pending', 'ready', 'failed'),\n seq: Schema.Number,\n})\n\nexport type I18nService = {\n readonly instance: I18nDriver\n readonly snapshot: SubscriptionRef.SubscriptionRef<I18nSnapshot>\n readonly token: (key: string, options?: I18nTokenOptionsInput) => I18nMessageToken\n readonly changeLanguage: (language: string) => Effect.Effect<void, never, never>\n readonly t: (key: string, options?: I18nTokenOptionsInput) => string\n readonly tReady: (\n key: string,\n options?: I18nTokenOptionsInput,\n timeoutMs?: number,\n ) => Effect.Effect<string, never, never>\n}\n\nexport class I18nTag extends Context.Tag('@logixjs/i18n/I18n')<I18nTag, I18nService>() {}\n\nconst asNonEmptyString = (value: unknown): string | undefined =>\n typeof value === 'string' && value.length > 0 ? value : undefined\n\nconst makeI18nService = (driver: I18nDriver): Effect.Effect<I18nService, never, Scope.Scope> =>\n Effect.gen(function* () {\n const runtime = yield* Effect.runtime<never>()\n\n const init: I18nInitState = driver.isInitialized ? 'ready' : 'pending'\n let currentSnapshot: I18nSnapshot = {\n language: driver.language,\n init,\n seq: 0,\n }\n const snapshotRef = yield* SubscriptionRef.make<I18nSnapshot>(currentSnapshot)\n\n const update = (patch: Partial<Pick<I18nSnapshot, 'language' | 'init'>>): Effect.Effect<void> =>\n SubscriptionRef.update(snapshotRef, (prev) => {\n const next: I18nSnapshot = {\n language: patch.language ?? prev.language,\n init: patch.init ?? prev.init,\n seq: prev.seq + 1,\n }\n currentSnapshot = next\n return next\n })\n\n const pushSnapshot = (patch: Partial<Pick<I18nSnapshot, 'language' | 'init'>>): void => {\n const next: I18nSnapshot = {\n language: patch.language ?? currentSnapshot.language,\n init: patch.init ?? currentSnapshot.init,\n seq: currentSnapshot.seq + 1,\n }\n currentSnapshot = next\n Runtime.runFork(runtime, SubscriptionRef.set(snapshotRef, next).pipe(Effect.catchAllCause(() => Effect.void)))\n }\n\n const onInitialized = (): void => {\n pushSnapshot({ init: 'ready', language: driver.language })\n }\n\n const onLanguageChanged = (lang: unknown): void => {\n pushSnapshot({\n init: 'ready',\n language: asNonEmptyString(lang) ?? driver.language,\n })\n }\n\n yield* Effect.sync(() => {\n driver.on('initialized', onInitialized)\n driver.on('languageChanged', onLanguageChanged)\n })\n\n const scope = yield* Effect.scope\n yield* Scope.addFinalizer(\n scope,\n Effect.sync(() => {\n driver.off('initialized', onInitialized)\n driver.off('languageChanged', onLanguageChanged)\n }),\n )\n\n const changeLanguage = (language: string): Effect.Effect<void, never, never> =>\n Effect.gen(function* () {\n yield* update({ language, init: 'pending' })\n const exit = yield* Effect.exit(\n Effect.tryPromise({\n try: () => Promise.resolve(driver.changeLanguage(language)),\n catch: () => undefined,\n }),\n )\n if (exit._tag === 'Failure') {\n yield* update({ init: 'failed' })\n } else {\n yield* update({ init: 'ready', language })\n }\n })\n\n const fallback = (key: string, options?: I18nTokenOptionsInput): string =>\n typeof options?.defaultValue === 'string' ? options.defaultValue : key\n\n const t = (key: string, options?: I18nTokenOptionsInput): string => {\n if (currentSnapshot.init !== 'ready') {\n return fallback(key, options)\n }\n try {\n return driver.t(key, options)\n } catch {\n return fallback(key, options)\n }\n }\n\n const tReady = (\n key: string,\n options?: I18nTokenOptionsInput,\n timeoutMs?: number,\n ): Effect.Effect<string, never, never> =>\n Effect.gen(function* () {\n const cap = timeoutMs ?? 5000\n const snap0 = yield* SubscriptionRef.get(snapshotRef)\n if (snap0.init === 'ready') return t(key, options)\n if (snap0.init === 'failed') return fallback(key, options)\n\n const wait = Stream.filter(snapshotRef.changes, (s) => s.init !== 'pending').pipe(\n Stream.runHead,\n Effect.timeoutFail({\n duration: Duration.millis(cap),\n onTimeout: () => undefined,\n }),\n Effect.catchAll(() => Effect.succeed(Option.none())),\n )\n\n const fiber = yield* Effect.fork(wait)\n\n const snap1 = yield* SubscriptionRef.get(snapshotRef)\n if (snap1.init !== 'pending') {\n yield* Fiber.interruptFork(fiber)\n return snap1.init === 'ready' ? t(key, options) : fallback(key, options)\n }\n\n const outcome = yield* Fiber.join(fiber)\n return Option.match(outcome, {\n onNone: () => fallback(key, options),\n onSome: (snap) => (snap.init === 'ready' ? t(key, options) : fallback(key, options)),\n })\n })\n\n return {\n instance: driver,\n snapshot: snapshotRef,\n token,\n changeLanguage,\n t,\n tReady,\n } as const\n })\n\nexport const I18n = {\n layer: (driver: I18nDriver): Layer.Layer<I18nTag, never, never> => Layer.scoped(I18nTag, makeI18nService(driver)),\n} as const\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import {
|
|
2
|
+
I18nSnapshotSchema,
|
|
3
|
+
I18nTag
|
|
4
|
+
} from "./chunk-7ZGW2A7L.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(i18n.snapshot.changes).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-B5AXXW7R.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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(i18n.snapshot.changes).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,KAAK,SAAS,OAAO,EAAE;AAAA,MAAQ,CAAC,SAC1C,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":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=chunk-FDPDEDU7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=chunk-LW6LHDDL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,116 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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":[]}
|