@lacqjs/nuxt-dict 0.0.4 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/module.d.mts CHANGED
@@ -1,9 +1,10 @@
1
1
  import * as _nuxt_schema from '@nuxt/schema';
2
2
  import * as __runtime_types from '../dist/runtime/types/index.js';
3
3
  import { ModuleOptions } from '../dist/runtime/types/index.js';
4
- export { DictItem, DictTranslator, GetDictItemOptions, ModuleOptions, TranslateOptions, TranslatePathOptions, TreeNode } from '../dist/runtime/types/index.js';
4
+ export { DictAdapter, DictItem, DictTranslator, GetDictItemOptions, ModuleOptions, TranslateOptions, TranslatePathOptions, TreeNode } from '../dist/runtime/types/index.js';
5
5
  export { DictManager } from '../dist/runtime/core/dict-manager.js';
6
6
  export { createDictTranslator } from '../dist/runtime/utils/dict-translator.js';
7
+ export { defineDictAdapter } from '../dist/runtime/utils/define-adapter.js';
7
8
 
8
9
  /**
9
10
  * Nuxt Dict 模块入口。
package/dist/module.d.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  import * as _nuxt_schema from '@nuxt/schema';
2
2
  import * as __runtime_types from '../dist/runtime/types/index.js';
3
3
  import { ModuleOptions } from '../dist/runtime/types/index.js';
4
- export { DictItem, DictTranslator, GetDictItemOptions, ModuleOptions, TranslateOptions, TranslatePathOptions, TreeNode } from '../dist/runtime/types/index.js';
4
+ export { DictAdapter, DictItem, DictTranslator, GetDictItemOptions, ModuleOptions, TranslateOptions, TranslatePathOptions, TreeNode } from '../dist/runtime/types/index.js';
5
5
  export { DictManager } from '../dist/runtime/core/dict-manager.js';
6
6
  export { createDictTranslator } from '../dist/runtime/utils/dict-translator.js';
7
+ export { defineDictAdapter } from '../dist/runtime/utils/define-adapter.js';
7
8
 
8
9
  /**
9
10
  * Nuxt Dict 模块入口。
package/dist/module.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lacqjs/nuxt-dict",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "configKey": "dict",
5
5
  "compatibility": {
6
6
  "nuxt": "^4.4.8"
package/dist/module.mjs CHANGED
@@ -1,10 +1,13 @@
1
- import { defineNuxtModule, useLogger, createResolver, addPlugin, addImportsDir, addTypeTemplate } from '@nuxt/kit';
1
+ import { defineNuxtModule, useLogger, createResolver, addTemplate, addTypeTemplate, addPlugin, addImportsDir } from '@nuxt/kit';
2
+ import { existsSync } from 'node:fs';
3
+ import { resolve } from 'node:path';
2
4
  import { defaultOptions } from '../dist/runtime/options.js';
3
5
  import { createLogger } from '../dist/runtime/utils/logger.js';
4
6
  export { createDictTranslator } from '../dist/runtime/utils/dict-translator.js';
7
+ export { defineDictAdapter } from '../dist/runtime/utils/define-adapter.js';
5
8
 
6
9
  const name = "@lacqjs/nuxt-dict";
7
- const version = "0.0.4";
10
+ const version = "0.0.6";
8
11
  const devDependencies = {
9
12
  nuxt: "^4.4.8"};
10
13
  const pkg = {
@@ -160,6 +163,14 @@ declare module '#app' {
160
163
  }
161
164
  });
162
165
  }
166
+ function resolveAdapterPath(nuxt, explicitPath, conventionName) {
167
+ if (typeof explicitPath === "string") return explicitPath;
168
+ const base = resolve(nuxt.options.srcDir, "dict", conventionName);
169
+ for (const ext of [".ts", ".js", ".mjs"]) {
170
+ if (existsSync(base + ext)) return (base + ext).replaceAll("\\", "/");
171
+ }
172
+ return void 0;
173
+ }
163
174
  const module$1 = defineNuxtModule().with({
164
175
  meta: {
165
176
  name: pkg.name,
@@ -180,7 +191,71 @@ const module$1 = defineNuxtModule().with({
180
191
  return;
181
192
  }
182
193
  const resolver = createResolver(import.meta.url);
183
- _nuxt.options.runtimeConfig.public.dict = _options;
194
+ const globalAdapterPath = resolveAdapterPath(
195
+ _nuxt,
196
+ _options.api?.adapter,
197
+ "dict-adapter"
198
+ );
199
+ const storeAdapterPaths = {};
200
+ for (const [name, config] of Object.entries(_options.stores ?? {})) {
201
+ const adapterPath = resolveAdapterPath(
202
+ _nuxt,
203
+ config.adapter,
204
+ `${name}-adapter`
205
+ );
206
+ if (adapterPath) storeAdapterPaths[name] = adapterPath;
207
+ }
208
+ addTemplate({
209
+ filename: "nuxt-dict/adapters.ts",
210
+ getContents: () => {
211
+ let code = "";
212
+ if (globalAdapterPath) {
213
+ code += `export { default as globalAdapter } from '${globalAdapterPath}'
214
+ `;
215
+ } else {
216
+ code += "export const globalAdapter = undefined\n";
217
+ }
218
+ const entries = Object.entries(storeAdapterPaths);
219
+ if (entries.length > 0) {
220
+ code += entries.map(
221
+ ([name, p]) => `import adapter_${name.replaceAll(/\W/gu, "_")} from '${p}'`
222
+ ).join("\n") + "\n";
223
+ code += `export const storeAdapters = { ${entries.map(
224
+ ([name]) => `'${name}': adapter_${name.replaceAll(/\W/gu, "_")}`
225
+ ).join(", ")} }
226
+ `;
227
+ } else {
228
+ code += "export const storeAdapters = {} as Record<string, never>\n";
229
+ }
230
+ return code;
231
+ }
232
+ });
233
+ addTypeTemplate({
234
+ filename: "types/nuxt-dict-adapters.d.ts",
235
+ getContents: () => `
236
+ declare module '#build/nuxt-dict/adapters' {
237
+ import type { DictAdapter } from '@lacqjs/nuxt-dict'
238
+ export const globalAdapter: DictAdapter | undefined
239
+ export const storeAdapters: Record<string, DictAdapter>
240
+ }
241
+ `
242
+ });
243
+ if (_options.api?.adapter && typeof _options.api.adapter !== "string") {
244
+ logger.warn(
245
+ "dict.api.adapter \u4E0D\u652F\u6301\u5185\u8054\u51FD\u6570\uFF08\u65E0\u6CD5\u5E8F\u5217\u5316\u5230\u5BA2\u6237\u7AEF\uFF09\u3002\u8BF7\u6539\u7528\u6587\u4EF6\u8DEF\u5F84\u6216\u5C06\u6587\u4EF6\u653E\u5728\u7EA6\u5B9A\u4F4D\u7F6E ~/dict/dict-adapter.ts"
246
+ );
247
+ }
248
+ const { adapter: _globalAdapter, ...apiWithoutAdapter } = _options.api;
249
+ const sanitizedStores = {};
250
+ for (const [k, v] of Object.entries(_options.stores ?? {})) {
251
+ const { adapter: _storeAdapter, ...rest } = v;
252
+ sanitizedStores[k] = rest;
253
+ }
254
+ _nuxt.options.runtimeConfig.public.dict = {
255
+ ..._options,
256
+ api: apiWithoutAdapter,
257
+ stores: sanitizedStores
258
+ };
184
259
  _nuxt.options.build.transpile.push(resolver.resolve("./runtime"));
185
260
  addPlugin(resolver.resolve("./runtime/plugins/dict"));
186
261
  addImportsDir(resolver.resolve("./runtime/composables"));
@@ -1,4 +1,4 @@
1
- import { shallowRef, ref, watch, onMounted, onBeforeUnmount } from "vue";
1
+ import { shallowRef, ref, watch, onMounted, onBeforeUnmount, triggerRef } from "vue";
2
2
  import { useNuxtApp } from "#imports";
3
3
  import { DEFAULT_STORE_NAME } from "../core/cache/indexeddb-cache.js";
4
4
  const activeInstances = /* @__PURE__ */ new Map();
@@ -7,7 +7,12 @@ async function fetchDictData(manager, dictType, storeName, data, loading, error,
7
7
  error.value = null;
8
8
  try {
9
9
  const entry = await (mode === "refresh" ? manager.refresh(dictType, storeName) : manager.getDict(dictType, storeName));
10
- data.value = entry.items;
10
+ if (data.value) {
11
+ data.value.splice(0, data.value.length, ...entry.items);
12
+ triggerRef(data);
13
+ } else {
14
+ data.value = entry.items;
15
+ }
11
16
  if (itemMap) {
12
17
  itemMap.clear();
13
18
  for (const item of entry.items) {
@@ -1,4 +1,4 @@
1
- import { shallowRef, ref, watch, onMounted } from "vue";
1
+ import { shallowRef, ref, watch, onMounted, triggerRef } from "vue";
2
2
  import { useNuxtApp } from "#imports";
3
3
  import { DEFAULT_STORE_NAME } from "../core/cache/indexeddb-cache.js";
4
4
  export function useDictTree(storeOrType, maybeType) {
@@ -29,7 +29,13 @@ export function useDictTree(storeOrType, maybeType) {
29
29
  loading.value = true;
30
30
  try {
31
31
  const entry = await manager.getDict(dictType, storeName);
32
- tree.value = entry.tree ?? null;
32
+ const newTree = entry.tree ?? null;
33
+ if (tree.value && newTree) {
34
+ tree.value.splice(0, tree.value.length, ...newTree);
35
+ triggerRef(tree);
36
+ } else {
37
+ tree.value = newTree;
38
+ }
33
39
  if (entry.tree) buildMaps(entry.tree, nodeMap, pathMap);
34
40
  } finally {
35
41
  loading.value = false;
@@ -39,7 +45,13 @@ export function useDictTree(storeOrType, maybeType) {
39
45
  loading.value = true;
40
46
  try {
41
47
  const entry = await manager.refresh(dictType, storeName);
42
- tree.value = entry.tree ?? null;
48
+ const newTree = entry.tree ?? null;
49
+ if (tree.value && newTree) {
50
+ tree.value.splice(0, tree.value.length, ...newTree);
51
+ triggerRef(tree);
52
+ } else {
53
+ tree.value = newTree;
54
+ }
43
55
  if (entry.tree) buildMaps(entry.tree, nodeMap, pathMap);
44
56
  } finally {
45
57
  loading.value = false;
@@ -192,7 +192,7 @@ export class DictManager {
192
192
  const key = this.buildKey(type, storeName);
193
193
  const entry = this.memoryCache.get(key);
194
194
  if (!entry) return String(value);
195
- const item = entry.data.items.find((i) => this.codeMatch(i.value, value));
195
+ const item = entry.data?.items?.find((i) => this.codeMatch(i.value, value));
196
196
  if (!item) return String(value);
197
197
  return item[field] ?? item.label;
198
198
  }
@@ -1,5 +1,6 @@
1
1
  import { watch } from "vue";
2
2
  import { defineNuxtPlugin, useRequestEvent, useCookie, useRoute } from "#imports";
3
+ import { globalAdapter, storeAdapters } from "#build/nuxt-dict/adapters";
3
4
  import { createDefaultAdapter } from "../core/adapter.js";
4
5
  import { IndexedDBCache, DEFAULT_STORE_NAME } from "../core/cache/indexeddb-cache.js";
5
6
  import { DictManager } from "../core/dict-manager.js";
@@ -70,7 +71,7 @@ async function executePrefetch(manager, types, logger) {
70
71
  }
71
72
  function createAdapters(options, logger) {
72
73
  const adapters = /* @__PURE__ */ new Map();
73
- const defaultAdapter = options.api.adapter ?? createDefaultAdapter({
74
+ const defaultAdapter = globalAdapter ?? createDefaultAdapter({
74
75
  baseURL: resolveBaseURL(options.api.baseURL),
75
76
  dictEndpoint: options.api.dictEndpoint,
76
77
  versionEndpoint: options.api.versionEndpoint,
@@ -82,7 +83,7 @@ function createAdapters(options, logger) {
82
83
  `Dict adapter created for default store '${DEFAULT_STORE_NAME}': ${options.api.baseURL}${options.api.dictEndpoint}`
83
84
  );
84
85
  for (const [storeName, storeApi] of Object.entries(options.stores)) {
85
- const adapter = storeApi.adapter ?? createDefaultAdapter({
86
+ const adapter = storeAdapters[storeName] ?? createDefaultAdapter({
86
87
  baseURL: resolveBaseURL(storeApi.baseURL ?? options.api.baseURL),
87
88
  dictEndpoint: storeApi.dictEndpoint ?? options.api.dictEndpoint,
88
89
  versionEndpoint: storeApi.versionEndpoint ?? options.api.versionEndpoint,
@@ -90,7 +91,7 @@ function createAdapters(options, logger) {
90
91
  apiHeaderKey: options.locale.apiHeaderKey
91
92
  });
92
93
  adapters.set(storeName, adapter);
93
- const desc = storeApi.adapter ? "custom adapter" : `${storeApi.baseURL ?? options.api.baseURL}${storeApi.dictEndpoint ?? options.api.dictEndpoint}`;
94
+ const desc = storeAdapters[storeName] ? "custom adapter" : `${storeApi.baseURL ?? options.api.baseURL}${storeApi.dictEndpoint ?? options.api.dictEndpoint}`;
94
95
  logger.debug(`Dict adapter created for store '${storeName}': ${desc}`);
95
96
  }
96
97
  return adapters;
@@ -86,8 +86,8 @@ export interface StoreApiOptions {
86
86
  dictEndpoint?: string;
87
87
  /** 版本号接口路径,默认继承全局 `api.versionEndpoint` */
88
88
  versionEndpoint?: string;
89
- /** 自定义字典适配器,不传则使用默认 REST 适配器(继承全局 api 配置) */
90
- adapter?: DictAdapter;
89
+ /** 自定义字典适配器文件路径(如 '~/dict/dict-adapter'),不传则按约定路径自动发现或使用默认 REST 适配器 */
90
+ adapter?: string;
91
91
  }
92
92
  /** 模块配置项(用户可传,字段均可选) */
93
93
  export interface ModuleOptions {
@@ -102,8 +102,8 @@ export interface ModuleOptions {
102
102
  dictEndpoint?: string;
103
103
  /** 版本号接口路径,默认 `'/dict/version'` */
104
104
  versionEndpoint?: string;
105
- /** 自定义字典适配器,不传则使用默认 REST 适配器 */
106
- adapter?: DictAdapter;
105
+ /** 自定义字典适配器文件路径(如 '~/dict/dict-adapter'),不传则按约定路径自动发现或使用默认 REST 适配器 */
106
+ adapter?: string;
107
107
  };
108
108
  cache?: {
109
109
  /** 内存缓存最大条目数,默认 `200` */
@@ -155,7 +155,7 @@ export interface ResolvedModuleOptions {
155
155
  baseURL: string;
156
156
  dictEndpoint: string;
157
157
  versionEndpoint: string;
158
- adapter?: DictAdapter;
158
+ adapter?: string;
159
159
  };
160
160
  cache: {
161
161
  memoryMax: number;
@@ -0,0 +1,26 @@
1
+ import type { DictAdapter } from '../types/index.js';
2
+ /**
3
+ * 定义自定义字典适配器(类型辅助函数)。
4
+ *
5
+ * @description 提供完整的 TypeScript 类型推导,确保适配器实现符合 DictAdapter 接口。
6
+ * 运行时原样返回,不做任何处理。用于自定义适配器文件(如 ~/dict/dict-adapter.ts)中导出适配器。
7
+ *
8
+ * @param {DictAdapter} adapter - 适配器对象,需实现 fetchDict 和 fetchVersion 方法
9
+ * @returns {DictAdapter} 原样返回传入的适配器对象
10
+ *
11
+ * @example
12
+ * // ~/dict/dict-adapter.ts
13
+ * import { defineDictAdapter } from '@lacqjs/nuxt-dict'
14
+ *
15
+ * export default defineDictAdapter({
16
+ * async fetchDict(storeName, { types, locale }) {
17
+ * const res = await fetch(`/api/dict?types=${types.join(',')}&lang=${locale}`)
18
+ * return res.json()
19
+ * },
20
+ * async fetchVersion(storeName) {
21
+ * const res = await fetch('/api/dict/version')
22
+ * return (await res.json()).version
23
+ * },
24
+ * })
25
+ */
26
+ export declare function defineDictAdapter(adapter: DictAdapter): DictAdapter;
@@ -0,0 +1,3 @@
1
+ export function defineDictAdapter(adapter) {
2
+ return adapter;
3
+ }
package/dist/types.d.mts CHANGED
@@ -1,7 +1,9 @@
1
- export { type DictItem, type DictTranslator, type GetDictItemOptions, type ModuleOptions, type TranslateOptions, type TranslatePathOptions, type TreeNode } from '../dist/runtime/types/index.js'
1
+ export { type DictAdapter, type DictItem, type DictTranslator, type GetDictItemOptions, type ModuleOptions, type TranslateOptions, type TranslatePathOptions, type TreeNode } from '../dist/runtime/types/index.js'
2
2
 
3
3
  export { type DictManager } from '../dist/runtime/core/dict-manager.js'
4
4
 
5
5
  export { type createDictTranslator } from '../dist/runtime/utils/dict-translator.js'
6
6
 
7
+ export { type defineDictAdapter } from '../dist/runtime/utils/define-adapter.js'
8
+
7
9
  export { default } from './module.mjs'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lacqjs/nuxt-dict",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "description": "Nuxt 数据字典模块,提供扁平/树形字典翻译、多语言国际化、三级缓存与 SSR 预取。",
5
5
  "keywords": [
6
6
  "@lacqjs/nuxt-dict",
@@ -79,6 +79,7 @@
79
79
  "docs:cleanup": "pnpx rimraf docs/.nuxt docs/.output docs/dist docs/node_modules docs/.data",
80
80
  "playground:cleanup": "pnpx rimraf playground/.nuxt playground/.output playground/dist playground/node_modules",
81
81
  "demo:base-api:dev": "nuxi dev examples/demo-base-api",
82
+ "demo:base-adapter:dev": "nuxi dev examples/demo-base-adapter",
82
83
  "release": "pnpm lint && pnpm typecheck && pnpm prepack && changelogen --release && pnpm publish && git push origin dev --follow-tags",
83
84
  "release:major": "pnpm lint && pnpm typecheck && pnpm prepack && changelogen --release --major && pnpm publish && git push origin dev --follow-tags",
84
85
  "release:e2e": "pnpm lint && pnpm e2e && pnpm typecheck && pnpm prepack && changelogen --release && pnpm publish && git push origin dev --follow-tags",