@broxium/compiler 1.3.3 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +125 -6
- package/dist/index.d.mts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +64 -7
- package/dist/index.mjs +64 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -123,6 +123,60 @@ Source files are written to a temporary directory under `os.tmpdir()` before com
|
|
|
123
123
|
|
|
124
124
|
---
|
|
125
125
|
|
|
126
|
+
## `config.json` format
|
|
127
|
+
|
|
128
|
+
Every component must include a `config.json` file alongside `App.tsx`. This file defines the props exposed in the website builder's property inspector panel.
|
|
129
|
+
|
|
130
|
+
**The format is a flat object** — prop name as key, field definition as value. Do not use a `name`/`slug`/`props` wrapper.
|
|
131
|
+
|
|
132
|
+
```json
|
|
133
|
+
{
|
|
134
|
+
"title": {
|
|
135
|
+
"label": "Title",
|
|
136
|
+
"type": "text",
|
|
137
|
+
"default": "Hello World"
|
|
138
|
+
},
|
|
139
|
+
"count": {
|
|
140
|
+
"label": "Item Count",
|
|
141
|
+
"type": "number",
|
|
142
|
+
"default": 3
|
|
143
|
+
},
|
|
144
|
+
"theme": {
|
|
145
|
+
"label": "Theme",
|
|
146
|
+
"type": "select",
|
|
147
|
+
"options": ["light", "dark"],
|
|
148
|
+
"default": "light"
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Supported field types
|
|
154
|
+
|
|
155
|
+
| `type` | Builder input | Extra keys |
|
|
156
|
+
|---|---|---|
|
|
157
|
+
| `text` | Text input | — |
|
|
158
|
+
| `textarea` | Multiline textarea | — |
|
|
159
|
+
| `url` | URL input (validated) | — |
|
|
160
|
+
| `number` | Number input | — |
|
|
161
|
+
| `select` | Dropdown | `options: string[]` |
|
|
162
|
+
| `color` | Color picker + hex | — |
|
|
163
|
+
| `boolean` | Checkbox | — |
|
|
164
|
+
| `range` | Slider | `min`, `max` |
|
|
165
|
+
| `brodox-*` | Custom Brodox field | varies |
|
|
166
|
+
|
|
167
|
+
### Optional field keys
|
|
168
|
+
|
|
169
|
+
| Key | Type | Description |
|
|
170
|
+
|---|---|---|
|
|
171
|
+
| `label` | `string` | Display name in the inspector panel |
|
|
172
|
+
| `type` | `string` | Input type (required) |
|
|
173
|
+
| `default` | `any` | Initial value when component is first dropped |
|
|
174
|
+
| `render` | `"client"` \| `"server"` | Badge shown in inspector (cosmetic only) |
|
|
175
|
+
|
|
176
|
+
> **Common crash:** If `config.json` is not a flat object (e.g. has a top-level `name` or `props` array key), the builder will crash with `Cannot read properties of undefined (reading 'startsWith')` when the component is dragged onto the canvas.
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
126
180
|
## `'use client'` and `'use server'` handling
|
|
127
181
|
|
|
128
182
|
The two esbuild builds use custom plugins to handle React-style directives:
|
|
@@ -153,11 +207,44 @@ Server-only code never runs in the browser.
|
|
|
153
207
|
|
|
154
208
|
The directive on the **entry file** (`App.tsx`) determines the `renderMode` stored in the Page Manifest:
|
|
155
209
|
|
|
156
|
-
| Entry file starts with | `renderMode` | Server renders | Client hydrates |
|
|
157
|
-
|
|
158
|
-
| `'use client'` | `client` | No | Yes |
|
|
159
|
-
| `'use server'` | `server` | Yes | No |
|
|
160
|
-
| _(nothing)_ | `both` | Yes | Yes |
|
|
210
|
+
| Entry file starts with | `renderMode` | Server renders | Client hydrates | Use when |
|
|
211
|
+
|---|---|---|---|---|
|
|
212
|
+
| `'use client'` | `client` | No | Yes (full) | `useState`, `useEffect`, event handlers, browser APIs |
|
|
213
|
+
| `'use server'` | `server` | Yes (full) | No | Display-only, no interactivity needed |
|
|
214
|
+
| _(nothing)_ | `both` | Yes | Yes (islands only) | Static shell with `<Client>` islands for interactive parts |
|
|
215
|
+
|
|
216
|
+
> **Note:** These directives are **not** the same as Next.js. `'use server'` here means "exclude from client bundle" — it does not create a server action.
|
|
217
|
+
|
|
218
|
+
### Common mistake — missing `'use client'`
|
|
219
|
+
|
|
220
|
+
Using `useState`, `useEffect`, or any hook at the top level of the entry file **without** `'use client'` causes the web engine to crash during SSR:
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
Cannot read properties of null (reading 'useState')
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Fix: add `'use client'` as the very first line of `App.tsx`.
|
|
227
|
+
|
|
228
|
+
```jsx
|
|
229
|
+
'use client';
|
|
230
|
+
|
|
231
|
+
import { useState } from 'react';
|
|
232
|
+
|
|
233
|
+
export default function App() {
|
|
234
|
+
const [count, setCount] = useState(0);
|
|
235
|
+
// ...
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### Sub-file directives
|
|
240
|
+
|
|
241
|
+
You can split a multi-file component by marking individual files:
|
|
242
|
+
|
|
243
|
+
```
|
|
244
|
+
App.tsx ← no directive (both: SSR shell + client hydration)
|
|
245
|
+
├── Counter.tsx ← 'use client' (stubbed on server, runs in browser)
|
|
246
|
+
└── DataTable.tsx← 'use server' (stubbed in browser, runs on server)
|
|
247
|
+
```
|
|
161
248
|
|
|
162
249
|
---
|
|
163
250
|
|
|
@@ -238,14 +325,46 @@ When `BundleService` catches a compilation error, it blocks the component from b
|
|
|
238
325
|
|
|
239
326
|
---
|
|
240
327
|
|
|
328
|
+
## `runtimeServerStubPlugin` — @broxium/runtime server stubs
|
|
329
|
+
|
|
330
|
+
During server bundle compilation, all `@broxium/runtime` imports are replaced
|
|
331
|
+
by inline server-safe stubs so the server bundle has zero external dependencies.
|
|
332
|
+
|
|
333
|
+
Key stub behaviours:
|
|
334
|
+
|
|
335
|
+
| Export | Server stub renders |
|
|
336
|
+
|---|---|
|
|
337
|
+
| `BrodoxLink` | `<a data-brodox-link href={href}>` — the `data-brodox-link` attribute is required for the shell's click interceptor |
|
|
338
|
+
| `BrodoxImage` | `<img src="/api/image?...">` with srcset, or raw `src` if `direct={true}` |
|
|
339
|
+
| `Client` | Empty placeholder div + sibling `<script type="application/json">` with props |
|
|
340
|
+
| `Server` | Transparent passthrough (Fragment) |
|
|
341
|
+
| `useRouter`, `useParams` | Static no-ops (return empty objects) |
|
|
342
|
+
| `BrodoxHead`, `BrodoxFont` | null |
|
|
343
|
+
|
|
344
|
+
**Important:** If you compile a component and the rendered `<a>` tags do not
|
|
345
|
+
have `data-brodox-link`, the shell will not intercept clicks on those links and
|
|
346
|
+
the browser will do a full page reload. This was fixed in v1.3.2 — ensure all
|
|
347
|
+
projects use `@broxium/compiler@^1.3.2` or later. Existing pre-1.3.2 server
|
|
348
|
+
bundles must be patched manually or recompiled.
|
|
349
|
+
|
|
350
|
+
---
|
|
351
|
+
|
|
241
352
|
## Package info
|
|
242
353
|
|
|
243
354
|
| | |
|
|
244
355
|
|---|---|
|
|
245
356
|
| Package | `@broxium/compiler` |
|
|
246
|
-
| Version | `1.
|
|
357
|
+
| Version | `1.3.3` |
|
|
247
358
|
| Formats | ESM (`dist/index.mjs`), CJS (`dist/index.js`) |
|
|
248
359
|
| Types | `dist/index.d.ts` |
|
|
249
360
|
| Runtime dependency | `esbuild ^0.25` |
|
|
250
361
|
| Node.js requirement | 20+ |
|
|
251
362
|
| Side effects | Writes files to `outputDir`, creates/removes temp directory |
|
|
363
|
+
|
|
364
|
+
## Changelog
|
|
365
|
+
|
|
366
|
+
| Version | Change |
|
|
367
|
+
|---|---|
|
|
368
|
+
| 1.3.3 | `BrodoxImage` stub: added `direct` prop support |
|
|
369
|
+
| 1.3.2 | `BrodoxLink` stub: added `data-brodox-link` attribute |
|
|
370
|
+
| 1.3.1 | Initial public release |
|
package/dist/index.d.mts
CHANGED
|
@@ -13,8 +13,12 @@ interface CompileInput {
|
|
|
13
13
|
interface CompileOutput {
|
|
14
14
|
serverJsPath: string;
|
|
15
15
|
clientJsPath: string;
|
|
16
|
+
/** Compiled CSS bundle path, or null if no CSS files were imported. */
|
|
17
|
+
cssPath: string | null;
|
|
16
18
|
serverJsName: string;
|
|
17
19
|
clientJsName: string;
|
|
20
|
+
/** CSS bundle filename, or null if no CSS files were imported. */
|
|
21
|
+
cssName: string | null;
|
|
18
22
|
compiledAt: Date;
|
|
19
23
|
}
|
|
20
24
|
|
package/dist/index.d.ts
CHANGED
|
@@ -13,8 +13,12 @@ interface CompileInput {
|
|
|
13
13
|
interface CompileOutput {
|
|
14
14
|
serverJsPath: string;
|
|
15
15
|
clientJsPath: string;
|
|
16
|
+
/** Compiled CSS bundle path, or null if no CSS files were imported. */
|
|
17
|
+
cssPath: string | null;
|
|
16
18
|
serverJsName: string;
|
|
17
19
|
clientJsName: string;
|
|
20
|
+
/** CSS bundle filename, or null if no CSS files were imported. */
|
|
21
|
+
cssName: string | null;
|
|
18
22
|
compiledAt: Date;
|
|
19
23
|
}
|
|
20
24
|
|
package/dist/index.js
CHANGED
|
@@ -154,9 +154,31 @@ export function useRouter() {
|
|
|
154
154
|
|
|
155
155
|
export function useParams() { return {}; }
|
|
156
156
|
|
|
157
|
-
export function BrodoxHead(
|
|
157
|
+
export function BrodoxHead({ title, description, cssContent }) {
|
|
158
|
+
if (title && typeof globalThis.__brodoxCollectHead === 'function')
|
|
159
|
+
globalThis.__brodoxCollectHead({ type: 'title', props: { content: title } });
|
|
160
|
+
if (description && typeof globalThis.__brodoxCollectHead === 'function')
|
|
161
|
+
globalThis.__brodoxCollectHead({ type: 'meta', props: { name: 'description', content: description } });
|
|
162
|
+
if (cssContent && typeof globalThis.__brodoxCollectHead === 'function')
|
|
163
|
+
globalThis.__brodoxCollectHead({ type: 'style', props: { content: cssContent } });
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
158
166
|
|
|
159
|
-
export function BrodoxFont(
|
|
167
|
+
export function BrodoxFont({ href, family, weights, display }) {
|
|
168
|
+
weights = weights || [400, 700];
|
|
169
|
+
display = display || 'swap';
|
|
170
|
+
var url = href;
|
|
171
|
+
if (!url && family) {
|
|
172
|
+
url = 'https://fonts.googleapis.com/css2?family='
|
|
173
|
+
+ encodeURIComponent(family) + ':wght@' + weights.join(';') + '&display=' + display;
|
|
174
|
+
}
|
|
175
|
+
if (url && typeof globalThis.__brodoxCollectHead === 'function') {
|
|
176
|
+
globalThis.__brodoxCollectHead({ type: 'link', props: { rel: 'preconnect', href: 'https://fonts.googleapis.com' } });
|
|
177
|
+
globalThis.__brodoxCollectHead({ type: 'link', props: { rel: 'preconnect', href: 'https://fonts.gstatic.com', crossOrigin: 'anonymous' } });
|
|
178
|
+
globalThis.__brodoxCollectHead({ type: 'link', props: { rel: 'stylesheet', href: url } });
|
|
179
|
+
}
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
160
182
|
|
|
161
183
|
export function BrodoxRouter({ children }) {
|
|
162
184
|
return createElement(Fragment, null, children);
|
|
@@ -170,7 +192,7 @@ export function BrodoxRouter({ children }) {
|
|
|
170
192
|
* The IslandHydrator walks the live DOM and mounts the component from the
|
|
171
193
|
* parent bundle's __registry__ after page load.
|
|
172
194
|
*/
|
|
173
|
-
export function Client({ children }) {
|
|
195
|
+
export function Client({ children, hydration = 'load' }) {
|
|
174
196
|
var id = __nextIslandId();
|
|
175
197
|
var child = Children.only(children);
|
|
176
198
|
var compType = child.type;
|
|
@@ -185,13 +207,13 @@ export function Client({ children }) {
|
|
|
185
207
|
return createElement(Fragment, null,
|
|
186
208
|
createElement('div', {
|
|
187
209
|
'data-brodox-island': id,
|
|
188
|
-
'data-hydration':
|
|
210
|
+
'data-hydration': hydration,
|
|
189
211
|
'data-client-js': '',
|
|
190
212
|
'data-component-slug': '',
|
|
191
213
|
'data-version': '',
|
|
192
214
|
'data-component': name,
|
|
193
215
|
}),
|
|
194
|
-
createElement('script', {
|
|
216
|
+
hydration === 'none' ? null : createElement('script', {
|
|
195
217
|
type: 'application/json',
|
|
196
218
|
'data-brodox-props': id,
|
|
197
219
|
dangerouslySetInnerHTML: { __html: safeProps },
|
|
@@ -303,7 +325,9 @@ var BrodoxCompiler = class {
|
|
|
303
325
|
outfile: serverJsPath,
|
|
304
326
|
minify: false,
|
|
305
327
|
sourcemap: false,
|
|
306
|
-
define: { "process.env.NODE_ENV": '"production"' }
|
|
328
|
+
define: { "process.env.NODE_ENV": '"production"' },
|
|
329
|
+
loader: { ".css": "text" }
|
|
330
|
+
// CSS imports return empty string in server bundle
|
|
307
331
|
});
|
|
308
332
|
const clientComponents = [];
|
|
309
333
|
for (const file of input.files) {
|
|
@@ -341,14 +365,47 @@ ${registryEntries}
|
|
|
341
365
|
minify: true,
|
|
342
366
|
sourcemap: false,
|
|
343
367
|
define: { "process.env.NODE_ENV": '"production"' },
|
|
344
|
-
banner: { js: 'import React from "react";' }
|
|
368
|
+
banner: { js: 'import React from "react";' },
|
|
369
|
+
loader: { ".css": "text" }
|
|
370
|
+
// CSS imports return the CSS string (injected via BrodoxHead or style tag)
|
|
345
371
|
});
|
|
372
|
+
const hasCss = input.files.some((f) => /\.css$/.test(f.path));
|
|
373
|
+
const cssName = hasCss ? `${safeName}.css` : null;
|
|
374
|
+
const cssPath = hasCss ? import_node_path3.default.join(input.outputDir, cssName) : null;
|
|
375
|
+
if (hasCss && cssPath) {
|
|
376
|
+
try {
|
|
377
|
+
await esbuild.build({
|
|
378
|
+
entryPoints: [entryPoint],
|
|
379
|
+
bundle: true,
|
|
380
|
+
format: "esm",
|
|
381
|
+
platform: "browser",
|
|
382
|
+
jsx: "automatic",
|
|
383
|
+
external: CLIENT_EXTERNALS,
|
|
384
|
+
plugins: [serverStubPlugin()],
|
|
385
|
+
outfile: cssPath.replace(/\.css$/, ".css.tmp.js"),
|
|
386
|
+
// esbuild needs a JS outfile
|
|
387
|
+
minify: true,
|
|
388
|
+
sourcemap: false,
|
|
389
|
+
define: { "process.env.NODE_ENV": '"production"' },
|
|
390
|
+
loader: { ".css": "css" }
|
|
391
|
+
});
|
|
392
|
+
const defaultCssOut = cssPath.replace(/\.css$/, ".css.tmp.css");
|
|
393
|
+
try {
|
|
394
|
+
await import_promises3.default.rename(defaultCssOut, cssPath);
|
|
395
|
+
} catch {
|
|
396
|
+
}
|
|
397
|
+
await import_promises3.default.rm(cssPath.replace(/\.css$/, ".css.tmp.js"), { force: true });
|
|
398
|
+
} catch {
|
|
399
|
+
}
|
|
400
|
+
}
|
|
346
401
|
await import_promises3.default.rm(tmpDir, { recursive: true, force: true });
|
|
347
402
|
return {
|
|
348
403
|
serverJsPath,
|
|
349
404
|
clientJsPath,
|
|
405
|
+
cssPath,
|
|
350
406
|
serverJsName,
|
|
351
407
|
clientJsName,
|
|
408
|
+
cssName,
|
|
352
409
|
compiledAt: /* @__PURE__ */ new Date()
|
|
353
410
|
};
|
|
354
411
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -125,9 +125,31 @@ export function useRouter() {
|
|
|
125
125
|
|
|
126
126
|
export function useParams() { return {}; }
|
|
127
127
|
|
|
128
|
-
export function BrodoxHead(
|
|
128
|
+
export function BrodoxHead({ title, description, cssContent }) {
|
|
129
|
+
if (title && typeof globalThis.__brodoxCollectHead === 'function')
|
|
130
|
+
globalThis.__brodoxCollectHead({ type: 'title', props: { content: title } });
|
|
131
|
+
if (description && typeof globalThis.__brodoxCollectHead === 'function')
|
|
132
|
+
globalThis.__brodoxCollectHead({ type: 'meta', props: { name: 'description', content: description } });
|
|
133
|
+
if (cssContent && typeof globalThis.__brodoxCollectHead === 'function')
|
|
134
|
+
globalThis.__brodoxCollectHead({ type: 'style', props: { content: cssContent } });
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
129
137
|
|
|
130
|
-
export function BrodoxFont(
|
|
138
|
+
export function BrodoxFont({ href, family, weights, display }) {
|
|
139
|
+
weights = weights || [400, 700];
|
|
140
|
+
display = display || 'swap';
|
|
141
|
+
var url = href;
|
|
142
|
+
if (!url && family) {
|
|
143
|
+
url = 'https://fonts.googleapis.com/css2?family='
|
|
144
|
+
+ encodeURIComponent(family) + ':wght@' + weights.join(';') + '&display=' + display;
|
|
145
|
+
}
|
|
146
|
+
if (url && typeof globalThis.__brodoxCollectHead === 'function') {
|
|
147
|
+
globalThis.__brodoxCollectHead({ type: 'link', props: { rel: 'preconnect', href: 'https://fonts.googleapis.com' } });
|
|
148
|
+
globalThis.__brodoxCollectHead({ type: 'link', props: { rel: 'preconnect', href: 'https://fonts.gstatic.com', crossOrigin: 'anonymous' } });
|
|
149
|
+
globalThis.__brodoxCollectHead({ type: 'link', props: { rel: 'stylesheet', href: url } });
|
|
150
|
+
}
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
131
153
|
|
|
132
154
|
export function BrodoxRouter({ children }) {
|
|
133
155
|
return createElement(Fragment, null, children);
|
|
@@ -141,7 +163,7 @@ export function BrodoxRouter({ children }) {
|
|
|
141
163
|
* The IslandHydrator walks the live DOM and mounts the component from the
|
|
142
164
|
* parent bundle's __registry__ after page load.
|
|
143
165
|
*/
|
|
144
|
-
export function Client({ children }) {
|
|
166
|
+
export function Client({ children, hydration = 'load' }) {
|
|
145
167
|
var id = __nextIslandId();
|
|
146
168
|
var child = Children.only(children);
|
|
147
169
|
var compType = child.type;
|
|
@@ -156,13 +178,13 @@ export function Client({ children }) {
|
|
|
156
178
|
return createElement(Fragment, null,
|
|
157
179
|
createElement('div', {
|
|
158
180
|
'data-brodox-island': id,
|
|
159
|
-
'data-hydration':
|
|
181
|
+
'data-hydration': hydration,
|
|
160
182
|
'data-client-js': '',
|
|
161
183
|
'data-component-slug': '',
|
|
162
184
|
'data-version': '',
|
|
163
185
|
'data-component': name,
|
|
164
186
|
}),
|
|
165
|
-
createElement('script', {
|
|
187
|
+
hydration === 'none' ? null : createElement('script', {
|
|
166
188
|
type: 'application/json',
|
|
167
189
|
'data-brodox-props': id,
|
|
168
190
|
dangerouslySetInnerHTML: { __html: safeProps },
|
|
@@ -274,7 +296,9 @@ var BrodoxCompiler = class {
|
|
|
274
296
|
outfile: serverJsPath,
|
|
275
297
|
minify: false,
|
|
276
298
|
sourcemap: false,
|
|
277
|
-
define: { "process.env.NODE_ENV": '"production"' }
|
|
299
|
+
define: { "process.env.NODE_ENV": '"production"' },
|
|
300
|
+
loader: { ".css": "text" }
|
|
301
|
+
// CSS imports return empty string in server bundle
|
|
278
302
|
});
|
|
279
303
|
const clientComponents = [];
|
|
280
304
|
for (const file of input.files) {
|
|
@@ -312,14 +336,47 @@ ${registryEntries}
|
|
|
312
336
|
minify: true,
|
|
313
337
|
sourcemap: false,
|
|
314
338
|
define: { "process.env.NODE_ENV": '"production"' },
|
|
315
|
-
banner: { js: 'import React from "react";' }
|
|
339
|
+
banner: { js: 'import React from "react";' },
|
|
340
|
+
loader: { ".css": "text" }
|
|
341
|
+
// CSS imports return the CSS string (injected via BrodoxHead or style tag)
|
|
316
342
|
});
|
|
343
|
+
const hasCss = input.files.some((f) => /\.css$/.test(f.path));
|
|
344
|
+
const cssName = hasCss ? `${safeName}.css` : null;
|
|
345
|
+
const cssPath = hasCss ? path3.join(input.outputDir, cssName) : null;
|
|
346
|
+
if (hasCss && cssPath) {
|
|
347
|
+
try {
|
|
348
|
+
await esbuild.build({
|
|
349
|
+
entryPoints: [entryPoint],
|
|
350
|
+
bundle: true,
|
|
351
|
+
format: "esm",
|
|
352
|
+
platform: "browser",
|
|
353
|
+
jsx: "automatic",
|
|
354
|
+
external: CLIENT_EXTERNALS,
|
|
355
|
+
plugins: [serverStubPlugin()],
|
|
356
|
+
outfile: cssPath.replace(/\.css$/, ".css.tmp.js"),
|
|
357
|
+
// esbuild needs a JS outfile
|
|
358
|
+
minify: true,
|
|
359
|
+
sourcemap: false,
|
|
360
|
+
define: { "process.env.NODE_ENV": '"production"' },
|
|
361
|
+
loader: { ".css": "css" }
|
|
362
|
+
});
|
|
363
|
+
const defaultCssOut = cssPath.replace(/\.css$/, ".css.tmp.css");
|
|
364
|
+
try {
|
|
365
|
+
await fs3.rename(defaultCssOut, cssPath);
|
|
366
|
+
} catch {
|
|
367
|
+
}
|
|
368
|
+
await fs3.rm(cssPath.replace(/\.css$/, ".css.tmp.js"), { force: true });
|
|
369
|
+
} catch {
|
|
370
|
+
}
|
|
371
|
+
}
|
|
317
372
|
await fs3.rm(tmpDir, { recursive: true, force: true });
|
|
318
373
|
return {
|
|
319
374
|
serverJsPath,
|
|
320
375
|
clientJsPath,
|
|
376
|
+
cssPath,
|
|
321
377
|
serverJsName,
|
|
322
378
|
clientJsName,
|
|
379
|
+
cssName,
|
|
323
380
|
compiledAt: /* @__PURE__ */ new Date()
|
|
324
381
|
};
|
|
325
382
|
}
|