@aidc-toolkit/core 1.0.22-beta → 1.0.24-beta
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/README.md +22 -16
- package/dist/index.cjs +173 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +170 -0
- package/dist/index.d.ts +166 -14
- package/dist/index.js +112 -1
- package/dist/index.js.map +1 -1
- package/package.json +7 -10
- package/src/index.ts +4 -1
- package/src/locale/i18n.ts +2 -50
- package/src/logger.ts +47 -0
- package/src/type-helper.ts +87 -0
- package/src/type.ts +44 -0
- package/tsup.config.ts +3 -0
- package/typedoc.json +1 -3
- package/dist/index.d.ts.map +0 -1
- package/dist/locale/i18n.d.ts +0 -68
- package/dist/locale/i18n.d.ts.map +0 -1
- package/dist/locale/i18n.js +0 -139
- package/dist/locale/i18n.js.map +0 -1
package/README.md
CHANGED
|
@@ -16,6 +16,14 @@ Unless required by applicable law or agreed to in writing, software distributed
|
|
|
16
16
|
|
|
17
17
|
The AIDC Toolkit `core` package contains artefacts to support other AIDC Toolkit packages; it does not itself provide any of the functionality of the AIDC Toolkit. It is a required dependency for all AIDC Toolkit packages.
|
|
18
18
|
|
|
19
|
+
## Types
|
|
20
|
+
|
|
21
|
+
Generic types that go beyond TypeScript's utility types are defined here. The types are designed to provide even greater type safety.
|
|
22
|
+
|
|
23
|
+
## Logger
|
|
24
|
+
|
|
25
|
+
This is a simple wrapper around [tslog](https://tslog.js.org) to support command-line applications in the AIDC Toolkit build process.
|
|
26
|
+
|
|
19
27
|
## Internationalization
|
|
20
28
|
|
|
21
29
|
All AIDC Toolkit packages require internationalization. The localization functionality in this package, built on the robust and popular [`i18next`](https://i18next.com) package, simplifies initialization and allows packages to share a common internationalization engine. Each package, up to and including the client application, is responsible for initializing internationalization for each of the AIDC Toolkit packages on which it depends.
|
|
@@ -27,12 +35,12 @@ All AIDC Toolkit packages require internationalization. The localization functio
|
|
|
27
35
|
Packages install their resources as follows in `i18n.ts` or similar:
|
|
28
36
|
|
|
29
37
|
```typescript
|
|
30
|
-
import {
|
|
38
|
+
import { i18nCoreInit, type I18nEnvironment } from "@aidc-toolkit/core";
|
|
31
39
|
import { dependency1Resources, i18nDependency1Init } from "@aidc-toolkit/dependency1";
|
|
32
40
|
import { dependency2Resources, i18nDependency2Init } from "@aidc-toolkit/dependency2";
|
|
33
41
|
import i18next, { type i18n, type Resource } from "i18next";
|
|
34
|
-
import { localeStrings as enLocaleStrings } from "./en/locale-strings
|
|
35
|
-
import { localeStrings as frLocaleStrings } from "./fr/locale-strings
|
|
42
|
+
import { localeStrings as enLocaleStrings } from "./en/locale-strings";
|
|
43
|
+
import { localeStrings as frLocaleStrings } from "./fr/locale-strings";
|
|
36
44
|
|
|
37
45
|
export const packageNS = "aidct_package";
|
|
38
46
|
|
|
@@ -41,8 +49,6 @@ export const packageNS = "aidct_package";
|
|
|
41
49
|
*/
|
|
42
50
|
export type PackageLocaleStrings = typeof enLocaleStrings;
|
|
43
51
|
|
|
44
|
-
i18nAssertValidResources(enLocaleStrings, "fr", frLocaleStrings);
|
|
45
|
-
|
|
46
52
|
/**
|
|
47
53
|
* Package resources.
|
|
48
54
|
*/
|
|
@@ -82,7 +88,7 @@ The resource types are declared in `i18next.d.ts` or similar:
|
|
|
82
88
|
```typescript
|
|
83
89
|
import type { Dependency1LocaleStrings } from "@aidc-toolkit/dependency1";
|
|
84
90
|
import type { Dependency2LocaleStrings } from "@aidc-toolkit/dependency2";
|
|
85
|
-
import type { PackageLocaleStrings } from "./i18n
|
|
91
|
+
import type { PackageLocaleStrings } from "./i18n";
|
|
86
92
|
|
|
87
93
|
/**
|
|
88
94
|
* Internationalization module.
|
|
@@ -104,13 +110,13 @@ declare module "i18next" {
|
|
|
104
110
|
|
|
105
111
|
Support is available for the following environments:
|
|
106
112
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
113
|
+
- [Command-line interface](#command-line-interface)
|
|
114
|
+
- Unit tests
|
|
115
|
+
- Batch applications
|
|
116
|
+
- Web server - **NOT YET IMPLEMENTED**
|
|
117
|
+
- [Web browser](#web-browser)
|
|
112
118
|
|
|
113
|
-
### Command-
|
|
119
|
+
### Command-Line Interface
|
|
114
120
|
|
|
115
121
|
Initializing internationalization for a command-line interface application is straightforward:
|
|
116
122
|
|
|
@@ -118,14 +124,14 @@ Initializing internationalization for a command-line interface application is st
|
|
|
118
124
|
await i18nPackageInit(I18nEnvironment.CLI);
|
|
119
125
|
```
|
|
120
126
|
|
|
121
|
-
### Web
|
|
127
|
+
### Web Browser
|
|
122
128
|
|
|
123
129
|
Initializing internationalization for a web browser requires awaiting the fulfillment of the `Promise` returned by the call to the initialization function before rendering any content. For example, in the React framework, this may be accomplished with a component like this:
|
|
124
130
|
|
|
125
131
|
```typescript jsx
|
|
126
132
|
import { I18nEnvironment } from "@aidc-toolkit/core";
|
|
127
133
|
import { type ReactElement, type ReactNode, useEffect, useState } from "react";
|
|
128
|
-
import { i18nPackageInit, i18nextPackage } from "./locale/i18n
|
|
134
|
+
import { i18nPackageInit, i18nextPackage } from "./locale/i18n";
|
|
129
135
|
|
|
130
136
|
/**
|
|
131
137
|
* I18n wrapper properties.
|
|
@@ -169,8 +175,8 @@ The component would then wrap the application as follows:
|
|
|
169
175
|
|
|
170
176
|
```typescript jsx
|
|
171
177
|
import { type ReactElement, StrictMode } from "react";
|
|
172
|
-
import { App } from "./App
|
|
173
|
-
import { I18n } from "./I18n
|
|
178
|
+
import { App } from "./App";
|
|
179
|
+
import { I18n } from "./I18n";
|
|
174
180
|
|
|
175
181
|
/**
|
|
176
182
|
* Index.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
I18nEnvironments: () => I18nEnvironments,
|
|
34
|
+
LogLevels: () => LogLevels,
|
|
35
|
+
getLogger: () => getLogger,
|
|
36
|
+
i18nCoreInit: () => i18nCoreInit,
|
|
37
|
+
isNullish: () => isNullish,
|
|
38
|
+
omit: () => omit,
|
|
39
|
+
pick: () => pick,
|
|
40
|
+
propertyAs: () => propertyAs
|
|
41
|
+
});
|
|
42
|
+
module.exports = __toCommonJS(index_exports);
|
|
43
|
+
|
|
44
|
+
// src/type-helper.ts
|
|
45
|
+
function omitOrPick(omitting, o, ...keys) {
|
|
46
|
+
return Object.fromEntries(Object.entries(o).filter(([key]) => keys.includes(key) !== omitting));
|
|
47
|
+
}
|
|
48
|
+
function omit(o, ...keys) {
|
|
49
|
+
return omitOrPick(true, o, ...keys);
|
|
50
|
+
}
|
|
51
|
+
function pick(o, ...keys) {
|
|
52
|
+
return omitOrPick(false, o, ...keys);
|
|
53
|
+
}
|
|
54
|
+
function propertyAs(o, key) {
|
|
55
|
+
return key in o ? {
|
|
56
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Force cast.
|
|
57
|
+
[key]: o[key]
|
|
58
|
+
} : {};
|
|
59
|
+
}
|
|
60
|
+
function isNullish(argument) {
|
|
61
|
+
return argument === null || argument === void 0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// src/logger.ts
|
|
65
|
+
var import_tslog = require("tslog");
|
|
66
|
+
var LogLevels = {
|
|
67
|
+
Silly: 0,
|
|
68
|
+
Trace: 1,
|
|
69
|
+
Debug: 2,
|
|
70
|
+
Info: 3,
|
|
71
|
+
Warn: 4,
|
|
72
|
+
Error: 5,
|
|
73
|
+
Fatal: 6
|
|
74
|
+
};
|
|
75
|
+
function getLogger(logLevel) {
|
|
76
|
+
let minLevel;
|
|
77
|
+
if (typeof logLevel === "string") {
|
|
78
|
+
if (logLevel in LogLevels) {
|
|
79
|
+
minLevel = LogLevels[logLevel];
|
|
80
|
+
} else {
|
|
81
|
+
throw new Error(`Unknown log level ${logLevel}`);
|
|
82
|
+
}
|
|
83
|
+
} else {
|
|
84
|
+
minLevel = logLevel ?? LogLevels.Info;
|
|
85
|
+
}
|
|
86
|
+
return new import_tslog.Logger({
|
|
87
|
+
minLevel
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// src/locale/i18n.ts
|
|
92
|
+
var import_i18next_browser_languagedetector = __toESM(require("i18next-browser-languagedetector"), 1);
|
|
93
|
+
var import_i18next_cli_language_detector = __toESM(require("i18next-cli-language-detector"), 1);
|
|
94
|
+
var I18nEnvironments = {
|
|
95
|
+
/**
|
|
96
|
+
* Command-line interface (e.g., unit tests).
|
|
97
|
+
*/
|
|
98
|
+
CLI: 0,
|
|
99
|
+
/**
|
|
100
|
+
* Web server.
|
|
101
|
+
*/
|
|
102
|
+
Server: 1,
|
|
103
|
+
/**
|
|
104
|
+
* Web browser.
|
|
105
|
+
*/
|
|
106
|
+
Browser: 2
|
|
107
|
+
};
|
|
108
|
+
function toLowerCase(s) {
|
|
109
|
+
return s.split(" ").map((word) => /[a-z]/.test(word) ? word.toLowerCase() : word).join(" ");
|
|
110
|
+
}
|
|
111
|
+
async function i18nCoreInit(i18next, environment, debug, defaultNS, ...resources) {
|
|
112
|
+
if (!i18next.isInitialized) {
|
|
113
|
+
const mergedResource = {};
|
|
114
|
+
for (const resource of resources) {
|
|
115
|
+
for (const [language, resourceLanguage] of Object.entries(resource)) {
|
|
116
|
+
if (!(language in mergedResource)) {
|
|
117
|
+
mergedResource[language] = {};
|
|
118
|
+
}
|
|
119
|
+
const mergedResourceLanguage = mergedResource[language];
|
|
120
|
+
for (const [namespace, resourceKey] of Object.entries(resourceLanguage)) {
|
|
121
|
+
mergedResourceLanguage[namespace] = resourceKey;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
let module2;
|
|
126
|
+
switch (environment) {
|
|
127
|
+
case I18nEnvironments.CLI:
|
|
128
|
+
module2 = import_i18next_cli_language_detector.default;
|
|
129
|
+
break;
|
|
130
|
+
case I18nEnvironments.Browser:
|
|
131
|
+
module2 = import_i18next_browser_languagedetector.default;
|
|
132
|
+
break;
|
|
133
|
+
default:
|
|
134
|
+
throw new Error("Not supported");
|
|
135
|
+
}
|
|
136
|
+
await i18next.use(module2).init({
|
|
137
|
+
debug,
|
|
138
|
+
resources: mergedResource,
|
|
139
|
+
fallbackLng: "en",
|
|
140
|
+
defaultNS
|
|
141
|
+
}).then(() => {
|
|
142
|
+
i18next.services.formatter?.add("toLowerCase", (value) => typeof value === "string" ? toLowerCase(value) : String(value));
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
147
|
+
0 && (module.exports = {
|
|
148
|
+
I18nEnvironments,
|
|
149
|
+
LogLevels,
|
|
150
|
+
getLogger,
|
|
151
|
+
i18nCoreInit,
|
|
152
|
+
isNullish,
|
|
153
|
+
omit,
|
|
154
|
+
pick,
|
|
155
|
+
propertyAs
|
|
156
|
+
});
|
|
157
|
+
/*!
|
|
158
|
+
* Copyright © 2024-2025 Dolphin Data Development Ltd. and AIDC Toolkit
|
|
159
|
+
* contributors
|
|
160
|
+
*
|
|
161
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
162
|
+
* you may not use this file except in compliance with the License.
|
|
163
|
+
* You may obtain a copy of the License at
|
|
164
|
+
*
|
|
165
|
+
* https://www.apache.org/licenses/LICENSE-2.0
|
|
166
|
+
*
|
|
167
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
168
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
169
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
170
|
+
* See the License for the specific language governing permissions and
|
|
171
|
+
* limitations under the License.
|
|
172
|
+
*/
|
|
173
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/type-helper.ts","../src/logger.ts","../src/locale/i18n.ts"],"sourcesContent":["/*!\n * Copyright © 2024-2025 Dolphin Data Development Ltd. and AIDC Toolkit\n * contributors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport type * from \"./type\";\nexport * from \"./type-helper\";\nexport * from \"./logger\";\nexport * from \"./locale/i18n\";\n","/**\n * Create an object with omitted or picked entries.\n *\n * @param omitting\n * True if omitting.\n *\n * @param o\n * Object.\n *\n * @param keys\n * Keys to omit or pick.\n *\n * @returns\n * Edited object.\n */\nfunction omitOrPick<Omitting extends boolean, T extends object, K extends keyof T>(omitting: Omitting, o: T, ...keys: K[]): Omitting extends true ? Omit<T, K> : Pick<T, K> {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Key and value types are known.\n return Object.fromEntries(Object.entries(o).filter(([key]) => keys.includes(key as K) !== omitting)) as ReturnType<typeof omitOrPick<Omitting, T, K>>;\n}\n\n/**\n * Create an object with omitted entries.\n *\n * @param o\n * Object.\n *\n * @param keys\n * Keys to omit.\n *\n * @returns\n * Edited object.\n */\nexport function omit<T extends object, K extends keyof T>(o: T, ...keys: K[]): Omit<T, K> {\n return omitOrPick(true, o, ...keys);\n}\n\n/**\n * Create an object with picked entries.\n *\n * @param o\n * Object.\n *\n * @param keys\n * Keys to pick.\n *\n * @returns\n * Edited object.\n */\nexport function pick<T extends object, K extends keyof T>(o: T, ...keys: K[]): Pick<T, K> {\n return omitOrPick(false, o, ...keys);\n}\n\n/**\n * Cast a property as a more narrow type.\n *\n * @param o\n * Object.\n *\n * @param key\n * Key of property to cast.\n *\n * @returns\n * Single-key object with property cast as desired type.\n */\nexport function propertyAs<TAsType extends T[K], T extends object, K extends keyof T>(o: T, key: K): Readonly<Omit<T, K> extends T ? Partial<Record<K, TAsType>> : Record<K, TAsType>> {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Type is determined by condition.\n return (key in o ?\n {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Force cast.\n [key]: o[key] as TAsType\n } :\n {}\n ) as ReturnType<typeof propertyAs<TAsType, T, K>>;\n}\n\n/**\n * Determine if argument is nullish. Application extension may pass `null` or `undefined` to missing parameters.\n *\n * @param argument\n * Argument.\n *\n * @returns\n * True if argument is undefined or null.\n */\nexport function isNullish<T>(argument: T | null | undefined): argument is null | undefined {\n return argument === null || argument === undefined;\n}\n","import { Logger } from \"tslog\";\n\n/**\n * Log levels.\n */\nexport const LogLevels = {\n Silly: 0,\n Trace: 1,\n Debug: 2,\n Info: 3,\n Warn: 4,\n Error: 5,\n Fatal: 6\n} as const;\n\n/**\n * Log level.\n */\nexport type LogLevel = typeof LogLevels[keyof typeof LogLevels];\n\n/**\n * Get a simple logger with an optional log level.\n *\n * @param logLevel\n * Log level as enumeration value or string if any.\n *\n * @returns\n * Logger.\n */\nexport function getLogger(logLevel?: string | number): Logger<unknown> {\n let minLevel: number;\n\n if (typeof logLevel === \"string\") {\n if (logLevel in LogLevels) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- String exists as a key.\n minLevel = LogLevels[logLevel as keyof typeof LogLevels];\n } else {\n throw new Error(`Unknown log level ${logLevel}`);\n }\n } else {\n minLevel = logLevel ?? LogLevels.Info;\n }\n\n return new Logger({\n minLevel\n });\n}\n","import type { i18n, LanguageDetectorModule, Resource } from \"i18next\";\nimport I18nextBrowserLanguageDetector from \"i18next-browser-languagedetector\";\nimport I18nextCLILanguageDetector from \"i18next-cli-language-detector\";\n\n/**\n * Locale strings type for generic manipulation.\n */\nexport interface LocaleResources {\n [key: string]: LocaleResources | string;\n}\n\n/**\n * Internationalization operating environments.\n */\nexport const I18nEnvironments = {\n /**\n * Command-line interface (e.g., unit tests).\n */\n CLI: 0,\n\n /**\n * Web server.\n */\n Server: 1,\n\n /**\n * Web browser.\n */\n Browser: 2\n} as const;\n\n/**\n * Internationalization operating environment.\n */\nexport type I18nEnvironment = typeof I18nEnvironments[keyof typeof I18nEnvironments];\n\n/**\n * Convert a string to lower case, skipping words that are all upper case.\n *\n * @param s\n * String.\n *\n * @returns\n * Lower case string.\n */\nfunction toLowerCase(s: string): string {\n // Words with no lower case letters are preserved as they are likely mnemonics.\n return s.split(\" \").map(word => /[a-z]/.test(word) ? word.toLowerCase() : word).join(\" \");\n}\n\n/**\n * Initialize internationalization.\n *\n * @param i18next\n * Internationalization object. As multiple objects exists, this parameter represents the one for the module for which\n * internationalization is being initialized.\n *\n * @param environment\n * Environment in which the application is running.\n *\n * @param debug\n * Debug setting.\n *\n * @param defaultNS\n * Default namespace.\n *\n * @param resources\n * Resources.\n *\n * @returns\n * Void promise.\n */\nexport async function i18nCoreInit(i18next: i18n, environment: I18nEnvironment, debug: boolean, defaultNS: string, ...resources: Resource[]): Promise<void> {\n // Initialization may be called more than once.\n if (!i18next.isInitialized) {\n const mergedResource: Resource = {};\n\n // Merge resources.\n for (const resource of resources) {\n // Merge languages.\n for (const [language, resourceLanguage] of Object.entries(resource)) {\n if (!(language in mergedResource)) {\n mergedResource[language] = {};\n }\n\n const mergedResourceLanguage = mergedResource[language];\n\n // Merge namespaces.\n for (const [namespace, resourceKey] of Object.entries(resourceLanguage)) {\n mergedResourceLanguage[namespace] = resourceKey;\n }\n }\n }\n\n let module: Parameters<typeof i18next.use>[0];\n\n switch (environment) {\n case I18nEnvironments.CLI:\n // TODO Refactor when https://github.com/neet/i18next-cli-language-detector/issues/281 resolved.\n // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Per above.\n module = I18nextCLILanguageDetector as unknown as LanguageDetectorModule;\n break;\n\n case I18nEnvironments.Browser:\n module = I18nextBrowserLanguageDetector;\n break;\n\n default:\n throw new Error(\"Not supported\");\n }\n\n await i18next.use(module).init({\n debug,\n resources: mergedResource,\n fallbackLng: \"en\",\n defaultNS\n }).then(() => {\n // Add toLowerCase function.\n i18next.services.formatter?.add(\"toLowerCase\", value => typeof value === \"string\" ? toLowerCase(value) : String(value));\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACeA,SAAS,WAA0E,UAAoB,MAAS,MAA4D;AAExK,SAAO,OAAO,YAAY,OAAO,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,KAAK,SAAS,GAAQ,MAAM,QAAQ,CAAC;AACvG;AAcO,SAAS,KAA0C,MAAS,MAAuB;AACtF,SAAO,WAAW,MAAM,GAAG,GAAG,IAAI;AACtC;AAcO,SAAS,KAA0C,MAAS,MAAuB;AACtF,SAAO,WAAW,OAAO,GAAG,GAAG,IAAI;AACvC;AAcO,SAAS,WAAsE,GAAM,KAA2F;AAEnL,SAAQ,OAAO,IACX;AAAA;AAAA,IAEI,CAAC,GAAG,GAAG,EAAE,GAAG;AAAA,EAChB,IACA,CAAC;AAET;AAWO,SAAS,UAAa,UAA8D;AACvF,SAAO,aAAa,QAAQ,aAAa;AAC7C;;;ACtFA,mBAAuB;AAKhB,IAAM,YAAY;AAAA,EACrB,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AACX;AAgBO,SAAS,UAAU,UAA6C;AACnE,MAAI;AAEJ,MAAI,OAAO,aAAa,UAAU;AAC9B,QAAI,YAAY,WAAW;AAEvB,iBAAW,UAAU,QAAkC;AAAA,IAC3D,OAAO;AACH,YAAM,IAAI,MAAM,qBAAqB,QAAQ,EAAE;AAAA,IACnD;AAAA,EACJ,OAAO;AACH,eAAW,YAAY,UAAU;AAAA,EACrC;AAEA,SAAO,IAAI,oBAAO;AAAA,IACd;AAAA,EACJ,CAAC;AACL;;;AC7CA,8CAA2C;AAC3C,2CAAuC;AAYhC,IAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA,EAI5B,KAAK;AAAA;AAAA;AAAA;AAAA,EAKL,QAAQ;AAAA;AAAA;AAAA;AAAA,EAKR,SAAS;AACb;AAgBA,SAAS,YAAY,GAAmB;AAEpC,SAAO,EAAE,MAAM,GAAG,EAAE,IAAI,UAAQ,QAAQ,KAAK,IAAI,IAAI,KAAK,YAAY,IAAI,IAAI,EAAE,KAAK,GAAG;AAC5F;AAwBA,eAAsB,aAAa,SAAe,aAA8B,OAAgB,cAAsB,WAAsC;AAExJ,MAAI,CAAC,QAAQ,eAAe;AACxB,UAAM,iBAA2B,CAAC;AAGlC,eAAW,YAAY,WAAW;AAE9B,iBAAW,CAAC,UAAU,gBAAgB,KAAK,OAAO,QAAQ,QAAQ,GAAG;AACjE,YAAI,EAAE,YAAY,iBAAiB;AAC/B,yBAAe,QAAQ,IAAI,CAAC;AAAA,QAChC;AAEA,cAAM,yBAAyB,eAAe,QAAQ;AAGtD,mBAAW,CAAC,WAAW,WAAW,KAAK,OAAO,QAAQ,gBAAgB,GAAG;AACrE,iCAAuB,SAAS,IAAI;AAAA,QACxC;AAAA,MACJ;AAAA,IACJ;AAEA,QAAIA;AAEJ,YAAQ,aAAa;AAAA,MACjB,KAAK,iBAAiB;AAGlB,QAAAA,UAAS,qCAAAC;AACT;AAAA,MAEJ,KAAK,iBAAiB;AAClB,QAAAD,UAAS,wCAAAE;AACT;AAAA,MAEJ;AACI,cAAM,IAAI,MAAM,eAAe;AAAA,IACvC;AAEA,UAAM,QAAQ,IAAIF,OAAM,EAAE,KAAK;AAAA,MAC3B;AAAA,MACA,WAAW;AAAA,MACX,aAAa;AAAA,MACb;AAAA,IACJ,CAAC,EAAE,KAAK,MAAM;AAEV,cAAQ,SAAS,WAAW,IAAI,eAAe,WAAS,OAAO,UAAU,WAAW,YAAY,KAAK,IAAI,OAAO,KAAK,CAAC;AAAA,IAC1H,CAAC;AAAA,EACL;AACJ;","names":["module","I18nextCLILanguageDetector","I18nextBrowserLanguageDetector"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { Logger } from 'tslog';
|
|
2
|
+
import { i18n, Resource } from 'i18next';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Typed function, applicable to any function, stricter than {@link Function}.
|
|
6
|
+
*/
|
|
7
|
+
type TypedFunction<TMethod extends (...args: Parameters<TMethod>) => ReturnType<TMethod>> = (...args: Parameters<TMethod>) => ReturnType<TMethod>;
|
|
8
|
+
/**
|
|
9
|
+
* Typed synchronous function, applicable to any function that doesn't return a Promise.
|
|
10
|
+
*/
|
|
11
|
+
type TypedSyncFunction<TMethod extends TypedFunction<TMethod>> = [ReturnType<TMethod>] extends [PromiseLike<unknown>] ? never : TypedFunction<TMethod>;
|
|
12
|
+
/**
|
|
13
|
+
* Determine the fundamental promised type. This is stricter than `Awaited\<Type\>` in that it requires a Promise.
|
|
14
|
+
*/
|
|
15
|
+
type PromisedType<T> = [T] extends [PromiseLike<infer TPromised>] ? TPromised : never;
|
|
16
|
+
/**
|
|
17
|
+
* Typed asynchronous function, applicable to any function that returns a Promise.
|
|
18
|
+
*/
|
|
19
|
+
type TypedAsyncFunction<TMethod extends (...args: Parameters<TMethod>) => PromiseLike<PromisedType<ReturnType<TMethod>>>> = (...args: Parameters<TMethod>) => Promise<PromisedType<ReturnType<TMethod>>>;
|
|
20
|
+
/**
|
|
21
|
+
* Nullishable type. Extends a type by allowing `null` and `undefined`.
|
|
22
|
+
*/
|
|
23
|
+
type Nullishable<T> = T | null | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Non-nullishable type. If T is an object type, it is spread and attributes within it are made non-nullishable.
|
|
26
|
+
* Equivalent to a deep `Required\<T\>` for an object and `NonNullable\<T\>` for any other type.
|
|
27
|
+
*/
|
|
28
|
+
type NonNullishable<T> = T extends object ? {
|
|
29
|
+
[P in keyof T]-?: NonNullishable<T[P]>;
|
|
30
|
+
} : NonNullable<T>;
|
|
31
|
+
/**
|
|
32
|
+
* Make some keys within a type optional.
|
|
33
|
+
*/
|
|
34
|
+
type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
|
|
35
|
+
/**
|
|
36
|
+
* Type to restrict property keys to those that are strings and that support a specified type.
|
|
37
|
+
*/
|
|
38
|
+
type PropertyKeys<T, TProperty> = {
|
|
39
|
+
[K in keyof T]: K extends string ? T[K] extends TProperty ? K : never : never;
|
|
40
|
+
}[keyof T];
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Create an object with omitted entries.
|
|
44
|
+
*
|
|
45
|
+
* @param o
|
|
46
|
+
* Object.
|
|
47
|
+
*
|
|
48
|
+
* @param keys
|
|
49
|
+
* Keys to omit.
|
|
50
|
+
*
|
|
51
|
+
* @returns
|
|
52
|
+
* Edited object.
|
|
53
|
+
*/
|
|
54
|
+
declare function omit<T extends object, K extends keyof T>(o: T, ...keys: K[]): Omit<T, K>;
|
|
55
|
+
/**
|
|
56
|
+
* Create an object with picked entries.
|
|
57
|
+
*
|
|
58
|
+
* @param o
|
|
59
|
+
* Object.
|
|
60
|
+
*
|
|
61
|
+
* @param keys
|
|
62
|
+
* Keys to pick.
|
|
63
|
+
*
|
|
64
|
+
* @returns
|
|
65
|
+
* Edited object.
|
|
66
|
+
*/
|
|
67
|
+
declare function pick<T extends object, K extends keyof T>(o: T, ...keys: K[]): Pick<T, K>;
|
|
68
|
+
/**
|
|
69
|
+
* Cast a property as a more narrow type.
|
|
70
|
+
*
|
|
71
|
+
* @param o
|
|
72
|
+
* Object.
|
|
73
|
+
*
|
|
74
|
+
* @param key
|
|
75
|
+
* Key of property to cast.
|
|
76
|
+
*
|
|
77
|
+
* @returns
|
|
78
|
+
* Single-key object with property cast as desired type.
|
|
79
|
+
*/
|
|
80
|
+
declare function propertyAs<TAsType extends T[K], T extends object, K extends keyof T>(o: T, key: K): Readonly<Omit<T, K> extends T ? Partial<Record<K, TAsType>> : Record<K, TAsType>>;
|
|
81
|
+
/**
|
|
82
|
+
* Determine if argument is nullish. Application extension may pass `null` or `undefined` to missing parameters.
|
|
83
|
+
*
|
|
84
|
+
* @param argument
|
|
85
|
+
* Argument.
|
|
86
|
+
*
|
|
87
|
+
* @returns
|
|
88
|
+
* True if argument is undefined or null.
|
|
89
|
+
*/
|
|
90
|
+
declare function isNullish<T>(argument: T | null | undefined): argument is null | undefined;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Log levels.
|
|
94
|
+
*/
|
|
95
|
+
declare const LogLevels: {
|
|
96
|
+
readonly Silly: 0;
|
|
97
|
+
readonly Trace: 1;
|
|
98
|
+
readonly Debug: 2;
|
|
99
|
+
readonly Info: 3;
|
|
100
|
+
readonly Warn: 4;
|
|
101
|
+
readonly Error: 5;
|
|
102
|
+
readonly Fatal: 6;
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Log level.
|
|
106
|
+
*/
|
|
107
|
+
type LogLevel = typeof LogLevels[keyof typeof LogLevels];
|
|
108
|
+
/**
|
|
109
|
+
* Get a simple logger with an optional log level.
|
|
110
|
+
*
|
|
111
|
+
* @param logLevel
|
|
112
|
+
* Log level as enumeration value or string if any.
|
|
113
|
+
*
|
|
114
|
+
* @returns
|
|
115
|
+
* Logger.
|
|
116
|
+
*/
|
|
117
|
+
declare function getLogger(logLevel?: string | number): Logger<unknown>;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Locale strings type for generic manipulation.
|
|
121
|
+
*/
|
|
122
|
+
interface LocaleResources {
|
|
123
|
+
[key: string]: LocaleResources | string;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Internationalization operating environments.
|
|
127
|
+
*/
|
|
128
|
+
declare const I18nEnvironments: {
|
|
129
|
+
/**
|
|
130
|
+
* Command-line interface (e.g., unit tests).
|
|
131
|
+
*/
|
|
132
|
+
readonly CLI: 0;
|
|
133
|
+
/**
|
|
134
|
+
* Web server.
|
|
135
|
+
*/
|
|
136
|
+
readonly Server: 1;
|
|
137
|
+
/**
|
|
138
|
+
* Web browser.
|
|
139
|
+
*/
|
|
140
|
+
readonly Browser: 2;
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* Internationalization operating environment.
|
|
144
|
+
*/
|
|
145
|
+
type I18nEnvironment = typeof I18nEnvironments[keyof typeof I18nEnvironments];
|
|
146
|
+
/**
|
|
147
|
+
* Initialize internationalization.
|
|
148
|
+
*
|
|
149
|
+
* @param i18next
|
|
150
|
+
* Internationalization object. As multiple objects exists, this parameter represents the one for the module for which
|
|
151
|
+
* internationalization is being initialized.
|
|
152
|
+
*
|
|
153
|
+
* @param environment
|
|
154
|
+
* Environment in which the application is running.
|
|
155
|
+
*
|
|
156
|
+
* @param debug
|
|
157
|
+
* Debug setting.
|
|
158
|
+
*
|
|
159
|
+
* @param defaultNS
|
|
160
|
+
* Default namespace.
|
|
161
|
+
*
|
|
162
|
+
* @param resources
|
|
163
|
+
* Resources.
|
|
164
|
+
*
|
|
165
|
+
* @returns
|
|
166
|
+
* Void promise.
|
|
167
|
+
*/
|
|
168
|
+
declare function i18nCoreInit(i18next: i18n, environment: I18nEnvironment, debug: boolean, defaultNS: string, ...resources: Resource[]): Promise<void>;
|
|
169
|
+
|
|
170
|
+
export { type I18nEnvironment, I18nEnvironments, type LocaleResources, type LogLevel, LogLevels, type NonNullishable, type Nullishable, type Optional, type PropertyKeys, type TypedAsyncFunction, type TypedFunction, type TypedSyncFunction, getLogger, i18nCoreInit, isNullish, omit, pick, propertyAs };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,18 +1,170 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { Logger } from 'tslog';
|
|
2
|
+
import { i18n, Resource } from 'i18next';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Typed function, applicable to any function, stricter than {@link Function}.
|
|
6
|
+
*/
|
|
7
|
+
type TypedFunction<TMethod extends (...args: Parameters<TMethod>) => ReturnType<TMethod>> = (...args: Parameters<TMethod>) => ReturnType<TMethod>;
|
|
8
|
+
/**
|
|
9
|
+
* Typed synchronous function, applicable to any function that doesn't return a Promise.
|
|
10
|
+
*/
|
|
11
|
+
type TypedSyncFunction<TMethod extends TypedFunction<TMethod>> = [ReturnType<TMethod>] extends [PromiseLike<unknown>] ? never : TypedFunction<TMethod>;
|
|
12
|
+
/**
|
|
13
|
+
* Determine the fundamental promised type. This is stricter than `Awaited\<Type\>` in that it requires a Promise.
|
|
14
|
+
*/
|
|
15
|
+
type PromisedType<T> = [T] extends [PromiseLike<infer TPromised>] ? TPromised : never;
|
|
16
|
+
/**
|
|
17
|
+
* Typed asynchronous function, applicable to any function that returns a Promise.
|
|
18
|
+
*/
|
|
19
|
+
type TypedAsyncFunction<TMethod extends (...args: Parameters<TMethod>) => PromiseLike<PromisedType<ReturnType<TMethod>>>> = (...args: Parameters<TMethod>) => Promise<PromisedType<ReturnType<TMethod>>>;
|
|
20
|
+
/**
|
|
21
|
+
* Nullishable type. Extends a type by allowing `null` and `undefined`.
|
|
22
|
+
*/
|
|
23
|
+
type Nullishable<T> = T | null | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Non-nullishable type. If T is an object type, it is spread and attributes within it are made non-nullishable.
|
|
26
|
+
* Equivalent to a deep `Required\<T\>` for an object and `NonNullable\<T\>` for any other type.
|
|
27
|
+
*/
|
|
28
|
+
type NonNullishable<T> = T extends object ? {
|
|
29
|
+
[P in keyof T]-?: NonNullishable<T[P]>;
|
|
30
|
+
} : NonNullable<T>;
|
|
31
|
+
/**
|
|
32
|
+
* Make some keys within a type optional.
|
|
33
|
+
*/
|
|
34
|
+
type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
|
|
35
|
+
/**
|
|
36
|
+
* Type to restrict property keys to those that are strings and that support a specified type.
|
|
37
|
+
*/
|
|
38
|
+
type PropertyKeys<T, TProperty> = {
|
|
39
|
+
[K in keyof T]: K extends string ? T[K] extends TProperty ? K : never : never;
|
|
40
|
+
}[keyof T];
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Create an object with omitted entries.
|
|
44
|
+
*
|
|
45
|
+
* @param o
|
|
46
|
+
* Object.
|
|
47
|
+
*
|
|
48
|
+
* @param keys
|
|
49
|
+
* Keys to omit.
|
|
50
|
+
*
|
|
51
|
+
* @returns
|
|
52
|
+
* Edited object.
|
|
53
|
+
*/
|
|
54
|
+
declare function omit<T extends object, K extends keyof T>(o: T, ...keys: K[]): Omit<T, K>;
|
|
55
|
+
/**
|
|
56
|
+
* Create an object with picked entries.
|
|
57
|
+
*
|
|
58
|
+
* @param o
|
|
59
|
+
* Object.
|
|
60
|
+
*
|
|
61
|
+
* @param keys
|
|
62
|
+
* Keys to pick.
|
|
63
|
+
*
|
|
64
|
+
* @returns
|
|
65
|
+
* Edited object.
|
|
66
|
+
*/
|
|
67
|
+
declare function pick<T extends object, K extends keyof T>(o: T, ...keys: K[]): Pick<T, K>;
|
|
68
|
+
/**
|
|
69
|
+
* Cast a property as a more narrow type.
|
|
70
|
+
*
|
|
71
|
+
* @param o
|
|
72
|
+
* Object.
|
|
73
|
+
*
|
|
74
|
+
* @param key
|
|
75
|
+
* Key of property to cast.
|
|
76
|
+
*
|
|
77
|
+
* @returns
|
|
78
|
+
* Single-key object with property cast as desired type.
|
|
79
|
+
*/
|
|
80
|
+
declare function propertyAs<TAsType extends T[K], T extends object, K extends keyof T>(o: T, key: K): Readonly<Omit<T, K> extends T ? Partial<Record<K, TAsType>> : Record<K, TAsType>>;
|
|
81
|
+
/**
|
|
82
|
+
* Determine if argument is nullish. Application extension may pass `null` or `undefined` to missing parameters.
|
|
83
|
+
*
|
|
84
|
+
* @param argument
|
|
85
|
+
* Argument.
|
|
86
|
+
*
|
|
87
|
+
* @returns
|
|
88
|
+
* True if argument is undefined or null.
|
|
89
|
+
*/
|
|
90
|
+
declare function isNullish<T>(argument: T | null | undefined): argument is null | undefined;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Log levels.
|
|
94
|
+
*/
|
|
95
|
+
declare const LogLevels: {
|
|
96
|
+
readonly Silly: 0;
|
|
97
|
+
readonly Trace: 1;
|
|
98
|
+
readonly Debug: 2;
|
|
99
|
+
readonly Info: 3;
|
|
100
|
+
readonly Warn: 4;
|
|
101
|
+
readonly Error: 5;
|
|
102
|
+
readonly Fatal: 6;
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Log level.
|
|
106
|
+
*/
|
|
107
|
+
type LogLevel = typeof LogLevels[keyof typeof LogLevels];
|
|
108
|
+
/**
|
|
109
|
+
* Get a simple logger with an optional log level.
|
|
110
|
+
*
|
|
111
|
+
* @param logLevel
|
|
112
|
+
* Log level as enumeration value or string if any.
|
|
113
|
+
*
|
|
114
|
+
* @returns
|
|
115
|
+
* Logger.
|
|
116
|
+
*/
|
|
117
|
+
declare function getLogger(logLevel?: string | number): Logger<unknown>;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Locale strings type for generic manipulation.
|
|
121
|
+
*/
|
|
122
|
+
interface LocaleResources {
|
|
123
|
+
[key: string]: LocaleResources | string;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Internationalization operating environments.
|
|
127
|
+
*/
|
|
128
|
+
declare const I18nEnvironments: {
|
|
129
|
+
/**
|
|
130
|
+
* Command-line interface (e.g., unit tests).
|
|
131
|
+
*/
|
|
132
|
+
readonly CLI: 0;
|
|
133
|
+
/**
|
|
134
|
+
* Web server.
|
|
135
|
+
*/
|
|
136
|
+
readonly Server: 1;
|
|
137
|
+
/**
|
|
138
|
+
* Web browser.
|
|
139
|
+
*/
|
|
140
|
+
readonly Browser: 2;
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* Internationalization operating environment.
|
|
144
|
+
*/
|
|
145
|
+
type I18nEnvironment = typeof I18nEnvironments[keyof typeof I18nEnvironments];
|
|
146
|
+
/**
|
|
147
|
+
* Initialize internationalization.
|
|
148
|
+
*
|
|
149
|
+
* @param i18next
|
|
150
|
+
* Internationalization object. As multiple objects exists, this parameter represents the one for the module for which
|
|
151
|
+
* internationalization is being initialized.
|
|
152
|
+
*
|
|
153
|
+
* @param environment
|
|
154
|
+
* Environment in which the application is running.
|
|
155
|
+
*
|
|
156
|
+
* @param debug
|
|
157
|
+
* Debug setting.
|
|
4
158
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* You may obtain a copy of the License at
|
|
159
|
+
* @param defaultNS
|
|
160
|
+
* Default namespace.
|
|
8
161
|
*
|
|
9
|
-
*
|
|
162
|
+
* @param resources
|
|
163
|
+
* Resources.
|
|
10
164
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
-
* See the License for the specific language governing permissions and
|
|
15
|
-
* limitations under the License.
|
|
165
|
+
* @returns
|
|
166
|
+
* Void promise.
|
|
16
167
|
*/
|
|
17
|
-
|
|
18
|
-
|
|
168
|
+
declare function i18nCoreInit(i18next: i18n, environment: I18nEnvironment, debug: boolean, defaultNS: string, ...resources: Resource[]): Promise<void>;
|
|
169
|
+
|
|
170
|
+
export { type I18nEnvironment, I18nEnvironments, type LocaleResources, type LogLevel, LogLevels, type NonNullishable, type Nullishable, type Optional, type PropertyKeys, type TypedAsyncFunction, type TypedFunction, type TypedSyncFunction, getLogger, i18nCoreInit, isNullish, omit, pick, propertyAs };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,115 @@
|
|
|
1
|
+
// src/type-helper.ts
|
|
2
|
+
function omitOrPick(omitting, o, ...keys) {
|
|
3
|
+
return Object.fromEntries(Object.entries(o).filter(([key]) => keys.includes(key) !== omitting));
|
|
4
|
+
}
|
|
5
|
+
function omit(o, ...keys) {
|
|
6
|
+
return omitOrPick(true, o, ...keys);
|
|
7
|
+
}
|
|
8
|
+
function pick(o, ...keys) {
|
|
9
|
+
return omitOrPick(false, o, ...keys);
|
|
10
|
+
}
|
|
11
|
+
function propertyAs(o, key) {
|
|
12
|
+
return key in o ? {
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Force cast.
|
|
14
|
+
[key]: o[key]
|
|
15
|
+
} : {};
|
|
16
|
+
}
|
|
17
|
+
function isNullish(argument) {
|
|
18
|
+
return argument === null || argument === void 0;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// src/logger.ts
|
|
22
|
+
import { Logger } from "tslog";
|
|
23
|
+
var LogLevels = {
|
|
24
|
+
Silly: 0,
|
|
25
|
+
Trace: 1,
|
|
26
|
+
Debug: 2,
|
|
27
|
+
Info: 3,
|
|
28
|
+
Warn: 4,
|
|
29
|
+
Error: 5,
|
|
30
|
+
Fatal: 6
|
|
31
|
+
};
|
|
32
|
+
function getLogger(logLevel) {
|
|
33
|
+
let minLevel;
|
|
34
|
+
if (typeof logLevel === "string") {
|
|
35
|
+
if (logLevel in LogLevels) {
|
|
36
|
+
minLevel = LogLevels[logLevel];
|
|
37
|
+
} else {
|
|
38
|
+
throw new Error(`Unknown log level ${logLevel}`);
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
minLevel = logLevel ?? LogLevels.Info;
|
|
42
|
+
}
|
|
43
|
+
return new Logger({
|
|
44
|
+
minLevel
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// src/locale/i18n.ts
|
|
49
|
+
import I18nextBrowserLanguageDetector from "i18next-browser-languagedetector";
|
|
50
|
+
import I18nextCLILanguageDetector from "i18next-cli-language-detector";
|
|
51
|
+
var I18nEnvironments = {
|
|
52
|
+
/**
|
|
53
|
+
* Command-line interface (e.g., unit tests).
|
|
54
|
+
*/
|
|
55
|
+
CLI: 0,
|
|
56
|
+
/**
|
|
57
|
+
* Web server.
|
|
58
|
+
*/
|
|
59
|
+
Server: 1,
|
|
60
|
+
/**
|
|
61
|
+
* Web browser.
|
|
62
|
+
*/
|
|
63
|
+
Browser: 2
|
|
64
|
+
};
|
|
65
|
+
function toLowerCase(s) {
|
|
66
|
+
return s.split(" ").map((word) => /[a-z]/.test(word) ? word.toLowerCase() : word).join(" ");
|
|
67
|
+
}
|
|
68
|
+
async function i18nCoreInit(i18next, environment, debug, defaultNS, ...resources) {
|
|
69
|
+
if (!i18next.isInitialized) {
|
|
70
|
+
const mergedResource = {};
|
|
71
|
+
for (const resource of resources) {
|
|
72
|
+
for (const [language, resourceLanguage] of Object.entries(resource)) {
|
|
73
|
+
if (!(language in mergedResource)) {
|
|
74
|
+
mergedResource[language] = {};
|
|
75
|
+
}
|
|
76
|
+
const mergedResourceLanguage = mergedResource[language];
|
|
77
|
+
for (const [namespace, resourceKey] of Object.entries(resourceLanguage)) {
|
|
78
|
+
mergedResourceLanguage[namespace] = resourceKey;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
let module;
|
|
83
|
+
switch (environment) {
|
|
84
|
+
case I18nEnvironments.CLI:
|
|
85
|
+
module = I18nextCLILanguageDetector;
|
|
86
|
+
break;
|
|
87
|
+
case I18nEnvironments.Browser:
|
|
88
|
+
module = I18nextBrowserLanguageDetector;
|
|
89
|
+
break;
|
|
90
|
+
default:
|
|
91
|
+
throw new Error("Not supported");
|
|
92
|
+
}
|
|
93
|
+
await i18next.use(module).init({
|
|
94
|
+
debug,
|
|
95
|
+
resources: mergedResource,
|
|
96
|
+
fallbackLng: "en",
|
|
97
|
+
defaultNS
|
|
98
|
+
}).then(() => {
|
|
99
|
+
i18next.services.formatter?.add("toLowerCase", (value) => typeof value === "string" ? toLowerCase(value) : String(value));
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
export {
|
|
104
|
+
I18nEnvironments,
|
|
105
|
+
LogLevels,
|
|
106
|
+
getLogger,
|
|
107
|
+
i18nCoreInit,
|
|
108
|
+
isNullish,
|
|
109
|
+
omit,
|
|
110
|
+
pick,
|
|
111
|
+
propertyAs
|
|
112
|
+
};
|
|
1
113
|
/*!
|
|
2
114
|
* Copyright © 2024-2025 Dolphin Data Development Ltd. and AIDC Toolkit
|
|
3
115
|
* contributors
|
|
@@ -14,5 +126,4 @@
|
|
|
14
126
|
* See the License for the specific language governing permissions and
|
|
15
127
|
* limitations under the License.
|
|
16
128
|
*/
|
|
17
|
-
export * from "./locale/i18n.js";
|
|
18
129
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"sources":["../src/type-helper.ts","../src/logger.ts","../src/locale/i18n.ts"],"sourcesContent":["/**\n * Create an object with omitted or picked entries.\n *\n * @param omitting\n * True if omitting.\n *\n * @param o\n * Object.\n *\n * @param keys\n * Keys to omit or pick.\n *\n * @returns\n * Edited object.\n */\nfunction omitOrPick<Omitting extends boolean, T extends object, K extends keyof T>(omitting: Omitting, o: T, ...keys: K[]): Omitting extends true ? Omit<T, K> : Pick<T, K> {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Key and value types are known.\n return Object.fromEntries(Object.entries(o).filter(([key]) => keys.includes(key as K) !== omitting)) as ReturnType<typeof omitOrPick<Omitting, T, K>>;\n}\n\n/**\n * Create an object with omitted entries.\n *\n * @param o\n * Object.\n *\n * @param keys\n * Keys to omit.\n *\n * @returns\n * Edited object.\n */\nexport function omit<T extends object, K extends keyof T>(o: T, ...keys: K[]): Omit<T, K> {\n return omitOrPick(true, o, ...keys);\n}\n\n/**\n * Create an object with picked entries.\n *\n * @param o\n * Object.\n *\n * @param keys\n * Keys to pick.\n *\n * @returns\n * Edited object.\n */\nexport function pick<T extends object, K extends keyof T>(o: T, ...keys: K[]): Pick<T, K> {\n return omitOrPick(false, o, ...keys);\n}\n\n/**\n * Cast a property as a more narrow type.\n *\n * @param o\n * Object.\n *\n * @param key\n * Key of property to cast.\n *\n * @returns\n * Single-key object with property cast as desired type.\n */\nexport function propertyAs<TAsType extends T[K], T extends object, K extends keyof T>(o: T, key: K): Readonly<Omit<T, K> extends T ? Partial<Record<K, TAsType>> : Record<K, TAsType>> {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Type is determined by condition.\n return (key in o ?\n {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Force cast.\n [key]: o[key] as TAsType\n } :\n {}\n ) as ReturnType<typeof propertyAs<TAsType, T, K>>;\n}\n\n/**\n * Determine if argument is nullish. Application extension may pass `null` or `undefined` to missing parameters.\n *\n * @param argument\n * Argument.\n *\n * @returns\n * True if argument is undefined or null.\n */\nexport function isNullish<T>(argument: T | null | undefined): argument is null | undefined {\n return argument === null || argument === undefined;\n}\n","import { Logger } from \"tslog\";\n\n/**\n * Log levels.\n */\nexport const LogLevels = {\n Silly: 0,\n Trace: 1,\n Debug: 2,\n Info: 3,\n Warn: 4,\n Error: 5,\n Fatal: 6\n} as const;\n\n/**\n * Log level.\n */\nexport type LogLevel = typeof LogLevels[keyof typeof LogLevels];\n\n/**\n * Get a simple logger with an optional log level.\n *\n * @param logLevel\n * Log level as enumeration value or string if any.\n *\n * @returns\n * Logger.\n */\nexport function getLogger(logLevel?: string | number): Logger<unknown> {\n let minLevel: number;\n\n if (typeof logLevel === \"string\") {\n if (logLevel in LogLevels) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- String exists as a key.\n minLevel = LogLevels[logLevel as keyof typeof LogLevels];\n } else {\n throw new Error(`Unknown log level ${logLevel}`);\n }\n } else {\n minLevel = logLevel ?? LogLevels.Info;\n }\n\n return new Logger({\n minLevel\n });\n}\n","import type { i18n, LanguageDetectorModule, Resource } from \"i18next\";\nimport I18nextBrowserLanguageDetector from \"i18next-browser-languagedetector\";\nimport I18nextCLILanguageDetector from \"i18next-cli-language-detector\";\n\n/**\n * Locale strings type for generic manipulation.\n */\nexport interface LocaleResources {\n [key: string]: LocaleResources | string;\n}\n\n/**\n * Internationalization operating environments.\n */\nexport const I18nEnvironments = {\n /**\n * Command-line interface (e.g., unit tests).\n */\n CLI: 0,\n\n /**\n * Web server.\n */\n Server: 1,\n\n /**\n * Web browser.\n */\n Browser: 2\n} as const;\n\n/**\n * Internationalization operating environment.\n */\nexport type I18nEnvironment = typeof I18nEnvironments[keyof typeof I18nEnvironments];\n\n/**\n * Convert a string to lower case, skipping words that are all upper case.\n *\n * @param s\n * String.\n *\n * @returns\n * Lower case string.\n */\nfunction toLowerCase(s: string): string {\n // Words with no lower case letters are preserved as they are likely mnemonics.\n return s.split(\" \").map(word => /[a-z]/.test(word) ? word.toLowerCase() : word).join(\" \");\n}\n\n/**\n * Initialize internationalization.\n *\n * @param i18next\n * Internationalization object. As multiple objects exists, this parameter represents the one for the module for which\n * internationalization is being initialized.\n *\n * @param environment\n * Environment in which the application is running.\n *\n * @param debug\n * Debug setting.\n *\n * @param defaultNS\n * Default namespace.\n *\n * @param resources\n * Resources.\n *\n * @returns\n * Void promise.\n */\nexport async function i18nCoreInit(i18next: i18n, environment: I18nEnvironment, debug: boolean, defaultNS: string, ...resources: Resource[]): Promise<void> {\n // Initialization may be called more than once.\n if (!i18next.isInitialized) {\n const mergedResource: Resource = {};\n\n // Merge resources.\n for (const resource of resources) {\n // Merge languages.\n for (const [language, resourceLanguage] of Object.entries(resource)) {\n if (!(language in mergedResource)) {\n mergedResource[language] = {};\n }\n\n const mergedResourceLanguage = mergedResource[language];\n\n // Merge namespaces.\n for (const [namespace, resourceKey] of Object.entries(resourceLanguage)) {\n mergedResourceLanguage[namespace] = resourceKey;\n }\n }\n }\n\n let module: Parameters<typeof i18next.use>[0];\n\n switch (environment) {\n case I18nEnvironments.CLI:\n // TODO Refactor when https://github.com/neet/i18next-cli-language-detector/issues/281 resolved.\n // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Per above.\n module = I18nextCLILanguageDetector as unknown as LanguageDetectorModule;\n break;\n\n case I18nEnvironments.Browser:\n module = I18nextBrowserLanguageDetector;\n break;\n\n default:\n throw new Error(\"Not supported\");\n }\n\n await i18next.use(module).init({\n debug,\n resources: mergedResource,\n fallbackLng: \"en\",\n defaultNS\n }).then(() => {\n // Add toLowerCase function.\n i18next.services.formatter?.add(\"toLowerCase\", value => typeof value === \"string\" ? toLowerCase(value) : String(value));\n });\n }\n}\n"],"mappings":";AAeA,SAAS,WAA0E,UAAoB,MAAS,MAA4D;AAExK,SAAO,OAAO,YAAY,OAAO,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,KAAK,SAAS,GAAQ,MAAM,QAAQ,CAAC;AACvG;AAcO,SAAS,KAA0C,MAAS,MAAuB;AACtF,SAAO,WAAW,MAAM,GAAG,GAAG,IAAI;AACtC;AAcO,SAAS,KAA0C,MAAS,MAAuB;AACtF,SAAO,WAAW,OAAO,GAAG,GAAG,IAAI;AACvC;AAcO,SAAS,WAAsE,GAAM,KAA2F;AAEnL,SAAQ,OAAO,IACX;AAAA;AAAA,IAEI,CAAC,GAAG,GAAG,EAAE,GAAG;AAAA,EAChB,IACA,CAAC;AAET;AAWO,SAAS,UAAa,UAA8D;AACvF,SAAO,aAAa,QAAQ,aAAa;AAC7C;;;ACtFA,SAAS,cAAc;AAKhB,IAAM,YAAY;AAAA,EACrB,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AACX;AAgBO,SAAS,UAAU,UAA6C;AACnE,MAAI;AAEJ,MAAI,OAAO,aAAa,UAAU;AAC9B,QAAI,YAAY,WAAW;AAEvB,iBAAW,UAAU,QAAkC;AAAA,IAC3D,OAAO;AACH,YAAM,IAAI,MAAM,qBAAqB,QAAQ,EAAE;AAAA,IACnD;AAAA,EACJ,OAAO;AACH,eAAW,YAAY,UAAU;AAAA,EACrC;AAEA,SAAO,IAAI,OAAO;AAAA,IACd;AAAA,EACJ,CAAC;AACL;;;AC7CA,OAAO,oCAAoC;AAC3C,OAAO,gCAAgC;AAYhC,IAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA,EAI5B,KAAK;AAAA;AAAA;AAAA;AAAA,EAKL,QAAQ;AAAA;AAAA;AAAA;AAAA,EAKR,SAAS;AACb;AAgBA,SAAS,YAAY,GAAmB;AAEpC,SAAO,EAAE,MAAM,GAAG,EAAE,IAAI,UAAQ,QAAQ,KAAK,IAAI,IAAI,KAAK,YAAY,IAAI,IAAI,EAAE,KAAK,GAAG;AAC5F;AAwBA,eAAsB,aAAa,SAAe,aAA8B,OAAgB,cAAsB,WAAsC;AAExJ,MAAI,CAAC,QAAQ,eAAe;AACxB,UAAM,iBAA2B,CAAC;AAGlC,eAAW,YAAY,WAAW;AAE9B,iBAAW,CAAC,UAAU,gBAAgB,KAAK,OAAO,QAAQ,QAAQ,GAAG;AACjE,YAAI,EAAE,YAAY,iBAAiB;AAC/B,yBAAe,QAAQ,IAAI,CAAC;AAAA,QAChC;AAEA,cAAM,yBAAyB,eAAe,QAAQ;AAGtD,mBAAW,CAAC,WAAW,WAAW,KAAK,OAAO,QAAQ,gBAAgB,GAAG;AACrE,iCAAuB,SAAS,IAAI;AAAA,QACxC;AAAA,MACJ;AAAA,IACJ;AAEA,QAAI;AAEJ,YAAQ,aAAa;AAAA,MACjB,KAAK,iBAAiB;AAGlB,iBAAS;AACT;AAAA,MAEJ,KAAK,iBAAiB;AAClB,iBAAS;AACT;AAAA,MAEJ;AACI,cAAM,IAAI,MAAM,eAAe;AAAA,IACvC;AAEA,UAAM,QAAQ,IAAI,MAAM,EAAE,KAAK;AAAA,MAC3B;AAAA,MACA,WAAW;AAAA,MACX,aAAa;AAAA,MACb;AAAA,IACJ,CAAC,EAAE,KAAK,MAAM;AAEV,cAAQ,SAAS,WAAW,IAAI,eAAe,WAAS,OAAO,UAAU,WAAW,YAAY,KAAK,IAAI,OAAO,KAAK,CAAC;AAAA,IAC1H,CAAC;AAAA,EACL;AACJ;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aidc-toolkit/core",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.24-beta",
|
|
4
4
|
"description": "Core functionality for AIDC Toolkit",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"homepage": "https://aidc-toolkit.com/",
|
|
8
|
-
"repository":
|
|
9
|
-
"type": "git",
|
|
10
|
-
"url": "git+https://github.com/aidc-toolkit/core.git"
|
|
11
|
-
},
|
|
8
|
+
"repository": "aidc-toolkit/core",
|
|
12
9
|
"bugs": {
|
|
13
10
|
"url": "https://github.com/aidc-toolkit/core/issues"
|
|
14
11
|
},
|
|
@@ -20,17 +17,17 @@
|
|
|
20
17
|
},
|
|
21
18
|
"scripts": {
|
|
22
19
|
"lint": "eslint",
|
|
23
|
-
"build:
|
|
24
|
-
"build:
|
|
25
|
-
"build:release": "npm run build:core -- node_modules/@aidc-toolkit/dev/tsconfig-build.json",
|
|
20
|
+
"build:dev": "tsup --define.mode=dev",
|
|
21
|
+
"build:release": "tsup",
|
|
26
22
|
"build:doc": "npm run build:dev"
|
|
27
23
|
},
|
|
28
24
|
"devDependencies": {
|
|
29
25
|
"@aidc-toolkit/dev": "beta"
|
|
30
26
|
},
|
|
31
27
|
"dependencies": {
|
|
32
|
-
"i18next": "^25.
|
|
28
|
+
"i18next": "^25.7.0",
|
|
33
29
|
"i18next-browser-languagedetector": "^8.2.0",
|
|
34
|
-
"i18next-cli-language-detector": "^1.1.8"
|
|
30
|
+
"i18next-cli-language-detector": "^1.1.8",
|
|
31
|
+
"tslog": "^4.10.2"
|
|
35
32
|
}
|
|
36
33
|
}
|
package/src/index.ts
CHANGED
|
@@ -14,4 +14,7 @@
|
|
|
14
14
|
* See the License for the specific language governing permissions and
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
|
-
export * from "./
|
|
17
|
+
export type * from "./type";
|
|
18
|
+
export * from "./type-helper";
|
|
19
|
+
export * from "./logger";
|
|
20
|
+
export * from "./locale/i18n";
|
package/src/locale/i18n.ts
CHANGED
|
@@ -5,8 +5,8 @@ import I18nextCLILanguageDetector from "i18next-cli-language-detector";
|
|
|
5
5
|
/**
|
|
6
6
|
* Locale strings type for generic manipulation.
|
|
7
7
|
*/
|
|
8
|
-
export interface
|
|
9
|
-
[key: string]:
|
|
8
|
+
export interface LocaleResources {
|
|
9
|
+
[key: string]: LocaleResources | string;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -34,54 +34,6 @@ export const I18nEnvironments = {
|
|
|
34
34
|
*/
|
|
35
35
|
export type I18nEnvironment = typeof I18nEnvironments[keyof typeof I18nEnvironments];
|
|
36
36
|
|
|
37
|
-
/**
|
|
38
|
-
* Assert that language resources are a type match for English (default) resources.
|
|
39
|
-
*
|
|
40
|
-
* @param enResources
|
|
41
|
-
* English resources.
|
|
42
|
-
*
|
|
43
|
-
* @param lng
|
|
44
|
-
* Language.
|
|
45
|
-
*
|
|
46
|
-
* @param lngResources
|
|
47
|
-
* Language resources.
|
|
48
|
-
*
|
|
49
|
-
* @param parent
|
|
50
|
-
* Parent key name (set recursively).
|
|
51
|
-
*/
|
|
52
|
-
export function i18nAssertValidResources(enResources: object, lng: string, lngResources: object, parent?: string): void {
|
|
53
|
-
const enResourcesMap = new Map<string, object>(Object.entries(enResources));
|
|
54
|
-
const lngResourcesMap = new Map<string, object>(Object.entries(lngResources));
|
|
55
|
-
|
|
56
|
-
const isLocale = lng.includes("-");
|
|
57
|
-
|
|
58
|
-
for (const [enKey, enValue] of enResourcesMap) {
|
|
59
|
-
const lngValue = lngResourcesMap.get(enKey);
|
|
60
|
-
|
|
61
|
-
if (lngValue !== undefined) {
|
|
62
|
-
const enValueType = typeof enValue;
|
|
63
|
-
const lngValueType = typeof lngValue;
|
|
64
|
-
|
|
65
|
-
if (lngValueType !== enValueType) {
|
|
66
|
-
throw new Error(`Invalid value type ${lngValueType} for key ${parent === undefined ? "" : `${parent}.`}${enKey} in ${lng} resources`);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (enValueType === "object") {
|
|
70
|
-
i18nAssertValidResources(enValue, lng, lngValue, `${parent === undefined ? "" : `${parent}.`}${enKey}`);
|
|
71
|
-
}
|
|
72
|
-
// Locale falls back to raw language so ignore if missing.
|
|
73
|
-
} else if (!isLocale) {
|
|
74
|
-
throw new Error(`Missing key ${parent === undefined ? "" : `${parent}.`}${enKey} from ${lng} resources`);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
for (const [lngKey] of lngResourcesMap) {
|
|
79
|
-
if (!enResourcesMap.has(lngKey)) {
|
|
80
|
-
throw new Error(`Extraneous key ${parent === undefined ? "" : `${parent}.`}${lngKey} in ${lng} resources`);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
37
|
/**
|
|
86
38
|
* Convert a string to lower case, skipping words that are all upper case.
|
|
87
39
|
*
|
package/src/logger.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Logger } from "tslog";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Log levels.
|
|
5
|
+
*/
|
|
6
|
+
export const LogLevels = {
|
|
7
|
+
Silly: 0,
|
|
8
|
+
Trace: 1,
|
|
9
|
+
Debug: 2,
|
|
10
|
+
Info: 3,
|
|
11
|
+
Warn: 4,
|
|
12
|
+
Error: 5,
|
|
13
|
+
Fatal: 6
|
|
14
|
+
} as const;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Log level.
|
|
18
|
+
*/
|
|
19
|
+
export type LogLevel = typeof LogLevels[keyof typeof LogLevels];
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Get a simple logger with an optional log level.
|
|
23
|
+
*
|
|
24
|
+
* @param logLevel
|
|
25
|
+
* Log level as enumeration value or string if any.
|
|
26
|
+
*
|
|
27
|
+
* @returns
|
|
28
|
+
* Logger.
|
|
29
|
+
*/
|
|
30
|
+
export function getLogger(logLevel?: string | number): Logger<unknown> {
|
|
31
|
+
let minLevel: number;
|
|
32
|
+
|
|
33
|
+
if (typeof logLevel === "string") {
|
|
34
|
+
if (logLevel in LogLevels) {
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- String exists as a key.
|
|
36
|
+
minLevel = LogLevels[logLevel as keyof typeof LogLevels];
|
|
37
|
+
} else {
|
|
38
|
+
throw new Error(`Unknown log level ${logLevel}`);
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
minLevel = logLevel ?? LogLevels.Info;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return new Logger({
|
|
45
|
+
minLevel
|
|
46
|
+
});
|
|
47
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create an object with omitted or picked entries.
|
|
3
|
+
*
|
|
4
|
+
* @param omitting
|
|
5
|
+
* True if omitting.
|
|
6
|
+
*
|
|
7
|
+
* @param o
|
|
8
|
+
* Object.
|
|
9
|
+
*
|
|
10
|
+
* @param keys
|
|
11
|
+
* Keys to omit or pick.
|
|
12
|
+
*
|
|
13
|
+
* @returns
|
|
14
|
+
* Edited object.
|
|
15
|
+
*/
|
|
16
|
+
function omitOrPick<Omitting extends boolean, T extends object, K extends keyof T>(omitting: Omitting, o: T, ...keys: K[]): Omitting extends true ? Omit<T, K> : Pick<T, K> {
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Key and value types are known.
|
|
18
|
+
return Object.fromEntries(Object.entries(o).filter(([key]) => keys.includes(key as K) !== omitting)) as ReturnType<typeof omitOrPick<Omitting, T, K>>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Create an object with omitted entries.
|
|
23
|
+
*
|
|
24
|
+
* @param o
|
|
25
|
+
* Object.
|
|
26
|
+
*
|
|
27
|
+
* @param keys
|
|
28
|
+
* Keys to omit.
|
|
29
|
+
*
|
|
30
|
+
* @returns
|
|
31
|
+
* Edited object.
|
|
32
|
+
*/
|
|
33
|
+
export function omit<T extends object, K extends keyof T>(o: T, ...keys: K[]): Omit<T, K> {
|
|
34
|
+
return omitOrPick(true, o, ...keys);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Create an object with picked entries.
|
|
39
|
+
*
|
|
40
|
+
* @param o
|
|
41
|
+
* Object.
|
|
42
|
+
*
|
|
43
|
+
* @param keys
|
|
44
|
+
* Keys to pick.
|
|
45
|
+
*
|
|
46
|
+
* @returns
|
|
47
|
+
* Edited object.
|
|
48
|
+
*/
|
|
49
|
+
export function pick<T extends object, K extends keyof T>(o: T, ...keys: K[]): Pick<T, K> {
|
|
50
|
+
return omitOrPick(false, o, ...keys);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Cast a property as a more narrow type.
|
|
55
|
+
*
|
|
56
|
+
* @param o
|
|
57
|
+
* Object.
|
|
58
|
+
*
|
|
59
|
+
* @param key
|
|
60
|
+
* Key of property to cast.
|
|
61
|
+
*
|
|
62
|
+
* @returns
|
|
63
|
+
* Single-key object with property cast as desired type.
|
|
64
|
+
*/
|
|
65
|
+
export function propertyAs<TAsType extends T[K], T extends object, K extends keyof T>(o: T, key: K): Readonly<Omit<T, K> extends T ? Partial<Record<K, TAsType>> : Record<K, TAsType>> {
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Type is determined by condition.
|
|
67
|
+
return (key in o ?
|
|
68
|
+
{
|
|
69
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Force cast.
|
|
70
|
+
[key]: o[key] as TAsType
|
|
71
|
+
} :
|
|
72
|
+
{}
|
|
73
|
+
) as ReturnType<typeof propertyAs<TAsType, T, K>>;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Determine if argument is nullish. Application extension may pass `null` or `undefined` to missing parameters.
|
|
78
|
+
*
|
|
79
|
+
* @param argument
|
|
80
|
+
* Argument.
|
|
81
|
+
*
|
|
82
|
+
* @returns
|
|
83
|
+
* True if argument is undefined or null.
|
|
84
|
+
*/
|
|
85
|
+
export function isNullish<T>(argument: T | null | undefined): argument is null | undefined {
|
|
86
|
+
return argument === null || argument === undefined;
|
|
87
|
+
}
|
package/src/type.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed function, applicable to any function, stricter than {@link Function}.
|
|
3
|
+
*/
|
|
4
|
+
export type TypedFunction<TMethod extends (...args: Parameters<TMethod>) => ReturnType<TMethod>> = (...args: Parameters<TMethod>) => ReturnType<TMethod>;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Typed synchronous function, applicable to any function that doesn't return a Promise.
|
|
8
|
+
*/
|
|
9
|
+
export type TypedSyncFunction<TMethod extends TypedFunction<TMethod>> = [ReturnType<TMethod>] extends [PromiseLike<unknown>] ? never : TypedFunction<TMethod>;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Determine the fundamental promised type. This is stricter than `Awaited\<Type\>` in that it requires a Promise.
|
|
13
|
+
*/
|
|
14
|
+
type PromisedType<T> = [T] extends [PromiseLike<infer TPromised>] ? TPromised : never;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Typed asynchronous function, applicable to any function that returns a Promise.
|
|
18
|
+
*/
|
|
19
|
+
export type TypedAsyncFunction<TMethod extends (...args: Parameters<TMethod>) => PromiseLike<PromisedType<ReturnType<TMethod>>>> = (...args: Parameters<TMethod>) => Promise<PromisedType<ReturnType<TMethod>>>;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Nullishable type. Extends a type by allowing `null` and `undefined`.
|
|
23
|
+
*/
|
|
24
|
+
export type Nullishable<T> = T | null | undefined;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Non-nullishable type. If T is an object type, it is spread and attributes within it are made non-nullishable.
|
|
28
|
+
* Equivalent to a deep `Required\<T\>` for an object and `NonNullable\<T\>` for any other type.
|
|
29
|
+
*/
|
|
30
|
+
export type NonNullishable<T> = T extends object ? {
|
|
31
|
+
[P in keyof T]-?: NonNullishable<T[P]>
|
|
32
|
+
} : NonNullable<T>;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Make some keys within a type optional.
|
|
36
|
+
*/
|
|
37
|
+
export type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Type to restrict property keys to those that are strings and that support a specified type.
|
|
41
|
+
*/
|
|
42
|
+
export type PropertyKeys<T, TProperty> = {
|
|
43
|
+
[K in keyof T]: K extends string ? T[K] extends TProperty ? K : never : never;
|
|
44
|
+
}[keyof T];
|
package/tsup.config.ts
ADDED
package/typedoc.json
CHANGED
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,cAAc,kBAAkB,CAAC"}
|
package/dist/locale/i18n.d.ts
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import type { i18n, Resource } from "i18next";
|
|
2
|
-
/**
|
|
3
|
-
* Locale strings type for generic manipulation.
|
|
4
|
-
*/
|
|
5
|
-
export interface LocaleStrings {
|
|
6
|
-
[key: string]: LocaleStrings | string;
|
|
7
|
-
}
|
|
8
|
-
/**
|
|
9
|
-
* Internationalization operating environments.
|
|
10
|
-
*/
|
|
11
|
-
export declare const I18nEnvironments: {
|
|
12
|
-
/**
|
|
13
|
-
* Command-line interface (e.g., unit tests).
|
|
14
|
-
*/
|
|
15
|
-
readonly CLI: 0;
|
|
16
|
-
/**
|
|
17
|
-
* Web server.
|
|
18
|
-
*/
|
|
19
|
-
readonly Server: 1;
|
|
20
|
-
/**
|
|
21
|
-
* Web browser.
|
|
22
|
-
*/
|
|
23
|
-
readonly Browser: 2;
|
|
24
|
-
};
|
|
25
|
-
/**
|
|
26
|
-
* Internationalization operating environment.
|
|
27
|
-
*/
|
|
28
|
-
export type I18nEnvironment = typeof I18nEnvironments[keyof typeof I18nEnvironments];
|
|
29
|
-
/**
|
|
30
|
-
* Assert that language resources are a type match for English (default) resources.
|
|
31
|
-
*
|
|
32
|
-
* @param enResources
|
|
33
|
-
* English resources.
|
|
34
|
-
*
|
|
35
|
-
* @param lng
|
|
36
|
-
* Language.
|
|
37
|
-
*
|
|
38
|
-
* @param lngResources
|
|
39
|
-
* Language resources.
|
|
40
|
-
*
|
|
41
|
-
* @param parent
|
|
42
|
-
* Parent key name (set recursively).
|
|
43
|
-
*/
|
|
44
|
-
export declare function i18nAssertValidResources(enResources: object, lng: string, lngResources: object, parent?: string): void;
|
|
45
|
-
/**
|
|
46
|
-
* Initialize internationalization.
|
|
47
|
-
*
|
|
48
|
-
* @param i18next
|
|
49
|
-
* Internationalization object. As multiple objects exists, this parameter represents the one for the module for which
|
|
50
|
-
* internationalization is being initialized.
|
|
51
|
-
*
|
|
52
|
-
* @param environment
|
|
53
|
-
* Environment in which the application is running.
|
|
54
|
-
*
|
|
55
|
-
* @param debug
|
|
56
|
-
* Debug setting.
|
|
57
|
-
*
|
|
58
|
-
* @param defaultNS
|
|
59
|
-
* Default namespace.
|
|
60
|
-
*
|
|
61
|
-
* @param resources
|
|
62
|
-
* Resources.
|
|
63
|
-
*
|
|
64
|
-
* @returns
|
|
65
|
-
* Void promise.
|
|
66
|
-
*/
|
|
67
|
-
export declare function i18nCoreInit(i18next: i18n, environment: I18nEnvironment, debug: boolean, defaultNS: string, ...resources: Resource[]): Promise<void>;
|
|
68
|
-
//# sourceMappingURL=i18n.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../src/locale/i18n.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAA0B,QAAQ,EAAE,MAAM,SAAS,CAAC;AAItE;;GAEG;AACH,MAAM,WAAW,aAAa;IAC1B,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,GAAG,MAAM,CAAC;CACzC;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB;IACzB;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;CAEG,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,gBAAgB,CAAC,MAAM,OAAO,gBAAgB,CAAC,CAAC;AAErF;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CA+BtH;AAgBD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,eAAe,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAiD1J"}
|
package/dist/locale/i18n.js
DELETED
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
import I18nextBrowserLanguageDetector from "i18next-browser-languagedetector";
|
|
2
|
-
import I18nextCLILanguageDetector from "i18next-cli-language-detector";
|
|
3
|
-
/**
|
|
4
|
-
* Internationalization operating environments.
|
|
5
|
-
*/
|
|
6
|
-
export const I18nEnvironments = {
|
|
7
|
-
/**
|
|
8
|
-
* Command-line interface (e.g., unit tests).
|
|
9
|
-
*/
|
|
10
|
-
CLI: 0,
|
|
11
|
-
/**
|
|
12
|
-
* Web server.
|
|
13
|
-
*/
|
|
14
|
-
Server: 1,
|
|
15
|
-
/**
|
|
16
|
-
* Web browser.
|
|
17
|
-
*/
|
|
18
|
-
Browser: 2
|
|
19
|
-
};
|
|
20
|
-
/**
|
|
21
|
-
* Assert that language resources are a type match for English (default) resources.
|
|
22
|
-
*
|
|
23
|
-
* @param enResources
|
|
24
|
-
* English resources.
|
|
25
|
-
*
|
|
26
|
-
* @param lng
|
|
27
|
-
* Language.
|
|
28
|
-
*
|
|
29
|
-
* @param lngResources
|
|
30
|
-
* Language resources.
|
|
31
|
-
*
|
|
32
|
-
* @param parent
|
|
33
|
-
* Parent key name (set recursively).
|
|
34
|
-
*/
|
|
35
|
-
export function i18nAssertValidResources(enResources, lng, lngResources, parent) {
|
|
36
|
-
const enResourcesMap = new Map(Object.entries(enResources));
|
|
37
|
-
const lngResourcesMap = new Map(Object.entries(lngResources));
|
|
38
|
-
const isLocale = lng.includes("-");
|
|
39
|
-
for (const [enKey, enValue] of enResourcesMap) {
|
|
40
|
-
const lngValue = lngResourcesMap.get(enKey);
|
|
41
|
-
if (lngValue !== undefined) {
|
|
42
|
-
const enValueType = typeof enValue;
|
|
43
|
-
const lngValueType = typeof lngValue;
|
|
44
|
-
if (lngValueType !== enValueType) {
|
|
45
|
-
throw new Error(`Invalid value type ${lngValueType} for key ${parent === undefined ? "" : `${parent}.`}${enKey} in ${lng} resources`);
|
|
46
|
-
}
|
|
47
|
-
if (enValueType === "object") {
|
|
48
|
-
i18nAssertValidResources(enValue, lng, lngValue, `${parent === undefined ? "" : `${parent}.`}${enKey}`);
|
|
49
|
-
}
|
|
50
|
-
// Locale falls back to raw language so ignore if missing.
|
|
51
|
-
}
|
|
52
|
-
else if (!isLocale) {
|
|
53
|
-
throw new Error(`Missing key ${parent === undefined ? "" : `${parent}.`}${enKey} from ${lng} resources`);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
for (const [lngKey] of lngResourcesMap) {
|
|
57
|
-
if (!enResourcesMap.has(lngKey)) {
|
|
58
|
-
throw new Error(`Extraneous key ${parent === undefined ? "" : `${parent}.`}${lngKey} in ${lng} resources`);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Convert a string to lower case, skipping words that are all upper case.
|
|
64
|
-
*
|
|
65
|
-
* @param s
|
|
66
|
-
* String.
|
|
67
|
-
*
|
|
68
|
-
* @returns
|
|
69
|
-
* Lower case string.
|
|
70
|
-
*/
|
|
71
|
-
function toLowerCase(s) {
|
|
72
|
-
// Words with no lower case letters are preserved as they are likely mnemonics.
|
|
73
|
-
return s.split(" ").map(word => /[a-z]/.test(word) ? word.toLowerCase() : word).join(" ");
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Initialize internationalization.
|
|
77
|
-
*
|
|
78
|
-
* @param i18next
|
|
79
|
-
* Internationalization object. As multiple objects exists, this parameter represents the one for the module for which
|
|
80
|
-
* internationalization is being initialized.
|
|
81
|
-
*
|
|
82
|
-
* @param environment
|
|
83
|
-
* Environment in which the application is running.
|
|
84
|
-
*
|
|
85
|
-
* @param debug
|
|
86
|
-
* Debug setting.
|
|
87
|
-
*
|
|
88
|
-
* @param defaultNS
|
|
89
|
-
* Default namespace.
|
|
90
|
-
*
|
|
91
|
-
* @param resources
|
|
92
|
-
* Resources.
|
|
93
|
-
*
|
|
94
|
-
* @returns
|
|
95
|
-
* Void promise.
|
|
96
|
-
*/
|
|
97
|
-
export async function i18nCoreInit(i18next, environment, debug, defaultNS, ...resources) {
|
|
98
|
-
// Initialization may be called more than once.
|
|
99
|
-
if (!i18next.isInitialized) {
|
|
100
|
-
const mergedResource = {};
|
|
101
|
-
// Merge resources.
|
|
102
|
-
for (const resource of resources) {
|
|
103
|
-
// Merge languages.
|
|
104
|
-
for (const [language, resourceLanguage] of Object.entries(resource)) {
|
|
105
|
-
if (!(language in mergedResource)) {
|
|
106
|
-
mergedResource[language] = {};
|
|
107
|
-
}
|
|
108
|
-
const mergedResourceLanguage = mergedResource[language];
|
|
109
|
-
// Merge namespaces.
|
|
110
|
-
for (const [namespace, resourceKey] of Object.entries(resourceLanguage)) {
|
|
111
|
-
mergedResourceLanguage[namespace] = resourceKey;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
let module;
|
|
116
|
-
switch (environment) {
|
|
117
|
-
case I18nEnvironments.CLI:
|
|
118
|
-
// TODO Refactor when https://github.com/neet/i18next-cli-language-detector/issues/281 resolved.
|
|
119
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Per above.
|
|
120
|
-
module = I18nextCLILanguageDetector;
|
|
121
|
-
break;
|
|
122
|
-
case I18nEnvironments.Browser:
|
|
123
|
-
module = I18nextBrowserLanguageDetector;
|
|
124
|
-
break;
|
|
125
|
-
default:
|
|
126
|
-
throw new Error("Not supported");
|
|
127
|
-
}
|
|
128
|
-
await i18next.use(module).init({
|
|
129
|
-
debug,
|
|
130
|
-
resources: mergedResource,
|
|
131
|
-
fallbackLng: "en",
|
|
132
|
-
defaultNS
|
|
133
|
-
}).then(() => {
|
|
134
|
-
// Add toLowerCase function.
|
|
135
|
-
i18next.services.formatter?.add("toLowerCase", value => typeof value === "string" ? toLowerCase(value) : String(value));
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
//# sourceMappingURL=i18n.js.map
|
package/dist/locale/i18n.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"i18n.js","sourceRoot":"","sources":["../../src/locale/i18n.ts"],"names":[],"mappings":"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"}
|