@morehao/dsh-plugin-kit 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,10 +4,12 @@ DeepSeek Harness(dsh)插件共用的工具包。当前提供这些能力:
4
4
 
5
5
  - **插件自更新引擎**(`./update`):查 npm 最新版 → 判断能不能一键更新 → 经宿主 `pluginManager` 重装自己。
6
6
  - **headless 客户端控制器**(`./update/client`):检查/更新的状态机与单飞,UI 由各插件自己渲染。
7
- - **HTTP 小工具**(`./http`):自定义头鉴权、`no-store` JSON、有上限的 JSON body。
7
+ - **HTTP 小工具**(`./http`):自定义头鉴权、`no-store` JSON、有上限的 JSON body,以及薄路由 dispatcher(`createRouteHandler`)。
8
8
  - **子进程执行**(`./exec`):argv 直传(不经 shell)、环境白名单、超时/取消、输出上限,外加 `pnpm view` 版本解析。
9
9
  - **原子写**(`./fs`):`writeFileAtomicSync` / `writeFileAtomic`,杜绝「半个文件」。
10
10
  - **JSON 状态持久化**(`./state`):`$DSH_HOME` 解析 + `<home>/<plugin>/*.json` 读写(读 fail-open、写抛错)。
11
+ - **GitHub 工具**(`./github`):仓库地址规范化 + Release 正文读取(带 TTL 缓存)。
12
+ - **插件身份**(`./meta`):从自家 `package.json` 读 name / version / repository。
11
13
 
12
14
  设计约束:**零 `@deepseek-ai/*` 运行时依赖**,宿主能力(`pluginManager` / `profileContext`)全部由调用方注入。进程策略由调用方把握:`./update` 常驻能力不主动 spawn,需要 `pnpm view` 时由调用方注入 `runPnpmView`;也可直接用 `./exec`(或 `createPnpmViewRunner`,默认走 `./exec`、可注入 `exec` 替换进程策略)。
13
15
 
@@ -110,11 +112,23 @@ await controller.apply();
110
112
  ## HTTP 小工具
111
113
 
112
114
  ```ts
113
- import { hasHeader, readJsonBody, sendJson } from '@morehao/dsh-plugin-kit/http';
115
+ import { hasHeader, readJsonBody, sendJson, createRouteHandler } from '@morehao/dsh-plugin-kit/http';
114
116
 
115
117
  if (!hasHeader(request, 'x-my-plugin')) return sendJson(response, 403, { ok: false, code: 'FORBIDDEN' });
116
118
  const body = await readJsonBody(request, { maxBytes: 512 * 1024 });
117
119
  sendJson(response, 200, { ok: true });
120
+
121
+ // 薄路由 dispatcher:统一 鉴权 → 剥前缀 → 读 body → 包 {ok:true} → 错误兜底。
122
+ // 不做路由表 DSL / 错误码翻译——matchRoute 与错误码映射留在你的 dispatch / onError 里。
123
+ const handler = createRouteHandler({
124
+ prefix: '/api/morehao/my-plugin',
125
+ header: 'x-dsh-my-plugin',
126
+ dispatch: async ({ method, pathname, body }) => {
127
+ if (method === 'GET' && pathname === '/state') return { state: getState() };
128
+ throw Object.assign(new Error('not found'), { code: 'NOT_FOUND' });
129
+ },
130
+ onError: (error) => ({ status: error.code === 'NOT_FOUND' ? 404 : 500, code: error.code, message: error.message }),
131
+ });
118
132
  ```
119
133
 
120
134
  ## 子进程执行(`./exec`)
@@ -181,15 +195,48 @@ const updater = createPluginUpdater({ meta, getPluginManager: () => ctx.get('plu
181
195
 
182
196
  拿不到 `profile.dir` / 命令失败 / 输出非法 / 版本不是合法 semver → 返回 `null`(交由 registry 兜底)。
183
197
 
198
+ ## GitHub 工具(`./github`)
199
+
200
+ 仓库地址规范化 + Release 正文读取(收敛各插件重复的正则与拉取逻辑):
201
+
202
+ ```ts
203
+ import { normalizeRepositoryUrl, repoSlug, createReleaseReader } from '@morehao/dsh-plugin-kit/github';
204
+
205
+ normalizeRepositoryUrl('git@github.com:o/r.git'); // → 'https://github.com/o/r'
206
+ repoSlug('https://github.com/o/r'); // → 'o/r'
207
+
208
+ const reader = createReleaseReader({ repo: 'o/r' }); // ttlMs / failureTtlMs / timeoutMs / fetchImpl 可注入
209
+ const info = await reader.release('1.2.3'); // { version, body, htmlUrl, name } | null
210
+ // 拉 https://api.github.com/repos/o/r/releases/tags/v1.2.3;成功与失败都做 TTL 缓存,失败 → null(不抛)
211
+ ```
212
+
213
+ 本模块只依赖 `./semver`,**不 import 任何 node 内置**。
214
+
215
+ ## 插件身份(`./meta`)
216
+
217
+ 从自家 `package.json` 读出 name / version / repository(收敛三仓的 `PLUGIN_META` / `readPluginInfo`):
218
+
219
+ ```ts
220
+ import { createPluginMeta, readInstalledVersion } from '@morehao/dsh-plugin-kit/meta';
221
+
222
+ const pkgUrl = new URL('../package.json', import.meta.url); // 层级由插件自己给
223
+ const meta = createPluginMeta({ pkgUrl, defaultName: '@you/plugin' });
224
+ // { name, version, repository?: 'https://github.com/o/r', repo: 'o/r' | null }
225
+
226
+ readInstalledVersion({ pkgUrl }); // 每次重读(更新后同进程读到新值);失败 → ''
227
+ ```
228
+
229
+ 只在 host 侧使用(含 `node:fs`),不被 `./update/client` 引用。
230
+
184
231
  ## 版本与兼容
185
232
 
186
233
  - Node `^22.20.0 || >=24.0.0`,纯 ESM。
187
- - `./update`、`./http`、`./exec`、`./fs`、`./state` 走 host 侧;`./update/client` 只含状态机,不 import node 内置模块(客户端产物只允许 react)。
234
+ - `./update`、`./http`、`./exec`、`./fs`、`./state`、`./github`、`./meta` 走 host 侧;`./update/client` 只含状态机,不 import node 内置模块(客户端产物只允许 react)。
188
235
  - 宿主服务形状按结构化类型处理(`PluginManagerLike` / `ProfileLike`),宿主版本变化不会把插件一起拖下去。
189
236
 
190
237
  ## 开发
191
238
 
192
239
  ```bash
193
240
  npm install
194
- npm run check # typecheck + build + 49 条离线测试(假 fetch / 假 pluginManager / 假 exec,不联网、不真装)
241
+ npm run check # typecheck + build + 67 条离线测试(假 fetch / 假 pluginManager / 假 exec,不联网、不真装)
195
242
  ```
@@ -0,0 +1,32 @@
1
+ /**
2
+ * `git+https://github.com/o/r.git` / `git@github.com:o/r.git` / `https://github.com/o/r`
3
+ * → `https://github.com/o/r`。非 GitHub / 解析失败 → undefined。
4
+ */
5
+ declare function normalizeRepositoryUrl(value: unknown): string | undefined;
6
+ /** 从仓库地址(或 `owner/repo` 短名)取 `owner/repo`;拿不到返回 null。 */
7
+ declare function repoSlug(value: unknown): string | null;
8
+ interface ReleaseInfo {
9
+ version: string;
10
+ body: string;
11
+ htmlUrl: string | null;
12
+ name: string | null;
13
+ }
14
+ interface ReleaseReaderDeps {
15
+ /** `owner/repo`。 */
16
+ repo: string;
17
+ fetchImpl?: typeof fetch;
18
+ /** 成功缓存 TTL;默认 10 分钟。 */
19
+ ttlMs?: number;
20
+ /** 失败短缓存 TTL;默认 = ttlMs(与既有实现一致,失败也缓存 10 分钟)。 */
21
+ failureTtlMs?: number;
22
+ /** 单次请求超时;默认 8s。 */
23
+ timeoutMs?: number;
24
+ now?: () => number;
25
+ }
26
+ interface ReleaseReader {
27
+ /** 拉某版本 Release 正文;无 repo / 网络 / 404 / 超时 / 非法版本 → null(不抛)。 */
28
+ release(version: string): Promise<ReleaseInfo | null>;
29
+ }
30
+ declare function createReleaseReader(deps: ReleaseReaderDeps): ReleaseReader;
31
+
32
+ export { type ReleaseInfo, type ReleaseReader, type ReleaseReaderDeps, createReleaseReader, normalizeRepositoryUrl, repoSlug };
package/dist/github.js ADDED
@@ -0,0 +1,90 @@
1
+ // src/semver.ts
2
+ import semver from "semver";
3
+ function parseSemver(value) {
4
+ const text = String(value ?? "").trim();
5
+ if (text === "") return void 0;
6
+ const parsed = semver.parse(text);
7
+ if (parsed === null) return void 0;
8
+ return {
9
+ core: [parsed.major, parsed.minor, parsed.patch],
10
+ // semver 会把纯数字预发布段解析为 number,这里统一转回字符串以保持旧契约。
11
+ prerelease: parsed.prerelease.map((part) => String(part))
12
+ };
13
+ }
14
+
15
+ // src/github.ts
16
+ var GITHUB_HOST = "github.com";
17
+ var DEFAULT_TIMEOUT_MS = 8e3;
18
+ var DEFAULT_TTL_MS = 10 * 60 * 1e3;
19
+ function normalizeRepositoryUrl(value) {
20
+ if (typeof value !== "string") return void 0;
21
+ let url = value.trim();
22
+ if (url === "") return void 0;
23
+ url = url.replace(/^git\+/i, "");
24
+ const ssh = /^git@github\.com:([^/]+)\/(.+?)(?:\.git)?$/i.exec(url);
25
+ if (ssh !== null) url = `https://github.com/${ssh[1]}/${ssh[2]}`;
26
+ url = url.replace(/\.git$/i, "");
27
+ try {
28
+ const parsed = new URL(url);
29
+ if (parsed.protocol !== "https:" && parsed.protocol !== "http:") return void 0;
30
+ if (parsed.hostname.toLowerCase() !== GITHUB_HOST) return void 0;
31
+ const pathname = parsed.pathname.replace(/\/+$/, "");
32
+ if (pathname === "") return void 0;
33
+ return `https://github.com${pathname}`;
34
+ } catch {
35
+ return void 0;
36
+ }
37
+ }
38
+ function repoSlug(value) {
39
+ if (typeof value !== "string") return null;
40
+ const text = value.trim();
41
+ if (text === "") return null;
42
+ if (/^[\w.-]+\/[\w.-]+$/.test(text)) return text;
43
+ const normalized = normalizeRepositoryUrl(text);
44
+ if (normalized === void 0) return null;
45
+ const pathname = normalized.slice(`https://github.com/`.length);
46
+ return pathname === "" ? null : pathname;
47
+ }
48
+ function createReleaseReader(deps) {
49
+ const fetchImpl = deps.fetchImpl ?? globalThis.fetch;
50
+ const ttlMs = deps.ttlMs ?? DEFAULT_TTL_MS;
51
+ const failureTtlMs = deps.failureTtlMs ?? ttlMs;
52
+ const timeoutMs = deps.timeoutMs ?? DEFAULT_TIMEOUT_MS;
53
+ const now = deps.now ?? Date.now;
54
+ const repo = deps.repo.trim();
55
+ const cache = /* @__PURE__ */ new Map();
56
+ async function release(version) {
57
+ const target = String(version ?? "").trim();
58
+ if (repo === "" || parseSemver(target) === void 0) return null;
59
+ const cached = cache.get(target);
60
+ if (cached !== void 0 && now() < cached.expiresAt) return cached.value;
61
+ const tag = `v${target.replace(/^v/, "")}`;
62
+ try {
63
+ const response = await fetchImpl(`https://api.github.com/repos/${repo}/releases/tags/${tag}`, {
64
+ headers: { accept: "application/vnd.github+json" },
65
+ redirect: "error",
66
+ signal: AbortSignal.timeout(timeoutMs)
67
+ });
68
+ const value = response.ok ? await response.json().then((raw) => {
69
+ const release2 = raw ?? {};
70
+ return {
71
+ version: target,
72
+ body: typeof release2.body === "string" ? release2.body : "",
73
+ htmlUrl: typeof release2.html_url === "string" ? release2.html_url : null,
74
+ name: typeof release2.name === "string" ? release2.name : null
75
+ };
76
+ }) : null;
77
+ cache.set(target, { value, expiresAt: now() + ttlMs });
78
+ return value;
79
+ } catch {
80
+ cache.set(target, { value: null, expiresAt: now() + failureTtlMs });
81
+ return null;
82
+ }
83
+ }
84
+ return { release };
85
+ }
86
+ export {
87
+ createReleaseReader,
88
+ normalizeRepositoryUrl,
89
+ repoSlug
90
+ };
package/dist/http.d.ts CHANGED
@@ -24,5 +24,38 @@ interface ReadJsonOptions {
24
24
  }
25
25
  /** 读一个 JSON 对象 body;超过上限抛 PAYLOAD_TOO_LARGE,非对象/非法 JSON 抛 INVALID_JSON。 */
26
26
  declare function readJsonBody(request: AsyncIterable<Uint8Array | string>, options?: ReadJsonOptions): Promise<Record<string, unknown>>;
27
+ interface RouteContext {
28
+ request: RequestLike & AsyncIterable<Uint8Array | string>;
29
+ url: URL;
30
+ /** 大写方法名。 */
31
+ method: string;
32
+ /** 已剥掉 prefix 的 pathname(`/state` 之类)。 */
33
+ pathname: string;
34
+ /** 已解析的 JSON body(超出上限/非法会先抛 HttpError);无 body 时空对象。 */
35
+ body: Record<string, unknown>;
36
+ }
37
+ /** 把插件自己的错误(IpcError / ServiceError …)映射成 HTTP 响应;返回 undefined 走默认 500。 */
38
+ type RouteErrorMapper = (error: unknown) => {
39
+ status: number;
40
+ code?: string;
41
+ message: string;
42
+ extra?: Record<string, unknown>;
43
+ } | undefined;
44
+ interface CreateRouteHandlerOptions {
45
+ /** 路由前缀,如 `/api/morehao/xxx`。 */
46
+ prefix: string;
47
+ /** 鉴权头名;要求值 `1`(跨源预检顺带挡 CSRF)。 */
48
+ header: string;
49
+ /** 业务 dispatch:返回结果对象(包成 `{ok:true,...}`)或自行写完响应(返回 void)。 */
50
+ dispatch: (ctx: RouteContext) => Promise<Record<string, unknown> | void>;
51
+ /** body 上限;默认 512 KiB。 */
52
+ maxBodyBytes?: number;
53
+ /** 错误映射;缺省 500 INTERNAL。 */
54
+ onError?: RouteErrorMapper;
55
+ logger?: (event: string, data?: Record<string, unknown>) => void;
56
+ }
57
+ type RouteHandler = (request: unknown, response: unknown) => Promise<void>;
58
+ /** 造一个宿主的 request 处理器:统一鉴权 / body / 响应 / 错误兜底。 */
59
+ declare function createRouteHandler(options: CreateRouteHandlerOptions): RouteHandler;
27
60
 
28
- export { HttpError, type HttpErrorCode, type ReadJsonOptions, type RequestLike, type ResponseLike, hasHeader, readJsonBody, sendJson };
61
+ export { type CreateRouteHandlerOptions, HttpError, type HttpErrorCode, type ReadJsonOptions, type RequestLike, type ResponseLike, type RouteContext, type RouteErrorMapper, type RouteHandler, createRouteHandler, hasHeader, readJsonBody, sendJson };
package/dist/http.js CHANGED
@@ -43,8 +43,48 @@ async function readJsonBody(request, options = {}) {
43
43
  }
44
44
  return value;
45
45
  }
46
+ function createRouteHandler(options) {
47
+ const maxBodyBytes = options.maxBodyBytes ?? 512 * 1024;
48
+ const logger = options.logger ?? (() => {
49
+ });
50
+ const prefix = options.prefix;
51
+ return async (rawRequest, rawResponse) => {
52
+ const request = rawRequest;
53
+ const response = rawResponse;
54
+ if (!hasHeader(request, options.header)) {
55
+ sendJson(response, 403, { ok: false, code: "FORBIDDEN", message: `\u7F3A\u5C11 ${options.header}: 1 \u5934` });
56
+ return;
57
+ }
58
+ const url = new URL(request.url ?? "/", "http://127.0.0.1");
59
+ const pathname = url.pathname.startsWith(prefix) ? url.pathname.slice(prefix.length) || "/" : url.pathname;
60
+ const method = (request.method ?? "GET").toUpperCase();
61
+ try {
62
+ const body = method === "GET" || method === "HEAD" ? {} : await readJsonBody(request, { maxBytes: maxBodyBytes });
63
+ const result = await options.dispatch({ request, url, method, pathname, body });
64
+ if (response.writableEnded !== true) {
65
+ sendJson(response, 200, result === void 0 ? { ok: true } : { ok: true, ...result });
66
+ }
67
+ } catch (error) {
68
+ if (response.writableEnded === true) return;
69
+ const mapped = options.onError?.(error);
70
+ if (mapped !== void 0) {
71
+ sendJson(response, mapped.status, {
72
+ ok: false,
73
+ ...mapped.code === void 0 ? {} : { code: mapped.code },
74
+ message: mapped.message,
75
+ ...mapped.extra === void 0 ? {} : mapped.extra
76
+ });
77
+ return;
78
+ }
79
+ const message = error instanceof Error ? error.message : String(error);
80
+ logger("route.error", { method, pathname, message });
81
+ sendJson(response, 500, { ok: false, code: "INTERNAL", message });
82
+ }
83
+ };
84
+ }
46
85
  export {
47
86
  HttpError,
87
+ createRouteHandler,
48
88
  hasHeader,
49
89
  readJsonBody,
50
90
  sendJson
package/dist/meta.d.ts ADDED
@@ -0,0 +1,28 @@
1
+ interface PluginMetaInfo {
2
+ name: string;
3
+ version: string;
4
+ /** 规范化后的 `https://github.com/owner/repo`;解析不了则缺省。 */
5
+ repository?: string;
6
+ /** `owner/repo` 短名;解析不了为 null。 */
7
+ repo: string | null;
8
+ }
9
+ interface ReadFileSyncLike {
10
+ (path: string | URL): string;
11
+ }
12
+ interface CreatePluginMetaOptions {
13
+ /** `new URL('../package.json', import.meta.url)` 这类导入地址。 */
14
+ pkgUrl: URL | string;
15
+ defaultName?: string;
16
+ /** 注入读文件(测试/奇特环境);默认 `node:fs` readFileSync。 */
17
+ readFileSync?: ReadFileSyncLike;
18
+ }
19
+ /** 读一次 package.json,产出插件身份;读失败用 defaultName + `0.0.0` 兜底。 */
20
+ declare function createPluginMeta(options: CreatePluginMetaOptions): PluginMetaInfo;
21
+ interface ReadInstalledVersionOptions {
22
+ pkgUrl: URL | string;
23
+ readFileSync?: ReadFileSyncLike;
24
+ }
25
+ /** 每次重读 package.json 的 version(更新插件后同进程能读到新值);失败 → ''。 */
26
+ declare function readInstalledVersion(options: ReadInstalledVersionOptions): string;
27
+
28
+ export { type CreatePluginMetaOptions, type PluginMetaInfo, type ReadFileSyncLike, type ReadInstalledVersionOptions, createPluginMeta, readInstalledVersion };
package/dist/meta.js ADDED
@@ -0,0 +1,82 @@
1
+ // src/meta.ts
2
+ import { readFileSync as fsReadFileSync } from "fs";
3
+
4
+ // src/semver.ts
5
+ import semver from "semver";
6
+
7
+ // src/github.ts
8
+ var GITHUB_HOST = "github.com";
9
+ var DEFAULT_TTL_MS = 10 * 60 * 1e3;
10
+ function normalizeRepositoryUrl(value) {
11
+ if (typeof value !== "string") return void 0;
12
+ let url = value.trim();
13
+ if (url === "") return void 0;
14
+ url = url.replace(/^git\+/i, "");
15
+ const ssh = /^git@github\.com:([^/]+)\/(.+?)(?:\.git)?$/i.exec(url);
16
+ if (ssh !== null) url = `https://github.com/${ssh[1]}/${ssh[2]}`;
17
+ url = url.replace(/\.git$/i, "");
18
+ try {
19
+ const parsed = new URL(url);
20
+ if (parsed.protocol !== "https:" && parsed.protocol !== "http:") return void 0;
21
+ if (parsed.hostname.toLowerCase() !== GITHUB_HOST) return void 0;
22
+ const pathname = parsed.pathname.replace(/\/+$/, "");
23
+ if (pathname === "") return void 0;
24
+ return `https://github.com${pathname}`;
25
+ } catch {
26
+ return void 0;
27
+ }
28
+ }
29
+ function repoSlug(value) {
30
+ if (typeof value !== "string") return null;
31
+ const text = value.trim();
32
+ if (text === "") return null;
33
+ if (/^[\w.-]+\/[\w.-]+$/.test(text)) return text;
34
+ const normalized = normalizeRepositoryUrl(text);
35
+ if (normalized === void 0) return null;
36
+ const pathname = normalized.slice(`https://github.com/`.length);
37
+ return pathname === "" ? null : pathname;
38
+ }
39
+
40
+ // src/meta.ts
41
+ function defaultReadFileSync(path) {
42
+ return fsReadFileSync(path, "utf8");
43
+ }
44
+ function createPluginMeta(options) {
45
+ const readFileSync = options.readFileSync ?? defaultReadFileSync;
46
+ const fallbackName = options.defaultName ?? "";
47
+ try {
48
+ const parsed = JSON.parse(readFileSync(options.pkgUrl));
49
+ if (parsed === null || typeof parsed !== "object") {
50
+ return { name: fallbackName, version: "0.0.0", repo: null };
51
+ }
52
+ const pkg = parsed;
53
+ const rawRepo = typeof pkg.repository === "string" ? pkg.repository : pkg.repository !== null && typeof pkg.repository === "object" ? pkg.repository.url : void 0;
54
+ const repository = normalizeRepositoryUrl(rawRepo);
55
+ const repo = repoSlug(repository);
56
+ return {
57
+ name: typeof pkg.name === "string" && pkg.name !== "" ? pkg.name : fallbackName,
58
+ version: typeof pkg.version === "string" && pkg.version !== "" ? pkg.version : "0.0.0",
59
+ ...repository === void 0 ? {} : { repository },
60
+ repo
61
+ };
62
+ } catch {
63
+ return { name: fallbackName, version: "0.0.0", repo: null };
64
+ }
65
+ }
66
+ function readInstalledVersion(options) {
67
+ const readFileSync = options.readFileSync ?? defaultReadFileSync;
68
+ try {
69
+ const parsed = JSON.parse(readFileSync(options.pkgUrl));
70
+ if (parsed !== null && typeof parsed === "object") {
71
+ const version = parsed.version;
72
+ if (typeof version === "string") return version.trim();
73
+ }
74
+ return "";
75
+ } catch {
76
+ return "";
77
+ }
78
+ }
79
+ export {
80
+ createPluginMeta,
81
+ readInstalledVersion
82
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@morehao/dsh-plugin-kit",
3
- "version": "0.3.0",
4
- "description": "DeepSeek Harness 插件共用工具包:插件自更新引擎(查 npm 最新版 + 经宿主 pluginManager 重装)、headless 客户端控制器、HTTP 小工具,以及子进程执行 / 原子写 / JSON 状态持久化等通用底座。零 @deepseek-ai 运行时依赖,宿主能力全部注入。",
3
+ "version": "0.3.1",
4
+ "description": "DeepSeek Harness 插件共用工具包:插件自更新引擎、headless 客户端控制器、HTTP 小工具与路由 dispatcher、子进程执行、原子写、JSON 状态持久化,以及 GitHub Release 读取与插件身份元数据等通用底座。零 @deepseek-ai 运行时依赖,宿主能力全部注入。",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -34,6 +34,14 @@
34
34
  "types": "./dist/state.d.ts",
35
35
  "default": "./dist/state.js"
36
36
  },
37
+ "./github": {
38
+ "types": "./dist/github.d.ts",
39
+ "default": "./dist/github.js"
40
+ },
41
+ "./meta": {
42
+ "types": "./dist/meta.d.ts",
43
+ "default": "./dist/meta.js"
44
+ },
37
45
  "./package.json": "./package.json"
38
46
  },
39
47
  "files": [