@synchjs/ewb 1.0.0 → 1.0.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.
@@ -3,12 +3,22 @@ export declare class ServeMemoryStore {
3
3
  private static _instance;
4
4
  private _assets;
5
5
  private _htmlCache;
6
+ private _cacheDir;
7
+ private _devMode;
8
+ private _watchers;
9
+ private _listeners;
6
10
  private constructor();
7
11
  static get instance(): ServeMemoryStore;
12
+ setDevMode(enabled: boolean): void;
13
+ onRebuild(listener: () => void): void;
14
+ private notify;
8
15
  getAsset(path: string): {
9
16
  type: string;
10
17
  content: Uint8Array;
11
18
  };
19
+ private getCacheKey;
20
+ private loadFromDisk;
21
+ private setupWatcher;
12
22
  buildAndCache(htmlPath: string, options?: TailwindOptions): Promise<string>;
13
23
  }
14
24
  //# sourceMappingURL=ServeMemoryStore.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ServeMemoryStore.d.ts","sourceRoot":"","sources":["../../src/Components/ServeMemoryStore.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAC,SAAS,CAAmB;IAC3C,OAAO,CAAC,OAAO,CACH;IACZ,OAAO,CAAC,UAAU,CAAkC;IAEpD,OAAO;IAEP,WAAkB,QAAQ,IAAI,gBAAgB,CAK7C;IAEM,QAAQ,CAAC,IAAI,EAAE,MAAM;cAbS,MAAM;iBAAW,UAAU;;IAmBnD,aAAa,CACxB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,eAAgD,GACxD,OAAO,CAAC,MAAM,CAAC;CAsEnB"}
1
+ {"version":3,"file":"ServeMemoryStore.d.ts","sourceRoot":"","sources":["../../src/Components/ServeMemoryStore.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAI/D,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAC,SAAS,CAAmB;IAC3C,OAAO,CAAC,OAAO,CACH;IACZ,OAAO,CAAC,UAAU,CAAkC;IACpD,OAAO,CAAC,SAAS,CAA0C;IAC3D,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,SAAS,CAAwC;IACzD,OAAO,CAAC,UAAU,CAAsB;IAExC,OAAO;IAUP,WAAkB,QAAQ,IAAI,gBAAgB,CAK7C;IAEM,UAAU,CAAC,OAAO,EAAE,OAAO;IAI3B,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI;IAIrC,OAAO,CAAC,MAAM;IAIP,QAAQ,CAAC,IAAI,EAAE,MAAM;cArCS,MAAM;iBAAW,UAAU;;IAyChE,OAAO,CAAC,WAAW;YAQL,YAAY;IAuB1B,OAAO,CAAC,YAAY;IA4CP,aAAa,CACxB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,eAAgD,GACxD,OAAO,CAAC,MAAM,CAAC;CAqHnB"}
@@ -1,27 +1,117 @@
1
1
  import tailwindPlugin from "bun-plugin-tailwind";
2
+ import fs from "fs";
3
+ import path from "path";
2
4
  export class ServeMemoryStore {
3
5
  static _instance;
4
6
  _assets = new Map();
5
7
  _htmlCache = new Map();
6
- constructor() { }
8
+ _cacheDir = path.join(process.cwd(), ".ebw-cache");
9
+ _devMode = false;
10
+ _watchers = new Map();
11
+ _listeners = [];
12
+ constructor() {
13
+ if (!fs.existsSync(this._cacheDir)) {
14
+ try {
15
+ fs.mkdirSync(this._cacheDir, { recursive: true });
16
+ }
17
+ catch (e) {
18
+ // Fallback if we can't create directory
19
+ }
20
+ }
21
+ }
7
22
  static get instance() {
8
23
  if (!ServeMemoryStore._instance) {
9
24
  ServeMemoryStore._instance = new ServeMemoryStore();
10
25
  }
11
26
  return ServeMemoryStore._instance;
12
27
  }
28
+ setDevMode(enabled) {
29
+ this._devMode = enabled;
30
+ }
31
+ onRebuild(listener) {
32
+ this._listeners.push(listener);
33
+ }
34
+ notify() {
35
+ this._listeners.forEach((l) => l());
36
+ }
13
37
  getAsset(path) {
14
- // Remove leading slash for matching if stored without it, or normalize.
15
- // We will store with leading slash.
16
38
  return this._assets.get(path);
17
39
  }
18
- async buildAndCache(htmlPath, options = { enable: false, plugins: [] }) {
19
- const cacheKey = htmlPath +
40
+ getCacheKey(htmlPath, options) {
41
+ return (htmlPath +
20
42
  (options.enable ? ":tw" : "") +
21
- (options.plugins ? ":" + options.plugins.length : "");
43
+ (options.plugins ? ":" + options.plugins.length : ""));
44
+ }
45
+ async loadFromDisk(cacheKey) {
46
+ const hash = Bun.hash(cacheKey).toString(16);
47
+ const cacheFile = path.join(this._cacheDir, `${hash}.json`);
48
+ if (fs.existsSync(cacheFile)) {
49
+ try {
50
+ const data = JSON.parse(fs.readFileSync(cacheFile, "utf-8"));
51
+ this._htmlCache.set(cacheKey, data.html);
52
+ for (const [webPath, asset] of Object.entries(data.assets)) {
53
+ this._assets.set(webPath, {
54
+ type: asset.type,
55
+ content: Buffer.from(asset.content, "base64"),
56
+ });
57
+ }
58
+ return data.html;
59
+ }
60
+ catch (e) {
61
+ console.error("Error loading cache from disk:", e);
62
+ }
63
+ }
64
+ return null;
65
+ }
66
+ setupWatcher(htmlPath, options) {
67
+ const cacheKey = this.getCacheKey(htmlPath, options);
68
+ if (this._watchers.has(cacheKey))
69
+ return;
70
+ const absolutePath = path.resolve(process.cwd(), htmlPath);
71
+ const watchDir = path.dirname(absolutePath);
72
+ const watcher = fs.watch(watchDir, { recursive: true }, async (event, filename) => {
73
+ if (!filename)
74
+ return;
75
+ // Ignore common noise
76
+ if (filename.includes("node_modules") ||
77
+ filename.includes(".git") ||
78
+ filename.includes(".ebw-cache"))
79
+ return;
80
+ console.log(`[HMR] Change detected in ${filename}. Rebuilding...`);
81
+ // Clear cache for this entry
82
+ this._htmlCache.delete(cacheKey);
83
+ // Clear disk cache by deleting file
84
+ const hash = Bun.hash(cacheKey).toString(16);
85
+ const cacheFile = path.join(this._cacheDir, `${hash}.json`);
86
+ if (fs.existsSync(cacheFile)) {
87
+ fs.unlinkSync(cacheFile);
88
+ }
89
+ try {
90
+ await this.buildAndCache(htmlPath, options);
91
+ this.notify();
92
+ }
93
+ catch (e) {
94
+ console.error("[HMR] Rebuild failed:", e);
95
+ }
96
+ });
97
+ this._watchers.set(cacheKey, watcher);
98
+ }
99
+ async buildAndCache(htmlPath, options = { enable: false, plugins: [] }) {
100
+ const cacheKey = this.getCacheKey(htmlPath, options);
101
+ // 1. Check Memory Cache
22
102
  if (this._htmlCache.has(cacheKey)) {
23
103
  return this._htmlCache.get(cacheKey);
24
104
  }
105
+ // 2. Check Disk Cache (unless in dev mode and we want to ensure fresh start,
106
+ // but usually disk cache is fine as watcher will invalidate it)
107
+ const diskHtml = await this.loadFromDisk(cacheKey);
108
+ if (diskHtml) {
109
+ if (this._devMode) {
110
+ this.setupWatcher(htmlPath, options);
111
+ }
112
+ return diskHtml;
113
+ }
114
+ // 3. Perform Build
25
115
  try {
26
116
  const plugins = [...(options.plugins || [])];
27
117
  if (options.enable) {
@@ -30,9 +120,9 @@ export class ServeMemoryStore {
30
120
  const build = await Bun.build({
31
121
  entrypoints: [htmlPath],
32
122
  target: "browser",
33
- minify: true,
34
- naming: "[name]-[hash].[ext]", // Ensure unique names
35
- publicPath: "/", // Assets served from root
123
+ minify: !this._devMode,
124
+ naming: "[name]-[hash].[ext]",
125
+ publicPath: "/",
36
126
  plugins: plugins,
37
127
  });
38
128
  if (!build.success) {
@@ -40,33 +130,61 @@ export class ServeMemoryStore {
40
130
  throw new Error("Build failed");
41
131
  }
42
132
  let htmlContent = "";
133
+ const currentBuildAssets = {};
43
134
  for (const output of build.outputs) {
44
135
  const content = await output.arrayBuffer();
45
- let text = await output.text(); // For HTML/CSS
46
- // output.path is the absolute path if we were writing, or the name.
47
- // With naming option, output.path usually contains the generated name.
48
- // For artifacts, we need to map the requested URL to this content.
49
- // output.kind gives us hint.
50
- // Parse the relative path (URL) from the output.
51
- // Since we didn't specify outdir, Bun might give us just the name or path relative to cwd.
52
- // However, with `publicPath: "/"`, the HTML imports will look like `/foo-hash.js`.
53
- // We need to store keys as `/foo-hash.js`.
54
- // Let's rely on the fact that `output.path` usually returns what would be written to disk.
55
- // We need the filename part.
136
+ const uint8 = new Uint8Array(content);
56
137
  const filename = output.path.split(/[/\\]/).pop();
57
138
  const webPath = "/" + filename;
58
139
  if (output.type === "text/html" || filename?.endsWith(".html")) {
59
- htmlContent = text;
140
+ htmlContent = await output.text();
60
141
  }
61
142
  else {
62
- let finalContent = new Uint8Array(content);
63
- this._assets.set(webPath, {
143
+ const asset = {
64
144
  type: output.type,
65
- content: finalContent,
66
- });
145
+ content: uint8,
146
+ };
147
+ this._assets.set(webPath, asset);
148
+ currentBuildAssets[webPath] = {
149
+ type: output.type,
150
+ content: Buffer.from(uint8).toString("base64"),
151
+ };
152
+ }
153
+ }
154
+ // Inject HMR/Reload script in dev mode
155
+ if (this._devMode) {
156
+ const reloadScript = `
157
+ <script id="ebw-hmr-script">
158
+ (function() {
159
+ const sse = new EventSource('/ebw-hmr');
160
+ sse.onmessage = (e) => {
161
+ if (e.data === 'reload') {
162
+ console.log('[HMR] Reloading page...');
163
+ location.reload();
164
+ }
165
+ };
166
+ sse.onerror = () => {
167
+ console.warn('[HMR] Connection lost. Attempting to reconnect...');
168
+ };
169
+ })();
170
+ </script>
171
+ `;
172
+ if (htmlContent.includes("</body>")) {
173
+ htmlContent = htmlContent.replace("</body>", `${reloadScript}</body>`);
174
+ }
175
+ else {
176
+ htmlContent += reloadScript;
67
177
  }
178
+ this.setupWatcher(htmlPath, options);
68
179
  }
180
+ // 4. Save to Memory and Disk
69
181
  this._htmlCache.set(cacheKey, htmlContent);
182
+ const hash = Bun.hash(cacheKey).toString(16);
183
+ const cacheFile = path.join(this._cacheDir, `${hash}.json`);
184
+ fs.writeFileSync(cacheFile, JSON.stringify({
185
+ html: htmlContent,
186
+ assets: currentBuildAssets,
187
+ }));
70
188
  return htmlContent;
71
189
  }
72
190
  catch (error) {
@@ -18,7 +18,10 @@ export declare class Server {
18
18
  private _controllerCount;
19
19
  private _routeCount;
20
20
  private _tailwindEnabled;
21
+ private _devMode;
22
+ private _sseClients;
21
23
  constructor(options: ServerOptions);
24
+ private setupHmr;
22
25
  private log;
23
26
  init(): Promise<void>;
24
27
  private printStartupMessage;
@@ -36,6 +39,7 @@ export interface ServerOptions {
36
39
  logging?: boolean;
37
40
  id: string;
38
41
  controllersDir?: string;
42
+ devMode?: boolean;
39
43
  corsOptions?: cors.CorsOptions;
40
44
  helmetOptions?: HelmetOptions;
41
45
  rateLimitOptions?: Partial<RateLimitOptions>;
@@ -1 +1 @@
1
- {"version":3,"file":"Server.d.ts","sourceRoot":"","sources":["../../src/Components/Server.ts"],"names":[],"mappings":"AAAA,OAAgB,EAEd,KAAK,OAAO,EACZ,KAAK,QAAQ,EACb,KAAK,YAAY,EAClB,MAAM,SAAS,CAAC;AAKjB,OAAe,EAAE,KAAK,aAAa,EAAE,MAAM,QAAQ,CAAC;AACpD,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAkB,EAChB,KAAK,OAAO,IAAI,gBAAgB,EACjC,MAAM,oBAAoB,CAAC;AAuB5B,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAU;IAC/B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,SAAgB,GAAG,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAU;IACzC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAU;IACzC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAM;IACxC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAM;IAC3B,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAGhC;IACF,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAgC;IAC5D,OAAO,CAAC,eAAe,CAAC,CAAa;IAErC,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,gBAAgB,CAAS;gBAErB,OAAO,EAAE,aAAa;IAkClC,OAAO,CAAC,GAAG;IAME,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAqClC,OAAO,CAAC,mBAAmB;IAmCpB,KAAK,IAAI,IAAI;YASN,eAAe;IAoP7B,OAAO,CAAC,mBAAmB;IAoB3B,OAAO,CAAC,oBAAoB;IAyD5B,OAAO,CAAC,0BAA0B;IAclC,OAAO,CAAC,YAAY;CAmErB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC;IAC/B,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,gBAAgB,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC7C,gBAAgB,CAAC,EAAE,MAAM,CACvB,MAAM,EACN,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,IAAI,CAC1D,CAAC;IACF,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACtC,SAAS,CAAC,EAAE;QAAE,GAAG,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,GAAG,CAAA;KAAE,CAAC;CAC3C"}
1
+ {"version":3,"file":"Server.d.ts","sourceRoot":"","sources":["../../src/Components/Server.ts"],"names":[],"mappings":"AAAA,OAAgB,EAEd,KAAK,OAAO,EACZ,KAAK,QAAQ,EACb,KAAK,YAAY,EAClB,MAAM,SAAS,CAAC;AAKjB,OAAe,EAAE,KAAK,aAAa,EAAE,MAAM,QAAQ,CAAC;AACpD,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAkB,EAChB,KAAK,OAAO,IAAI,gBAAgB,EACjC,MAAM,oBAAoB,CAAC;AAwB5B,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAU;IAC/B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,SAAgB,GAAG,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAU;IACzC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAU;IACzC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAM;IACxC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAM;IAC3B,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAGhC;IACF,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAgC;IAC5D,OAAO,CAAC,eAAe,CAAC,CAAa;IAErC,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,WAAW,CAAkB;gBAEzB,OAAO,EAAE,aAAa;IAuClC,OAAO,CAAC,QAAQ;IAyBhB,OAAO,CAAC,GAAG;IAME,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAqClC,OAAO,CAAC,mBAAmB;IAsCpB,KAAK,IAAI,IAAI;YASN,eAAe;IAkQ7B,OAAO,CAAC,mBAAmB;IAoB3B,OAAO,CAAC,oBAAoB;IAyD5B,OAAO,CAAC,0BAA0B;IAclC,OAAO,CAAC,YAAY;CAmErB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC;IAC/B,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,gBAAgB,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC7C,gBAAgB,CAAC,EAAE,MAAM,CACvB,MAAM,EACN,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,IAAI,CAC1D,CAAC;IACF,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACtC,SAAS,CAAC,EAAE;QAAE,GAAG,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,GAAG,CAAA;KAAE,CAAC;CAC3C"}
@@ -13,6 +13,7 @@ import * as jwt from "jsonwebtoken";
13
13
  import { AUTH_METADATA_KEY, PUBLIC_METADATA_KEY, } from "../Decorations/Authorized";
14
14
  import { SECURITY_METADATA_KEY, } from "../Decorations/Security";
15
15
  import { TAILWIND_METADATA_KEY, } from "../Decorations/Tailwind";
16
+ import { SERVE_HTML_METADATA_KEY } from "../Decorations/Serve";
16
17
  import { ServeMemoryStore } from "./ServeMemoryStore";
17
18
  import boxen from "boxen";
18
19
  import pc from "picocolors";
@@ -33,6 +34,8 @@ export class Server {
33
34
  _controllerCount = 0;
34
35
  _routeCount = 0;
35
36
  _tailwindEnabled = false;
37
+ _devMode = false;
38
+ _sseClients = [];
36
39
  constructor(options) {
37
40
  this._port = options.port;
38
41
  this._app = express();
@@ -56,8 +59,31 @@ export class Server {
56
59
  max: 100,
57
60
  }));
58
61
  this._app.use(express.json());
62
+ this._devMode = options.devMode ?? process.env.NODE_ENV === "development";
63
+ if (this._devMode) {
64
+ this.setupHmr();
65
+ }
59
66
  global.servers.set(this._id, this._app);
60
67
  }
68
+ setupHmr() {
69
+ ServeMemoryStore.instance.setDevMode(true);
70
+ ServeMemoryStore.instance.onRebuild(() => {
71
+ this.log(`[${this._id}] Sending reload signal to ${this._sseClients.length} clients`);
72
+ this._sseClients.forEach((res) => {
73
+ res.write("data: reload\n\n");
74
+ });
75
+ });
76
+ this._app.get("/ebw-hmr", (req, res) => {
77
+ res.setHeader("Content-Type", "text/event-stream");
78
+ res.setHeader("Cache-Control", "no-cache");
79
+ res.setHeader("Connection", "keep-alive");
80
+ res.flushHeaders();
81
+ this._sseClients.push(res);
82
+ req.on("close", () => {
83
+ this._sseClients = this._sseClients.filter((c) => c !== res);
84
+ });
85
+ });
86
+ }
61
87
  log(message) {
62
88
  if (this._enableLogging) {
63
89
  console.log(message);
@@ -103,6 +129,7 @@ export class Server {
103
129
  `${pc.bold(pad("Controllers:"))}${this._controllerCount}`,
104
130
  `${pc.bold(pad("Routes:"))}${this._routeCount}`,
105
131
  `${pc.bold(pad("Tailwind:"))}${this._tailwindEnabled ? pc.blue("Enabled") : pc.dim("Disabled")}`,
132
+ `${pc.bold(pad("HMR:"))}${this._devMode ? pc.cyan("Active") : pc.dim("Inactive")}`,
106
133
  ];
107
134
  if (this._enableSwagger) {
108
135
  lines.push(`${pc.bold(pad("Swagger:"))}http://localhost:${this._port}${this._swaggerPath}`);
@@ -300,6 +327,12 @@ export class Server {
300
327
  };
301
328
  this._app[route.method](fullPath, ...middlewares, handler);
302
329
  this._routeCount++;
330
+ // Pre-build if @Serve is used
331
+ const htmlPath = Reflect.getMetadata(SERVE_HTML_METADATA_KEY, controller.target.prototype, route.handlerName);
332
+ if (htmlPath) {
333
+ this.log(`[${this._id}] Pre-building HTML: ${htmlPath}`);
334
+ await ServeMemoryStore.instance.buildAndCache(htmlPath, tailwindOptions);
335
+ }
303
336
  }
304
337
  }
305
338
  }
@@ -1,2 +1,3 @@
1
+ export declare const SERVE_HTML_METADATA_KEY = "serve:html";
1
2
  export declare function Serve(htmlPath: string): MethodDecorator;
2
3
  //# sourceMappingURL=Serve.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Serve.d.ts","sourceRoot":"","sources":["../../src/Decorations/Serve.ts"],"names":[],"mappings":"AAIA,wBAAgB,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,CA2CvD"}
1
+ {"version":3,"file":"Serve.d.ts","sourceRoot":"","sources":["../../src/Decorations/Serve.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,uBAAuB,eAAe,CAAC;AAEpD,wBAAgB,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,CAmDvD"}
@@ -1,7 +1,10 @@
1
1
  import { ServeMemoryStore } from "../Components/ServeMemoryStore";
2
2
  import { TAILWIND_METADATA_KEY } from "./Tailwind";
3
+ export const SERVE_HTML_METADATA_KEY = "serve:html";
3
4
  export function Serve(htmlPath) {
4
5
  return function (target, propertyKey, descriptor) {
6
+ // Store the HTML path in metadata for pre-building
7
+ Reflect.defineMetadata(SERVE_HTML_METADATA_KEY, htmlPath, target, propertyKey);
5
8
  const originalMethod = descriptor.value;
6
9
  descriptor.value = async function (req, res, next) {
7
10
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synchjs/ewb",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },