dsh-mnemon 0.5.2 → 0.5.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/README.md +63 -183
- package/README.zh-CN.md +66 -186
- package/SECURITY.md +6 -6
- package/lib/client.js +1578 -1273
- package/lib/extension-sdk.js +1 -9
- package/lib/index.js +399 -290
- package/lib/strategy-configuration-B_DsZRQG.js +90 -0
- package/lib/types/src/client/locales.d.ts +976 -900
- package/lib/types/src/host/config-values.d.ts +6 -6
- package/lib/types/src/host/config.d.ts +2 -4
- package/lib/types/src/host/protocol.d.ts +10 -1
- package/lib/types/src/sdk/strategy-configuration.d.ts +5 -0
- package/package.json +19 -18
- package/lib/storage-lock-Bqrhkyag.js +0 -20
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { n as deepFreeze, t as canonicalMemoryJson } from "./definitions-j0FLgE0-.js";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
//#region src/sdk/storage-lock.ts
|
|
4
|
+
const queues = /* @__PURE__ */ new Map();
|
|
5
|
+
/**
|
|
6
|
+
* Serialize in-process work on one local storage root, including work from
|
|
7
|
+
* independently loaded plugins. File locks still own cross-process safety.
|
|
8
|
+
* Callers must not acquire the same root recursively.
|
|
9
|
+
*/
|
|
10
|
+
function withMemoryStorageLock(directory, operation) {
|
|
11
|
+
const key = resolve(directory);
|
|
12
|
+
const result = (queues.get(key) ?? Promise.resolve()).then(operation);
|
|
13
|
+
const settled = result.then(() => {}, () => {});
|
|
14
|
+
queues.set(key, settled);
|
|
15
|
+
settled.then(() => {
|
|
16
|
+
if (queues.get(key) === settled) queues.delete(key);
|
|
17
|
+
});
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/sdk/strategy-configuration.ts
|
|
22
|
+
function defineMemoryStrategyConfiguration(value) {
|
|
23
|
+
return readMemoryStrategyConfiguration({
|
|
24
|
+
...value,
|
|
25
|
+
apiVersion: "dsh-mnemon/strategy-configuration/v1"
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
/** Host discovery also validates modules that do not use the author helper. */
|
|
29
|
+
function readMemoryStrategyConfiguration(value) {
|
|
30
|
+
const text = (input) => typeof input === "object" && input !== null && ["en", "zh-CN"].every((key) => {
|
|
31
|
+
const item = input[key];
|
|
32
|
+
return typeof item === "string" && item.trim() !== "" && item.length <= 4e3;
|
|
33
|
+
});
|
|
34
|
+
if (!value || value.apiVersion !== "dsh-mnemon/strategy-configuration/v1" || typeof value.create !== "function" || !["strategy", "strategy-extension"].includes(value.kind) || !/^[a-z][a-z0-9-]{0,127}$/u.test(value.typeId) || !Array.isArray(value.fields) || value.fields.length > 16 || value.fields.some((field) => !field || !/^[a-zA-Z][a-zA-Z0-9]{0,99}$/u.test(field.key) || ![
|
|
35
|
+
"number",
|
|
36
|
+
"text",
|
|
37
|
+
"textarea",
|
|
38
|
+
"string-list",
|
|
39
|
+
"source-list"
|
|
40
|
+
].includes(field.input) || !text(field.label) || field.description !== void 0 && !text(field.description) || [field.minimum, field.maximum].some((bound) => bound !== void 0 && (typeof bound !== "number" || !Number.isFinite(bound))) || field.sourceRoles !== void 0 && (!Array.isArray(field.sourceRoles) || field.sourceRoles.length > 32 || field.sourceRoles.some((role) => typeof role !== "string" || !role || role.length > 128))) || new Set(value.fields.map((field) => field.key)).size !== value.fields.length || !text(value.label) || !text(value.description)) throw new Error("Invalid plugin configuration descriptor");
|
|
41
|
+
const json = canonicalMemoryJson({
|
|
42
|
+
label: value.label,
|
|
43
|
+
description: value.description,
|
|
44
|
+
fields: value.fields
|
|
45
|
+
}, "Plugin editor metadata");
|
|
46
|
+
if (json.length > 65536) throw new Error("Plugin editor metadata exceeds 64 KiB");
|
|
47
|
+
const metadata = deepFreeze(JSON.parse(json));
|
|
48
|
+
const factory = value.create;
|
|
49
|
+
const definition = Object.freeze({
|
|
50
|
+
apiVersion: value.apiVersion,
|
|
51
|
+
kind: value.kind,
|
|
52
|
+
typeId: value.typeId,
|
|
53
|
+
...metadata,
|
|
54
|
+
create(input) {
|
|
55
|
+
const contribution = factory(memoryStrategyConfigurationValues(definition, input));
|
|
56
|
+
if (!contribution || !Array.isArray(contribution.strategies ?? []) || !Array.isArray(contribution.strategyExtensions ?? [])) throw new Error("Plugin factory must return a Strategy contribution");
|
|
57
|
+
const values = [...contribution.strategies ?? [], ...contribution.strategyExtensions ?? []];
|
|
58
|
+
if ((contribution.sources?.length ?? 0) !== 0 || values.length !== 1 || values[0]?.manifest?.typeId !== definition.typeId || values[0]?.manifest?.kind !== definition.kind || contribution.plugin !== void 0 && contribution.plugin.packageName !== values[0].manifest.packageName) throw new Error("Plugin factory does not match its declared contribution");
|
|
59
|
+
return contribution;
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
for (const field of definition.fields) if (field.defaultValue !== void 0) memoryStrategyConfigurationValues(definition, { [field.key]: field.defaultValue });
|
|
63
|
+
return definition;
|
|
64
|
+
}
|
|
65
|
+
/** Validate and copy supplied values without applying defaults or executing code. */
|
|
66
|
+
function memoryStrategyConfigurationValues(definition, input) {
|
|
67
|
+
const value = input ?? {};
|
|
68
|
+
if (typeof value !== "object" || Array.isArray(value)) throw new Error("Plugin configuration must be an object");
|
|
69
|
+
const json = JSON.stringify(value);
|
|
70
|
+
if (json.length > 65536) throw new Error("Plugin configuration exceeds 64 KiB");
|
|
71
|
+
const config = JSON.parse(json);
|
|
72
|
+
const fields = new Map(definition.fields.map((field) => [field.key, field]));
|
|
73
|
+
for (const [key, value] of Object.entries(config)) {
|
|
74
|
+
if ([
|
|
75
|
+
"__proto__",
|
|
76
|
+
"prototype",
|
|
77
|
+
"constructor"
|
|
78
|
+
].includes(key)) throw new Error("Unsafe plugin configuration key");
|
|
79
|
+
const field = fields.get(key);
|
|
80
|
+
if (!field) throw new Error(`Plugin field is not declared for management: ${key}`);
|
|
81
|
+
if (field.input === "number") {
|
|
82
|
+
if (typeof value !== "number" || !Number.isFinite(value) || !Number.isInteger(value) || field.minimum !== void 0 && value < field.minimum || field.maximum !== void 0 && value > field.maximum) throw new Error(`Invalid numeric plugin field: ${key}`);
|
|
83
|
+
} else if (field.input === "source-list" || field.input === "string-list") {
|
|
84
|
+
if (!Array.isArray(value) || value.length > 32 || value.some((item) => typeof item !== "string" || !item.trim() || item.length > 500) || new Set(value).size !== value.length) throw new Error(`Invalid plugin list: ${key}`);
|
|
85
|
+
} else if (typeof value !== "string" || value.length > (field.maximum ?? 4e3)) throw new Error(`Invalid plugin text: ${key}`);
|
|
86
|
+
}
|
|
87
|
+
return config;
|
|
88
|
+
}
|
|
89
|
+
//#endregion
|
|
90
|
+
export { withMemoryStorageLock as i, memoryStrategyConfigurationValues as n, readMemoryStrategyConfiguration as r, defineMemoryStrategyConfiguration as t };
|