@quilted/rollup 0.1.4 → 0.1.5

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 (63) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/build/cjs/app.cjs +144 -142
  3. package/build/cjs/features/assets.cjs +130 -0
  4. package/build/cjs/{env.cjs → features/env.cjs} +4 -4
  5. package/build/cjs/{request-router.cjs → features/request-router.cjs} +3 -3
  6. package/build/cjs/{shared → features}/source-code.cjs +1 -1
  7. package/build/cjs/features/system-js.cjs +35 -0
  8. package/build/cjs/index.cjs +0 -7
  9. package/build/cjs/shared/rollup.cjs +0 -4
  10. package/build/esm/app.mjs +146 -144
  11. package/build/esm/features/assets.mjs +107 -0
  12. package/build/esm/{env.mjs → features/env.mjs} +4 -4
  13. package/build/esm/{request-router.mjs → features/request-router.mjs} +3 -3
  14. package/build/esm/features/system-js.mjs +33 -0
  15. package/build/esm/index.mjs +1 -3
  16. package/build/esm/shared/rollup.mjs +1 -4
  17. package/build/esnext/app.esnext +146 -144
  18. package/build/esnext/features/assets.esnext +107 -0
  19. package/build/esnext/{env.esnext → features/env.esnext} +4 -4
  20. package/build/esnext/{request-router.esnext → features/request-router.esnext} +3 -3
  21. package/build/esnext/features/system-js.esnext +33 -0
  22. package/build/esnext/index.esnext +1 -3
  23. package/build/esnext/shared/rollup.esnext +1 -4
  24. package/build/tsconfig.tsbuildinfo +1 -1
  25. package/build/typescript/app.d.ts +32 -144
  26. package/build/typescript/app.d.ts.map +1 -1
  27. package/build/typescript/features/assets.d.ts +13 -0
  28. package/build/typescript/features/assets.d.ts.map +1 -0
  29. package/build/typescript/features/css.d.ts +16 -0
  30. package/build/typescript/features/css.d.ts.map +1 -0
  31. package/build/typescript/features/env.d.ts +57 -0
  32. package/build/typescript/features/env.d.ts.map +1 -0
  33. package/build/typescript/features/graphql/transform.d.ts +17 -0
  34. package/build/typescript/features/graphql/transform.d.ts.map +1 -0
  35. package/build/typescript/features/graphql.d.ts +6 -0
  36. package/build/typescript/features/graphql.d.ts.map +1 -0
  37. package/build/typescript/features/request-router.d.ts +15 -0
  38. package/build/typescript/features/request-router.d.ts.map +1 -0
  39. package/build/typescript/features/source-code.d.ts +5 -0
  40. package/build/typescript/features/source-code.d.ts.map +1 -0
  41. package/build/typescript/features/system-js.d.ts +7 -0
  42. package/build/typescript/features/system-js.d.ts.map +1 -0
  43. package/build/typescript/index.d.ts +1 -3
  44. package/build/typescript/index.d.ts.map +1 -1
  45. package/package.json +5 -2
  46. package/source/app.ts +168 -124
  47. package/source/features/assets.ts +183 -0
  48. package/source/features/css.ts +91 -0
  49. package/source/{env.ts → features/env.ts} +4 -4
  50. package/source/{request-router.ts → features/request-router.ts} +3 -3
  51. package/source/features/system-js.ts +36 -0
  52. package/source/index.ts +0 -5
  53. /package/build/cjs/{graphql → features/graphql}/transform.cjs +0 -0
  54. /package/build/cjs/{graphql.cjs → features/graphql.cjs} +0 -0
  55. /package/build/esm/{graphql → features/graphql}/transform.mjs +0 -0
  56. /package/build/esm/{graphql.mjs → features/graphql.mjs} +0 -0
  57. /package/build/esm/{shared → features}/source-code.mjs +0 -0
  58. /package/build/esnext/{graphql → features/graphql}/transform.esnext +0 -0
  59. /package/build/esnext/{graphql.esnext → features/graphql.esnext} +0 -0
  60. /package/build/esnext/{shared → features}/source-code.esnext +0 -0
  61. /package/source/{graphql → features/graphql}/transform.ts +0 -0
  62. /package/source/{graphql.ts → features/graphql.ts} +0 -0
  63. /package/source/{shared → features}/source-code.ts +0 -0
package/source/app.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as path from 'path';
2
2
 
3
- import type {GetManualChunk, Plugin} from 'rollup';
3
+ import type {Plugin, RollupOptions, GetManualChunk} from 'rollup';
4
4
 
5
5
  import {
6
6
  MAGIC_MODULE_ENTRY,
@@ -8,10 +8,10 @@ import {
8
8
  MAGIC_MODULE_BROWSER_ASSETS,
9
9
  MAGIC_MODULE_REQUEST_ROUTER,
10
10
  } from './constants.ts';
11
- import type {MagicModuleEnvOptions} from './env.ts';
11
+ import type {MagicModuleEnvOptions} from './features/env.ts';
12
12
 
13
13
  import {multiline} from './shared/strings.ts';
14
- import {getNodePlugins, rollupPluginsToArray} from './shared/rollup.ts';
14
+ import {getNodePlugins} from './shared/rollup.ts';
15
15
  import {createMagicModulePlugin} from './shared/magic-module.ts';
16
16
 
17
17
  export interface AppOptions {
@@ -22,8 +22,9 @@ export interface AppOptions {
22
22
  * to create browser and server-side entries for your project.
23
23
  *
24
24
  * If you only want to use a custom entry module for the browser build, use the
25
- * `browser.entry` option instead. If you only want to use a custom entry module
26
- * for the server-side build, use the `server.entry` option instead.
25
+ * `entry` option of the `quiltAppBrowser()` instead. If you only want to use a
26
+ * custom entry module for the server-side build, use the `server.entry` option
27
+ * instead.
27
28
  *
28
29
  * @example './App.tsx'
29
30
  */
@@ -46,7 +47,18 @@ export interface AppOptions {
46
47
 
47
48
  export interface AppBrowserOptions extends AppOptions {
48
49
  /**
49
- * Customizes the magic `quilt:module/browser` entry module.
50
+ * The entry module for this browser. This should be an absolute path, or relative
51
+ * path from the root directory containing your project. This entry should be the
52
+ * browser entrypoint.
53
+ *
54
+ * @example './browser.tsx'
55
+ * @default 'quilt:module/entry'
56
+ */
57
+ entry?: string;
58
+
59
+ /**
60
+ * Customizes the magic `quilt:module/entry` module, which can be used as a "magic"
61
+ * entry for your application.
50
62
  */
51
63
  module?: AppBrowserModuleOptions;
52
64
 
@@ -81,8 +93,9 @@ export interface AppBrowserAssetsOptions {
81
93
  minify?: boolean;
82
94
  }
83
95
 
84
- export function quiltAppBrowser({
96
+ export async function quiltAppBrowser({
85
97
  app,
98
+ entry = MAGIC_MODULE_ENTRY,
86
99
  env,
87
100
  assets,
88
101
  module,
@@ -90,78 +103,82 @@ export function quiltAppBrowser({
90
103
  }: AppBrowserOptions = {}) {
91
104
  const mode =
92
105
  (typeof env === 'object' ? env?.mode : undefined) ?? 'production';
106
+ const minify = assets?.minify ?? true;
107
+
108
+ const [
109
+ {visualizer},
110
+ {sourceCode},
111
+ {rawAssets, staticAssets},
112
+ {systemJS},
113
+ nodePlugins,
114
+ ] = await Promise.all([
115
+ import('rollup-plugin-visualizer'),
116
+ import('./features/source-code.ts'),
117
+ import('./features/assets.ts'),
118
+ import('./features/system-js.ts'),
119
+ getNodePlugins(),
120
+ ]);
121
+
122
+ const plugins: Plugin[] = [
123
+ ...nodePlugins,
124
+ systemJS(),
125
+ sourceCode({mode}),
126
+ rawAssets(),
127
+ staticAssets(),
128
+ ];
129
+
130
+ if (env) {
131
+ const {magicModuleEnv, replaceProcessEnv} = await import(
132
+ './features/env.ts'
133
+ );
134
+
135
+ if (typeof env === 'boolean') {
136
+ plugins.push(replaceProcessEnv({mode}));
137
+ plugins.push(magicModuleEnv({mode}));
138
+ } else {
139
+ plugins.push(replaceProcessEnv({mode}));
140
+ plugins.push(magicModuleEnv({mode}));
141
+ }
142
+ }
93
143
 
94
- return {
95
- name: '@quilted/app/browser',
96
- async options(originalOptions) {
97
- const newPlugins = rollupPluginsToArray(originalOptions.plugins);
98
- const newOptions = {...originalOptions, plugins: newPlugins};
99
-
100
- const [{visualizer}, {sourceCode}, nodePlugins] = await Promise.all([
101
- import('rollup-plugin-visualizer'),
102
- import('./shared/source-code.ts'),
103
- getNodePlugins(),
104
- ]);
105
-
106
- newPlugins.push(...nodePlugins);
107
- newPlugins.push(sourceCode({mode}));
108
-
109
- if (env) {
110
- const {magicModuleEnv, replaceProcessEnv} = await import('./env.ts');
111
-
112
- if (typeof env === 'boolean') {
113
- newPlugins.push(replaceProcessEnv({mode: 'production'}));
114
- newPlugins.push(magicModuleEnv({mode: 'production'}));
115
- } else {
116
- newPlugins.push(replaceProcessEnv({mode: env.mode ?? 'production'}));
117
- newPlugins.push(magicModuleEnv({mode: 'production', ...env}));
118
- }
119
- }
120
-
121
- if (app) {
122
- newPlugins.push(magicModuleAppComponent({entry: app}));
123
- }
124
-
125
- newPlugins.push(magicModuleAppBrowserEntry(module));
144
+ if (app) {
145
+ plugins.push(magicModuleAppComponent({entry: app}));
146
+ }
126
147
 
127
- if (graphql) {
128
- const {graphql} = await import('./graphql.ts');
129
- newPlugins.push(
130
- graphql({manifest: path.resolve(`manifests/graphql.json`)}),
131
- );
132
- }
148
+ plugins.push(magicModuleAppBrowserEntry(module));
133
149
 
134
- const minify = assets?.minify ?? true;
150
+ if (graphql) {
151
+ const {graphql} = await import('./features/graphql.ts');
152
+ plugins.push(graphql({manifest: path.resolve(`manifests/graphql.json`)}));
153
+ }
135
154
 
136
- if (minify) {
137
- const {minify} = await import('rollup-plugin-esbuild');
138
- newPlugins.push(minify());
139
- }
155
+ if (minify) {
156
+ const {minify} = await import('rollup-plugin-esbuild');
157
+ plugins.push(minify());
158
+ }
140
159
 
141
- newPlugins.push(
142
- visualizer({
143
- template: 'treemap',
144
- open: false,
145
- brotliSize: true,
146
- filename: path.resolve(`reports/bundle-visualizer.html`),
147
- }),
148
- );
160
+ plugins.push(
161
+ visualizer({
162
+ template: 'treemap',
163
+ open: false,
164
+ brotliSize: true,
165
+ filename: path.resolve(`reports/bundle-visualizer.html`),
166
+ }),
167
+ );
149
168
 
150
- return newOptions;
151
- },
152
- outputOptions(originalOptions) {
153
- return {
154
- ...originalOptions,
155
- // format: isESM ? 'esm' : 'systemjs',
156
- format: 'esm',
157
- dir: path.resolve(`build/assets`),
158
- entryFileNames: `app.[hash].js`,
159
- assetFileNames: `[name].[hash].[ext]`,
160
- chunkFileNames: `[name].[hash].js`,
161
- manualChunks: createManualChunksSorter(),
162
- };
169
+ return {
170
+ input: entry,
171
+ plugins,
172
+ output: {
173
+ // format: isESM ? 'esm' : 'systemjs',
174
+ format: 'esm',
175
+ dir: path.resolve(`build/assets`),
176
+ entryFileNames: `app.[hash].js`,
177
+ assetFileNames: `[name].[hash].[ext]`,
178
+ chunkFileNames: `[name].[hash].js`,
179
+ manualChunks: createManualChunksSorter(),
163
180
  },
164
- } satisfies Plugin;
181
+ } satisfies RollupOptions;
165
182
  }
166
183
 
167
184
  export interface AppServerOptions extends AppOptions {
@@ -171,69 +188,96 @@ export interface AppServerOptions extends AppOptions {
171
188
  * the specific server runtime you configure.
172
189
  */
173
190
  entry?: string;
191
+
192
+ /**
193
+ * Whether to minify the JavaScript outputs for your server.
194
+ *
195
+ * @default false
196
+ */
197
+ minify?: boolean;
174
198
  }
175
199
 
176
- export function quiltAppServer({
200
+ export async function quiltAppServer({
177
201
  app,
178
202
  env,
179
203
  graphql,
180
- entry,
204
+ entry = MAGIC_MODULE_ENTRY,
205
+ minify = false,
181
206
  }: AppServerOptions = {}) {
182
207
  const mode =
183
208
  (typeof env === 'object' ? env?.mode : undefined) ?? 'production';
184
209
 
185
- return {
186
- name: '@quilted/app/server',
187
- async options(originalOptions) {
188
- const newPlugins = rollupPluginsToArray(originalOptions.plugins);
189
- const newOptions = {...originalOptions, plugins: newPlugins};
190
-
191
- const [{magicModuleRequestRouterEntry}, {sourceCode}, nodePlugins] =
192
- await Promise.all([
193
- import('./request-router.ts'),
194
- import('./shared/source-code.ts'),
195
- getNodePlugins(),
196
- ]);
197
-
198
- newPlugins.push(...nodePlugins);
199
- newPlugins.push(sourceCode({mode}));
200
-
201
- if (env) {
202
- const {magicModuleEnv, replaceProcessEnv} = await import('./env.ts');
203
-
204
- if (typeof env === 'boolean') {
205
- newPlugins.push(replaceProcessEnv({mode}));
206
- newPlugins.push(magicModuleEnv({mode}));
207
- } else {
208
- newPlugins.push(replaceProcessEnv({mode}));
209
- newPlugins.push(magicModuleEnv({mode, ...env}));
210
- }
211
- }
212
-
213
- if (app) {
214
- newPlugins.push(magicModuleAppComponent({entry: app}));
215
- }
216
-
217
- newPlugins.push(magicModuleRequestRouterEntry());
218
- newPlugins.push(magicModuleAppRequestRouter({entry}));
219
-
220
- if (graphql) {
221
- const {graphql} = await import('./graphql.ts');
222
- newPlugins.push(graphql({manifest: false}));
223
- }
210
+ const [
211
+ {visualizer},
212
+ {sourceCode},
213
+ {rawAssets, staticAssets},
214
+ {magicModuleRequestRouterEntry},
215
+ nodePlugins,
216
+ ] = await Promise.all([
217
+ import('rollup-plugin-visualizer'),
218
+ import('./features/source-code.ts'),
219
+ import('./features/assets.ts'),
220
+ import('./features/request-router.ts'),
221
+ getNodePlugins(),
222
+ ]);
223
+
224
+ const plugins: Plugin[] = [
225
+ ...nodePlugins,
226
+ sourceCode({mode}),
227
+ rawAssets(),
228
+ staticAssets({emit: false}),
229
+ ];
230
+
231
+ if (env) {
232
+ const {magicModuleEnv, replaceProcessEnv} = await import(
233
+ './features/env.ts'
234
+ );
235
+
236
+ if (typeof env === 'boolean') {
237
+ plugins.push(replaceProcessEnv({mode}));
238
+ plugins.push(magicModuleEnv({mode}));
239
+ } else {
240
+ plugins.push(replaceProcessEnv({mode}));
241
+ plugins.push(magicModuleEnv({mode}));
242
+ }
243
+ }
244
+
245
+ if (app) {
246
+ plugins.push(magicModuleAppComponent({entry: app}));
247
+ }
248
+
249
+ plugins.push(magicModuleRequestRouterEntry());
250
+ plugins.push(magicModuleAppRequestRouter({entry}));
251
+
252
+ if (graphql) {
253
+ const {graphql} = await import('./features/graphql.ts');
254
+ plugins.push(graphql({manifest: false}));
255
+ }
256
+
257
+ if (minify) {
258
+ const {minify} = await import('rollup-plugin-esbuild');
259
+ plugins.push(minify());
260
+ }
261
+
262
+ plugins.push(
263
+ visualizer({
264
+ template: 'treemap',
265
+ open: false,
266
+ brotliSize: true,
267
+ filename: path.resolve(`reports/bundle-visualizer.html`),
268
+ }),
269
+ );
224
270
 
225
- return newOptions;
226
- },
227
- outputOptions(originalOptions) {
228
- return {
229
- ...originalOptions,
230
- // format,
231
- format: 'esm',
232
- dir: path.resolve(`build/server`),
233
- entryFileNames: 'server.js',
234
- };
271
+ return {
272
+ input: entry,
273
+ plugins,
274
+ output: {
275
+ // format: isESM ? 'esm' : 'systemjs',
276
+ format: 'esm',
277
+ dir: path.resolve(`build/server`),
278
+ entryFileNames: 'server.js',
235
279
  },
236
- } satisfies Plugin;
280
+ } satisfies RollupOptions;
237
281
  }
238
282
 
239
283
  export function magicModuleAppComponent({entry}: {entry: string}) {
@@ -0,0 +1,183 @@
1
+ import * as path from 'path';
2
+ import {readFile} from 'fs/promises';
3
+ import {createHash} from 'crypto';
4
+
5
+ import type {Plugin} from 'rollup';
6
+ import * as mime from 'mrmime';
7
+
8
+ const QUERY_PATTERN = /\?.*$/s;
9
+ const HASH_PATTERN = /#.*$/s;
10
+ const RAW_PATTERN = /(\?|&)raw(?:&|$)/;
11
+
12
+ const DEFAULT_INLINE_LIMIT = 4096;
13
+ const DEFAULT_OUTPUT_PATTERN = '[name].[hash].[ext]';
14
+ const DEFAULT_STATIC_ASSET_EXTENSIONS = [
15
+ // images
16
+ '.png',
17
+ '.jpg',
18
+ '.jpeg',
19
+ '.gif',
20
+ '.svg',
21
+ '.ico',
22
+ '.webp',
23
+ '.avif',
24
+
25
+ // media
26
+ '.mp4',
27
+ '.webm',
28
+ '.ogg',
29
+ '.mp3',
30
+ '.wav',
31
+ '.flac',
32
+ '.aac',
33
+
34
+ // fonts
35
+ '.woff',
36
+ '.woff2',
37
+ '.eot',
38
+ '.ttf',
39
+ '.otf',
40
+
41
+ // other
42
+ '.webmanifest',
43
+ '.pdf',
44
+ '.txt',
45
+ ];
46
+
47
+ export function rawAssets(): Plugin {
48
+ return {
49
+ name: '@quilted/raw-assets',
50
+ async load(id) {
51
+ if (id.startsWith('\0') || !RAW_PATTERN.test(id)) {
52
+ return null;
53
+ }
54
+
55
+ const moduleId = cleanModuleIdentifier(id);
56
+
57
+ this.addWatchFile(moduleId);
58
+
59
+ const file = await readFile(moduleId, {
60
+ encoding: 'utf-8',
61
+ });
62
+
63
+ return `export default ${JSON.stringify(file)}`;
64
+ },
65
+ };
66
+ }
67
+
68
+ export function staticAssets({
69
+ emit = true,
70
+ baseURL = '/',
71
+ extensions = DEFAULT_STATIC_ASSET_EXTENSIONS,
72
+ inlineLimit = DEFAULT_INLINE_LIMIT,
73
+ outputPattern = DEFAULT_OUTPUT_PATTERN,
74
+ }: {
75
+ emit?: boolean;
76
+ baseURL?: string;
77
+ extensions?: readonly string[];
78
+ inlineLimit?: number;
79
+ outputPattern?: string;
80
+ } = {}) {
81
+ const assetCache = new Map<string, string>();
82
+ const assetMatcher = new RegExp(
83
+ `\\.(` +
84
+ extensions
85
+ .map((extension) =>
86
+ extension.startsWith('.') ? extension.slice(1) : extension,
87
+ )
88
+ .join('|') +
89
+ `)(\\?.*)?$`,
90
+ );
91
+
92
+ return {
93
+ name: '@quilted/static-assets',
94
+ async load(id) {
95
+ if (id.startsWith('\0') || !assetMatcher.test(id)) {
96
+ return null;
97
+ }
98
+
99
+ const cached = assetCache.get(id);
100
+
101
+ if (cached) {
102
+ return cached;
103
+ }
104
+
105
+ const file = cleanModuleIdentifier(id);
106
+ const content = await readFile(file);
107
+
108
+ let url: string;
109
+
110
+ if (!file.endsWith('.svg') && content.length < inlineLimit) {
111
+ // base64 inlined as a string
112
+ url = `data:${mime.lookup(file)};base64,${content.toString('base64')}`;
113
+ } else {
114
+ const contentHash = getHash(content);
115
+
116
+ const filename = assetFileNamesToFileName(
117
+ outputPattern,
118
+ file,
119
+ contentHash,
120
+ );
121
+
122
+ url = `${
123
+ baseURL.endsWith('/') ? baseURL.slice(0, -1) : baseURL
124
+ }/${filename}`;
125
+
126
+ if (emit) {
127
+ this.emitFile({
128
+ name: file,
129
+ type: 'asset',
130
+ fileName: filename,
131
+ source: content,
132
+ });
133
+ }
134
+ }
135
+
136
+ const source = `export default ${JSON.stringify(url)};`;
137
+
138
+ assetCache.set(id, source);
139
+
140
+ return source;
141
+ },
142
+ } satisfies Plugin;
143
+ }
144
+
145
+ function assetFileNamesToFileName(
146
+ pattern: string,
147
+ file: string,
148
+ contentHash: string,
149
+ ): string {
150
+ const basename = path.basename(file);
151
+
152
+ const extname = path.extname(basename);
153
+ const ext = extname.substring(1);
154
+ const name = basename.slice(0, -extname.length);
155
+ const hash = contentHash;
156
+
157
+ return pattern.replace(/\[\w+\]/g, (placeholder) => {
158
+ switch (placeholder) {
159
+ case '[ext]':
160
+ return ext;
161
+
162
+ case '[extname]':
163
+ return extname;
164
+
165
+ case '[hash]':
166
+ return hash;
167
+
168
+ case '[name]':
169
+ return name;
170
+ }
171
+ throw new Error(
172
+ `invalid placeholder ${placeholder} in assetFileNames "${pattern}"`,
173
+ );
174
+ });
175
+ }
176
+
177
+ function getHash(text: Buffer | string): string {
178
+ return createHash('sha256').update(text).digest('hex').substring(0, 8);
179
+ }
180
+
181
+ function cleanModuleIdentifier(url: string) {
182
+ return url.replace(HASH_PATTERN, '').replace(QUERY_PATTERN, '');
183
+ }
@@ -0,0 +1,91 @@
1
+ import type {Plugin} from 'rollup';
2
+
3
+ export interface Options {
4
+ minify?: boolean;
5
+ extract?: boolean;
6
+ }
7
+
8
+ const CSS_REGEX = /\.css$/;
9
+ const CSS_MODULE_REGEX = /\.module\.css$/;
10
+
11
+ export function cssRollupPlugin({minify = true, extract = true}: Options) {
12
+ const styles = new Map<string, string>();
13
+
14
+ return {
15
+ name: '@quilted/css',
16
+ async transform(code, id) {
17
+ if (!CSS_REGEX.test(id)) return;
18
+
19
+ const {transform} = await import('lightningcss');
20
+
21
+ const transformed = transform({
22
+ filename: id,
23
+ code: new TextEncoder().encode(code),
24
+ cssModules: CSS_MODULE_REGEX.test(id),
25
+ minify,
26
+ });
27
+
28
+ styles.set(id, new TextDecoder().decode(transformed.code));
29
+
30
+ const exports = transformed.exports
31
+ ? Object.fromEntries(
32
+ Object.entries(transformed.exports).map(([key, exported]) => [
33
+ key,
34
+ exported.name,
35
+ ]),
36
+ )
37
+ : undefined;
38
+
39
+ return {
40
+ code: exports
41
+ ? `export default JSON.parse(${JSON.stringify(
42
+ JSON.stringify(exports),
43
+ )})`
44
+ : `export default undefined;`,
45
+ map: {mappings: ''},
46
+ moduleSideEffects: 'no-treeshake',
47
+ };
48
+ },
49
+ async renderChunk(_, chunk) {
50
+ if (!extract) return null;
51
+
52
+ let chunkCss = '';
53
+
54
+ for (const id of Object.keys(chunk.modules)) {
55
+ if (CSS_REGEX.test(id) && styles.has(id)) {
56
+ chunkCss += styles.get(id);
57
+ }
58
+ }
59
+
60
+ if (chunkCss.length === 0) return null;
61
+
62
+ const code = chunkCss;
63
+
64
+ // if (minify) {
65
+ // const {default: CleanCSS} = await import('clean-css');
66
+
67
+ // const cleaner = new CleanCSS({
68
+ // rebase: false,
69
+ // });
70
+
71
+ // const minified = cleaner.minify(chunkCss);
72
+
73
+ // if (minified.errors.length > 0) {
74
+ // throw minified.errors[0];
75
+ // }
76
+
77
+ // code = minified.styles;
78
+ // }
79
+
80
+ const fileHandle = this.emitFile({
81
+ type: 'asset',
82
+ name: `${chunk.fileName.split('.')[0]}.css`,
83
+ source: code,
84
+ });
85
+
86
+ chunk.imports.push(this.getFileName(fileHandle));
87
+
88
+ return null;
89
+ },
90
+ } satisfies Plugin;
91
+ }
@@ -3,10 +3,10 @@ import * as fs from 'fs';
3
3
 
4
4
  import type {PluginContext} from 'rollup';
5
5
 
6
- import {MAGIC_MODULE_ENV} from './constants.ts';
7
- import {multiline} from './shared/strings.ts';
8
- import {smartReplace} from './shared/rollup.ts';
9
- import {createMagicModulePlugin} from './shared/magic-module.ts';
6
+ import {MAGIC_MODULE_ENV} from '../constants.ts';
7
+ import {multiline} from '../shared/strings.ts';
8
+ import {smartReplace} from '../shared/rollup.ts';
9
+ import {createMagicModulePlugin} from '../shared/magic-module.ts';
10
10
 
11
11
  const EMPTY_PROCESS_ENV_OBJECT = {
12
12
  'globalThis.process.env.': `({}).`,
@@ -1,7 +1,7 @@
1
- import {MAGIC_MODULE_ENTRY, MAGIC_MODULE_REQUEST_ROUTER} from './constants.ts';
1
+ import {MAGIC_MODULE_ENTRY, MAGIC_MODULE_REQUEST_ROUTER} from '../constants.ts';
2
2
 
3
- import {createMagicModulePlugin} from './shared/magic-module.ts';
4
- import {multiline} from './shared/strings.ts';
3
+ import {createMagicModulePlugin} from '../shared/magic-module.ts';
4
+ import {multiline} from '../shared/strings.ts';
5
5
 
6
6
  export function magicModuleRequestRouterEntry({
7
7
  host,
@@ -0,0 +1,36 @@
1
+ import {readFile} from 'fs/promises';
2
+ import {createRequire} from 'module';
3
+
4
+ import type {Plugin} from 'rollup';
5
+
6
+ export function systemJS({minify = false} = {}) {
7
+ return {
8
+ name: '@quilted/system-js',
9
+ async renderChunk(_, chunk, options) {
10
+ if (options.format !== 'system' || !chunk.isEntry) return null;
11
+
12
+ const require = createRequire(import.meta.url);
13
+ const systemjs = minify
14
+ ? require.resolve('systemjs/dist/s.min.js')
15
+ : require.resolve('systemjs/dist/s.js');
16
+
17
+ // We write the systemjs loader to a dedicated file, and we make it the
18
+ // "first import" of the chunk so that it is the first file listed in
19
+ // the manifest.
20
+ const fileHandle = this.emitFile({
21
+ type: 'asset',
22
+ name: 'loader.js',
23
+ source: (await readFile(systemjs, {encoding: 'utf8'})).replace(
24
+ // Remove the source map comment, if it is present, because we don’t upload the
25
+ // sourcemap for this file.
26
+ /\n?[/][/]# sourceMappingURL=s.*\.map\n?$/,
27
+ '',
28
+ ),
29
+ });
30
+
31
+ chunk.imports.unshift(this.getFileName(fileHandle));
32
+
33
+ return null;
34
+ },
35
+ } satisfies Plugin;
36
+ }