@quilted/rollup 0.1.19 → 0.2.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.
Files changed (129) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/build/esm/app.mjs +450 -222
  3. package/build/esm/constants.mjs +5 -5
  4. package/build/esm/features/assets.mjs +93 -81
  5. package/build/esm/features/async.mjs +186 -0
  6. package/build/esm/features/css.mjs +26 -39
  7. package/build/esm/features/env.mjs +47 -44
  8. package/build/esm/features/esnext.mjs +57 -0
  9. package/build/esm/features/graphql/transform.mjs +60 -56
  10. package/build/esm/features/graphql.mjs +65 -47
  11. package/build/esm/features/request-router.mjs +6 -4
  12. package/build/esm/features/source-code.mjs +54 -28
  13. package/build/esm/features/system-js.mjs +29 -20
  14. package/build/esm/features/typescript.mjs +13 -10
  15. package/build/esm/features/workers.mjs +173 -0
  16. package/build/esm/index.mjs +3 -2
  17. package/build/esm/module.mjs +69 -62
  18. package/build/esm/package.mjs +275 -84
  19. package/build/esm/server.mjs +118 -0
  20. package/build/esm/shared/browserslist.mjs +141 -16
  21. package/build/esm/shared/magic-module.mjs +9 -7
  22. package/build/esm/shared/package-json.mjs +7 -1
  23. package/build/esm/shared/path.mjs +7 -0
  24. package/build/esm/shared/rollup.mjs +89 -25
  25. package/build/esm/shared/strings.mjs +7 -6
  26. package/build/tsconfig.tsbuildinfo +1 -1
  27. package/build/typescript/app.d.ts +132 -29
  28. package/build/typescript/app.d.ts.map +1 -1
  29. package/build/typescript/features/assets.d.ts +1 -2
  30. package/build/typescript/features/assets.d.ts.map +1 -1
  31. package/build/typescript/features/async.d.ts +10 -0
  32. package/build/typescript/features/async.d.ts.map +1 -0
  33. package/build/typescript/features/css.d.ts +2 -1
  34. package/build/typescript/features/css.d.ts.map +1 -1
  35. package/build/typescript/features/env.d.ts +1 -0
  36. package/build/typescript/features/env.d.ts.map +1 -1
  37. package/build/typescript/features/esnext.d.ts +9 -0
  38. package/build/typescript/features/esnext.d.ts.map +1 -0
  39. package/build/typescript/features/graphql.d.ts +2 -2
  40. package/build/typescript/features/graphql.d.ts.map +1 -1
  41. package/build/typescript/features/source-code.d.ts +9 -3
  42. package/build/typescript/features/source-code.d.ts.map +1 -1
  43. package/build/typescript/features/system-js.d.ts +4 -1
  44. package/build/typescript/features/system-js.d.ts.map +1 -1
  45. package/build/typescript/features/workers.d.ts +52 -0
  46. package/build/typescript/features/workers.d.ts.map +1 -0
  47. package/build/typescript/index.d.ts +3 -2
  48. package/build/typescript/index.d.ts.map +1 -1
  49. package/build/typescript/module.d.ts +24 -6
  50. package/build/typescript/module.d.ts.map +1 -1
  51. package/build/typescript/package.d.ts +196 -4
  52. package/build/typescript/package.d.ts.map +1 -1
  53. package/build/typescript/server.d.ts +98 -0
  54. package/build/typescript/server.d.ts.map +1 -0
  55. package/build/typescript/shared/browserslist.d.ts +20 -3
  56. package/build/typescript/shared/browserslist.d.ts.map +1 -1
  57. package/build/typescript/shared/path.d.ts +2 -0
  58. package/build/typescript/shared/path.d.ts.map +1 -0
  59. package/build/typescript/shared/rollup.d.ts +27 -1
  60. package/build/typescript/shared/rollup.d.ts.map +1 -1
  61. package/configuration/rollup.config.js +40 -0
  62. package/package.json +62 -9
  63. package/source/app.ts +475 -99
  64. package/source/features/assets.ts +5 -7
  65. package/source/features/async.ts +249 -0
  66. package/source/features/css.ts +4 -2
  67. package/source/features/env.ts +6 -0
  68. package/source/features/esnext.ts +70 -0
  69. package/source/features/graphql.ts +4 -2
  70. package/source/features/source-code.ts +27 -9
  71. package/source/features/system-js.ts +25 -2
  72. package/source/features/workers.ts +292 -0
  73. package/source/index.ts +4 -0
  74. package/source/module.ts +45 -19
  75. package/source/package.ts +394 -36
  76. package/source/server.ts +245 -0
  77. package/source/shared/browserslist.ts +208 -18
  78. package/source/shared/path.ts +5 -0
  79. package/source/shared/rollup.ts +102 -4
  80. package/tsconfig.json +6 -2
  81. package/build/cjs/app.cjs +0 -441
  82. package/build/cjs/constants.cjs +0 -13
  83. package/build/cjs/features/assets.cjs +0 -240
  84. package/build/cjs/features/css.cjs +0 -71
  85. package/build/cjs/features/env.cjs +0 -135
  86. package/build/cjs/features/graphql/transform.cjs +0 -186
  87. package/build/cjs/features/graphql.cjs +0 -86
  88. package/build/cjs/features/request-router.cjs +0 -31
  89. package/build/cjs/features/source-code.cjs +0 -54
  90. package/build/cjs/features/system-js.cjs +0 -36
  91. package/build/cjs/features/typescript.cjs +0 -56
  92. package/build/cjs/index.cjs +0 -13
  93. package/build/cjs/module.cjs +0 -121
  94. package/build/cjs/package.cjs +0 -170
  95. package/build/cjs/shared/browserslist.cjs +0 -25
  96. package/build/cjs/shared/magic-module.cjs +0 -32
  97. package/build/cjs/shared/package-json.cjs +0 -31
  98. package/build/cjs/shared/rollup.cjs +0 -72
  99. package/build/cjs/shared/strings.cjs +0 -16
  100. package/build/esnext/app.esnext +0 -414
  101. package/build/esnext/constants.esnext +0 -7
  102. package/build/esnext/features/assets.esnext +0 -215
  103. package/build/esnext/features/css.esnext +0 -69
  104. package/build/esnext/features/env.esnext +0 -112
  105. package/build/esnext/features/graphql/transform.esnext +0 -181
  106. package/build/esnext/features/graphql.esnext +0 -84
  107. package/build/esnext/features/request-router.esnext +0 -29
  108. package/build/esnext/features/source-code.esnext +0 -51
  109. package/build/esnext/features/system-js.esnext +0 -33
  110. package/build/esnext/features/typescript.esnext +0 -34
  111. package/build/esnext/index.esnext +0 -3
  112. package/build/esnext/module.esnext +0 -100
  113. package/build/esnext/package.esnext +0 -148
  114. package/build/esnext/shared/browserslist.esnext +0 -23
  115. package/build/esnext/shared/magic-module.esnext +0 -30
  116. package/build/esnext/shared/package-json.esnext +0 -10
  117. package/build/esnext/shared/rollup.esnext +0 -49
  118. package/build/esnext/shared/strings.esnext +0 -14
  119. package/build/typescript/env.d.ts +0 -55
  120. package/build/typescript/env.d.ts.map +0 -1
  121. package/build/typescript/graphql/transform.d.ts +0 -17
  122. package/build/typescript/graphql/transform.d.ts.map +0 -1
  123. package/build/typescript/graphql.d.ts +0 -6
  124. package/build/typescript/graphql.d.ts.map +0 -1
  125. package/build/typescript/request-router.d.ts +0 -15
  126. package/build/typescript/request-router.d.ts.map +0 -1
  127. package/build/typescript/shared/source-code.d.ts +0 -5
  128. package/build/typescript/shared/source-code.d.ts.map +0 -1
  129. package/quilt.project.ts +0 -5
package/build/esm/app.mjs CHANGED
@@ -1,13 +1,66 @@
1
1
  import * as path from 'node:path';
2
2
  import * as fs from 'node:fs/promises';
3
3
  import { glob } from 'glob';
4
- import { fileURLToPath } from 'node:url';
4
+ import { createRequire } from 'node:module';
5
5
  import { MAGIC_MODULE_ENTRY, MAGIC_MODULE_APP_COMPONENT, MAGIC_MODULE_REQUEST_ROUTER, MAGIC_MODULE_BROWSER_ASSETS } from './constants.mjs';
6
+ import { resolveEnvOption } from './features/env.mjs';
6
7
  import { multiline } from './shared/strings.mjs';
7
8
  import { getNodePlugins, removeBuildFiles } from './shared/rollup.mjs';
8
9
  import { createMagicModulePlugin } from './shared/magic-module.mjs';
9
- import { getBrowserTargetDetails } from './shared/browserslist.mjs';
10
+ import { getBrowserGroups, getBrowserGroupTargetDetails, targetsSupportModules, rollupGenerateOptionsForBrowsers, getBrowserGroupRegularExpressions } from './shared/browserslist.mjs';
11
+ import { loadPackageJSON } from './shared/package-json.mjs';
12
+ import { resolveRoot } from './shared/path.mjs';
10
13
 
14
+ const require = createRequire(import.meta.url);
15
+ async function quiltApp({
16
+ root: rootPath = process.cwd(),
17
+ app,
18
+ env,
19
+ graphql,
20
+ assets,
21
+ browser: browserOptions,
22
+ server: serverOptions
23
+ } = {}) {
24
+ const root = resolveRoot(rootPath);
25
+ const browserGroups = await getBrowserGroups({ root });
26
+ const browserGroupEntries = Object.entries(browserGroups);
27
+ const hasMultipleBrowserGroups = browserGroupEntries.length > 1;
28
+ const optionPromises = [];
29
+ browserGroupEntries.forEach(([name, browsers], index) => {
30
+ optionPromises.push(
31
+ quiltAppBrowser({
32
+ root,
33
+ app,
34
+ graphql,
35
+ ...browserOptions,
36
+ env: {
37
+ ...resolveEnvOption(env),
38
+ ...resolveEnvOption(browserOptions?.env)
39
+ },
40
+ assets: {
41
+ ...assets,
42
+ ...browserOptions?.assets,
43
+ // Only clean on the first build, otherwise each subsequent build removes
44
+ // assets from the previous ones.
45
+ clean: index === 0,
46
+ priority: index,
47
+ targets: hasMultipleBrowserGroups ? { name, browsers } : browsers
48
+ }
49
+ })
50
+ );
51
+ });
52
+ optionPromises.push(
53
+ quiltAppServer({
54
+ root,
55
+ app,
56
+ graphql,
57
+ ...serverOptions,
58
+ env: { ...resolveEnvOption(env), ...resolveEnvOption(serverOptions?.env) },
59
+ assets: { ...assets, ...serverOptions?.assets }
60
+ })
61
+ );
62
+ return Promise.all(optionPromises);
63
+ }
11
64
  async function quiltAppBrowser({
12
65
  root: rootPath = process.cwd(),
13
66
  app,
@@ -17,231 +70,310 @@ async function quiltAppBrowser({
17
70
  module,
18
71
  graphql = true
19
72
  } = {}) {
20
- const root = typeof rootPath === 'string' ? rootPath : fileURLToPath(rootPath);
21
- const mode = (typeof env === 'object' ? env?.mode : undefined) ?? 'production';
22
- const minify = assets?.minify ?? mode === 'production';
23
- const baseURL = assets?.baseURL ?? '/assets/';
24
- const browserTarget = await getBrowserTargetDetails(assets?.targets, {
73
+ const root = resolveRoot(rootPath);
74
+ const mode = (typeof env === "object" ? env?.mode : env) ?? "production";
75
+ const minify = assets?.minify ?? mode === "production";
76
+ const baseURL = assets?.baseURL ?? "/assets/";
77
+ const assetsInline = assets?.inline ?? true;
78
+ const browserGroup = await getBrowserGroupTargetDetails(assets?.targets, {
25
79
  root
26
80
  });
27
- const targetFilenamePart = browserTarget.name ? `.${browserTarget.name}` : '';
28
- const [{
29
- visualizer
30
- }, {
31
- magicModuleEnv,
32
- replaceProcessEnv
33
- }, {
34
- sourceCode
35
- }, {
36
- createTSConfigAliasPlugin
37
- }, {
38
- css
39
- }, {
40
- assetManifest,
41
- rawAssets,
42
- staticAssets
43
- }, {
44
- systemJS
45
- }, nodePlugins] = await Promise.all([import('rollup-plugin-visualizer'), import('./features/env.mjs'), import('./features/source-code.mjs'), import('./features/typescript.mjs'), import('./features/css.mjs'), import('./features/assets.mjs'), import('./features/system-js.mjs'), getNodePlugins()]);
46
- const plugins = [...nodePlugins, systemJS({
47
- minify
48
- }), replaceProcessEnv({
49
- mode
50
- }), magicModuleEnv({
51
- ...env,
52
- mode
53
- }), sourceCode({
54
- mode,
55
- targets: browserTarget.browsers
56
- }), css({
57
- minify,
58
- emit: true
59
- }), rawAssets(), staticAssets({
60
- baseURL,
61
- emit: true
62
- }), removeBuildFiles(['build/assets', 'build/manifests', 'build/reports'], {
63
- root
64
- })];
81
+ const targetFilenamePart = browserGroup.name ? `.${browserGroup.name}` : "";
82
+ const [
83
+ { visualizer },
84
+ { magicModuleEnv, replaceProcessEnv },
85
+ { sourceCode },
86
+ { createTSConfigAliasPlugin },
87
+ { css },
88
+ { assetManifest, rawAssets, staticAssets },
89
+ { asyncModules },
90
+ { systemJS },
91
+ { workers },
92
+ { esnext },
93
+ nodePlugins,
94
+ packageJSON
95
+ ] = await Promise.all([
96
+ import('rollup-plugin-visualizer'),
97
+ import('./features/env.mjs'),
98
+ import('./features/source-code.mjs'),
99
+ import('./features/typescript.mjs'),
100
+ import('./features/css.mjs'),
101
+ import('./features/assets.mjs'),
102
+ import('./features/async.mjs'),
103
+ import('./features/system-js.mjs'),
104
+ import('./features/workers.mjs'),
105
+ import('./features/esnext.mjs'),
106
+ getNodePlugins({ bundle: true }),
107
+ loadPackageJSON(root)
108
+ ]);
109
+ const plugins = [
110
+ ...nodePlugins,
111
+ systemJS({ minify }),
112
+ replaceProcessEnv({ mode }),
113
+ magicModuleEnv({ ...resolveEnvOption(env), mode }),
114
+ sourceCode({
115
+ mode,
116
+ targets: browserGroup.browsers,
117
+ babel: {
118
+ useBuiltIns: "entry",
119
+ options(options) {
120
+ return {
121
+ ...options,
122
+ plugins: [
123
+ ...options?.plugins ?? [],
124
+ require.resolve("@quilted/babel/async"),
125
+ require.resolve("@quilted/babel/workers")
126
+ ]
127
+ };
128
+ }
129
+ }
130
+ }),
131
+ esnext({
132
+ mode,
133
+ targets: browserGroup.browsers
134
+ }),
135
+ css({ minify, emit: true }),
136
+ rawAssets(),
137
+ staticAssets({
138
+ baseURL,
139
+ emit: true,
140
+ inlineLimit: assetsInline ? typeof assetsInline === "boolean" ? void 0 : assetsInline?.limit : Number.POSITIVE_INFINITY
141
+ }),
142
+ asyncModules({
143
+ baseURL,
144
+ preload: true,
145
+ moduleID: ({ imported }) => path.relative(root, imported)
146
+ }),
147
+ workers({
148
+ baseURL,
149
+ outputOptions: {
150
+ format: "iife",
151
+ inlineDynamicImports: true,
152
+ dir: path.resolve(root, `build/assets`),
153
+ entryFileNames: `[name]${targetFilenamePart}.[hash].js`,
154
+ assetFileNames: `[name]${targetFilenamePart}.[hash].[ext]`,
155
+ chunkFileNames: `[name]${targetFilenamePart}.[hash].js`
156
+ }
157
+ })
158
+ ];
159
+ if (assets?.clean ?? true) {
160
+ plugins.push(
161
+ removeBuildFiles(["build/assets", "build/manifests", "build/reports"], {
162
+ root
163
+ })
164
+ );
165
+ }
65
166
  const tsconfigAliases = await createTSConfigAliasPlugin();
66
167
  if (tsconfigAliases) {
67
168
  plugins.push(tsconfigAliases);
68
169
  }
69
- const appEntry = app ?? (await glob('{App,app,input}.{ts,tsx,mjs,js,jsx}', {
70
- cwd: root,
71
- nodir: true,
72
- absolute: true
73
- }).then(files => files[0]));
170
+ const appEntry = await resolveAppEntry(app, { root, packageJSON });
74
171
  if (appEntry) {
75
- plugins.push(magicModuleAppComponent({
76
- entry: appEntry
77
- }));
172
+ plugins.push(magicModuleAppComponent({ entry: appEntry }));
78
173
  }
79
174
  plugins.push(magicModuleAppBrowserEntry(module));
80
175
  if (graphql) {
81
- const {
82
- graphql
83
- } = await import('./features/graphql.mjs');
84
- plugins.push(graphql({
85
- manifest: path.resolve(`manifests/graphql${targetFilenamePart}.json`)
86
- }));
176
+ const { graphql: graphql2 } = await import('./features/graphql.mjs');
177
+ plugins.push(
178
+ graphql2({
179
+ manifest: path.resolve(`manifests/graphql${targetFilenamePart}.json`)
180
+ })
181
+ );
87
182
  }
88
183
  if (minify) {
89
- const {
90
- minify
91
- } = await import('rollup-plugin-esbuild');
92
- plugins.push(minify());
184
+ const { minify: minify2 } = await import('rollup-plugin-esbuild');
185
+ plugins.push(minify2());
186
+ }
187
+ const cacheKey = new URLSearchParams();
188
+ if (browserGroup.name) {
189
+ cacheKey.set("browserGroup", browserGroup.name);
93
190
  }
94
- const cacheKey = browserTarget.name ? {
95
- browserTarget: browserTarget.name
96
- } : undefined;
97
- const id = browserTarget.name ? browserTarget.name : undefined;
98
- plugins.push(assetManifest({
99
- id,
100
- cacheKey,
101
- baseURL,
102
- file: path.resolve(`build/manifests/assets${targetFilenamePart}.json`),
103
- priority: assets?.priority
104
- }), visualizer({
105
- template: 'treemap',
106
- open: false,
107
- brotliSize: true,
108
- filename: path.resolve(`build/reports/bundle-visualizer${targetFilenamePart}.html`)
109
- }));
110
- const finalEntry = entry ?? (await glob('{browser,client}.{ts,tsx,mjs,js,jsx}', {
191
+ plugins.push(
192
+ assetManifest({
193
+ baseURL,
194
+ cacheKey,
195
+ file: path.resolve(`build/manifests/assets${targetFilenamePart}.json`),
196
+ priority: assets?.priority
197
+ }),
198
+ visualizer({
199
+ template: "treemap",
200
+ open: false,
201
+ brotliSize: true,
202
+ filename: path.resolve(
203
+ `build/reports/bundle-visualizer${targetFilenamePart}.html`
204
+ )
205
+ })
206
+ );
207
+ const finalEntry = entry ? path.resolve(root, entry) : await glob("{browser,client,web}.{ts,tsx,mjs,js,jsx}", {
111
208
  cwd: root,
112
209
  nodir: true,
113
210
  absolute: true
114
- }).then(files => files[0])) ?? MAGIC_MODULE_ENTRY;
211
+ }).then((files) => files[0]) ?? MAGIC_MODULE_ENTRY;
212
+ const isESM = await targetsSupportModules(browserGroup.browsers);
115
213
  return {
116
- input: finalEntry,
214
+ // If we are using the "magic entry", give it an explicit name of `browser`.
215
+ // Otherwise, Rollup will use the file name as the output name.
216
+ input: finalEntry === MAGIC_MODULE_ENTRY ? { browser: finalEntry } : finalEntry,
117
217
  plugins,
118
218
  onwarn(warning, defaultWarn) {
119
- // Removes annoying warnings for React-focused libraries that
120
- // include 'use client' directives.
121
- if (warning.code === 'MODULE_LEVEL_DIRECTIVE' && /['"]use client['"]/.test(warning.message)) {
219
+ if (warning.code === "MODULE_LEVEL_DIRECTIVE" && /['"]use client['"]/.test(warning.message)) {
122
220
  return;
123
221
  }
124
222
  defaultWarn(warning);
125
223
  },
126
224
  output: {
127
- // format: isESM ? 'esm' : 'systemjs',
128
- format: 'esm',
129
- dir: path.resolve(`build/assets`),
130
- entryFileNames: `app${targetFilenamePart}.[hash].js`,
225
+ format: isESM ? "esm" : "systemjs",
226
+ dir: path.resolve(root, `build/assets`),
227
+ entryFileNames: `[name]${targetFilenamePart}.[hash].js`,
131
228
  assetFileNames: `[name]${targetFilenamePart}.[hash].[ext]`,
132
229
  chunkFileNames: `[name]${targetFilenamePart}.[hash].js`,
133
- manualChunks: createManualChunksSorter()
230
+ manualChunks: createManualChunksSorter(),
231
+ generatedCode: await rollupGenerateOptionsForBrowsers(
232
+ browserGroup.browsers
233
+ )
134
234
  }
135
235
  };
136
236
  }
137
237
  async function quiltAppServer({
238
+ root: rootPath = process.cwd(),
138
239
  app,
139
240
  env,
140
241
  entry,
242
+ format = "request-router",
141
243
  graphql = true,
142
- minify = false
244
+ assets,
245
+ output
143
246
  } = {}) {
144
- const root = process.cwd();
145
- const mode = (typeof env === 'object' ? env?.mode : undefined) ?? 'production';
146
- const [{
147
- visualizer
148
- }, {
149
- magicModuleEnv,
150
- replaceProcessEnv
151
- }, {
152
- sourceCode
153
- }, {
154
- createTSConfigAliasPlugin
155
- }, {
156
- css
157
- }, {
158
- rawAssets,
159
- staticAssets
160
- }, {
161
- magicModuleRequestRouterEntry
162
- }, nodePlugins] = await Promise.all([import('rollup-plugin-visualizer'), import('./features/env.mjs'), import('./features/source-code.mjs'), import('./features/typescript.mjs'), import('./features/css.mjs'), import('./features/assets.mjs'), import('./features/request-router.mjs'), getNodePlugins()]);
163
- const plugins = [...nodePlugins, replaceProcessEnv({
164
- mode
165
- }), magicModuleEnv({
166
- ...env,
167
- mode
168
- }), sourceCode({
169
- mode,
170
- targets: ['current node']
171
- }), css({
172
- emit: false,
173
- minify
174
- }), rawAssets(), staticAssets({
175
- emit: false
176
- }), removeBuildFiles(['build/server'], {
177
- root
178
- })];
247
+ const root = resolveRoot(rootPath);
248
+ const mode = (typeof env === "object" ? env?.mode : env) ?? "production";
249
+ const baseURL = assets?.baseURL ?? "/assets/";
250
+ const assetsInline = assets?.inline ?? true;
251
+ const bundle = output?.bundle;
252
+ const minify = output?.minify ?? false;
253
+ const hash = output?.hash ?? "async-only";
254
+ const outputFormat = output?.format ?? "esmodules";
255
+ const [
256
+ { visualizer },
257
+ { magicModuleEnv, replaceProcessEnv },
258
+ { sourceCode },
259
+ { createTSConfigAliasPlugin },
260
+ { css },
261
+ { rawAssets, staticAssets },
262
+ { asyncModules },
263
+ { esnext },
264
+ nodePlugins,
265
+ packageJSON
266
+ ] = await Promise.all([
267
+ import('rollup-plugin-visualizer'),
268
+ import('./features/env.mjs'),
269
+ import('./features/source-code.mjs'),
270
+ import('./features/typescript.mjs'),
271
+ import('./features/css.mjs'),
272
+ import('./features/assets.mjs'),
273
+ import('./features/async.mjs'),
274
+ import('./features/esnext.mjs'),
275
+ getNodePlugins({ bundle }),
276
+ loadPackageJSON(root)
277
+ ]);
278
+ const plugins = [
279
+ ...nodePlugins,
280
+ replaceProcessEnv({ mode }),
281
+ magicModuleEnv({ ...resolveEnvOption(env), mode }),
282
+ sourceCode({
283
+ mode,
284
+ targets: ["current node"],
285
+ babel: {
286
+ options(options) {
287
+ return {
288
+ ...options,
289
+ plugins: [
290
+ ...options?.plugins ?? [],
291
+ require.resolve("@quilted/babel/async"),
292
+ [require.resolve("@quilted/babel/workers"), { noop: true }]
293
+ ]
294
+ };
295
+ }
296
+ }
297
+ }),
298
+ esnext({
299
+ mode,
300
+ targets: ["current node"]
301
+ }),
302
+ css({ emit: false, minify }),
303
+ rawAssets(),
304
+ staticAssets({
305
+ emit: false,
306
+ baseURL,
307
+ inlineLimit: assetsInline ? typeof assetsInline === "boolean" ? void 0 : assetsInline?.limit : Number.POSITIVE_INFINITY
308
+ }),
309
+ asyncModules({
310
+ baseURL,
311
+ preload: false,
312
+ moduleID: ({ imported }) => path.relative(root, imported)
313
+ }),
314
+ removeBuildFiles(["build/server"], { root })
315
+ ];
179
316
  const tsconfigAliases = await createTSConfigAliasPlugin();
180
317
  if (tsconfigAliases) {
181
318
  plugins.push(tsconfigAliases);
182
319
  }
183
- const appEntry = app ?? (await glob('{App,app,input}.{ts,tsx,mjs,js,jsx}', {
320
+ const appEntry = await resolveAppEntry(app, { root, packageJSON });
321
+ if (appEntry) {
322
+ plugins.push(magicModuleAppComponent({ entry: appEntry }));
323
+ }
324
+ const serverEntry = entry ? path.resolve(root, entry) : await glob("{server,service,backend}.{ts,tsx,mjs,js,jsx}", {
184
325
  cwd: root,
185
326
  nodir: true,
186
327
  absolute: true
187
- }).then(files => files[0]));
188
- if (appEntry) {
189
- plugins.push(magicModuleAppComponent({
190
- entry: appEntry
191
- }));
192
- }
193
- plugins.push(magicModuleRequestRouterEntry(), magicModuleAppRequestRouter({
194
- entry
195
- }), magicModuleAppAssetManifests());
328
+ }).then((files) => files[0]);
329
+ const finalEntry = format === "request-router" ? MAGIC_MODULE_ENTRY : serverEntry ?? MAGIC_MODULE_ENTRY;
330
+ plugins.push(
331
+ magicModuleAppServerEntry({
332
+ assets: { baseURL }
333
+ }),
334
+ magicModuleAppRequestRouter({ entry: serverEntry }),
335
+ magicModuleAppAssetManifests()
336
+ );
196
337
  if (graphql) {
197
- const {
198
- graphql
199
- } = await import('./features/graphql.mjs');
200
- plugins.push(graphql({
201
- manifest: false
202
- }));
338
+ const { graphql: graphql2 } = await import('./features/graphql.mjs');
339
+ plugins.push(graphql2({ manifest: false }));
203
340
  }
204
341
  if (minify) {
205
- const {
206
- minify
207
- } = await import('rollup-plugin-esbuild');
208
- plugins.push(minify());
342
+ const { minify: minify2 } = await import('rollup-plugin-esbuild');
343
+ plugins.push(minify2());
209
344
  }
210
- plugins.push(visualizer({
211
- template: 'treemap',
212
- open: false,
213
- brotliSize: false,
214
- filename: path.resolve(`build/reports/bundle-visualizer.server.html`)
215
- }));
216
- const finalEntry = entry ?? (await glob('{server,service,backend}.{ts,tsx,mjs,js,jsx}', {
217
- cwd: root,
218
- nodir: true,
219
- absolute: true
220
- }).then(files => files[0])) ?? MAGIC_MODULE_ENTRY;
345
+ plugins.push(
346
+ visualizer({
347
+ template: "treemap",
348
+ open: false,
349
+ brotliSize: false,
350
+ filename: path.resolve(`build/reports/bundle-visualizer.server.html`)
351
+ })
352
+ );
221
353
  return {
222
- input: finalEntry,
354
+ // If we are using the "magic entry", give it an explicit name of `server`.
355
+ // Otherwise, Rollup will use the file name as the output name.
356
+ input: finalEntry === MAGIC_MODULE_ENTRY ? { server: finalEntry } : finalEntry,
223
357
  plugins,
224
358
  onwarn(warning, defaultWarn) {
225
- // Removes annoying warnings for React-focused libraries that
226
- // include 'use client' directives.
227
- if (warning.code === 'MODULE_LEVEL_DIRECTIVE' && /['"]use client['"]/.test(warning.message)) {
359
+ if (warning.code === "MODULE_LEVEL_DIRECTIVE" && /['"]use client['"]/.test(warning.message)) {
228
360
  return;
229
361
  }
230
362
  defaultWarn(warning);
231
363
  },
232
364
  output: {
233
- // format: isESM ? 'esm' : 'systemjs',
234
- format: 'esm',
365
+ format: outputFormat === "commonjs" || outputFormat === "cjs" ? "cjs" : "esm",
235
366
  dir: path.resolve(`build/server`),
236
- entryFileNames: 'server.js'
367
+ entryFileNames: `[name]${hash === true ? `.[hash]` : ""}.js`,
368
+ chunkFileNames: `[name]${hash === true || hash === "async-only" ? `.[hash]` : ""}.js`,
369
+ assetFileNames: `[name]${hash === true ? `.[hash]` : ""}.[ext]`,
370
+ generatedCode: "es2015"
237
371
  }
238
372
  };
239
373
  }
240
- function magicModuleAppComponent({
241
- entry
242
- }) {
374
+ function magicModuleAppComponent({ entry }) {
243
375
  return createMagicModulePlugin({
244
- name: '@quilted/magic-module/app',
376
+ name: "@quilted/magic-module/app",
245
377
  module: MAGIC_MODULE_APP_COMPONENT,
246
378
  alias: entry
247
379
  });
@@ -250,10 +382,10 @@ function magicModuleAppRequestRouter({
250
382
  entry
251
383
  } = {}) {
252
384
  return createMagicModulePlugin({
253
- name: '@quilted/magic-module/app-request-router',
385
+ name: "@quilted/magic-module/app-request-router",
254
386
  module: MAGIC_MODULE_REQUEST_ROUTER,
255
387
  alias: entry,
256
- source: entry ? undefined : async function source() {
388
+ source: entry ? void 0 : async function source() {
257
389
  return multiline`
258
390
  import '@quilted/quilt/globals';
259
391
 
@@ -262,7 +394,9 @@ function magicModuleAppRequestRouter({
262
394
  import {renderToResponse} from '@quilted/quilt/server';
263
395
 
264
396
  import App from ${JSON.stringify(MAGIC_MODULE_APP_COMPONENT)};
265
- import {BrowserAssets} from ${JSON.stringify(MAGIC_MODULE_BROWSER_ASSETS)};
397
+ import {BrowserAssets} from ${JSON.stringify(
398
+ MAGIC_MODULE_BROWSER_ASSETS
399
+ )};
266
400
 
267
401
  const router = new RequestRouter();
268
402
  const assets = new BrowserAssets();
@@ -284,14 +418,14 @@ function magicModuleAppRequestRouter({
284
418
  }
285
419
  function magicModuleAppBrowserEntry({
286
420
  hydrate = true,
287
- selector = '#app'
421
+ selector = "#app"
288
422
  } = {}) {
289
423
  return createMagicModulePlugin({
290
- name: '@quilted/magic-module/app-browser-entry',
424
+ name: "@quilted/magic-module/app-browser-entry",
291
425
  module: MAGIC_MODULE_ENTRY,
292
426
  sideEffects: true,
293
427
  async source() {
294
- const reactRootFunction = hydrate ? 'hydrateRoot' : 'createRoot';
428
+ const reactRootFunction = hydrate ? "hydrateRoot" : "createRoot";
295
429
  return multiline`
296
430
  import '@quilted/quilt/globals';
297
431
 
@@ -307,27 +441,86 @@ function magicModuleAppBrowserEntry({
307
441
  }
308
442
  });
309
443
  }
444
+ function magicModuleAppServerEntry({
445
+ host,
446
+ port,
447
+ assets,
448
+ format = "module"
449
+ } = {}) {
450
+ const baseURL = typeof assets === "object" ? assets.baseURL : "/assets/";
451
+ return createMagicModulePlugin({
452
+ name: "@quilted/request-router/app-server",
453
+ module: MAGIC_MODULE_ENTRY,
454
+ sideEffects: true,
455
+ async source() {
456
+ const serveAssets = Boolean(assets);
457
+ return multiline`
458
+ ${serveAssets ? `import * as path from 'path';` : ""}
459
+ ${serveAssets && format === "module" ? `import {fileURLToPath} from 'url';` : ""}
460
+ import {createServer} from 'http';
461
+
462
+ import requestRouter from ${JSON.stringify(
463
+ MAGIC_MODULE_REQUEST_ROUTER
464
+ )};
465
+
466
+ import {createHttpRequestListener${serveAssets ? ", serveStatic" : ""}} from '@quilted/quilt/request-router/node';
467
+
468
+ const port = ${port ?? "Number.parseInt(process.env.PORT, 10)"};
469
+ const host = ${host ? JSON.stringify(host) : "process.env.HOST"};
470
+
471
+ ${serveAssets ? `const dirname = ${format === "module" ? "path.dirname(fileURLToPath(import.meta.url))" : "__dirname"};
472
+ const serve = serveStatic(path.resolve(dirname, '../assets'), {
473
+ baseUrl: ${JSON.stringify(baseURL)},
474
+ });` : ""}
475
+ const listener = createHttpRequestListener(requestRouter);
476
+
477
+ createServer(async (request, response) => {
478
+ ${serveAssets ? `if (request.url.startsWith(${JSON.stringify(
479
+ baseURL
480
+ )})) return serve(request, response);` : ""}
481
+
482
+ await listener(request, response);
483
+ }).listen(port, host);
484
+ `;
485
+ }
486
+ });
487
+ }
310
488
  function magicModuleAppAssetManifests() {
311
489
  return createMagicModulePlugin({
312
- name: '@quilted/magic-module/asset-manifests',
490
+ name: "@quilted/magic-module/asset-manifests",
313
491
  module: MAGIC_MODULE_BROWSER_ASSETS,
314
492
  async source() {
315
- const {
316
- glob
317
- } = await import('glob');
318
- const manifestFiles = await glob('assets*.json', {
493
+ const { glob: glob2 } = await import('glob');
494
+ const manifestFiles = await glob2("assets*.json", {
319
495
  nodir: true,
320
496
  absolute: true,
321
497
  cwd: path.resolve(`build/manifests`)
322
498
  });
323
- const manifests = await Promise.all(manifestFiles.map(async file => JSON.parse(await fs.readFile(file, 'utf8'))));
324
- manifests.sort((manifestA, manifestB) => (manifestA.priority ?? 0) - (manifestB.priority ?? 0));
499
+ const manifests = await Promise.all(
500
+ manifestFiles.map(
501
+ async (file) => JSON.parse(await fs.readFile(file, "utf8"))
502
+ )
503
+ );
504
+ manifests.sort(
505
+ (manifestA, manifestB) => (manifestA.priority ?? 0) - (manifestB.priority ?? 0)
506
+ );
507
+ const browserGroupRegexes = await getBrowserGroupRegularExpressions();
325
508
  return multiline`
326
509
  import {BrowserAssetsFromManifests} from '@quilted/quilt/server';
327
510
 
328
511
  export class BrowserAssets extends BrowserAssetsFromManifests {
329
512
  constructor() {
330
- const manifests = JSON.parse(${JSON.stringify(JSON.stringify(manifests))});
513
+ const manifests = JSON.parse(${JSON.stringify(
514
+ JSON.stringify(manifests)
515
+ )});
516
+
517
+ const browserGroupTests = [
518
+ ${Object.entries(browserGroupRegexes).map(
519
+ ([name, test]) => `[${JSON.stringify(name)}, new RegExp(${JSON.stringify(
520
+ test.source
521
+ )})]`
522
+ ).join(", ")}
523
+ ];
331
524
 
332
525
  // The default manifest is the last one, since it has the widest browser support.
333
526
  const defaultManifest = manifests.at(-1);
@@ -335,6 +528,14 @@ function magicModuleAppAssetManifests() {
335
528
  super(manifests, {
336
529
  defaultManifest,
337
530
  cacheKey(request) {
531
+ const userAgent = request.headers.get('User-Agent');
532
+
533
+ if (userAgent) {
534
+ for (const [name, test] of browserGroupTests) {
535
+ if (test.test(userAgent)) return {browserGroup: name};
536
+ }
537
+ }
538
+
338
539
  return {};
339
540
  },
340
541
  });
@@ -344,71 +545,98 @@ function magicModuleAppAssetManifests() {
344
545
  }
345
546
  });
346
547
  }
347
- const FRAMEWORK_CHUNK_NAME = 'framework';
348
- const POLYFILLS_CHUNK_NAME = 'polyfills';
349
- const VENDOR_CHUNK_NAME = 'vendor';
350
- const INTERNALS_CHUNK_NAME = 'internals';
351
- const SHARED_CHUNK_NAME = 'shared';
352
- const PACKAGES_CHUNK_NAME = 'packages';
353
- const GLOBAL_CHUNK_NAME = 'global';
354
- const FRAMEWORK_TEST_STRINGS = ['/node_modules/preact/', '/node_modules/react/', '/node_modules/js-cookie/', '/node_modules/@quilted/quilt/', '/node_modules/@preact/signals/', '/node_modules/@preact/signals-core/',
355
- // TODO I should turn this into an allowlist
356
- /node_modules[/]@quilted[/](?!react-query|swr)/];
357
- const POLYFILL_TEST_STRINGS = ['/node_modules/@quilted/polyfills/', '/node_modules/core-js/', '/node_modules/whatwg-fetch/', '/node_modules/regenerator-runtime/', '/node_modules/abort-controller/'];
358
- const INTERNALS_TEST_STRINGS = ['\x00commonjsHelpers.js', '/node_modules/@babel/runtime/'];
359
-
360
- // When building from source, quilt packages are not in node_modules,
361
- // so we instead add their repo paths to the list of framework test strings.
548
+ const FRAMEWORK_CHUNK_NAME = "framework";
549
+ const POLYFILLS_CHUNK_NAME = "polyfills";
550
+ const VENDOR_CHUNK_NAME = "vendor";
551
+ const INTERNALS_CHUNK_NAME = "internals";
552
+ const SHARED_CHUNK_NAME = "shared";
553
+ const PACKAGES_CHUNK_NAME = "packages";
554
+ const GLOBAL_CHUNK_NAME = "global";
555
+ const FRAMEWORK_TEST_STRINGS = [
556
+ "/node_modules/preact/",
557
+ "/node_modules/react/",
558
+ "/node_modules/js-cookie/",
559
+ "/node_modules/@quilted/quilt/",
560
+ "/node_modules/@preact/signals/",
561
+ "/node_modules/@preact/signals-core/",
562
+ // TODO I should turn this into an allowlist
563
+ /node_modules[/]@quilted[/](?!react-query|swr)/
564
+ ];
565
+ const POLYFILL_TEST_STRINGS = [
566
+ "/node_modules/core-js/",
567
+ "/node_modules/whatwg-fetch/",
568
+ "/node_modules/regenerator-runtime/",
569
+ "/node_modules/abort-controller/"
570
+ ];
571
+ const INTERNALS_TEST_STRINGS = [
572
+ "\0commonjsHelpers.js",
573
+ "/node_modules/@babel/runtime/"
574
+ ];
362
575
  if (process.env.QUILT_FROM_SOURCE) {
363
- FRAMEWORK_TEST_STRINGS.push('/quilt/packages/');
576
+ FRAMEWORK_TEST_STRINGS.push("/quilt/packages/");
364
577
  }
365
-
366
- // Inspired by Vite: https://github.com/vitejs/vite/blob/c69f83615292953d40f07b1178d1ed1d72abe695/packages/vite/source/node/build.ts#L567
367
578
  function createManualChunksSorter() {
368
- // TODO: make this more configurable, and make it so that we bundle more intelligently
369
- // for split entries
370
- const packagesPath = path.resolve('packages') + path.sep;
371
- const globalPath = path.resolve('global') + path.sep;
372
- const sharedPath = path.resolve('shared') + path.sep;
373
- return (id, {
374
- getModuleInfo
375
- }) => {
376
- if (INTERNALS_TEST_STRINGS.some(test => id.includes(test))) {
579
+ const packagesPath = path.resolve("packages") + path.sep;
580
+ const globalPath = path.resolve("global") + path.sep;
581
+ const sharedPath = path.resolve("shared") + path.sep;
582
+ return (id, { getModuleInfo }) => {
583
+ if (INTERNALS_TEST_STRINGS.some((test) => id.includes(test))) {
377
584
  return INTERNALS_CHUNK_NAME;
378
585
  }
379
- if (FRAMEWORK_TEST_STRINGS.some(test => typeof test === 'string' ? id.includes(test) : test.test(id))) {
586
+ if (FRAMEWORK_TEST_STRINGS.some(
587
+ (test) => typeof test === "string" ? id.includes(test) : test.test(id)
588
+ )) {
380
589
  return FRAMEWORK_CHUNK_NAME;
381
590
  }
382
- if (POLYFILL_TEST_STRINGS.some(test => id.includes(test))) {
591
+ if (POLYFILL_TEST_STRINGS.some((test) => id.includes(test))) {
383
592
  return POLYFILLS_CHUNK_NAME;
384
593
  }
385
594
  let bundleBaseName;
386
595
  let relativeId;
387
- if (id.includes('/node_modules/')) {
596
+ if (id.includes("/node_modules/")) {
388
597
  const moduleInfo = getModuleInfo(id);
389
-
390
- // If the only dependency is another vendor, let Rollup handle the naming
391
- if (moduleInfo == null) return;
392
- if (moduleInfo.importers.length > 0 && moduleInfo.importers.every(importer => importer.includes('/node_modules/'))) {
598
+ if (moduleInfo == null)
599
+ return;
600
+ if (moduleInfo.importers.length > 0 && moduleInfo.importers.every(
601
+ (importer) => importer.includes("/node_modules/")
602
+ )) {
393
603
  return;
394
604
  }
395
605
  bundleBaseName = VENDOR_CHUNK_NAME;
396
- relativeId = id.replace(/^.*[/]node_modules[/]/, '');
606
+ relativeId = id.replace(/^.*[/]node_modules[/]/, "");
397
607
  } else if (id.startsWith(packagesPath)) {
398
608
  bundleBaseName = PACKAGES_CHUNK_NAME;
399
- relativeId = id.replace(packagesPath, '');
609
+ relativeId = id.replace(packagesPath, "");
400
610
  } else if (id.startsWith(globalPath)) {
401
611
  bundleBaseName = GLOBAL_CHUNK_NAME;
402
- relativeId = id.replace(globalPath, '');
612
+ relativeId = id.replace(globalPath, "");
403
613
  } else if (id.startsWith(sharedPath)) {
404
614
  bundleBaseName = SHARED_CHUNK_NAME;
405
- relativeId = id.replace(sharedPath, '');
615
+ relativeId = id.replace(sharedPath, "");
406
616
  }
407
617
  if (bundleBaseName == null || relativeId == null) {
408
618
  return;
409
619
  }
410
- return `${bundleBaseName}-${relativeId.split(path.sep)[0]?.split('.')[0]}`;
620
+ return `${bundleBaseName}-${relativeId.split(path.sep)[0]?.split(".")[0]}`;
411
621
  };
412
622
  }
623
+ async function resolveAppEntry(entry, { root, packageJSON }) {
624
+ if (entry) {
625
+ return path.resolve(root, entry);
626
+ }
627
+ if (typeof packageJSON.main === "string") {
628
+ return path.resolve(root, packageJSON.main);
629
+ }
630
+ const rootEntry = packageJSON.exports?.["."];
631
+ if (typeof rootEntry === "string") {
632
+ return path.resolve(root, rootEntry);
633
+ }
634
+ const globbed = await glob("{App,app,index}.{ts,tsx,mjs,js,jsx}", {
635
+ cwd: root,
636
+ nodir: true,
637
+ absolute: true
638
+ });
639
+ return globbed[0];
640
+ }
413
641
 
414
- export { magicModuleAppAssetManifests, magicModuleAppBrowserEntry, magicModuleAppComponent, magicModuleAppRequestRouter, quiltAppBrowser, quiltAppServer };
642
+ export { magicModuleAppAssetManifests, magicModuleAppBrowserEntry, magicModuleAppComponent, magicModuleAppRequestRouter, magicModuleAppServerEntry, quiltApp, quiltAppBrowser, quiltAppServer };