@wuchale/vite-plugin 0.15.7 → 0.16.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/dist/index.d.ts CHANGED
@@ -9,6 +9,7 @@ type HotUpdateCtx = {
9
9
  invalidateModule: Function;
10
10
  };
11
11
  };
12
+ read: () => string | Promise<string>;
12
13
  timestamp: number;
13
14
  };
14
15
  declare class Wuchale {
@@ -25,7 +26,7 @@ declare class Wuchale {
25
26
  transform: {
26
27
  order: "pre";
27
28
  handler: (code: string, id: string, options?: {
28
- ssr?: boolean;
29
+ ssr?: boolean | undefined;
29
30
  }) => Promise<{
30
31
  code?: string;
31
32
  map?: any;
package/dist/index.js CHANGED
@@ -3,16 +3,16 @@ import { relative, resolve } from "node:path";
3
3
  import { platform } from "node:process";
4
4
  import { getConfig as getConfig, Logger, AdapterHandler } from "wuchale";
5
5
  const pluginName = 'wuchale';
6
+ const confUpdateName = 'confUpdate.json';
6
7
  class Wuchale {
7
8
  name = pluginName;
8
9
  #config;
9
10
  #projectRoot = '';
10
- #adapters = {};
11
- #adaptersByLoaderPath = {};
12
- #adaptersByCatalogPath = {};
11
+ #adapters = new Map();
12
+ #adaptersByConfUpdate = new Map();
13
+ #adaptersByCatalogPath = new Map();
13
14
  #granularLoadAdapters = [];
14
15
  #singleCompiledCatalogs = new Set();
15
- #locales = [];
16
16
  #log;
17
17
  #mode;
18
18
  #configPath;
@@ -24,23 +24,24 @@ class Wuchale {
24
24
  #init = async () => {
25
25
  this.#config = await getConfig(this.#configPath);
26
26
  this.#log = new Logger(this.#config.logLevel);
27
- this.#locales = [this.#config.sourceLocale, ...this.#config.otherLocales];
28
- if (Object.keys(this.#config.adapters).length === 0) {
27
+ const adaptersData = Object.entries(this.#config.adapters);
28
+ if (adaptersData.length === 0) {
29
29
  throw Error('At least one adapter is needed.');
30
30
  }
31
- const sharedState = {};
32
- for (const [key, adapter] of Object.entries(this.#config.adapters)) {
31
+ const sharedState = new Map();
32
+ const adaptersByLoaderPath = new Map();
33
+ for (const [key, adapter] of adaptersData) {
33
34
  const handler = new AdapterHandler(adapter, key, this.#config, this.#mode, this.#projectRoot, this.#log);
34
35
  await handler.init(sharedState);
35
36
  handler.onBeforeWritePO = () => {
36
37
  this.#lastSourceTriggeredPOWrite = performance.now();
37
38
  };
38
- this.#adapters[key] = handler;
39
+ this.#adapters.set(key, handler);
39
40
  if (adapter.granularLoad) {
40
41
  this.#granularLoadAdapters.push(handler);
41
42
  }
42
43
  else {
43
- for (const locale of this.#locales) {
44
+ for (const locale of this.#config.locales) {
44
45
  this.#singleCompiledCatalogs.add(resolve(handler.getCompiledFilePath(locale, null)));
45
46
  }
46
47
  }
@@ -50,8 +51,8 @@ class Wuchale {
50
51
  // seems vite does this for the importer field in the resolveId hook
51
52
  loaderPath = loaderPath.replaceAll('\\', '/');
52
53
  }
53
- if (loaderPath in this.#adaptersByLoaderPath) {
54
- const otherKey = this.#adaptersByLoaderPath[loaderPath].key;
54
+ if (adaptersByLoaderPath.has(loaderPath)) {
55
+ const otherKey = adaptersByLoaderPath.get(loaderPath)?.key;
55
56
  if (otherKey === key) {
56
57
  // same loader for both ssr and client, no problem
57
58
  continue;
@@ -62,12 +63,18 @@ class Wuchale {
62
63
  'Specify a different loaderPath for one of them.'
63
64
  ].join('\n'));
64
65
  }
65
- this.#adaptersByLoaderPath[loaderPath] = handler;
66
+ adaptersByLoaderPath.set(loaderPath, handler);
66
67
  }
67
68
  for (const fname of Object.keys(handler.catalogPathsToLocales)) {
68
- this.#adaptersByCatalogPath[fname] ??= [];
69
- this.#adaptersByCatalogPath[fname].push(handler);
69
+ const handlers = this.#adaptersByCatalogPath.get(fname);
70
+ if (handlers) {
71
+ handlers.push(handler);
72
+ }
73
+ else {
74
+ this.#adaptersByCatalogPath.set(fname, [handler]);
75
+ }
70
76
  }
77
+ this.#adaptersByConfUpdate.set(resolve(adapter.localesDir, confUpdateName), handler);
71
78
  }
72
79
  };
73
80
  configResolved = async (config) => {
@@ -81,11 +88,18 @@ class Wuchale {
81
88
  await this.#init();
82
89
  };
83
90
  handleHotUpdate = async (ctx) => {
91
+ if (this.#adaptersByConfUpdate.has(ctx.file)) {
92
+ const update = JSON.parse(await ctx.read());
93
+ console.log(`${pluginName}: config update received:`, update);
94
+ this.#config.hmr = update.hmr;
95
+ return [];
96
+ }
84
97
  if (!this.#config.hmr) {
85
98
  return;
86
99
  }
87
100
  // This is mainly to make sure that PO catalog changes result in a page reload with new catalogs
88
- if (!(ctx.file in this.#adaptersByCatalogPath)) {
101
+ const adapters = this.#adaptersByCatalogPath.get(ctx.file);
102
+ if (adapters == null) {
89
103
  // prevent reloading whole app because of a change in compiled catalog
90
104
  // triggered by extraction from single file, hmr handled by embedding patch
91
105
  if (this.#singleCompiledCatalogs.has(ctx.file)) {
@@ -93,7 +107,7 @@ class Wuchale {
93
107
  }
94
108
  // for granular as well
95
109
  for (const adapter of this.#granularLoadAdapters) {
96
- for (const loc of this.#locales) {
110
+ for (const loc of this.#config.locales) {
97
111
  for (const id in adapter.granularStateByID) {
98
112
  if (resolve(adapter.getCompiledFilePath(loc, id)) === ctx.file) {
99
113
  return [];
@@ -107,7 +121,7 @@ class Wuchale {
107
121
  // catalog changed
108
122
  const sourceTriggered = performance.now() - this.#lastSourceTriggeredPOWrite < 1000; // long enough threshold
109
123
  const invalidatedModules = new Set();
110
- for (const adapter of this.#adaptersByCatalogPath[ctx.file]) {
124
+ for (const adapter of adapters) {
111
125
  const loc = adapter.catalogPathsToLocales[ctx.file];
112
126
  if (!sourceTriggered) {
113
127
  await adapter.loadCatalogNCompile(loc, this.#hmrVersion);
@@ -128,8 +142,16 @@ class Wuchale {
128
142
  if (this.#mode === 'dev' && !this.#config.hmr) {
129
143
  return {};
130
144
  }
131
- const filename = relative(this.#projectRoot, id);
132
- for (const adapter of Object.values(this.#adapters)) {
145
+ let filename = relative(this.#projectRoot, id);
146
+ const queryIndex = filename.indexOf('?');
147
+ if (queryIndex >= 0) {
148
+ const query = new URLSearchParams(filename.slice(queryIndex));
149
+ if (query.size === 1 && query.has('v')) {
150
+ // trim after this, like ?v=b65b2c3b when it's from node_modules
151
+ filename = filename.slice(0, queryIndex);
152
+ }
153
+ }
154
+ for (const adapter of this.#adapters.values()) {
133
155
  if (adapter.fileMatches(filename)) {
134
156
  return await adapter.transform(code, filename, this.#hmrVersion, options?.ssr);
135
157
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wuchale/vite-plugin",
3
- "version": "0.15.7",
3
+ "version": "0.16.1",
4
4
  "description": "Protobuf-like i18n from plain code: Vite plugin",
5
5
  "scripts": {
6
6
  "dev": "tsc --watch",
@@ -40,7 +40,7 @@
40
40
  "author": "K1DV5",
41
41
  "license": "MIT",
42
42
  "dependencies": {
43
- "wuchale": "^0.18.11"
43
+ "wuchale": "^0.19.0"
44
44
  },
45
45
  "devDependencies": {
46
46
  "typescript": "^5.9.3"