ember-vite-hmr 1.5.4 → 1.6.0

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
@@ -7,7 +7,9 @@ this can hot reload
7
7
  - helpers
8
8
  - modifiers
9
9
  - components + templates, fcct components and its deps
10
- - routes/controllers/route-templates (although it refreshes the whole route and thus looses all state)
10
+ - routes/controllers/route-templates
11
+
12
+ this tries to keep the state of properties in components and controller
11
13
 
12
14
  it cannot hot reload local properties that turn out to be helpers/modifiers/components.
13
15
 
@@ -24,9 +26,7 @@ update your `vite.config.mjs` with
24
26
  ```js
25
27
  import { hmr } from 'ember-vite-hmr';
26
28
 
27
- plugins: [
28
- hmr()
29
- ]
29
+ plugins: [hmr()];
30
30
  ```
31
31
 
32
32
  update you `babel.config.cjs`
@@ -272,9 +272,12 @@ function hotReplaceAst(babel) {
272
272
  'default';
273
273
  const ast = (0, core_1.parse)(`
274
274
  (async () => {
275
- const c = await import('/ember-vite-hmr/virtual/component:${source}:${specifierName}.gjs');
275
+ const c = await import('/ember-vite-hmr/virtual/component:${source}:${specifierName}.gjs?timestamp=${Date.now()}');
276
276
  ${exports.hotAstProcessor.meta.importVar}.${imp} = c.default;
277
277
  })()
278
+ import.meta.hot.accept('/ember-vite-hmr/virtual/component:${source}:${specifierName}.gjs', (c) => {
279
+ ${exports.hotAstProcessor.meta.importVar}.${imp} = c['${specifierName}'];
280
+ });
278
281
  import.meta.hot.accept('${source}');
279
282
  `);
280
283
  const importVirtual = ast.program.body;
package/dist/lib/hmr.js CHANGED
@@ -15,7 +15,29 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.hmr = hmr;
16
16
  const path_1 = __importDefault(require("path"));
17
17
  const core_1 = require("@babel/core");
18
- const getHotComponent = (imp, specifier) => `
18
+ const fs_1 = require("fs");
19
+ function generateContent(yields) {
20
+ if (!yields.includes('default')) {
21
+ yields.push('default');
22
+ }
23
+ let all = yields.map((y) => `(has-block '${y}')`).join(' ');
24
+ let str = '';
25
+ for (const y of yields) {
26
+ str += `
27
+ <:${y} as |a b c d e f g h i j k l|>{{yield a b c d e f g h i j k l to='${y}'}}</:${y}>
28
+ `;
29
+ }
30
+ return `
31
+ {{#if (notAny ${all})}}
32
+ <this.curried @__hot__={{this.hot}} />
33
+ {{else}}
34
+ <this.curried @__hot__={{this.hot}} >
35
+ ${str}
36
+ </this.curried>
37
+ {{/if}}
38
+ `;
39
+ }
40
+ const getHotComponent = (imp, specifier, yields) => `
19
41
  import { ${specifier} as TargetComponent } from "${imp}";
20
42
  import Component from "@glimmer/component";
21
43
  import { tracked } from "@glimmer/tracking";
@@ -23,6 +45,10 @@ import { createComputeRef } from "@glimmer/reference";
23
45
  import { curry } from '@glimmer/runtime';
24
46
  import { CurriedTypes } from '@glimmer/vm';
25
47
 
48
+ function notAny(...yields) {
49
+ return !yields.some((y) => !!y);
50
+ }
51
+
26
52
  export default class HotComponent extends Component {
27
53
  @tracked curried;
28
54
  hot = {};
@@ -42,16 +68,50 @@ export default class HotComponent extends Component {
42
68
  }
43
69
  }
44
70
  <template>
45
- <this.curried @__hot__={{this.hot}}></this.curried>
71
+ ${generateContent(yields)}
46
72
  </template>
47
73
  }
48
74
  `;
75
+ const cachedYields = {};
76
+ function getYieldsFromFile(filename, noCache) {
77
+ if (cachedYields[filename] && !noCache) {
78
+ return cachedYields[filename];
79
+ }
80
+ const content = (0, fs_1.readFileSync)(filename).toString();
81
+ // very basic, todo: make this use AST
82
+ const matches = content.matchAll(/to=['"](\w+)['"]/g);
83
+ const yields = new Set([...matches].map((m) => m === null || m === void 0 ? void 0 : m[1]).filter((m) => !!m));
84
+ if (noCache) {
85
+ return {
86
+ yields,
87
+ modules: [],
88
+ };
89
+ }
90
+ cachedYields[filename] = {
91
+ yields,
92
+ modules: [],
93
+ };
94
+ return cachedYields[filename];
95
+ }
96
+ function difference(a, b) {
97
+ const diff = [];
98
+ for (const bElement of b) {
99
+ if (!a.has(bElement)) {
100
+ diff.push(bElement);
101
+ }
102
+ }
103
+ return diff;
104
+ }
49
105
  const virtualPrefix = '/ember-vite-hmr/virtual/component:';
50
106
  function hmr(enableViteHmrForModes = ['development']) {
51
107
  let conf;
108
+ let server;
52
109
  return {
53
110
  name: 'hmr-plugin',
54
111
  enforce: 'post',
112
+ configureServer(s) {
113
+ server = s;
114
+ },
55
115
  configResolved(config) {
56
116
  conf = config;
57
117
  process.env['EMBER_VITE_HMR_ENABLED'] = enableViteHmrForModes
@@ -77,12 +137,38 @@ function hmr(enableViteHmrForModes = ['development']) {
77
137
  }
78
138
  },
79
139
  load(id) {
80
- if (id.startsWith(virtualPrefix)) {
81
- const [imp, specifier] = id
82
- .slice(virtualPrefix.length, -'.gts'.length)
83
- .split(':');
84
- return getHotComponent(imp, specifier);
85
- }
140
+ return __awaiter(this, void 0, void 0, function* () {
141
+ if (cachedYields[id] &&
142
+ difference(cachedYields[id].yields, getYieldsFromFile(id, true).yields).length) {
143
+ for (const y of getYieldsFromFile(id, true).yields) {
144
+ cachedYields[id].yields.add(y);
145
+ }
146
+ const modules = cachedYields[id].modules;
147
+ delete cachedYields[id];
148
+ for (const module of modules) {
149
+ server.moduleGraph.onFileChange(module);
150
+ let m = server.moduleGraph.getModuleById(module);
151
+ if (m) {
152
+ yield server.reloadModule(m);
153
+ }
154
+ }
155
+ }
156
+ if (id.startsWith(virtualPrefix)) {
157
+ const [imp, specifier] = id
158
+ .split('?')[0]
159
+ .slice(virtualPrefix.length, -'.gts'.length)
160
+ .split(':');
161
+ let filename = imp;
162
+ if (filename.includes('__vpc__')) {
163
+ filename = filename.split('__vpc__')[0];
164
+ }
165
+ const resolved = yield this.resolve(filename, id);
166
+ const cached = getYieldsFromFile(resolved.id);
167
+ const yields = cached.yields;
168
+ cached.modules.push(id);
169
+ return getHotComponent(imp, specifier, [...yields].filter((y) => !!y));
170
+ }
171
+ });
86
172
  },
87
173
  transformIndexHtml(html) {
88
174
  if (process.env['EMBER_VITE_HMR_ENABLED'] !== 'true') {
@@ -113,21 +199,9 @@ function hmr(enableViteHmrForModes = ['development']) {
113
199
  transform(source, id) {
114
200
  return __awaiter(this, void 0, void 0, function* () {
115
201
  const resourcePath = id.replace(/\\/g, '/').split('?')[0];
116
- const supportedPaths = ['routers', 'controllers', 'routes', 'templates'];
117
- const supportedFileNames = [
118
- 'route.js',
119
- 'route.ts',
120
- 'route.gts',
121
- 'route.gjs',
122
- 'controller.js',
123
- 'controller.ts',
124
- ];
125
- if (resourcePath.includes('/-components/')) {
126
- return source;
127
- }
128
202
  let didReplaceSources = false;
129
203
  const name = require(`${process.cwd()}/package.json`).name;
130
- if (resourcePath.includes(`/assets/${name}.js`)) {
204
+ if (resourcePath.includes(`${name}/app/-embroider-entrypoint.js`)) {
131
205
  const result = [...source.matchAll(/import \* as [^ ]+ from (.*);/g)];
132
206
  source += result
133
207
  .map((r) => {
@@ -138,10 +212,10 @@ function hmr(enableViteHmrForModes = ['development']) {
138
212
  })
139
213
  .join('');
140
214
  }
141
- if (resourcePath.endsWith('.hbs') ||
142
- resourcePath.endsWith('.gjs') ||
143
- resourcePath.endsWith('.gts') ||
144
- resourcePath.includes(`/assets/${name}.js`)) {
215
+ if (resourcePath.includes('ember-vite-hmr/virtual/components')) {
216
+ return source;
217
+ }
218
+ if (!resourcePath.includes(`node_modules`)) {
145
219
  const resolveDep = (dep) => __awaiter(this, void 0, void 0, function* () {
146
220
  const resolved = yield this.resolve(dep, resourcePath, {});
147
221
  let id = resolved === null || resolved === void 0 ? void 0 : resolved.id;
@@ -167,7 +241,7 @@ function hmr(enableViteHmrForModes = ['development']) {
167
241
  return id;
168
242
  });
169
243
  const result = [
170
- ...source.matchAll(/import.meta.hot.accept\(\'([^']+)\'/g),
244
+ ...source.matchAll(/import.meta.hot.accept\(['"]([^'"]+)['"]/g),
171
245
  ];
172
246
  for (const resultElement of result) {
173
247
  const dep = resultElement[1];
@@ -178,8 +252,9 @@ function hmr(enableViteHmrForModes = ['development']) {
178
252
  continue;
179
253
  didReplaceSources = true;
180
254
  source = source.replace(`import.meta.hot.accept('${dep}'`, `import.meta.hot.accept('${id}'`);
255
+ source = source.replace(`import.meta.hot.accept("${dep}"`, `import.meta.hot.accept("${id}"`);
181
256
  }
182
- const importMatches = [...source.matchAll(/import\('([^']+)'/g)];
257
+ const importMatches = [...source.matchAll(/import\(['"]([^']+)['"]/g)];
183
258
  for (const resultElement of importMatches) {
184
259
  const dep = resultElement[1];
185
260
  if (!dep.startsWith(virtualPrefix)) {
@@ -195,6 +270,7 @@ function hmr(enableViteHmrForModes = ['development']) {
195
270
  continue;
196
271
  didReplaceSources = true;
197
272
  source = source.replace(`import('${virtualPrefix}${imp}`, `import('${virtualPrefix}${id}`);
273
+ source = source.replace(`import("${virtualPrefix}${imp}`, `import("${virtualPrefix}${id}`);
198
274
  }
199
275
  }
200
276
  if (didReplaceSources) {
@@ -224,6 +300,18 @@ function hmr(enableViteHmrForModes = ['development']) {
224
300
  ],
225
301
  }).code;
226
302
  }
303
+ const supportedPaths = ['routers', 'controllers', 'routes', 'templates'];
304
+ const supportedFileNames = [
305
+ 'route.js',
306
+ 'route.ts',
307
+ 'route.gts',
308
+ 'route.gjs',
309
+ 'controller.js',
310
+ 'controller.ts',
311
+ ];
312
+ if (resourcePath.includes('/-components/')) {
313
+ return source;
314
+ }
227
315
  if (!supportedPaths.some((s) => resourcePath.includes(`/${s}/`)) &&
228
316
  !supportedFileNames.some((s) => resourcePath.endsWith(s))) {
229
317
  return source;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ember-vite-hmr",
3
- "version": "1.5.4",
3
+ "version": "1.6.0",
4
4
  "keywords": [
5
5
  "ember-addon"
6
6
  ],