tungsten 0.3.1 → 0.3.2
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/Components.d.ts +2 -1
- package/dist/Components.d.ts.map +1 -1
- package/dist/Components.js +10 -1
- package/dist/DomRegion.js +1 -1
- package/dist/FrameworkConfig.d.ts +4 -0
- package/dist/FrameworkConfig.d.ts.map +1 -1
- package/dist/FunctionComponentStandIn.d.ts +2 -0
- package/dist/FunctionComponentStandIn.d.ts.map +1 -1
- package/dist/FunctionComponentStandIn.js +10 -1
- package/dist/FunctionComponentStandIn.sxyt.d.ts +2 -0
- package/dist/FunctionComponentStandIn.sxyt.d.ts.map +1 -0
- package/dist/FunctionComponentStandIn.sxyt.js +52 -0
- package/dist/Servers/DevServer.d.ts +2 -0
- package/dist/Servers/DevServer.d.ts.map +1 -1
- package/dist/Servers/DevServer.js +32 -5
- package/dist/Servers/devErrorPageAutoRetry.d.ts +4 -0
- package/dist/Servers/devErrorPageAutoRetry.d.ts.map +1 -0
- package/dist/Servers/devErrorPageAutoRetry.js +26 -0
- package/dist/Servers/devErrorPageAutoRetry.sxyt.d.ts +2 -0
- package/dist/Servers/devErrorPageAutoRetry.sxyt.d.ts.map +1 -0
- package/dist/Servers/devErrorPageAutoRetry.sxyt.js +117 -0
- package/dist/api/getExport.d.ts.map +1 -1
- package/dist/api/getExport.js +2 -1
- package/dist/babelPlugins/BabelAddDevCacheBust.d.ts +11 -0
- package/dist/babelPlugins/BabelAddDevCacheBust.d.ts.map +1 -0
- package/dist/babelPlugins/BabelAddDevCacheBust.js +68 -0
- package/dist/babelPlugins/BabelAddDevCacheBust.sxyt.d.ts +2 -0
- package/dist/babelPlugins/BabelAddDevCacheBust.sxyt.d.ts.map +1 -0
- package/dist/babelPlugins/BabelAddDevCacheBust.sxyt.js +138 -0
- package/dist/bin/commands/dev.d.ts.map +1 -1
- package/dist/bin/commands/dev.js +2 -0
- package/dist/build/compileUserApp.js +2 -2
- package/dist/build/makeBabelUserDevConfig.d.ts.map +1 -1
- package/dist/build/makeBabelUserDevConfig.js +6 -1
- package/dist/defaultConfig.d.ts +2 -0
- package/dist/defaultConfig.d.ts.map +1 -1
- package/dist/defaultConfig.js +3 -1
- package/dist/env/getEnvSchemas.d.ts.map +1 -1
- package/dist/env/getEnvSchemas.js +2 -1
- package/dist/getComponent.d.ts.map +1 -1
- package/dist/getComponent.js +2 -1
- package/dist/getRoutes.d.ts.map +1 -1
- package/dist/getRoutes.js +2 -1
- package/dist/hmr/applyHmrModule.d.ts +11 -0
- package/dist/hmr/applyHmrModule.d.ts.map +1 -0
- package/dist/hmr/applyHmrModule.js +78 -0
- package/dist/hmr/applyHmrModule.sxyt.d.ts +2 -0
- package/dist/hmr/applyHmrModule.sxyt.d.ts.map +1 -0
- package/dist/hmr/applyHmrModule.sxyt.js +182 -0
- package/dist/hmr/componentIdentity.d.ts +9 -0
- package/dist/hmr/componentIdentity.d.ts.map +1 -0
- package/dist/hmr/componentIdentity.js +17 -0
- package/dist/hmr/instanceRegistry.d.ts +4 -0
- package/dist/hmr/instanceRegistry.d.ts.map +1 -0
- package/dist/hmr/instanceRegistry.js +6 -0
- package/dist/hmr/instanceRegistry.sxyt.d.ts +2 -0
- package/dist/hmr/instanceRegistry.sxyt.d.ts.map +1 -0
- package/dist/hmr/instanceRegistry.sxyt.js +24 -0
- package/dist/hmr/liveReloadHub.d.ts +10 -0
- package/dist/hmr/liveReloadHub.d.ts.map +1 -0
- package/dist/{dev → hmr}/liveReloadHub.js +8 -2
- package/dist/hmr/refreshStylesheets.d.ts +2 -0
- package/dist/hmr/refreshStylesheets.d.ts.map +1 -0
- package/dist/hmr/refreshStylesheets.js +26 -0
- package/dist/hmr/refreshStylesheets.sxyt.d.ts +2 -0
- package/dist/hmr/refreshStylesheets.sxyt.d.ts.map +1 -0
- package/dist/hmr/refreshStylesheets.sxyt.js +46 -0
- package/dist/hydrate/hydrate.d.ts +9 -1
- package/dist/hydrate/hydrate.d.ts.map +1 -1
- package/dist/hydrate/hydrate.js +31 -7
- package/dist/hydrate/hydrate.sxyt.d.ts +2 -0
- package/dist/hydrate/hydrate.sxyt.d.ts.map +1 -0
- package/dist/hydrate/hydrate.sxyt.js +302 -0
- package/dist/hydrate/reconcileHydratedAttributes.d.ts.map +1 -1
- package/dist/hydrate/reconcileHydratedAttributes.js +10 -2
- package/dist/hydrate/reconcileHydratedAttributes.sxyt.js +17 -0
- package/dist/importDevModuleWithRetry.d.ts +3 -0
- package/dist/importDevModuleWithRetry.d.ts.map +1 -0
- package/dist/importDevModuleWithRetry.js +46 -0
- package/dist/importDevModuleWithRetry.sxyt.d.ts +2 -0
- package/dist/importDevModuleWithRetry.sxyt.d.ts.map +1 -0
- package/dist/importDevModuleWithRetry.sxyt.js +104 -0
- package/dist/render/HeadData.d.ts +1 -0
- package/dist/render/HeadData.d.ts.map +1 -1
- package/dist/render/contentToHtml.d.ts.map +1 -1
- package/dist/render/contentToHtml.js +2 -1
- package/dist/render/processHead.d.ts.map +1 -1
- package/dist/render/processHead.js +47 -6
- package/dist/render/processHead.sxyt.d.ts +2 -0
- package/dist/render/processHead.sxyt.d.ts.map +1 -0
- package/dist/render/processHead.sxyt.js +93 -0
- package/dist/update/hotSwap.sxyt.d.ts +2 -0
- package/dist/update/hotSwap.sxyt.d.ts.map +1 -0
- package/dist/update/hotSwap.sxyt.js +252 -0
- package/dist/update/integrateUpdateVdom.d.ts +5 -1
- package/dist/update/integrateUpdateVdom.d.ts.map +1 -1
- package/dist/update/integrateUpdateVdom.js +107 -4
- package/dist/warnOnFrameworkChange.d.ts +2 -0
- package/dist/warnOnFrameworkChange.d.ts.map +1 -0
- package/dist/warnOnFrameworkChange.js +27 -0
- package/package.json +1 -1
- package/dist/dev/liveReloadHub.d.ts +0 -6
- package/dist/dev/liveReloadHub.d.ts.map +0 -1
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// BabelAddDevCacheBust
|
|
2
|
+
// exports MakeBabelAddDevCacheBust (function)
|
|
3
|
+
//
|
|
4
|
+
// Dev-only. Appends a `?v=<mtime>` query to every relative import/re-export
|
|
5
|
+
// specifier, versioned off the imported file's own mtime as it sits in
|
|
6
|
+
// codeLocation (the tsc-emitted, pre-final-babel intermediate directory).
|
|
7
|
+
//
|
|
8
|
+
// Without this, the client's HMR reload script only cache-busts the
|
|
9
|
+
// top-level file(s) named in the SSE payload (`?t=<now>`); anything THAT
|
|
10
|
+
// file statically imports by its plain URL still resolves against whatever
|
|
11
|
+
// the browser had cached for that plain URL. On a rename that touches two
|
|
12
|
+
// files in the same edit (e.g. `Button.tsx` renaming an export while
|
|
13
|
+
// `Home.tsx` updates its import of it), the freshly re-fetched `Home.js`'s
|
|
14
|
+
// own static `import ... from '../components/Button.js'` could resolve to a
|
|
15
|
+
// stale cached `Button.js` that doesn't have the new export yet, throwing a
|
|
16
|
+
// genuine browser SyntaxError before HMR ever gets a chance to run - see
|
|
17
|
+
// docs/hmr.md's "stale-module-cache SyntaxError" finding. Stamping every
|
|
18
|
+
// import with the target's current mtime means an edited dependency always
|
|
19
|
+
// gets a URL the browser has never cached, regardless of which file in the
|
|
20
|
+
// chain was named in the SSE event.
|
|
21
|
+
//
|
|
22
|
+
// Must run after BabelTransformJsxExtensionsToJs (registered later in the
|
|
23
|
+
// dev plugin list) so it seess the corrected '.js' specifier - but resolution
|
|
24
|
+
// tries both '.js' and '.jsx' on disk regardless, since codeLocation only
|
|
25
|
+
// ever contains the pre-rename '.jsx' file, so this works whichever order
|
|
26
|
+
// plugins actually end up running in.
|
|
27
|
+
import { dirname, join } from 'path';
|
|
28
|
+
import fs from 'fs';
|
|
29
|
+
function resolveOnDiskMtime(fromDir, specifier) {
|
|
30
|
+
if (!specifier.startsWith('.')) return undefined;
|
|
31
|
+
const candidates = specifier.endsWith('.jsx') ? [specifier, specifier.slice(0, -1)] : specifier.endsWith('.js') ? [specifier, `${specifier.slice(0, -3)}.jsx`] : [];
|
|
32
|
+
for (const candidate of candidates) {
|
|
33
|
+
const abs = join(fromDir, candidate);
|
|
34
|
+
if (fs.existsSync(abs)) return fs.statSync(abs).mtimeMs;
|
|
35
|
+
}
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
function versionedSpecifier(fromDir, specifier) {
|
|
39
|
+
const mtimeMs = resolveOnDiskMtime(fromDir, specifier);
|
|
40
|
+
if (mtimeMs === undefined) return specifier;
|
|
41
|
+
const separator = specifier.includes('?') ? '&' : '?';
|
|
42
|
+
return `${specifier}${separator}v=${mtimeMs}`;
|
|
43
|
+
}
|
|
44
|
+
export function MakeBabelAddDevCacheBust() {
|
|
45
|
+
return function BabelAddDevCacheBust() {
|
|
46
|
+
let fileDir = '';
|
|
47
|
+
return {
|
|
48
|
+
pre(state) {
|
|
49
|
+
const stateFilename = state.opts.filename;
|
|
50
|
+
fileDir = typeof stateFilename === 'string' ? dirname(stateFilename) : '';
|
|
51
|
+
},
|
|
52
|
+
visitor: {
|
|
53
|
+
ImportDeclaration(path) {
|
|
54
|
+
if (fileDir === '') return;
|
|
55
|
+
path.node.source.value = versionedSpecifier(fileDir, path.node.source.value);
|
|
56
|
+
},
|
|
57
|
+
ExportNamedDeclaration(path) {
|
|
58
|
+
if (fileDir === '' || path.node.source == null) return;
|
|
59
|
+
path.node.source.value = versionedSpecifier(fileDir, path.node.source.value);
|
|
60
|
+
},
|
|
61
|
+
ExportAllDeclaration(path) {
|
|
62
|
+
if (fileDir === '') return;
|
|
63
|
+
path.node.source.value = versionedSpecifier(fileDir, path.node.source.value);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BabelAddDevCacheBust.sxyt.d.ts","sourceRoot":"","sources":["../../src/babelPlugins/BabelAddDevCacheBust.sxyt.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { expect } from 'chai';
|
|
2
|
+
import { describe } from 'sxy-test-runner';
|
|
3
|
+
import { transformSync } from '@babel/core';
|
|
4
|
+
import { mkdir, mkdtemp, rm, writeFile, utimes } from 'fs/promises';
|
|
5
|
+
import { statSync, readFileSync } from 'fs';
|
|
6
|
+
import { tmpdir } from 'os';
|
|
7
|
+
import { join } from 'path';
|
|
8
|
+
import { MakeBabelAddDevCacheBust } from "./BabelAddDevCacheBust.js";
|
|
9
|
+
async function makeFixture() {
|
|
10
|
+
const dir = await mkdtemp(join(tmpdir(), 'tungsten-add-dev-cache-bust-'));
|
|
11
|
+
const components = join(dir, 'components');
|
|
12
|
+
const pages = join(dir, 'pages');
|
|
13
|
+
await mkdir(components, {
|
|
14
|
+
recursive: true
|
|
15
|
+
});
|
|
16
|
+
await mkdir(pages, {
|
|
17
|
+
recursive: true
|
|
18
|
+
});
|
|
19
|
+
const buttonPath = join(components, 'Button.jsx');
|
|
20
|
+
await writeFile(buttonPath, `export function Button() { return null }\n`);
|
|
21
|
+
const homePath = join(pages, 'Home.jsx');
|
|
22
|
+
await writeFile(homePath, `import { Button } from '../components/Button.jsx'\nexport const x = Button\n`);
|
|
23
|
+
return {
|
|
24
|
+
dir,
|
|
25
|
+
buttonPath,
|
|
26
|
+
homePath,
|
|
27
|
+
components,
|
|
28
|
+
pages
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function transform(filename) {
|
|
32
|
+
const result = transformSync(readFileSync(filename, 'utf8'), {
|
|
33
|
+
filename,
|
|
34
|
+
babelrc: false,
|
|
35
|
+
configFile: false,
|
|
36
|
+
plugins: [MakeBabelAddDevCacheBust()]
|
|
37
|
+
});
|
|
38
|
+
if (result === null || typeof result.code !== 'string') throw new Error('babel transform returned no code');
|
|
39
|
+
return result.code;
|
|
40
|
+
}
|
|
41
|
+
describe('BabelAddDevCacheBust', ({
|
|
42
|
+
it
|
|
43
|
+
}) => {
|
|
44
|
+
it(`appends the imported file's on-disk mtime as a '?v=' query to a relative import`, async () => {
|
|
45
|
+
const {
|
|
46
|
+
dir,
|
|
47
|
+
buttonPath,
|
|
48
|
+
homePath
|
|
49
|
+
} = await makeFixture();
|
|
50
|
+
try {
|
|
51
|
+
const code = transform(homePath);
|
|
52
|
+
const mtimeMs = statSync(buttonPath).mtimeMs;
|
|
53
|
+
expect(code).to.contain(`../components/Button.jsx?v=${mtimeMs}`);
|
|
54
|
+
} finally {
|
|
55
|
+
await rm(dir, {
|
|
56
|
+
recursive: true,
|
|
57
|
+
force: true
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
it(`produces a different '?v=' value once the imported file is edited - so a fresh dependent refetch resolves a URL the browser has never cached`, async () => {
|
|
62
|
+
const {
|
|
63
|
+
dir,
|
|
64
|
+
buttonPath,
|
|
65
|
+
homePath
|
|
66
|
+
} = await makeFixture();
|
|
67
|
+
try {
|
|
68
|
+
const before = transform(homePath);
|
|
69
|
+
const beforeMatch = before.match(/\?v=([0-9.]+)["']/);
|
|
70
|
+
expect(beforeMatch).to.not.equal(null);
|
|
71
|
+
// simulate the developer editing Button.jsx a moment later
|
|
72
|
+
const future = new Date(Date.now() + 5000);
|
|
73
|
+
await utimes(buttonPath, future, future);
|
|
74
|
+
const after = transform(homePath);
|
|
75
|
+
const afterMatch = after.match(/\?v=([0-9.]+)["']/);
|
|
76
|
+
expect(afterMatch).to.not.equal(null);
|
|
77
|
+
expect(afterMatch[1]).to.not.equal(beforeMatch[1]);
|
|
78
|
+
} finally {
|
|
79
|
+
await rm(dir, {
|
|
80
|
+
recursive: true,
|
|
81
|
+
force: true
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
it(`resolves correctly even when the specifier's extension has already been rewritten from .jsx to .js by an earlier plugin`, async () => {
|
|
86
|
+
const {
|
|
87
|
+
dir,
|
|
88
|
+
buttonPath,
|
|
89
|
+
pages
|
|
90
|
+
} = await makeFixture();
|
|
91
|
+
try {
|
|
92
|
+
const homeAlreadyJsPath = join(pages, 'HomeAlreadyJs.jsx');
|
|
93
|
+
await writeFile(homeAlreadyJsPath, `import { Button } from '../components/Button.js'\nexport const x = Button\n`);
|
|
94
|
+
const code = transform(homeAlreadyJsPath);
|
|
95
|
+
const mtimeMs = statSync(buttonPath).mtimeMs;
|
|
96
|
+
expect(code).to.contain(`../components/Button.js?v=${mtimeMs}`);
|
|
97
|
+
} finally {
|
|
98
|
+
await rm(dir, {
|
|
99
|
+
recursive: true,
|
|
100
|
+
force: true
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
it(`leaves a bare (package) import untouched`, async () => {
|
|
105
|
+
const {
|
|
106
|
+
dir,
|
|
107
|
+
homePath
|
|
108
|
+
} = await makeFixture();
|
|
109
|
+
try {
|
|
110
|
+
await writeFile(homePath, `import { StatefulComponent } from 'tungsten'\nexport const x = StatefulComponent\n`);
|
|
111
|
+
const code = transform(homePath);
|
|
112
|
+
expect(code).to.contain(`tungsten`);
|
|
113
|
+
expect(code).to.not.contain(`?v=`);
|
|
114
|
+
} finally {
|
|
115
|
+
await rm(dir, {
|
|
116
|
+
recursive: true,
|
|
117
|
+
force: true
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
it(`leaves a relative import untouched when the target file cannot be found on disk`, async () => {
|
|
122
|
+
const {
|
|
123
|
+
dir,
|
|
124
|
+
homePath
|
|
125
|
+
} = await makeFixture();
|
|
126
|
+
try {
|
|
127
|
+
await writeFile(homePath, `import { Ghost } from '../components/Ghost.jsx'\nexport const x = Ghost\n`);
|
|
128
|
+
const code = transform(homePath);
|
|
129
|
+
expect(code).to.contain(`../components/Ghost.jsx`);
|
|
130
|
+
expect(code).to.not.contain(`?v=`);
|
|
131
|
+
} finally {
|
|
132
|
+
await rm(dir, {
|
|
133
|
+
recursive: true,
|
|
134
|
+
force: true
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../../src/bin/commands/dev.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../../src/bin/commands/dev.ts"],"names":[],"mappings":"AA2CA,OAAO,EAAE,CAAA"}
|
package/dist/bin/commands/dev.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import open from 'open';
|
|
2
2
|
import { cliOut } from "../../cliOutput.js";
|
|
3
3
|
import { Framework } from "../../Framework.js";
|
|
4
|
+
import { warnOnFrameworkChange } from "../../warnOnFrameworkChange.js";
|
|
4
5
|
//import dotenv from 'dotenv'
|
|
5
6
|
//dotenv.config({ path: '.private.env' })
|
|
6
7
|
cliOut(`Starting dev mode`);
|
|
@@ -17,6 +18,7 @@ await sxyFramework.build('dev');
|
|
|
17
18
|
const devServer = await sxyFramework.createDevServer();
|
|
18
19
|
//cliOut('Dev server ready')
|
|
19
20
|
const devServerLocation = await devServer.start();
|
|
21
|
+
if (sxyFramework.config?.warnOnFrameworkChange) warnOnFrameworkChange();
|
|
20
22
|
// do a dummy request to trigger any error immediately during dev
|
|
21
23
|
//axios.get(sxyFramework.devServer.location)
|
|
22
24
|
cliOut('Booting to the dev site in your browser');
|
|
@@ -5,7 +5,7 @@ import { copyAssets } from "./copyAssets.js";
|
|
|
5
5
|
import { copyPublicFiles } from "./copyPublicFiles.js";
|
|
6
6
|
import { buildCodeSubPath, bundleFolder, devBuildOuterFolder, prodBuildFolder } from "../settings.js";
|
|
7
7
|
import { combineComponentCss } from "./combineComponentCss.js";
|
|
8
|
-
import { emitReloadEvent } from "../
|
|
8
|
+
import { emitReloadEvent } from "../hmr/liveReloadHub.js";
|
|
9
9
|
//import { compileEnv } from './compileEnv.js'
|
|
10
10
|
export async function compileUserApp(projectDir, appConfig, mode) {
|
|
11
11
|
const codeLocation = join(projectDir, appConfig.codeDir);
|
|
@@ -17,7 +17,7 @@ export async function compileUserApp(projectDir, appConfig, mode) {
|
|
|
17
17
|
const buildCodeLocation = join(buildLocation, codeSubPath);
|
|
18
18
|
const compileJavascriptPromise = compileJavascript(projectDir, appConfig, codeLocation, sourceLocation, styleImportBase, buildLocation, buildCodeLocation, mode, true, mode === 'dev' ? {
|
|
19
19
|
onCycleComplete: cycle => {
|
|
20
|
-
if (cycle.success) emitReloadEvent('js');
|
|
20
|
+
if (cycle.success) emitReloadEvent('js', cycle.file);
|
|
21
21
|
}
|
|
22
22
|
} : {});
|
|
23
23
|
//const compileEnvPromise = compileEnv(projectDir, appConfig, codeLocation, buildLocation, mode)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"makeBabelUserDevConfig.d.ts","sourceRoot":"","sources":["../../src/build/makeBabelUserDevConfig.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAKnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAEvD,OAAO,EAAoC,eAAe,EAAE,MAAM,iDAAiD,CAAA;
|
|
1
|
+
{"version":3,"file":"makeBabelUserDevConfig.d.ts","sourceRoot":"","sources":["../../src/build/makeBabelUserDevConfig.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAKnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAEvD,OAAO,EAAoC,eAAe,EAAE,MAAM,iDAAiD,CAAA;AAOnH,wBAAgB,sBAAsB,CAClC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,kBAAkB,EAAE,MAAM,EAC1B,aAAa,EAAE,MAAM,EACrB,iBAAiB,EAAE,MAAM,EACzB,qBAAqB,EAAE,MAAM,EAC7B,2BAA2B,EAAE,WAAW,CAAC,MAAM,CAAC,EAChD,kBAAkB,EAAE,eAAe,EACnC,eAAe,EAAE,eAAe,EAChC,aAAa,EAAE,aAAa,EAC5B,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,GACzB,gBAAgB,CAgClB"}
|
|
@@ -6,6 +6,7 @@ import { MakeBabelTransformPackageImports } from "../babelPlugins/BabelTransform
|
|
|
6
6
|
import { componentCssFolder, componentCssFile } from "../settings.js";
|
|
7
7
|
import userCommonConfig from "./babel.user.common.config.js";
|
|
8
8
|
import { MakeBabelTransformCssImports } from "../babelPlugins/BabelTransformCssImports.js";
|
|
9
|
+
import { MakeBabelAddDevCacheBust } from "../babelPlugins/BabelAddDevCacheBust.js";
|
|
9
10
|
export function makeBabelUserDevConfig(projectDir, absCodeDir, absSourceDir, absStyleImportBase, buildLocation, buildCodeLocation, packagesCacheLocation, skipPackageCompilationFiles, oldDependencyGraph, dependencyGraph, importAliases, promises) {
|
|
10
11
|
const userDevConfig = objectCopy(userCommonConfig);
|
|
11
12
|
userDevConfig.plugins.push(MakeBabelTransformPackageImports({
|
|
@@ -29,6 +30,10 @@ export function makeBabelUserDevConfig(projectDir, absCodeDir, absSourceDir, abs
|
|
|
29
30
|
projectAbsStyleImportDir: absStyleImportBase,
|
|
30
31
|
classNameFormat: '[folder]-[name]_[local]',
|
|
31
32
|
cssOutputFile: join(buildLocation, componentCssFolder, componentCssFile)
|
|
32
|
-
})
|
|
33
|
+
}),
|
|
34
|
+
// Dev-only: keeps every relative import's browser-cached URL in sync with the
|
|
35
|
+
// imported file's own on-disk mtime - see BabelAddDevCacheBust.ts and
|
|
36
|
+
// docs/hmr.md's "stale-module-cache SyntaxError" finding.
|
|
37
|
+
MakeBabelAddDevCacheBust());
|
|
33
38
|
return userDevConfig;
|
|
34
39
|
}
|
package/dist/defaultConfig.d.ts
CHANGED
|
@@ -15,6 +15,8 @@ export declare const defaultConfig: {
|
|
|
15
15
|
apiPath: string;
|
|
16
16
|
suppressNoHeadWarning: false;
|
|
17
17
|
suppressOriginMismatchWarning: false;
|
|
18
|
+
warnOnFrameworkChange: true;
|
|
19
|
+
hmr: true;
|
|
18
20
|
};
|
|
19
21
|
export type FrameworkConfigDefault = typeof defaultConfig;
|
|
20
22
|
//# sourceMappingURL=defaultConfig.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaultConfig.d.ts","sourceRoot":"","sources":["../src/defaultConfig.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,aAAa
|
|
1
|
+
{"version":3,"file":"defaultConfig.d.ts","sourceRoot":"","sources":["../src/defaultConfig.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;CAuBS,CAAA;AAEnC,MAAM,MAAM,sBAAsB,GAAG,OAAO,aAAa,CAAA"}
|
package/dist/defaultConfig.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getEnvSchemas.d.ts","sourceRoot":"","sources":["../../src/env/getEnvSchemas.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAA;AAEpE,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,CAAA;
|
|
1
|
+
{"version":3,"file":"getEnvSchemas.d.ts","sourceRoot":"","sources":["../../src/env/getEnvSchemas.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAA;AAEpE,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,CAAA;AAK7B,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAGxC,MAAM,MAAM,UAAU,GAAG;IACrB,gBAAgB,CAAC,EAAE,OAAO,CAAC,WAAW,GAAG,kBAAkB,CAAC,CAAC;IAC7D,eAAe,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;CAC1C,CAAA;AAKD,wBAAsB,aAAa,CAAC,MAAM,EAAE,uBAAuB,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,GAChG,OAAO,CAAC,UAAU,CAAC,CAAA;AACrB,wBAAsB,aAAa,CAAC,MAAM,EAAE,uBAAuB,EAAE,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,EAAE,MAAM,GACjG,OAAO,CAAC,UAAU,CAAC,CAAA;AAoErB,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,uBAAuB,EAAE,SAAS,EAAE,MAAM,uBAGlF"}
|
|
@@ -2,6 +2,7 @@ import { join } from 'path';
|
|
|
2
2
|
import { fixExtension } from "../fixExtension.js";
|
|
3
3
|
import { throwError } from "../throwError.js";
|
|
4
4
|
import { iterationQueryString } from "../iterationQueryString.js";
|
|
5
|
+
import { importDevModuleWithRetry } from "../importDevModuleWithRetry.js";
|
|
5
6
|
export async function getEnvSchemas(config, iteration = null, mode = 'prod') {
|
|
6
7
|
const {
|
|
7
8
|
envSchemasLocation
|
|
@@ -16,7 +17,7 @@ export async function getEnvSchemas(config, iteration = null, mode = 'prod') {
|
|
|
16
17
|
if (iteration === null) throwError('getEnvSchemas()', 'iteration is null');
|
|
17
18
|
//if (!load) throwError('getEnvSchemas()', 'load is null')
|
|
18
19
|
//module = await load(fullFilePath)
|
|
19
|
-
module = await
|
|
20
|
+
module = await importDevModuleWithRetry(iterationQueryString(fullFilePath, iteration));
|
|
20
21
|
} else {
|
|
21
22
|
module = await import(fullFilePath);
|
|
22
23
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getComponent.d.ts","sourceRoot":"","sources":["../src/getComponent.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAG7D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"getComponent.d.ts","sourceRoot":"","sources":["../src/getComponent.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAG7D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAOhC,wBAAsB,YAAY,CAC9B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAEhB,SAAS,GAAE,MAAM,GAAG,IAAW,EAC/B,IAAI,GAAE,IAAa,GACpB,OAAO,CAAC,gBAAgB,CAAC,CA6B3B"}
|
package/dist/getComponent.js
CHANGED
|
@@ -2,6 +2,7 @@ import { fixExtension } from "./fixExtension.js";
|
|
|
2
2
|
import { TungstenError } from "./TungstenError.js";
|
|
3
3
|
import { throwError } from "./throwError.js";
|
|
4
4
|
import { iterationQueryString } from "./iterationQueryString.js";
|
|
5
|
+
import { importDevModuleWithRetry } from "./importDevModuleWithRetry.js";
|
|
5
6
|
//let load //// !! future improvement
|
|
6
7
|
export async function getComponent(filePath, filename,
|
|
7
8
|
//load: Load | null = null,
|
|
@@ -16,7 +17,7 @@ iteration = null, mode = 'prod') {
|
|
|
16
17
|
//const load = await createLoad(import.meta.url, sxyLoaderConfig)
|
|
17
18
|
//console.log('load', filePath)
|
|
18
19
|
//module = await load(filePath)
|
|
19
|
-
module = await
|
|
20
|
+
module = await importDevModuleWithRetry(iterationQueryString(filePath, iteration));
|
|
20
21
|
} else {
|
|
21
22
|
//console.log('import', filePath)
|
|
22
23
|
module = await import(filePath); // import the module
|
package/dist/getRoutes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getRoutes.d.ts","sourceRoot":"","sources":["../src/getRoutes.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AACvD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAGrC,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAA;AAE9D,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAA;
|
|
1
|
+
{"version":3,"file":"getRoutes.d.ts","sourceRoot":"","sources":["../src/getRoutes.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AACvD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAGrC,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAA;AAE9D,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAM5D,wBAAsB,SAAS,CAC3B,eAAe,EAAE,eAAe,EAChC,MAAM,EAAE,uBAAuB,EAE/B,SAAS,GAAE,MAAM,GAAG,IAAW,EAC/B,IAAI,GAAE,IAAa,GACnB,OAAO,CAAC,SAAS,CAAC,CAmCrB"}
|
package/dist/getRoutes.js
CHANGED
|
@@ -3,6 +3,7 @@ import { fixExtension } from "./fixExtension.js";
|
|
|
3
3
|
import { TungstenError } from "./TungstenError.js";
|
|
4
4
|
import { iterationQueryString } from "./iterationQueryString.js";
|
|
5
5
|
import { throwError } from "./throwError.js";
|
|
6
|
+
import { importDevModuleWithRetry } from "./importDevModuleWithRetry.js";
|
|
6
7
|
export async function getRoutes(compilationInfo, config,
|
|
7
8
|
//load: Load | null = null,
|
|
8
9
|
iteration = null, mode = 'prod') {
|
|
@@ -22,7 +23,7 @@ iteration = null, mode = 'prod') {
|
|
|
22
23
|
// can we share load across the render?
|
|
23
24
|
//const load = await createLoad(import.meta.url, sxyLoaderConfig)
|
|
24
25
|
//module = await load(filePath)
|
|
25
|
-
module = await
|
|
26
|
+
module = await importDevModuleWithRetry(iterationQueryString(filePath, iteration));
|
|
26
27
|
} else {
|
|
27
28
|
module = await import(filePath); // import the module
|
|
28
29
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { refreshStylesheets } from './refreshStylesheets.js';
|
|
2
|
+
export type ApplyHmrModuleResult = {
|
|
3
|
+
matched: true;
|
|
4
|
+
count: number;
|
|
5
|
+
orphaned: boolean;
|
|
6
|
+
} | {
|
|
7
|
+
matched: false;
|
|
8
|
+
orphaned: boolean;
|
|
9
|
+
};
|
|
10
|
+
export declare function applyHmrModule(moduleExports: Record<string, unknown>, file?: string): Promise<ApplyHmrModuleResult>;
|
|
11
|
+
//# sourceMappingURL=applyHmrModule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applyHmrModule.d.ts","sourceRoot":"","sources":["../../src/hmr/applyHmrModule.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAE5D,MAAM,MAAM,oBAAoB,GAC1B;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,GACnD;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAA;AAsB3C,wBAAsB,cAAc,CAChC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM,GACtD,OAAO,CAAC,oBAAoB,CAAC,CAkD/B"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { AnyComponentIsFunctionComponentStandIn } from "../AnyComponent.js";
|
|
2
|
+
import { hotSwapClassComponent, hotSwapFunctionComponent } from "../update/integrateUpdateVdom.js";
|
|
3
|
+
import { componentTypeIdentityKey, componentTypeKind, liveComponentIdentityKey, liveComponentKind } from "./componentIdentity.js";
|
|
4
|
+
import { getCurrentInstance } from "./instanceRegistry.js";
|
|
5
|
+
export { refreshStylesheets } from "./refreshStylesheets.js";
|
|
6
|
+
function identityToken(kind, key) {
|
|
7
|
+
return `${kind}:${key}`;
|
|
8
|
+
}
|
|
9
|
+
function tokenKind(token) {
|
|
10
|
+
return token.startsWith('function:') ? 'function' : 'class';
|
|
11
|
+
}
|
|
12
|
+
function tokenKey(token) {
|
|
13
|
+
return token.slice(token.indexOf(':') + 1);
|
|
14
|
+
}
|
|
15
|
+
// Per source file, the set of component identity tokens ('kind:key') it exported the last time
|
|
16
|
+
// this ran. Lets a later edit to the same file detect "this used to export a component that's
|
|
17
|
+
// still live, and doesn't anymore" (a rename or delete) - see tungsten/docs/hmr.md's "orphaned
|
|
18
|
+
// components" note. Cleared naturally on a real page load, since this module state doesn't
|
|
19
|
+
// survive a full reload.
|
|
20
|
+
const previousFileExportIdentities = new Map();
|
|
21
|
+
// Given the freshly re-imported exports of one recompiled file, find every live component
|
|
22
|
+
// instance that came from a same-named, same-kind definition and rebuild it in place. See
|
|
23
|
+
// tungsten/docs/hmr.md for the full design and the reasoning behind the identity key.
|
|
24
|
+
export async function applyHmrModule(moduleExports, file) {
|
|
25
|
+
const instance = getCurrentInstance();
|
|
26
|
+
if (instance === undefined) return {
|
|
27
|
+
matched: false,
|
|
28
|
+
orphaned: false
|
|
29
|
+
};
|
|
30
|
+
let matchedCount = 0;
|
|
31
|
+
const currentIdentities = new Set();
|
|
32
|
+
for (const exportName in moduleExports) {
|
|
33
|
+
const exported = moduleExports[exportName];
|
|
34
|
+
if (typeof exported !== 'function') continue;
|
|
35
|
+
const NewType = exported; // eslint-disable-line no-type-assertion/no-type-assertion -- narrowed by typeof above, definitively a function/class value
|
|
36
|
+
const newKind = componentTypeKind(NewType);
|
|
37
|
+
const newKey = componentTypeIdentityKey(NewType);
|
|
38
|
+
currentIdentities.add(identityToken(newKind, newKey));
|
|
39
|
+
// snapshot: hot-swapping unregisters the old instance and registers its replacement,
|
|
40
|
+
// mutating registeredComponents mid-loop otherwise
|
|
41
|
+
for (const component of [...instance.registeredComponents]) {
|
|
42
|
+
const anyComponent = component; // eslint-disable-line no-type-assertion/no-type-assertion -- every registered component is actually a class instance or FunctionElement stand-in
|
|
43
|
+
if (liveComponentKind(anyComponent) !== newKind) continue;
|
|
44
|
+
if (liveComponentIdentityKey(anyComponent) !== newKey) continue;
|
|
45
|
+
const swapped = AnyComponentIsFunctionComponentStandIn(anyComponent) ? await hotSwapFunctionComponent(anyComponent, NewType) // eslint-disable-line no-type-assertion/no-type-assertion -- newKind === 'function' guaranteed by the kind check above
|
|
46
|
+
: await hotSwapClassComponent(anyComponent, NewType); // eslint-disable-line no-type-assertion/no-type-assertion -- newKind === 'class' guaranteed by the kind check above
|
|
47
|
+
if (swapped !== null) matchedCount++;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
let orphaned = false;
|
|
51
|
+
if (file !== undefined) {
|
|
52
|
+
const previousIdentities = previousFileExportIdentities.get(file);
|
|
53
|
+
if (previousIdentities !== undefined) {
|
|
54
|
+
for (const previousToken of previousIdentities) {
|
|
55
|
+
if (currentIdentities.has(previousToken)) continue;
|
|
56
|
+
const kind = tokenKind(previousToken);
|
|
57
|
+
const key = tokenKey(previousToken);
|
|
58
|
+
const stillLive = [...instance.registeredComponents].some(component => {
|
|
59
|
+
const anyComponent = component; // eslint-disable-line no-type-assertion/no-type-assertion -- every registered component is actually a class instance or FunctionElement stand-in
|
|
60
|
+
return liveComponentKind(anyComponent) === kind && liveComponentIdentityKey(anyComponent) === key;
|
|
61
|
+
});
|
|
62
|
+
if (stillLive) {
|
|
63
|
+
orphaned = true;
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
previousFileExportIdentities.set(file, currentIdentities);
|
|
69
|
+
}
|
|
70
|
+
return matchedCount > 0 ? {
|
|
71
|
+
matched: true,
|
|
72
|
+
count: matchedCount,
|
|
73
|
+
orphaned
|
|
74
|
+
} : {
|
|
75
|
+
matched: false,
|
|
76
|
+
orphaned
|
|
77
|
+
};
|
|
78
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applyHmrModule.sxyt.d.ts","sourceRoot":"","sources":["../../src/hmr/applyHmrModule.sxyt.tsx"],"names":[],"mappings":""}
|