@swissjs/swite 0.3.0 → 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.
Files changed (187) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/adapters/proxy/SwiteProxyError.d.ts.map +1 -0
  3. package/dist/{proxy → adapters/proxy}/proxyToPython.d.ts +1 -1
  4. package/dist/adapters/proxy/proxyToPython.d.ts.map +1 -0
  5. package/dist/build-engine/builder.d.ts.map +1 -0
  6. package/dist/{builder.js → build-engine/builder.js} +8 -14
  7. package/dist/cli.js +5 -5
  8. package/dist/config/config-loader.d.ts.map +1 -0
  9. package/dist/{config.d.ts → config/config.d.ts} +11 -0
  10. package/dist/config/config.d.ts.map +1 -0
  11. package/dist/config/env.d.ts +25 -0
  12. package/dist/config/env.d.ts.map +1 -0
  13. package/dist/config/env.js +84 -0
  14. package/dist/{handlers → dev-engine/handlers}/base-handler.d.ts +5 -1
  15. package/dist/dev-engine/handlers/base-handler.d.ts.map +1 -0
  16. package/dist/dev-engine/handlers/base-handler.js +58 -0
  17. package/dist/dev-engine/handlers/js-handler.d.ts.map +1 -0
  18. package/dist/{handlers → dev-engine/handlers}/js-handler.js +1 -1
  19. package/dist/dev-engine/handlers/mjs-handler.d.ts.map +1 -0
  20. package/dist/{handlers → dev-engine/handlers}/mjs-handler.js +1 -1
  21. package/dist/dev-engine/handlers/node-module-handler.d.ts.map +1 -0
  22. package/dist/{handlers → dev-engine/handlers}/node-module-handler.js +33 -44
  23. package/dist/{handlers → dev-engine/handlers}/ts-handler.d.ts +0 -4
  24. package/dist/dev-engine/handlers/ts-handler.d.ts.map +1 -0
  25. package/dist/{handlers → dev-engine/handlers}/ts-handler.js +5 -28
  26. package/dist/{handlers → dev-engine/handlers}/ui-handler.d.ts +0 -4
  27. package/dist/dev-engine/handlers/ui-handler.d.ts.map +1 -0
  28. package/dist/dev-engine/handlers/ui-handler.js +84 -0
  29. package/dist/{handlers → dev-engine/handlers}/uix-handler.d.ts +0 -4
  30. package/dist/dev-engine/handlers/uix-handler.d.ts.map +1 -0
  31. package/dist/dev-engine/handlers/uix-handler.js +70 -0
  32. package/dist/dev-engine/hmr/hmr-client-template.d.ts +10 -0
  33. package/dist/dev-engine/hmr/hmr-client-template.d.ts.map +1 -0
  34. package/dist/dev-engine/hmr/hmr-client-template.js +122 -0
  35. package/dist/dev-engine/hmr/hmr.d.ts.map +1 -0
  36. package/dist/{hmr.js → dev-engine/hmr/hmr.js} +2 -134
  37. package/dist/{middleware → dev-engine/middleware}/hmr-routes.d.ts +2 -2
  38. package/dist/dev-engine/middleware/hmr-routes.d.ts.map +1 -0
  39. package/dist/{middleware → dev-engine/middleware}/hmr-routes.js +1 -1
  40. package/dist/dev-engine/middleware/middleware-setup.d.ts +35 -0
  41. package/dist/dev-engine/middleware/middleware-setup.d.ts.map +1 -0
  42. package/dist/dev-engine/middleware/middleware-setup.js +327 -0
  43. package/dist/dev-engine/middleware/static-files.d.ts.map +1 -0
  44. package/dist/{middleware → dev-engine/middleware}/static-files.js +2 -2
  45. package/dist/{dev → dev-engine}/pythonDevManager.d.ts +1 -1
  46. package/dist/dev-engine/pythonDevManager.d.ts.map +1 -0
  47. package/dist/{dev → dev-engine}/pythonDevManager.js +1 -1
  48. package/dist/{router → dev-engine/router}/file-router.d.ts +4 -4
  49. package/dist/dev-engine/router/file-router.d.ts.map +1 -0
  50. package/dist/{router → dev-engine/router}/file-router.js +4 -4
  51. package/dist/dev-engine/server.d.ts.map +1 -0
  52. package/dist/{server.js → dev-engine/server.js} +10 -6
  53. package/dist/index.d.ts +13 -13
  54. package/dist/index.d.ts.map +1 -1
  55. package/dist/index.js +9 -9
  56. package/dist/internal/cache/compilation-cache.d.ts.map +1 -0
  57. package/dist/{cache → internal/cache}/compilation-cache.js +3 -2
  58. package/dist/internal/generate-import-map-cli.d.ts.map +1 -0
  59. package/dist/{utils → internal}/generate-import-map-cli.js +1 -1
  60. package/dist/internal/generate-import-map.d.ts.map +1 -0
  61. package/dist/{utils → internal}/generate-import-map.js +3 -3
  62. package/dist/{utils → kernel}/package-finder.d.ts +7 -5
  63. package/dist/kernel/package-finder.d.ts.map +1 -0
  64. package/dist/kernel/package-finder.js +154 -0
  65. package/dist/kernel/package-registry.d.ts.map +1 -0
  66. package/dist/kernel/workspace.d.ts.map +1 -0
  67. package/dist/{resolver → resolution}/bare-import-resolver.d.ts +1 -1
  68. package/dist/resolution/bare-import-resolver.d.ts.map +1 -0
  69. package/dist/{resolver → resolution}/bare-import-resolver.js +25 -53
  70. package/dist/resolution/cdn/cdn-fallback.d.ts.map +1 -0
  71. package/dist/{utils → resolution/path}/file-path-resolver.d.ts +2 -1
  72. package/dist/resolution/path/file-path-resolver.d.ts.map +1 -0
  73. package/dist/{utils → resolution/path}/file-path-resolver.js +46 -28
  74. package/dist/resolution/path/path-fixup.d.ts +13 -0
  75. package/dist/resolution/path/path-fixup.d.ts.map +1 -0
  76. package/dist/resolution/path/path-fixup.js +20 -0
  77. package/dist/{resolver.d.ts → resolution/resolver.d.ts} +1 -1
  78. package/dist/resolution/resolver.d.ts.map +1 -0
  79. package/dist/{resolver.js → resolution/resolver.js} +8 -37
  80. package/dist/{import-rewriter.d.ts → resolution/rewriting/import-rewriter.d.ts} +1 -1
  81. package/dist/resolution/rewriting/import-rewriter.d.ts.map +1 -0
  82. package/dist/resolution/rewriting/import-rewriter.js +199 -0
  83. package/dist/{resolver → resolution}/symlink-registry.d.ts +1 -1
  84. package/dist/resolution/symlink-registry.d.ts.map +1 -0
  85. package/dist/{resolver → resolution}/symlink-registry.js +1 -1
  86. package/dist/resolution/url-resolver.d.ts.map +1 -0
  87. package/dist/{resolver → resolution}/url-resolver.js +38 -109
  88. package/dist/resolution/workspace-package-resolver.d.ts.map +1 -0
  89. package/dist/resolution/workspace-package-resolver.js +77 -0
  90. package/docs/architecture/build-pipeline.md +97 -0
  91. package/docs/architecture/dev-server.md +87 -0
  92. package/docs/architecture/hmr.md +78 -0
  93. package/docs/architecture/import-rewriting.md +101 -0
  94. package/docs/architecture/index.md +16 -0
  95. package/docs/architecture/python-integration.md +93 -0
  96. package/docs/architecture/resolution.md +92 -0
  97. package/docs/cli/build.md +78 -0
  98. package/docs/cli/dev.md +90 -0
  99. package/docs/cli/index.md +15 -0
  100. package/docs/cli/start.md +45 -0
  101. package/docs/development/contributing.md +74 -0
  102. package/docs/development/index.md +12 -0
  103. package/docs/development/internals.md +101 -0
  104. package/docs/guide/configuration.md +89 -0
  105. package/docs/guide/index.md +13 -0
  106. package/docs/guide/project-structure.md +75 -0
  107. package/docs/guide/quickstart.md +113 -0
  108. package/docs/index.md +16 -0
  109. package/package.json +5 -5
  110. package/src/cli.ts +1 -1
  111. package/src/config/config.ts +11 -0
  112. package/src/dev-engine/handlers/base-handler.ts +4 -2
  113. package/src/dev-engine/handlers/node-module-handler.ts +51 -78
  114. package/src/dev-engine/middleware/middleware-setup.ts +1 -0
  115. package/src/dev-engine/server.ts +38 -33
  116. package/src/kernel/package-finder.ts +59 -43
  117. package/src/resolution/bare-import-resolver.ts +14 -4
  118. package/src/resolution/path/file-path-resolver.ts +44 -10
  119. package/src/resolution/url-resolver.ts +1 -1
  120. package/dist/builder.d.ts.map +0 -1
  121. package/dist/cache/compilation-cache.d.ts.map +0 -1
  122. package/dist/config-loader.d.ts.map +0 -1
  123. package/dist/config.d.ts.map +0 -1
  124. package/dist/dev/pythonDevManager.d.ts.map +0 -1
  125. package/dist/env.d.ts +0 -19
  126. package/dist/env.d.ts.map +0 -1
  127. package/dist/env.js +0 -112
  128. package/dist/handlers/base-handler.d.ts.map +0 -1
  129. package/dist/handlers/base-handler.js +0 -38
  130. package/dist/handlers/js-handler.d.ts.map +0 -1
  131. package/dist/handlers/mjs-handler.d.ts.map +0 -1
  132. package/dist/handlers/node-module-handler.d.ts.map +0 -1
  133. package/dist/handlers/ts-handler.d.ts.map +0 -1
  134. package/dist/handlers/ui-handler.d.ts.map +0 -1
  135. package/dist/handlers/ui-handler.js +0 -182
  136. package/dist/handlers/uix-handler.d.ts.map +0 -1
  137. package/dist/handlers/uix-handler.js +0 -135
  138. package/dist/hmr.d.ts.map +0 -1
  139. package/dist/import-rewriter.d.ts.map +0 -1
  140. package/dist/import-rewriter.js +0 -351
  141. package/dist/middleware/hmr-routes.d.ts.map +0 -1
  142. package/dist/middleware/middleware-setup.d.ts +0 -23
  143. package/dist/middleware/middleware-setup.d.ts.map +0 -1
  144. package/dist/middleware/middleware-setup.js +0 -596
  145. package/dist/middleware/static-files.d.ts.map +0 -1
  146. package/dist/proxy/SwiteProxyError.d.ts.map +0 -1
  147. package/dist/proxy/proxyToPython.d.ts.map +0 -1
  148. package/dist/resolver/bare-import-resolver.d.ts.map +0 -1
  149. package/dist/resolver/symlink-registry.d.ts.map +0 -1
  150. package/dist/resolver/url-resolver.d.ts.map +0 -1
  151. package/dist/resolver/workspace-package-resolver.d.ts.map +0 -1
  152. package/dist/resolver/workspace-package-resolver.js +0 -185
  153. package/dist/resolver.d.ts.map +0 -1
  154. package/dist/router/file-router.d.ts.map +0 -1
  155. package/dist/server.d.ts.map +0 -1
  156. package/dist/utils/cdn-fallback.d.ts.map +0 -1
  157. package/dist/utils/file-path-resolver.d.ts.map +0 -1
  158. package/dist/utils/generate-import-map-cli.d.ts.map +0 -1
  159. package/dist/utils/generate-import-map.d.ts.map +0 -1
  160. package/dist/utils/package-finder.d.ts.map +0 -1
  161. package/dist/utils/package-finder.js +0 -161
  162. package/dist/utils/package-registry.d.ts.map +0 -1
  163. package/dist/utils/workspace.d.ts.map +0 -1
  164. /package/dist/{proxy → adapters/proxy}/SwiteProxyError.d.ts +0 -0
  165. /package/dist/{proxy → adapters/proxy}/SwiteProxyError.js +0 -0
  166. /package/dist/{proxy → adapters/proxy}/proxyToPython.js +0 -0
  167. /package/dist/{builder.d.ts → build-engine/builder.d.ts} +0 -0
  168. /package/dist/{config-loader.d.ts → config/config-loader.d.ts} +0 -0
  169. /package/dist/{config-loader.js → config/config-loader.js} +0 -0
  170. /package/dist/{config.js → config/config.js} +0 -0
  171. /package/dist/{handlers → dev-engine/handlers}/js-handler.d.ts +0 -0
  172. /package/dist/{handlers → dev-engine/handlers}/mjs-handler.d.ts +0 -0
  173. /package/dist/{handlers → dev-engine/handlers}/node-module-handler.d.ts +0 -0
  174. /package/dist/{hmr.d.ts → dev-engine/hmr/hmr.d.ts} +0 -0
  175. /package/dist/{middleware → dev-engine/middleware}/static-files.d.ts +0 -0
  176. /package/dist/{server.d.ts → dev-engine/server.d.ts} +0 -0
  177. /package/dist/{cache → internal/cache}/compilation-cache.d.ts +0 -0
  178. /package/dist/{utils → internal}/generate-import-map-cli.d.ts +0 -0
  179. /package/dist/{utils → internal}/generate-import-map.d.ts +0 -0
  180. /package/dist/{utils → kernel}/package-registry.d.ts +0 -0
  181. /package/dist/{utils → kernel}/package-registry.js +0 -0
  182. /package/dist/{utils → kernel}/workspace.d.ts +0 -0
  183. /package/dist/{utils → kernel}/workspace.js +0 -0
  184. /package/dist/{utils → resolution/cdn}/cdn-fallback.d.ts +0 -0
  185. /package/dist/{utils → resolution/cdn}/cdn-fallback.js +0 -0
  186. /package/dist/{resolver → resolution}/url-resolver.d.ts +0 -0
  187. /package/dist/{resolver → resolution}/workspace-package-resolver.d.ts +0 -0
@@ -0,0 +1,84 @@
1
+ /*
2
+ * Copyright (c) 2024 Themba Mzumara
3
+ * SWITE - SWISS Development Server
4
+ * Licensed under the MIT License.
5
+ */
6
+ import { promises as fs } from "node:fs";
7
+ import { UiCompiler } from "@swissjs/compiler";
8
+ import chalk from "chalk";
9
+ import { rewriteImports } from "../../resolution/rewriting/import-rewriter.js";
10
+ import { inlineEnvReferences } from "../../config/env.js";
11
+ import { compilationCache } from "../../internal/cache/compilation-cache.js";
12
+ import { fixSwissLibPaths } from "../../resolution/path/path-fixup.js";
13
+ import { BaseHandler, setDevHeaders, } from "./base-handler.js";
14
+ export class UIHandler extends BaseHandler {
15
+ constructor(context) {
16
+ super(context);
17
+ this.compiler = new UiCompiler();
18
+ }
19
+ async handle(url, res) {
20
+ const filePath = await this.resolveFilePath(url);
21
+ console.log(chalk.blue(`[.ui] ${url} → ${filePath}`));
22
+ try {
23
+ await fs.access(filePath);
24
+ }
25
+ catch {
26
+ console.error(chalk.red(`[.ui] File not found: ${filePath}`));
27
+ throw new Error(`File not found: ${url} (resolved to: ${filePath})`);
28
+ }
29
+ // Cache hit
30
+ const cached = await compilationCache.get(filePath, (compiled) => this.getDependencies(compiled));
31
+ if (cached) {
32
+ const fixed = fixSwissLibPaths(cached);
33
+ setDevHeaders(res);
34
+ res.setHeader("Content-Type", "application/javascript; charset=utf-8");
35
+ res.setHeader("Content-Length", Buffer.byteLength(fixed, "utf-8"));
36
+ res.end(fixed, "utf-8");
37
+ return;
38
+ }
39
+ // Cache miss — compile
40
+ const source = await fs.readFile(filePath, "utf-8");
41
+ let compiled = await this.compiler.compileAsync(source, filePath);
42
+ const esbuild = await import("esbuild");
43
+ const tsResult = await esbuild.transform(compiled, {
44
+ loader: "ts",
45
+ format: "esm",
46
+ target: "esnext",
47
+ sourcefile: filePath,
48
+ });
49
+ compiled = tsResult.code;
50
+ // Fix compiler-emitted wrong paths before import rewriting
51
+ compiled = fixSwissLibPaths(compiled);
52
+ // Inline import.meta.env references before import rewriting
53
+ compiled = inlineEnvReferences(compiled, this.context.env);
54
+ // Strip CSS static-asset imports — they are not ES modules
55
+ compiled = stripCssImports(compiled, url);
56
+ const bareImportPattern = /(?:import|from|export).*['"](@[^'"]+\/[^'"]+)(?!\/)[^'"]*['"]/;
57
+ if (bareImportPattern.test(compiled)) {
58
+ console.warn(`[.ui] Compiled output contains bare imports: ${url}`);
59
+ }
60
+ const rewritten = await rewriteImports(compiled, filePath, this.context.resolver);
61
+ const finalCode = fixSwissLibPaths(rewritten);
62
+ await compilationCache.set(filePath, compiled, finalCode, (c) => this.getDependencies(c));
63
+ if (bareImportPattern.test(finalCode)) {
64
+ console.error(`[.ui] Bare imports still present after rewriting: ${url}`);
65
+ for (const m of Array.from(rewritten.matchAll(/(?:import|from|export).*['"](@[^'"]+\/[^'"]+)(?!\/)[^'"]*['"]/g)).slice(0, 3)) {
66
+ console.error(`[.ui] Unresolved import: ${m[1]}`);
67
+ }
68
+ }
69
+ setDevHeaders(res);
70
+ res.setHeader("Content-Type", "application/javascript; charset=utf-8");
71
+ res.setHeader("Content-Length", Buffer.byteLength(finalCode, "utf-8"));
72
+ res.end(finalCode, "utf-8");
73
+ }
74
+ }
75
+ function stripCssImports(code, url) {
76
+ // Single well-ordered pass: static imports first, then dynamic imports
77
+ const before = code;
78
+ code = code.replace(/^[^\S\r\n]*import\s[^'"]*['"][^'"]*\.css['"]\s*;?[^\S\r\n]*$/gm, "");
79
+ code = code.replace(/\bimport\s*\(\s*['"][^'"]*\.css['"]\s*\)/g, "undefined");
80
+ if (before !== code) {
81
+ console.log(chalk.blue(`[.ui] Stripped CSS imports from ${url}`));
82
+ }
83
+ return code;
84
+ }
@@ -3,10 +3,6 @@ import { BaseHandler, type HandlerContext } from "./base-handler.js";
3
3
  export declare class UIXHandler extends BaseHandler {
4
4
  private compiler;
5
5
  constructor(context: HandlerContext);
6
- /**
7
- * Extract dependencies from compiled code (import paths)
8
- */
9
- private getDependencies;
10
6
  handle(url: string, res: Response): Promise<void>;
11
7
  }
12
8
  //# sourceMappingURL=uix-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uix-handler.d.ts","sourceRoot":"","sources":["../../../src/dev-engine/handlers/uix-handler.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAQxC,OAAO,EACL,WAAW,EAEX,KAAK,cAAc,EACpB,MAAM,mBAAmB,CAAC;AAE3B,qBAAa,UAAW,SAAQ,WAAW;IACzC,OAAO,CAAC,QAAQ,CAAoB;gBAExB,OAAO,EAAE,cAAc;IAI7B,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CA8DxD"}
@@ -0,0 +1,70 @@
1
+ /*
2
+ * Copyright (c) 2024 Themba Mzumara
3
+ * SWITE - SWISS Development Server
4
+ * Licensed under the MIT License.
5
+ */
6
+ import { promises as fs } from "node:fs";
7
+ import { UiCompiler } from "@swissjs/compiler";
8
+ import chalk from "chalk";
9
+ import { rewriteImports } from "../../resolution/rewriting/import-rewriter.js";
10
+ import { inlineEnvReferences } from "../../config/env.js";
11
+ import { compilationCache } from "../../internal/cache/compilation-cache.js";
12
+ import { fixSwissLibPaths } from "../../resolution/path/path-fixup.js";
13
+ import { BaseHandler, setDevHeaders, } from "./base-handler.js";
14
+ export class UIXHandler extends BaseHandler {
15
+ constructor(context) {
16
+ super(context);
17
+ this.compiler = new UiCompiler();
18
+ }
19
+ async handle(url, res) {
20
+ const filePath = await this.resolveFilePath(url);
21
+ console.log(chalk.blue(`[.uix] ${url}`));
22
+ // Cache hit
23
+ const cached = await compilationCache.get(filePath, (compiled) => this.getDependencies(compiled));
24
+ if (cached) {
25
+ const fixed = fixSwissLibPaths(cached);
26
+ setDevHeaders(res);
27
+ res.setHeader("Content-Type", "application/javascript; charset=utf-8");
28
+ res.send(fixed);
29
+ return;
30
+ }
31
+ // Cache miss — compile
32
+ const source = await fs.readFile(filePath, "utf-8");
33
+ let compiled = await this.compiler.compileAsync(source, filePath);
34
+ const esbuild = await import("esbuild");
35
+ const tsResult = await esbuild.transform(compiled, {
36
+ loader: "ts",
37
+ format: "esm",
38
+ target: "esnext",
39
+ sourcefile: filePath,
40
+ });
41
+ compiled = tsResult.code;
42
+ // Fix compiler-emitted wrong paths before import rewriting
43
+ compiled = fixSwissLibPaths(compiled);
44
+ // Inline import.meta.env references before import rewriting
45
+ compiled = inlineEnvReferences(compiled, this.context.env);
46
+ // Strip CSS static-asset imports — they are not ES modules
47
+ const beforeCss = compiled;
48
+ compiled = compiled.replace(/^[^\S\r\n]*import\s[^'"]*['"][^'"]*\.css['"]\s*;?[^\S\r\n]*$/gm, "");
49
+ compiled = compiled.replace(/\bimport\s*\(\s*['"][^'"]*\.css['"]\s*\)/g, "undefined");
50
+ if (beforeCss !== compiled) {
51
+ console.log(chalk.blue(`[.uix] Stripped CSS imports from ${url}`));
52
+ }
53
+ const bareImportPattern = /(?:import|from|export).*['"](@[^'"]+\/[^'"]+)(?!\/)[^'"]*['"]/;
54
+ if (bareImportPattern.test(compiled)) {
55
+ console.warn(`[.uix] Compiled output contains bare imports: ${url}`);
56
+ }
57
+ const rewritten = await rewriteImports(compiled, filePath, this.context.resolver);
58
+ const finalCode = fixSwissLibPaths(rewritten);
59
+ await compilationCache.set(filePath, compiled, finalCode, (c) => this.getDependencies(c));
60
+ if (bareImportPattern.test(finalCode)) {
61
+ console.error(`[.uix] Bare imports still present after rewriting: ${url}`);
62
+ for (const m of Array.from(rewritten.matchAll(/(?:import|from|export).*['"](@[^'"]+\/[^'"]+)(?!\/)[^'"]*['"]/g)).slice(0, 3)) {
63
+ console.error(`[.uix] Unresolved import: ${m[1]}`);
64
+ }
65
+ }
66
+ setDevHeaders(res);
67
+ res.setHeader("Content-Type", "application/javascript; charset=utf-8");
68
+ res.send(finalCode);
69
+ }
70
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Build the HMR client script served to the browser at /__swite_hmr_client.
3
+ *
4
+ * The client is plain JavaScript (no TS syntax) because it is injected into
5
+ * browser pages as-is. Keeping it in a separate module rather than embedded
6
+ * inside hmr.ts makes it editable with syntax highlighting and avoids
7
+ * template-literal escaping issues.
8
+ */
9
+ export declare function buildHmrClientScript(port: number): string;
10
+ //# sourceMappingURL=hmr-client-template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hmr-client-template.d.ts","sourceRoot":"","sources":["../../../src/dev-engine/hmr/hmr-client-template.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAiHzD"}
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Build the HMR client script served to the browser at /__swite_hmr_client.
3
+ *
4
+ * The client is plain JavaScript (no TS syntax) because it is injected into
5
+ * browser pages as-is. Keeping it in a separate module rather than embedded
6
+ * inside hmr.ts makes it editable with syntax highlighting and avoids
7
+ * template-literal escaping issues.
8
+ */
9
+ export function buildHmrClientScript(port) {
10
+ return `// SWITE HMR Client
11
+ console.log('[SWITE] HMR enabled');
12
+
13
+ const socket = new WebSocket('ws://' + window.location.hostname + ':${port}');
14
+ const moduleGraph = new Map();
15
+ const hotModules = new Map();
16
+
17
+ socket.addEventListener('open', () => {
18
+ console.log('[SWITE] HMR connected');
19
+ });
20
+
21
+ socket.addEventListener('message', async (event) => {
22
+ const data = JSON.parse(event.data);
23
+
24
+ if (data.type === 'update') {
25
+ console.log('[SWITE] Processing update:', data.path, 'Type:', data.updateType);
26
+
27
+ if (data.updateType === 'style') {
28
+ updateStyles();
29
+ console.log('[SWITE] Styles hot updated');
30
+ } else if (data.updateType === 'hot') {
31
+ const moduleName = extractModuleName(data.path);
32
+
33
+ if (moduleName && hotModules.has(moduleName)) {
34
+ try {
35
+ invalidateModule(moduleName);
36
+ invalidateDependents(moduleName);
37
+
38
+ const updatedModule = await import(data.path + '?t=' + Date.now());
39
+ hotModules.set(moduleName, updatedModule);
40
+
41
+ updateComponent(moduleName, updatedModule);
42
+ console.log('[SWITE] Component hot updated:', moduleName);
43
+ } catch (error) {
44
+ console.error('[SWITE] Hot update failed:', error);
45
+ window.location.reload();
46
+ }
47
+ } else {
48
+ console.log('[SWITE] New component detected, reloading page');
49
+ window.location.reload();
50
+ }
51
+ } else {
52
+ console.log('[SWITE] Full page reload required');
53
+ window.location.reload();
54
+ }
55
+ }
56
+ });
57
+
58
+ function updateStyles() {
59
+ const links = document.querySelectorAll('link[rel="stylesheet"]');
60
+ links.forEach(link => {
61
+ const href = link.getAttribute('href');
62
+ if (href) {
63
+ const base = href.replace(/[?&]t=\\d+/, '');
64
+ link.setAttribute('href', base + (base.includes('?') ? '&' : '?') + 't=' + Date.now());
65
+ }
66
+ });
67
+ }
68
+
69
+ function extractModuleName(filePath) {
70
+ const parts = filePath.split('/');
71
+ const fileName = parts[parts.length - 1];
72
+ return fileName ? fileName.replace(/\\.[^.]+$/, '') : null;
73
+ }
74
+
75
+ function invalidateModule(moduleName) {
76
+ if (window.__swiss_modules__) {
77
+ delete window.__swiss_modules__[moduleName];
78
+ }
79
+ }
80
+
81
+ function invalidateDependents(moduleName) {
82
+ const dependents = moduleGraph.get(moduleName);
83
+ if (dependents) {
84
+ for (const dependent of dependents) {
85
+ invalidateModule(dependent);
86
+ }
87
+ }
88
+ }
89
+
90
+ function updateComponent(moduleName, newModule) {
91
+ if (window.__swiss_instances__) {
92
+ const instances = window.__swiss_instances__[moduleName];
93
+ if (instances && Array.isArray(instances)) {
94
+ instances.forEach(instance => {
95
+ if (instance && typeof instance.update === 'function') {
96
+ instance.update(newModule.default || newModule);
97
+ }
98
+ });
99
+ }
100
+ }
101
+ }
102
+
103
+ socket.addEventListener('close', () => {
104
+ console.log('[SWITE] HMR disconnected');
105
+ });
106
+
107
+ socket.addEventListener('error', (error) => {
108
+ console.error('[SWITE] HMR error:', error);
109
+ });
110
+
111
+ window.__swiss_modules__ = window.__swiss_modules__ || {};
112
+ window.__swiss_instances__ = window.__swiss_instances__ || {};
113
+
114
+ const currentScript = document.currentScript;
115
+ if (currentScript && currentScript.src) {
116
+ const moduleName = extractModuleName(currentScript.src);
117
+ if (moduleName) {
118
+ window.__swiss_modules__[moduleName] = true;
119
+ }
120
+ }
121
+ `;
122
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hmr.d.ts","sourceRoot":"","sources":["../../../src/dev-engine/hmr/hmr.ts"],"names":[],"mappings":"AAUA,qBAAa,SAAS;IAOlB,OAAO,CAAC,IAAI;IANd,OAAO,CAAC,GAAG,CAAmB;IAC9B,OAAO,CAAC,OAAO,CAAC,CAAqB;IACrC,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,IAAI,CAAS;gBAGX,IAAI,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,MAAM;IAOZ,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;YAiBnB,kBAAkB;IAUhC,OAAO,CAAC,cAAc;YAYR,YAAY;IAmB1B,OAAO,IAAI,MAAM;IAIX,KAAK;IA4BX,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAYpC,eAAe,IAAI,MAAM;IAIzB,OAAO,CAAC,aAAa;IAuBrB,OAAO,CAAC,SAAS;IAcX,IAAI;CAIX"}
@@ -5,6 +5,7 @@ import * as chokidar from "chokidar";
5
5
  import { WebSocketServer, WebSocket } from "ws";
6
6
  import * as net from "net";
7
7
  import chalk from "chalk";
8
+ import { buildHmrClientScript } from "./hmr-client-template.js";
8
9
  export class HMREngine {
9
10
  constructor(root, hmrPort) {
10
11
  this.root = root;
@@ -98,140 +99,7 @@ export class HMREngine {
98
99
  });
99
100
  }
100
101
  getClientScript() {
101
- return `
102
- // SWITE HMR Client
103
- console.log('[SWITE] HMR enabled');
104
-
105
- const socket = new WebSocket('ws://localhost:${this.port}');
106
- const moduleGraph = new Map<string, Set<string>>();
107
- const hotModules = new Map<string, any>();
108
-
109
- socket.addEventListener('open', () => {
110
- console.log('[SWITE] HMR connected');
111
- });
112
-
113
- socket.addEventListener('message', (event) => {
114
- const data = JSON.parse(event.data);
115
-
116
- if (data.type === 'update') {
117
- console.log('[SWITE] Processing update:', data.path, 'Type:', data.updateType);
118
-
119
- if (data.updateType === 'style') {
120
- // Hot swap CSS
121
- updateStyles();
122
- console.log('[SWITE] Styles hot updated');
123
- } else if (data.updateType === 'hot') {
124
- // Hot reload component
125
- const moduleName = extractModuleName(data.path);
126
-
127
- if (moduleName && hotModules.has(moduleName)) {
128
- const oldModule = hotModules.get(moduleName);
129
- try {
130
- invalidateModule(moduleName);
131
- invalidateDependents(moduleName);
132
-
133
- const updatedModule = await import(data.path + '?t=' + Date.now());
134
- hotModules.set(moduleName, updatedModule);
135
-
136
- updateComponent(moduleName, updatedModule);
137
- console.log('[SWITE] Component hot updated:', moduleName);
138
- } catch (error) {
139
- console.error('[SWITE] Hot update failed:', error);
140
- window.location.reload();
141
- }
142
- } else {
143
- console.log('[SWITE] New component detected, reloading page');
144
- window.location.reload();
145
- }
146
- } else {
147
- // Full reload for everything else
148
- console.log('[SWITE] Full page reload required');
149
- window.location.reload();
150
- }
151
- }
152
- });
153
-
154
- function updateStyles() {
155
- // Find all style and link tags
156
- const styles = document.querySelectorAll('link[rel="stylesheet"], style');
157
- styles.forEach(style => {
158
- if (style.tagName === 'LINK' && style.getAttribute('href')) {
159
- const href = style.getAttribute('href');
160
- if (href && !href.includes('?t=')) {
161
- // Add timestamp to force reload
162
- style.setAttribute('href', href + '?t=' + Date.now());
163
- }
164
- }
165
- });
166
- }
167
-
168
- function extractModuleName(path: string): string | null {
169
- // Extract module name from file path
170
- const parts = path.split('/');
171
- const fileName = parts[parts.length - 1];
172
-
173
- if (fileName) {
174
- const nameWithoutExt = fileName.replace(/.[^.]+$/, "");
175
- return nameWithoutExt;
176
- }
177
-
178
- return null;
179
- }
180
-
181
- function invalidateModule(moduleName: string) {
182
- // Clear module from cache
183
- if (typeof window !== 'undefined' && (window as any).__swiss_modules__) {
184
- delete (window as any).__swiss_modules__[moduleName];
185
- }
186
- }
187
-
188
- function invalidateDependents(moduleName: string) {
189
- const dependents = moduleGraph.get(moduleName);
190
- if (dependents) {
191
- for (const dependent of dependents) {
192
- invalidateModule(dependent);
193
- }
194
- }
195
- }
196
-
197
- function updateComponent(moduleName: string, newModule: any) {
198
- // Find and update component instances
199
- if (typeof window !== 'undefined' && (window as any).__swiss_instances__) {
200
- const instances = (window as any).__swiss_instances__[moduleName];
201
- if (instances && Array.isArray(instances)) {
202
- instances.forEach(instance => {
203
- // Update component state if it has update method
204
- if (instance && typeof instance.update === 'function') {
205
- instance.update(newModule.default || newModule);
206
- }
207
- });
208
- }
209
- }
210
- }
211
-
212
- socket.addEventListener('close', () => {
213
- console.log('[SWITE] HMR disconnected');
214
- });
215
-
216
- socket.addEventListener('error', (error) => {
217
- console.error('[SWITE] HMR error:', error);
218
- });
219
-
220
- // Register module for hot reloading
221
- if (typeof window !== 'undefined') {
222
- (window as any).__swiss_modules__ = (window as any).__swiss_modules__ || {};
223
- (window as any).__swiss_instances__ = (window as any).__swiss_instances__ || {};
224
-
225
- // Auto-register current module
226
- const currentScript = document.currentScript;
227
- if (currentScript && currentScript.src) {
228
- const moduleName = extractModuleName(currentScript.src);
229
- if (moduleName) {
230
- (window as any).__swiss_modules__[moduleName] = true;
231
- }
232
- }
233
- }
234
- `;
102
+ return buildHmrClientScript(this.port);
235
103
  }
236
104
  getUpdateType(fileExt, filePath) {
237
105
  if (!fileExt || !filePath)
@@ -1,6 +1,6 @@
1
1
  import type { Express } from "express";
2
- import type { RouteDefinition } from "@kibologic/core";
3
- import { HMREngine } from "../hmr.js";
2
+ import type { RouteDefinition } from "@swissjs/core";
3
+ import { HMREngine } from "../hmr/hmr.js";
4
4
  export interface HMRRoutesConfig {
5
5
  hmr: HMREngine;
6
6
  routes: RouteDefinition[];
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hmr-routes.d.ts","sourceRoot":"","sources":["../../../src/dev-engine/middleware/hmr-routes.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,SAAS,CAAC;IACf,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAqG1E"}
@@ -3,7 +3,7 @@
3
3
  * SWITE - SWISS Development Server
4
4
  * Licensed under the MIT License.
5
5
  */
6
- import { HMREngine } from "../hmr.js";
6
+ import { HMREngine } from "../hmr/hmr.js";
7
7
  /**
8
8
  * Setup HMR client endpoint and routes endpoint
9
9
  */
@@ -0,0 +1,35 @@
1
+ import type { Express } from "express";
2
+ import type { RouteDefinition } from "@swissjs/core";
3
+ import { RouteScanner } from "@swissjs/plugin-file-router/core";
4
+ import { createFileWatcher } from "@swissjs/plugin-file-router/dev";
5
+ import { ModuleResolver } from "../../resolution/resolver.js";
6
+ import { HMREngine } from "../hmr/hmr.js";
7
+ export interface MiddlewareConfig {
8
+ root: string;
9
+ workspaceRoot?: string | null;
10
+ publicDir: string;
11
+ resolver: ModuleResolver;
12
+ hmr: HMREngine;
13
+ userConfig?: import("../../config/config.js").SwiteUserConfig;
14
+ }
15
+ export interface MiddlewareResult {
16
+ routes: RouteDefinition[];
17
+ routeScanner: RouteScanner | null;
18
+ routeWatcher: Awaited<ReturnType<typeof createFileWatcher>> | null;
19
+ }
20
+ /**
21
+ * Setup all middleware for the SWITE server.
22
+ *
23
+ * Middleware registration order (matters for Express):
24
+ * 1. File router + HMR routes
25
+ * 2. /packages source files
26
+ * 3. /src source files (highest priority for that prefix)
27
+ * 4. /lib source files (pre-static guard)
28
+ * 5. .ui/.uix MIME-type guard (belt-and-suspenders for slipped-through requests)
29
+ * 6. /.skltn/modules.css → 204
30
+ * 7. Static file serving (public/, node_modules/, lib/)
31
+ * 8. General source-file transformation (all other paths)
32
+ * 9. SPA fallback
33
+ */
34
+ export declare function setupMiddleware(app: Express, config: MiddlewareConfig): Promise<MiddlewareResult>;
35
+ //# sourceMappingURL=middleware-setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware-setup.d.ts","sourceRoot":"","sources":["../../../src/dev-engine/middleware/middleware-setup.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,OAAO,EAAmC,MAAM,SAAS,CAAC;AACxE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAIpE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAa9D,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAK1C,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,cAAc,CAAC;IACzB,GAAG,EAAE,SAAS,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,wBAAwB,EAAE,eAAe,CAAC;CAC/D;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;IAClC,YAAY,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC,GAAG,IAAI,CAAC;CACpE;AAuBD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,gBAAgB,CAAC,CA2Q3B"}