@wener/common 2.0.2 → 2.0.3
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/lib/ai/qwen3vl/index.js +2 -0
- package/lib/ai/qwen3vl/index.js.map +1 -0
- package/lib/ai/qwen3vl/utils.js +31 -0
- package/lib/ai/qwen3vl/utils.js.map +1 -0
- package/lib/ai/vision/DocLayoutElementTypeSchema.js +28 -0
- package/lib/ai/vision/DocLayoutElementTypeSchema.js.map +1 -0
- package/lib/ai/vision/ImageAnnotationSchema.js +50 -0
- package/lib/ai/vision/ImageAnnotationSchema.js.map +1 -0
- package/lib/ai/vision/index.js +3 -0
- package/lib/ai/vision/index.js.map +1 -0
- package/lib/ai/vision/resolveImageAnnotation.js +105 -0
- package/lib/ai/vision/resolveImageAnnotation.js.map +1 -0
- package/lib/cn/ChineseResidentIdNo.js +21 -14
- package/lib/cn/ChineseResidentIdNo.js.map +1 -0
- package/lib/cn/ChineseResidentIdNo.test.js +1 -1
- package/lib/cn/DivisionCode.js +30 -25
- package/lib/cn/DivisionCode.js.map +1 -0
- package/lib/cn/DivisionCode.test.js +1 -1
- package/lib/cn/Mod11.js +38 -81
- package/lib/cn/Mod11.js.map +1 -0
- package/lib/cn/Mod31.js +41 -90
- package/lib/cn/Mod31.js.map +1 -0
- package/lib/cn/UnifiedSocialCreditCode.js +43 -34
- package/lib/cn/UnifiedSocialCreditCode.js.map +1 -0
- package/lib/cn/UnifiedSocialCreditCode.test.js +1 -1
- package/lib/cn/formatChineseAmount.js +77 -0
- package/lib/cn/formatChineseAmount.js.map +1 -0
- package/lib/cn/index.js +7 -1
- package/lib/cn/index.js.map +1 -0
- package/lib/cn/parseChineseNumber.js +94 -0
- package/lib/cn/parseChineseNumber.js.map +1 -0
- package/lib/cn/parseChineseNumber.test.js +278 -0
- package/lib/cn/pinyin/cartesianProduct.js +22 -0
- package/lib/cn/pinyin/cartesianProduct.js.map +1 -0
- package/lib/cn/pinyin/cartesianProduct.test.js +179 -0
- package/lib/cn/pinyin/data.json +23573 -0
- package/lib/cn/pinyin/loader.js +14 -0
- package/lib/cn/pinyin/loader.js.map +1 -0
- package/lib/cn/pinyin/preload.js +3 -0
- package/lib/cn/pinyin/preload.js.map +1 -0
- package/lib/cn/pinyin/toPinyin.test.js +167 -0
- package/lib/cn/pinyin/toPinyinPure.js +33 -0
- package/lib/cn/pinyin/toPinyinPure.js.map +1 -0
- package/lib/cn/pinyin/transform.js +14 -0
- package/lib/cn/pinyin/transform.js.map +1 -0
- package/lib/cn/types.d.js +2 -0
- package/lib/cn/types.d.js.map +1 -0
- package/lib/consola/createStandardConsolaReporter.js +6 -6
- package/lib/consola/createStandardConsolaReporter.js.map +1 -0
- package/lib/consola/formatLogObject.js +65 -145
- package/lib/consola/formatLogObject.js.map +1 -0
- package/lib/consola/formatLogObject.test.js +184 -0
- package/lib/consola/index.js +1 -0
- package/lib/consola/index.js.map +1 -0
- package/lib/data/formatSort.js +6 -5
- package/lib/data/formatSort.js.map +1 -0
- package/lib/data/index.js +1 -0
- package/lib/data/index.js.map +1 -0
- package/lib/data/maybeNumber.js +5 -7
- package/lib/data/maybeNumber.js.map +1 -0
- package/lib/data/parseSort.js +22 -28
- package/lib/data/parseSort.js.map +1 -0
- package/lib/data/resolvePagination.js +13 -17
- package/lib/data/resolvePagination.js.map +1 -0
- package/lib/data/types.d.js +2 -0
- package/lib/data/types.d.js.map +1 -0
- package/lib/dayjs/dayjs.js +21 -19
- package/lib/dayjs/dayjs.js.map +1 -0
- package/lib/dayjs/formatDuration.js +15 -14
- package/lib/dayjs/formatDuration.js.map +1 -0
- package/lib/dayjs/index.js +2 -0
- package/lib/dayjs/index.js.map +1 -0
- package/lib/dayjs/parseDuration.js +5 -8
- package/lib/dayjs/parseDuration.js.map +1 -0
- package/lib/dayjs/parseRelativeTime.js +90 -0
- package/lib/dayjs/parseRelativeTime.js.map +1 -0
- package/lib/dayjs/parseRelativeTime.test.js +247 -0
- package/lib/dayjs/resolveRelativeTime.js +158 -0
- package/lib/dayjs/resolveRelativeTime.js.map +1 -0
- package/lib/dayjs/resolveRelativeTime.test.js +310 -0
- package/lib/decimal/index.js +1 -0
- package/lib/decimal/index.js.map +1 -0
- package/lib/decimal/parseDecimal.js +3 -1
- package/lib/decimal/parseDecimal.js.map +1 -0
- package/lib/emittery/emitter.js +10 -0
- package/lib/emittery/emitter.js.map +1 -0
- package/lib/emittery/index.js +2 -0
- package/lib/emittery/index.js.map +1 -0
- package/lib/foundation/schema/SexType.js +5 -3
- package/lib/foundation/schema/SexType.js.map +1 -0
- package/lib/foundation/schema/index.js +1 -0
- package/lib/foundation/schema/index.js.map +1 -0
- package/lib/foundation/schema/parseSexType.js +1 -0
- package/lib/foundation/schema/parseSexType.js.map +1 -0
- package/lib/foundation/schema/types.js +4 -2
- package/lib/foundation/schema/types.js.map +1 -0
- package/lib/fs/FileSystemError.js +23 -0
- package/lib/fs/FileSystemError.js.map +1 -0
- package/lib/fs/IFileSystem.d.js +3 -0
- package/lib/fs/IFileSystem.d.js.map +1 -0
- package/lib/fs/MemoryFileSystem.test.js +188 -0
- package/lib/fs/createBrowserFileSystem.js +248 -0
- package/lib/fs/createBrowserFileSystem.js.map +1 -0
- package/lib/fs/createMemoryFileSystem.js +516 -0
- package/lib/fs/createMemoryFileSystem.js.map +1 -0
- package/lib/fs/createSandboxFileSystem.js +108 -0
- package/lib/fs/createSandboxFileSystem.js.map +1 -0
- package/lib/fs/createWebDavFileSystem.js +137 -0
- package/lib/fs/createWebDavFileSystem.js.map +1 -0
- package/lib/fs/findMimeType.js +17 -0
- package/lib/fs/findMimeType.js.map +1 -0
- package/lib/fs/index.js +8 -0
- package/lib/fs/index.js.map +1 -0
- package/lib/fs/orpc/FileSystemContract.js +93 -0
- package/lib/fs/orpc/FileSystemContract.js.map +1 -0
- package/lib/fs/orpc/createContractClientFileSystem.js +93 -0
- package/lib/fs/orpc/createContractClientFileSystem.js.map +1 -0
- package/lib/fs/orpc/index.js +3 -0
- package/lib/fs/orpc/index.js.map +1 -0
- package/lib/fs/orpc/server/createFileSystemContractImpl.js +63 -0
- package/lib/fs/orpc/server/createFileSystemContractImpl.js.map +1 -0
- package/lib/fs/orpc/server/index.js +2 -0
- package/lib/fs/orpc/server/index.js.map +1 -0
- package/lib/fs/s3/createS3MiniFileSystem.js +705 -0
- package/lib/fs/s3/createS3MiniFileSystem.js.map +1 -0
- package/lib/fs/s3/index.js +2 -0
- package/lib/fs/s3/index.js.map +1 -0
- package/lib/fs/s3/s3mini.test.js +584 -0
- package/lib/fs/scandir.js +59 -0
- package/lib/fs/scandir.js.map +1 -0
- package/lib/fs/server/createDatabaseFileSystem.js +750 -0
- package/lib/fs/server/createDatabaseFileSystem.js.map +1 -0
- package/lib/fs/server/createNodeFileSystem.js +401 -0
- package/lib/fs/server/createNodeFileSystem.js.map +1 -0
- package/lib/fs/server/dbfs.test.js +221 -0
- package/lib/fs/server/index.js +2 -0
- package/lib/fs/server/index.js.map +1 -0
- package/lib/fs/server/loadTestDatabase.js +127 -0
- package/lib/fs/server/loadTestDatabase.js.map +1 -0
- package/lib/fs/tests/runFileSystemTest.js +318 -0
- package/lib/fs/tests/runFileSystemTest.js.map +1 -0
- package/lib/fs/types.js +27 -0
- package/lib/fs/types.js.map +1 -0
- package/lib/fs/utils/getFileUrl.js +35 -0
- package/lib/fs/utils/getFileUrl.js.map +1 -0
- package/lib/fs/utils.js +22 -0
- package/lib/fs/utils.js.map +1 -0
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -0
- package/lib/jsonschema/JsonSchema.js +146 -172
- package/lib/jsonschema/JsonSchema.js.map +1 -0
- package/lib/jsonschema/forEachJsonSchema.js +44 -0
- package/lib/jsonschema/forEachJsonSchema.js.map +1 -0
- package/lib/jsonschema/index.js +2 -0
- package/lib/jsonschema/index.js.map +1 -0
- package/lib/jsonschema/types.d.js +2 -0
- package/lib/jsonschema/types.d.js.map +1 -0
- package/lib/meta/defineFileType.js +20 -103
- package/lib/meta/defineFileType.js.map +1 -0
- package/lib/meta/defineInit.js +31 -250
- package/lib/meta/defineInit.js.map +1 -0
- package/lib/meta/defineMetadata.js +24 -140
- package/lib/meta/defineMetadata.js.map +1 -0
- package/lib/meta/index.js +1 -0
- package/lib/meta/index.js.map +1 -0
- package/lib/orpc/createOpenApiContractClient.js +27 -0
- package/lib/orpc/createOpenApiContractClient.js.map +1 -0
- package/lib/orpc/createRpcContractClient.js +34 -0
- package/lib/orpc/createRpcContractClient.js.map +1 -0
- package/lib/orpc/index.js +3 -0
- package/lib/orpc/index.js.map +1 -0
- package/lib/orpc/resolveLinkPlugins.js +28 -0
- package/lib/orpc/resolveLinkPlugins.js.map +1 -0
- package/lib/password/PHC.js +63 -87
- package/lib/password/PHC.js.map +1 -0
- package/lib/password/PHC.test.js +11 -3
- package/lib/password/Password.js +29 -294
- package/lib/password/Password.js.map +1 -0
- package/lib/password/Password.test.js +35 -22
- package/lib/password/createArgon2PasswordAlgorithm.js +35 -191
- package/lib/password/createArgon2PasswordAlgorithm.js.map +1 -0
- package/lib/password/createBase64PasswordAlgorithm.js +8 -141
- package/lib/password/createBase64PasswordAlgorithm.js.map +1 -0
- package/lib/password/createBcryptPasswordAlgorithm.js +13 -168
- package/lib/password/createBcryptPasswordAlgorithm.js.map +1 -0
- package/lib/password/createPBKDF2PasswordAlgorithm.js +46 -228
- package/lib/password/createPBKDF2PasswordAlgorithm.js.map +1 -0
- package/lib/password/createScryptPasswordAlgorithm.js +55 -211
- package/lib/password/createScryptPasswordAlgorithm.js.map +1 -0
- package/lib/password/index.js +1 -0
- package/lib/password/index.js.map +1 -0
- package/lib/password/server/index.js +1 -0
- package/lib/password/server/index.js.map +1 -0
- package/lib/resource/Identifiable.js +2 -0
- package/lib/resource/Identifiable.js.map +1 -0
- package/lib/resource/ListQuery.js +21 -93
- package/lib/resource/ListQuery.js.map +1 -0
- package/lib/resource/getTitleOfResource.js +3 -5
- package/lib/resource/getTitleOfResource.js.map +1 -0
- package/lib/resource/index.js +1 -0
- package/lib/resource/index.js.map +1 -0
- package/lib/resource/schema/AnyResourceSchema.js +2 -1
- package/lib/resource/schema/AnyResourceSchema.js.map +1 -0
- package/lib/resource/schema/BaseResourceSchema.js +2 -1
- package/lib/resource/schema/BaseResourceSchema.js.map +1 -0
- package/lib/resource/schema/ResourceActionType.js +6 -4
- package/lib/resource/schema/ResourceActionType.js.map +1 -0
- package/lib/resource/schema/ResourceStatus.js +5 -3
- package/lib/resource/schema/ResourceStatus.js.map +1 -0
- package/lib/resource/schema/ResourceType.js +5 -3
- package/lib/resource/schema/ResourceType.js.map +1 -0
- package/lib/resource/schema/index.js +1 -0
- package/lib/resource/schema/index.js.map +1 -0
- package/lib/resource/schema/types.js +16 -20
- package/lib/resource/schema/types.js.map +1 -0
- package/lib/s3/formatS3Url.js +65 -0
- package/lib/s3/formatS3Url.js.map +1 -0
- package/lib/s3/formatS3Url.test.js +262 -0
- package/lib/s3/index.js +3 -0
- package/lib/s3/index.js.map +1 -0
- package/lib/s3/parseS3Url.js +65 -0
- package/lib/s3/parseS3Url.js.map +1 -0
- package/lib/s3/parseS3Url.test.js +270 -0
- package/lib/schema/SchemaRegistry.js +38 -38
- package/lib/schema/SchemaRegistry.js.map +1 -0
- package/lib/schema/TypeSchema.d.js +2 -0
- package/lib/schema/TypeSchema.d.js.map +1 -0
- package/lib/schema/createSchemaData.js +26 -125
- package/lib/schema/createSchemaData.js.map +1 -0
- package/lib/schema/findJsonSchemaByPath.js +13 -36
- package/lib/schema/findJsonSchemaByPath.js.map +1 -0
- package/lib/schema/formatZodError.js +140 -0
- package/lib/schema/formatZodError.js.map +1 -0
- package/lib/schema/formatZodError.test.js +196 -0
- package/lib/schema/getSchemaCache.js +5 -5
- package/lib/schema/getSchemaCache.js.map +1 -0
- package/lib/schema/getSchemaOptions.js +8 -11
- package/lib/schema/getSchemaOptions.js.map +1 -0
- package/lib/schema/index.js +2 -1
- package/lib/schema/index.js.map +1 -0
- package/lib/schema/toJsonSchema.js +47 -290
- package/lib/schema/toJsonSchema.js.map +1 -0
- package/lib/schema/validate.js +33 -45
- package/lib/schema/validate.js.map +1 -0
- package/lib/tools/generateSchema.js +39 -197
- package/lib/tools/generateSchema.js.map +1 -0
- package/lib/tools/renderJsonSchemaToMarkdownDoc.js +55 -143
- package/lib/tools/renderJsonSchemaToMarkdownDoc.js.map +1 -0
- package/lib/utils/buildBaseUrl.js +13 -0
- package/lib/utils/buildBaseUrl.js.map +1 -0
- package/lib/utils/buildRedactorFormSchema.js +59 -0
- package/lib/utils/buildRedactorFormSchema.js.map +1 -0
- package/lib/utils/getEstimateProcessTime.js +12 -11
- package/lib/utils/getEstimateProcessTime.js.map +1 -0
- package/lib/utils/index.js +3 -0
- package/lib/utils/index.js.map +1 -0
- package/lib/utils/resolveFeatureOptions.js +12 -0
- package/lib/utils/resolveFeatureOptions.js.map +1 -0
- package/package.json +61 -13
- package/src/ai/qwen3vl/index.ts +1 -0
- package/src/ai/qwen3vl/utils.ts +36 -0
- package/src/ai/vision/DocLayoutElementTypeSchema.ts +30 -0
- package/src/ai/vision/ImageAnnotationSchema.ts +60 -0
- package/src/ai/vision/index.ts +2 -0
- package/src/ai/vision/resolveImageAnnotation.ts +135 -0
- package/src/cn/ChineseResidentIdNo.test.ts +1 -1
- package/src/cn/ChineseResidentIdNo.ts +8 -0
- package/src/cn/DivisionCode.test.ts +1 -1
- package/src/cn/DivisionCode.ts +8 -0
- package/src/cn/UnifiedSocialCreditCode.test.ts +1 -1
- package/src/cn/UnifiedSocialCreditCode.ts +15 -0
- package/src/cn/__snapshots__/UnifiedSocialCreditCode.test.ts.snap +23 -0
- package/src/cn/formatChineseAmount.ts +61 -0
- package/src/cn/index.ts +7 -1
- package/src/cn/parseChineseNumber.test.ts +159 -0
- package/src/cn/parseChineseNumber.ts +97 -0
- package/src/cn/pinyin/cartesianProduct.test.ts +64 -0
- package/src/cn/pinyin/cartesianProduct.ts +24 -0
- package/src/cn/pinyin/data.json +23573 -0
- package/src/cn/pinyin/loader.ts +12 -0
- package/src/cn/pinyin/preload.ts +3 -0
- package/src/cn/pinyin/toPinyin.test.ts +12 -0
- package/src/cn/pinyin/toPinyinPure.ts +43 -0
- package/src/cn/pinyin/transform.ts +12 -0
- package/src/consola/formatLogObject.test.ts +27 -0
- package/src/consola/formatLogObject.ts +34 -6
- package/src/dayjs/dayjs.ts +18 -18
- package/src/dayjs/index.ts +3 -1
- package/src/dayjs/parseRelativeTime.test.ts +185 -0
- package/src/dayjs/parseRelativeTime.ts +115 -0
- package/src/dayjs/resolveRelativeTime.test.ts +357 -0
- package/src/dayjs/resolveRelativeTime.ts +167 -0
- package/src/emittery/emitter.ts +9 -0
- package/src/emittery/index.ts +1 -0
- package/src/fs/FileSystemError.ts +26 -0
- package/src/fs/IFileSystem.d.ts +102 -0
- package/src/fs/MemoryFileSystem.test.ts +37 -0
- package/src/fs/createBrowserFileSystem.ts +291 -0
- package/src/fs/createMemoryFileSystem.ts +604 -0
- package/src/fs/createSandboxFileSystem.ts +136 -0
- package/src/fs/createWebDavFileSystem.ts +172 -0
- package/src/fs/findMimeType.ts +23 -0
- package/src/fs/index.ts +8 -0
- package/src/fs/orpc/FileSystemContract.ts +92 -0
- package/src/fs/orpc/createContractClientFileSystem.ts +115 -0
- package/src/fs/orpc/index.ts +2 -0
- package/src/fs/orpc/server/createFileSystemContractImpl.ts +64 -0
- package/src/fs/orpc/server/index.ts +1 -0
- package/src/fs/s3/createS3MiniFileSystem.ts +830 -0
- package/src/fs/s3/index.ts +1 -0
- package/src/fs/s3/s3mini.test.ts +264 -0
- package/src/fs/scandir.ts +75 -0
- package/src/fs/server/createDatabaseFileSystem.ts +668 -0
- package/src/fs/server/createNodeFileSystem.ts +499 -0
- package/src/fs/server/dbfs.test.ts +47 -0
- package/src/fs/server/index.ts +1 -0
- package/src/fs/server/loadTestDatabase.ts +131 -0
- package/src/fs/tests/runFileSystemTest.ts +288 -0
- package/src/fs/types.ts +29 -0
- package/src/fs/utils/getFileUrl.ts +44 -0
- package/src/fs/utils.ts +23 -0
- package/src/jsonschema/JsonSchema.ts +118 -110
- package/src/jsonschema/forEachJsonSchema.ts +50 -0
- package/src/jsonschema/index.ts +1 -0
- package/src/orpc/createOpenApiContractClient.ts +52 -0
- package/src/orpc/createRpcContractClient.ts +50 -0
- package/src/orpc/index.ts +2 -0
- package/src/orpc/resolveLinkPlugins.ts +29 -0
- package/src/password/PHC.ts +3 -3
- package/src/password/Password.test.ts +1 -1
- package/src/password/createPBKDF2PasswordAlgorithm.ts +2 -2
- package/src/resource/schema/AnyResourceSchema.ts +16 -2
- package/src/s3/formatS3Url.test.ts +254 -0
- package/src/s3/formatS3Url.ts +84 -0
- package/src/s3/index.ts +2 -0
- package/src/s3/parseS3Url.test.ts +258 -0
- package/src/s3/parseS3Url.ts +88 -0
- package/src/schema/SchemaRegistry.ts +35 -33
- package/src/schema/formatZodError.test.ts +196 -0
- package/src/schema/formatZodError.ts +151 -0
- package/src/schema/getSchemaOptions.ts +2 -2
- package/src/schema/index.ts +1 -1
- package/src/utils/buildBaseUrl.ts +12 -0
- package/src/utils/buildRedactorFormSchema.ts +85 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/resolveFeatureOptions.ts +14 -0
- package/src/cn/ChineseResidentIdNo.mod.ts +0 -7
- package/src/cn/DivisionCode.mod.ts +0 -7
- package/src/cn/UnifiedSocialCreditCode.mod.ts +0 -7
- package/src/cn/mod.ts +0 -3
- package/src/schema/SchemaRegistry.mod.ts +0 -1
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { setCharToPinyinTable } from './toPinyinPure';
|
|
2
|
+
import { transformData } from './transform';
|
|
3
|
+
|
|
4
|
+
export function loadCharToPinyinTable(): Promise<Record<string, string[]>> {
|
|
5
|
+
return import('./data.json' as unknown as string, { with: { type: 'json' } })
|
|
6
|
+
.then((v) => v.default as Record<string, string[]>)
|
|
7
|
+
.then((data) => {
|
|
8
|
+
let out = transformData(data);
|
|
9
|
+
setCharToPinyinTable(out);
|
|
10
|
+
return out;
|
|
11
|
+
});
|
|
12
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { assert, test } from 'vitest';
|
|
2
|
+
import { loadCharToPinyinTable } from './loader';
|
|
3
|
+
import { toPinyinPure } from './toPinyinPure';
|
|
4
|
+
|
|
5
|
+
test('toPinyin', async () => {
|
|
6
|
+
await loadCharToPinyinTable();
|
|
7
|
+
assert.deepEqual(toPinyinPure('真思'), ['zhen,sai', 'zhen,si']);
|
|
8
|
+
|
|
9
|
+
// char to py -> 350k
|
|
10
|
+
// py to char -> 145k
|
|
11
|
+
// csv -> 96k
|
|
12
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { cartesianProduct } from './cartesianProduct';
|
|
2
|
+
|
|
3
|
+
let CharToPinyinTable: Record<string, string[]> | undefined;
|
|
4
|
+
|
|
5
|
+
export function setCharToPinyinTable(table: Record<string, string[]>) {
|
|
6
|
+
CharToPinyinTable = table;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function getCharToPinyinTable() {
|
|
10
|
+
if (!CharToPinyinTable) {
|
|
11
|
+
return {};
|
|
12
|
+
}
|
|
13
|
+
return CharToPinyinTable;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function toPinyinPureFirst(s: string, sep = ','): string {
|
|
17
|
+
let tab = getCharToPinyinTable();
|
|
18
|
+
return s
|
|
19
|
+
.split('')
|
|
20
|
+
.map((c) => tab[c]?.[0])
|
|
21
|
+
.filter(Boolean)
|
|
22
|
+
.join(sep);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function toPinyinPure(s: string, sep = ','): string[] {
|
|
26
|
+
let tab = getCharToPinyinTable();
|
|
27
|
+
// ensure order
|
|
28
|
+
return cartesianProduct(s.split('').map((c) => tab[c] || ''))
|
|
29
|
+
.sort((a, b) => {
|
|
30
|
+
for (let i = 0; i < a.length; i++) {
|
|
31
|
+
let x = a[i];
|
|
32
|
+
let y = b[i];
|
|
33
|
+
if (x < y) return -1;
|
|
34
|
+
if (x > y) return 1;
|
|
35
|
+
}
|
|
36
|
+
return 0;
|
|
37
|
+
})
|
|
38
|
+
.map((v) => v.filter(Boolean).join(sep));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// export function lookupPinyinPure(s: string): Array<Array<string>> {
|
|
42
|
+
// return cartesianProductOfArray(s.split('').map(c => Lookup[c]));
|
|
43
|
+
// }
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function transformData(input: Record<string, string[]>) {
|
|
2
|
+
let out = {} as Record<string, string[]>;
|
|
3
|
+
for (let [py, chars] of Object.entries(input)) {
|
|
4
|
+
for (let c of chars) {
|
|
5
|
+
if (!out[c]) {
|
|
6
|
+
out[c] = [];
|
|
7
|
+
}
|
|
8
|
+
out[c].push(py);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return out;
|
|
12
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import consola from 'consola';
|
|
2
|
+
import { Consola, type ConsolaInstance } from 'consola/core';
|
|
3
|
+
import { test } from 'vitest';
|
|
4
|
+
import { createStandardConsolaReporter } from './createStandardConsolaReporter';
|
|
5
|
+
|
|
6
|
+
test('formatLogObject', async () => {
|
|
7
|
+
const log: ConsolaInstance = new Consola({
|
|
8
|
+
reporters: [createStandardConsolaReporter({})],
|
|
9
|
+
}).create({
|
|
10
|
+
formatOptions: {
|
|
11
|
+
colors: true,
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
consola.warn({ name: 'wener' });
|
|
15
|
+
|
|
16
|
+
log.info({ name: 'wener' });
|
|
17
|
+
log.info('message', {
|
|
18
|
+
name: 'wener',
|
|
19
|
+
});
|
|
20
|
+
log.info('complex object', {
|
|
21
|
+
name: 'wener',
|
|
22
|
+
age: 30,
|
|
23
|
+
active: true,
|
|
24
|
+
tags: ['developer', 'typescript'],
|
|
25
|
+
meta: { level: 'senior', remote: true },
|
|
26
|
+
});
|
|
27
|
+
});
|
|
@@ -80,7 +80,7 @@ export function formatLogObject(
|
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
{
|
|
83
|
-
const [message, ...additional] = formatArgs(o.args,
|
|
83
|
+
const [message, ...additional] = formatArgs(o.args, { colors: shouldColor }).split('\n');
|
|
84
84
|
|
|
85
85
|
out.push(characterFormat(message));
|
|
86
86
|
|
|
@@ -159,16 +159,44 @@ function formatArgs(args: any[], opts: FormatOptions) {
|
|
|
159
159
|
|
|
160
160
|
// Only supported with Node >= 10
|
|
161
161
|
// https://nodejs.org/api/util.html#util_util_inspect_object_options
|
|
162
|
-
return formatWithOptions(opts, ..._args);
|
|
162
|
+
return formatWithOptions(Boolean(opts.colors), ..._args);
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
-
function formatWithOptions(
|
|
166
|
-
|
|
167
|
-
|
|
165
|
+
function formatWithOptions(shouldColor: boolean, ...params: any[]) {
|
|
166
|
+
return params.map((value) => formatValue(value, shouldColor)).join(' ');
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function formatValue(value: any, shouldColor: boolean = false): string {
|
|
170
|
+
const colors = shouldColor ? Colors : NoColors;
|
|
171
|
+
|
|
172
|
+
if (value === null) return 'null';
|
|
173
|
+
if (value === undefined) return 'undefined';
|
|
174
|
+
if (typeof value === 'string') return value;
|
|
175
|
+
if (typeof value === 'number' || typeof value === 'boolean') return String(value);
|
|
176
|
+
|
|
177
|
+
if (typeof value === 'object' && value.constructor === Object) {
|
|
178
|
+
const entries = Object.entries(value);
|
|
179
|
+
if (entries.length === 0) return '{}';
|
|
180
|
+
return entries
|
|
181
|
+
.map(([key, val]) => {
|
|
182
|
+
const keyStr = shouldColor ? colors.blue(key) : key;
|
|
183
|
+
const valStr = shouldColor ? colors.green(JSON.stringify(val)) : JSON.stringify(val);
|
|
184
|
+
return `${keyStr}=${valStr}`;
|
|
185
|
+
})
|
|
186
|
+
.join(' ');
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// For arrays and other objects, use JSON.stringify directly
|
|
190
|
+
try {
|
|
191
|
+
const result = JSON.stringify(value);
|
|
192
|
+
return shouldColor ? colors.green(result) : result;
|
|
193
|
+
} catch {
|
|
194
|
+
return String(value);
|
|
195
|
+
}
|
|
168
196
|
}
|
|
169
197
|
|
|
170
198
|
function formatError(err: any, opts: FormatOptions): string {
|
|
171
|
-
const message = err.message ?? formatWithOptions(opts, err);
|
|
199
|
+
const message = err.message ?? formatWithOptions(Boolean(opts.colors), err);
|
|
172
200
|
const stack = err.stack ? formatStack(err.stack, message, opts) : '';
|
|
173
201
|
|
|
174
202
|
const level = opts?.errorLevel || 0;
|
package/src/dayjs/dayjs.ts
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import dayjs from 'dayjs';
|
|
2
|
-
import advancedFormat from 'dayjs/plugin/advancedFormat';
|
|
3
|
-
import dayOfYear from 'dayjs/plugin/dayOfYear';
|
|
4
|
-
import duration from 'dayjs/plugin/duration';
|
|
5
|
-
import isBetween from 'dayjs/plugin/isBetween';
|
|
6
|
-
import isSameOrAfter from 'dayjs/plugin/isSameOrAfter';
|
|
7
|
-
import isSameOrBefore from 'dayjs/plugin/isSameOrBefore';
|
|
8
|
-
import isToday from 'dayjs/plugin/isToday';
|
|
9
|
-
import isTomorrow from 'dayjs/plugin/isTomorrow';
|
|
10
|
-
import isYesterday from 'dayjs/plugin/isYesterday';
|
|
11
|
-
import localeData from 'dayjs/plugin/localeData';
|
|
12
|
-
import objectSupport from 'dayjs/plugin/objectSupport';
|
|
13
|
-
import quarterOfYear from 'dayjs/plugin/quarterOfYear';
|
|
14
|
-
import relativeTime from 'dayjs/plugin/relativeTime';
|
|
15
|
-
import timezone from 'dayjs/plugin/timezone';
|
|
16
|
-
import toObject from 'dayjs/plugin/toObject';
|
|
17
|
-
import utc from 'dayjs/plugin/utc';
|
|
18
|
-
import 'dayjs/locale/zh-cn';
|
|
19
|
-
import 'dayjs/locale/zh';
|
|
2
|
+
import advancedFormat from 'dayjs/plugin/advancedFormat.js';
|
|
3
|
+
import dayOfYear from 'dayjs/plugin/dayOfYear.js';
|
|
4
|
+
import duration from 'dayjs/plugin/duration.js';
|
|
5
|
+
import isBetween from 'dayjs/plugin/isBetween.js';
|
|
6
|
+
import isSameOrAfter from 'dayjs/plugin/isSameOrAfter.js';
|
|
7
|
+
import isSameOrBefore from 'dayjs/plugin/isSameOrBefore.js';
|
|
8
|
+
import isToday from 'dayjs/plugin/isToday.js';
|
|
9
|
+
import isTomorrow from 'dayjs/plugin/isTomorrow.js';
|
|
10
|
+
import isYesterday from 'dayjs/plugin/isYesterday.js';
|
|
11
|
+
import localeData from 'dayjs/plugin/localeData.js';
|
|
12
|
+
import objectSupport from 'dayjs/plugin/objectSupport.js';
|
|
13
|
+
import quarterOfYear from 'dayjs/plugin/quarterOfYear.js';
|
|
14
|
+
import relativeTime from 'dayjs/plugin/relativeTime.js';
|
|
15
|
+
import timezone from 'dayjs/plugin/timezone.js';
|
|
16
|
+
import toObject from 'dayjs/plugin/toObject.js';
|
|
17
|
+
import utc from 'dayjs/plugin/utc.js';
|
|
18
|
+
import 'dayjs/locale/zh-cn.js';
|
|
19
|
+
import 'dayjs/locale/zh.js';
|
|
20
20
|
|
|
21
21
|
dayjs.extend(advancedFormat);
|
|
22
22
|
dayjs.extend(dayOfYear);
|
package/src/dayjs/index.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export { dayjs } from './dayjs';
|
|
2
|
-
export { parseDuration } from './parseDuration';
|
|
2
|
+
export { parseDuration, type MaybeDuration } from './parseDuration';
|
|
3
3
|
export { formatDuration } from './formatDuration';
|
|
4
|
+
|
|
5
|
+
export { resolveRelativeTime } from './resolveRelativeTime';
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import dayjs from 'dayjs';
|
|
2
|
+
import duration from 'dayjs/plugin/duration';
|
|
3
|
+
import { describe, expect, it } from 'vitest';
|
|
4
|
+
import { parseRelativeTime } from './parseRelativeTime';
|
|
5
|
+
|
|
6
|
+
dayjs.extend(duration);
|
|
7
|
+
|
|
8
|
+
describe('parseRelativeTime', () => {
|
|
9
|
+
it('should return empty array for "now"', () => {
|
|
10
|
+
const result = parseRelativeTime('now');
|
|
11
|
+
expect(result).toEqual([]);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('should parse simple addition operations', () => {
|
|
15
|
+
const result = parseRelativeTime('now+1h');
|
|
16
|
+
expect(result).toHaveLength(1);
|
|
17
|
+
expect(result[0]).toEqual({
|
|
18
|
+
operator: '+',
|
|
19
|
+
duration: dayjs.duration({ hours: 1 }),
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('should parse simple subtraction operations', () => {
|
|
24
|
+
const result = parseRelativeTime('now-30m');
|
|
25
|
+
expect(result).toHaveLength(1);
|
|
26
|
+
expect(result[0]).toEqual({
|
|
27
|
+
operator: '-',
|
|
28
|
+
duration: dayjs.duration({ minutes: 30 }),
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should parse milliseconds', () => {
|
|
33
|
+
const result = parseRelativeTime('now+500ms');
|
|
34
|
+
expect(result).toHaveLength(1);
|
|
35
|
+
expect(result[0]).toEqual({
|
|
36
|
+
operator: '+',
|
|
37
|
+
duration: dayjs.duration({ milliseconds: 500 }),
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('should parse complex duration combinations', () => {
|
|
42
|
+
const result = parseRelativeTime('now+1d6h30m');
|
|
43
|
+
expect(result).toHaveLength(1);
|
|
44
|
+
expect(result[0]).toEqual({
|
|
45
|
+
operator: '+',
|
|
46
|
+
duration: dayjs.duration({ days: 1, hours: 6, minutes: 30 }),
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should parse truncation operations', () => {
|
|
51
|
+
const result = parseRelativeTime('now/d');
|
|
52
|
+
expect(result).toHaveLength(1);
|
|
53
|
+
expect(result[0]).toEqual({
|
|
54
|
+
operator: '/',
|
|
55
|
+
unit: 'd',
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const result2 = parseRelativeTime('now\\M');
|
|
59
|
+
expect(result2).toHaveLength(1);
|
|
60
|
+
expect(result2[0]).toEqual({
|
|
61
|
+
operator: '\\',
|
|
62
|
+
unit: 'M',
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('should parse multiple operations', () => {
|
|
67
|
+
const result = parseRelativeTime('now-1h+30m');
|
|
68
|
+
expect(result).toHaveLength(2);
|
|
69
|
+
expect(result[0]).toEqual({
|
|
70
|
+
operator: '-',
|
|
71
|
+
duration: dayjs.duration({ hours: 1 }),
|
|
72
|
+
});
|
|
73
|
+
expect(result[1]).toEqual({
|
|
74
|
+
operator: '+',
|
|
75
|
+
duration: dayjs.duration({ minutes: 30 }),
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('should parse mixed arithmetic and truncation operations', () => {
|
|
80
|
+
const result = parseRelativeTime('now-1M/M');
|
|
81
|
+
expect(result).toHaveLength(2);
|
|
82
|
+
expect(result[0]).toEqual({
|
|
83
|
+
operator: '-',
|
|
84
|
+
duration: dayjs.duration({ months: 1 }),
|
|
85
|
+
});
|
|
86
|
+
expect(result[1]).toEqual({
|
|
87
|
+
operator: '/',
|
|
88
|
+
unit: 'M',
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('should handle all supported units', () => {
|
|
93
|
+
const units = ['ms', 's', 'm', 'h', 'd', 'w', 'M', 'Q', 'y'];
|
|
94
|
+
|
|
95
|
+
for (const unit of units) {
|
|
96
|
+
const result = parseRelativeTime(`now+1${unit}`);
|
|
97
|
+
expect(result).toHaveLength(1);
|
|
98
|
+
expect(result[0]).toEqual({
|
|
99
|
+
operator: '+',
|
|
100
|
+
duration: dayjs.duration({ [unit]: 1 }),
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('should handle complex multi-unit expressions', () => {
|
|
106
|
+
const result = parseRelativeTime('now+1y2M3w4d5h6m7s8ms');
|
|
107
|
+
expect(result).toHaveLength(1);
|
|
108
|
+
expect(result[0]).toEqual({
|
|
109
|
+
operator: '+',
|
|
110
|
+
duration: dayjs.duration({
|
|
111
|
+
years: 1,
|
|
112
|
+
months: 2,
|
|
113
|
+
weeks: 3,
|
|
114
|
+
days: 4,
|
|
115
|
+
hours: 5,
|
|
116
|
+
minutes: 6,
|
|
117
|
+
seconds: 7,
|
|
118
|
+
milliseconds: 8,
|
|
119
|
+
}),
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('should handle same unit multiple times (should sum)', () => {
|
|
124
|
+
const result = parseRelativeTime('now+1h2h3h');
|
|
125
|
+
expect(result).toHaveLength(1);
|
|
126
|
+
expect(result[0]).toEqual({
|
|
127
|
+
operator: '+',
|
|
128
|
+
duration: dayjs.duration({ hours: 6 }), // 1+2+3
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('should throw error for invalid format', () => {
|
|
133
|
+
expect(() => parseRelativeTime('invalid')).toThrow('Invalid relative time format');
|
|
134
|
+
expect(() => parseRelativeTime('now+')).toThrow('Invalid relative time format');
|
|
135
|
+
expect(() => parseRelativeTime('now+abc')).toThrow('Invalid duration specification');
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('should throw error for invalid units in truncation', () => {
|
|
139
|
+
expect(() => parseRelativeTime('now/invalid')).toThrow('Invalid unit');
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('should throw error for invalid units in duration', () => {
|
|
143
|
+
expect(() => parseRelativeTime('now+1invalid')).toThrow('Invalid unit');
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('should handle whitespace correctly', () => {
|
|
147
|
+
// The regex should handle operands without extra whitespace issues
|
|
148
|
+
const result = parseRelativeTime('now+1h30m');
|
|
149
|
+
expect(result).toHaveLength(1);
|
|
150
|
+
expect(result[0]).toEqual({
|
|
151
|
+
operator: '+',
|
|
152
|
+
duration: dayjs.duration({ hours: 1, minutes: 30 }),
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('should parse real-world examples', () => {
|
|
157
|
+
// Last 24 hours
|
|
158
|
+
const result1 = parseRelativeTime('now-24h');
|
|
159
|
+
expect(result1).toHaveLength(1);
|
|
160
|
+
expect(result1[0]).toEqual({
|
|
161
|
+
operator: '-',
|
|
162
|
+
duration: dayjs.duration({ hours: 24 }),
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
// Start of previous month
|
|
166
|
+
const result2 = parseRelativeTime('now-1M/M');
|
|
167
|
+
expect(result2).toHaveLength(2);
|
|
168
|
+
expect(result2[0]).toEqual({
|
|
169
|
+
operator: '-',
|
|
170
|
+
duration: dayjs.duration({ months: 1 }),
|
|
171
|
+
});
|
|
172
|
+
expect(result2[1]).toEqual({
|
|
173
|
+
operator: '/',
|
|
174
|
+
unit: 'M',
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// Complex time ago
|
|
178
|
+
const result3 = parseRelativeTime('now-1w2d3h');
|
|
179
|
+
expect(result3).toHaveLength(1);
|
|
180
|
+
expect(result3[0]).toEqual({
|
|
181
|
+
operator: '-',
|
|
182
|
+
duration: dayjs.duration({ weeks: 1, days: 2, hours: 3 }),
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
});
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import dayjs from 'dayjs';
|
|
2
|
+
import type { Duration } from 'dayjs/plugin/duration';
|
|
3
|
+
import { checkDurationUnit, RelativeDurationUnits, type RelativeDurationUnit } from './resolveRelativeTime';
|
|
4
|
+
|
|
5
|
+
export type TimeOperation =
|
|
6
|
+
| {
|
|
7
|
+
operator: '+' | '-';
|
|
8
|
+
duration: Duration;
|
|
9
|
+
}
|
|
10
|
+
| {
|
|
11
|
+
operator: '/' | '\\';
|
|
12
|
+
unit: RelativeDurationUnit;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Parses a relative time string and returns an array of operations.
|
|
17
|
+
*
|
|
18
|
+
* @param s - The relative time string to parse (must start with "now")
|
|
19
|
+
* @returns Array of operations that can be applied sequentially
|
|
20
|
+
* @throws {Error} When the format is invalid
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* parseRelativeTime('now-1h+30m') // [{ operator: '-', duration: dayjs.duration(1, 'h') }, { operator: '+', duration: dayjs.duration(30, 'm') }]
|
|
25
|
+
* parseRelativeTime('now+1d6h') // [{ operator: '+', duration: dayjs.duration({ days: 1, hours: 6 }) }]
|
|
26
|
+
* parseRelativeTime('now/d') // [{ operator: '/', unit: 'd' }]
|
|
27
|
+
* parseRelativeTime('now\\M') // [{ operator: '\\', unit: 'M' }]
|
|
28
|
+
* parseRelativeTime('now-1M/M') // [{ operator: '-', duration: dayjs.duration(1, 'M') }, { operator: '/', unit: 'M' }]
|
|
29
|
+
* parseRelativeTime('now+500ms') // [{ operator: '+', duration: dayjs.duration(500, 'ms') }]
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export function parseRelativeTime(s: string): TimeOperation[] {
|
|
33
|
+
if (typeof s !== 'string' || !s.startsWith('now')) {
|
|
34
|
+
throw new Error(`Invalid relative time format: ${s}`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const remaining = s.slice(3); // Remove 'now'
|
|
38
|
+
|
|
39
|
+
if (!remaining) {
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const operations: TimeOperation[] = [];
|
|
44
|
+
|
|
45
|
+
// Single regex to match all operations: <op><duration_spec> or <op><unit>
|
|
46
|
+
// Where duration_spec can be: 1h, 1d6h, 500ms, etc.
|
|
47
|
+
const operationRegex = /([+\-/\\])([^+\-/\\]+)/g;
|
|
48
|
+
let match: RegExpExecArray | null;
|
|
49
|
+
let lastIndex = 0;
|
|
50
|
+
|
|
51
|
+
while ((match = operationRegex.exec(remaining)) !== null) {
|
|
52
|
+
const [, operator, operand] = match;
|
|
53
|
+
|
|
54
|
+
if (operator === '/' || operator === '\\') {
|
|
55
|
+
// Truncation operation - single unit only
|
|
56
|
+
checkDurationUnit(operand.trim());
|
|
57
|
+
operations.push({
|
|
58
|
+
operator: operator as '/' | '\\',
|
|
59
|
+
unit: operand.trim() as RelativeDurationUnit,
|
|
60
|
+
});
|
|
61
|
+
} else {
|
|
62
|
+
// Addition or subtraction operation - parse complex duration
|
|
63
|
+
const parsedDuration = parseDurationSpec(operand.trim());
|
|
64
|
+
operations.push({
|
|
65
|
+
operator: operator as '+' | '-',
|
|
66
|
+
duration: parsedDuration,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
lastIndex = operationRegex.lastIndex;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Check if we parsed the entire remaining string
|
|
73
|
+
if (lastIndex < remaining.length) {
|
|
74
|
+
throw new Error(`Invalid relative time format: ${s}`);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return operations;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Parses a duration specification like "1h", "1d6h", "500ms" into a dayjs Duration.
|
|
82
|
+
* Supports multiple units in a single specification.
|
|
83
|
+
*/
|
|
84
|
+
function parseDurationSpec(spec: string): Duration {
|
|
85
|
+
// Match all number+unit pairs: 1d, 6h, 30m, 500ms, etc.
|
|
86
|
+
const durationRegex = /(\d+)(ms|[smhdwMQy])/g;
|
|
87
|
+
const durationObj: Record<string, number> = {};
|
|
88
|
+
let match: RegExpExecArray | null;
|
|
89
|
+
let hasMatch = false;
|
|
90
|
+
|
|
91
|
+
while ((match = durationRegex.exec(spec)) !== null) {
|
|
92
|
+
const [, amountStr, unit] = match;
|
|
93
|
+
checkDurationUnit(unit);
|
|
94
|
+
const amount = parseInt(amountStr, 10);
|
|
95
|
+
|
|
96
|
+
// Dayjs duration supports unit strings directly
|
|
97
|
+
durationObj[unit] = (durationObj[unit] || 0) + amount;
|
|
98
|
+
hasMatch = true;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (!hasMatch) {
|
|
102
|
+
// Check if there are invalid units by looking for number+invalid_unit patterns
|
|
103
|
+
const invalidUnitRegex = /\d+([a-zA-Z]+)/g;
|
|
104
|
+
let invalidMatch: RegExpExecArray | null;
|
|
105
|
+
while ((invalidMatch = invalidUnitRegex.exec(spec)) !== null) {
|
|
106
|
+
const [, unit] = invalidMatch;
|
|
107
|
+
if (!RelativeDurationUnits.includes(unit as RelativeDurationUnit)) {
|
|
108
|
+
throw new Error(`Invalid unit: ${unit}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
throw new Error(`Invalid duration specification: ${spec}`);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return dayjs.duration(durationObj);
|
|
115
|
+
}
|