@quilted/rollup 0.2.3 → 0.2.4

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/source/app.ts CHANGED
@@ -3,7 +3,12 @@ import * as fs from 'fs/promises';
3
3
  import {glob} from 'glob';
4
4
  import {createRequire} from 'module';
5
5
 
6
- import type {Plugin, RollupOptions, GetManualChunk} from 'rollup';
6
+ import type {
7
+ Plugin,
8
+ RollupOptions,
9
+ InputPluginOption,
10
+ GetManualChunk,
11
+ } from 'rollup';
7
12
  import type {AssetsBuildManifest} from '@quilted/assets';
8
13
 
9
14
  import {
@@ -18,6 +23,7 @@ import {multiline} from './shared/strings.ts';
18
23
  import {
19
24
  getNodePlugins,
20
25
  removeBuildFiles,
26
+ normalizeRollupInput,
21
27
  type RollupNodePluginOptions,
22
28
  } from './shared/rollup.ts';
23
29
  import {createMagicModulePlugin} from './shared/magic-module.ts';
@@ -218,9 +224,16 @@ export interface AppServerOutputOptions
218
224
  format?: 'esmodules' | 'esm' | 'es' | 'commonjs' | 'cjs';
219
225
  }
220
226
 
227
+ export {
228
+ MAGIC_MODULE_ENTRY,
229
+ MAGIC_MODULE_APP_COMPONENT,
230
+ MAGIC_MODULE_BROWSER_ASSETS,
231
+ MAGIC_MODULE_REQUEST_ROUTER,
232
+ };
233
+
221
234
  const require = createRequire(import.meta.url);
222
235
 
223
- export async function quiltApp({
236
+ export async function quiltAppOptions({
224
237
  root: rootPath = process.cwd(),
225
238
  app,
226
239
  env,
@@ -239,7 +252,7 @@ export async function quiltApp({
239
252
 
240
253
  browserGroupEntries.forEach(([name, browsers], index) => {
241
254
  optionPromises.push(
242
- quiltAppBrowser({
255
+ quiltAppBrowserOptions({
243
256
  root,
244
257
  app,
245
258
  graphql,
@@ -262,12 +275,15 @@ export async function quiltApp({
262
275
  });
263
276
 
264
277
  optionPromises.push(
265
- quiltAppServer({
278
+ quiltAppServerOptions({
266
279
  root,
267
280
  app,
268
281
  graphql,
269
282
  ...serverOptions,
270
- env: {...resolveEnvOption(env), ...resolveEnvOption(serverOptions?.env)},
283
+ env: {
284
+ ...resolveEnvOption(env),
285
+ ...resolveEnvOption(serverOptions?.env),
286
+ },
271
287
  assets: {...assets, ...serverOptions?.assets},
272
288
  }),
273
289
  );
@@ -275,6 +291,37 @@ export async function quiltApp({
275
291
  return Promise.all(optionPromises);
276
292
  }
277
293
 
294
+ export async function quiltAppBrowserOptions(options: AppBrowserOptions = {}) {
295
+ const {root: rootPath = process.cwd(), assets} = options;
296
+ const root = resolveRoot(rootPath);
297
+
298
+ const [plugins, browserGroup] = await Promise.all([
299
+ quiltAppBrowser(options),
300
+ getBrowserGroupTargetDetails(assets?.targets, {
301
+ root,
302
+ }),
303
+ ]);
304
+
305
+ const targetFilenamePart = browserGroup.name ? `.${browserGroup.name}` : '';
306
+ const [isESM, generatedCode] = await Promise.all([
307
+ targetsSupportModules(browserGroup.browsers),
308
+ rollupGenerateOptionsForBrowsers(browserGroup.browsers),
309
+ ]);
310
+
311
+ return {
312
+ plugins,
313
+ output: {
314
+ format: isESM ? 'esm' : 'systemjs',
315
+ dir: path.resolve(root, `build/assets`),
316
+ entryFileNames: `[name]${targetFilenamePart}.[hash].js`,
317
+ assetFileNames: `[name]${targetFilenamePart}.[hash].[ext]`,
318
+ chunkFileNames: `[name]${targetFilenamePart}.[hash].js`,
319
+ manualChunks: createManualChunksSorter(),
320
+ generatedCode,
321
+ },
322
+ } satisfies RollupOptions;
323
+ }
324
+
278
325
  export async function quiltAppBrowser({
279
326
  root: rootPath = process.cwd(),
280
327
  app,
@@ -299,7 +346,8 @@ export async function quiltAppBrowser({
299
346
  {visualizer},
300
347
  {magicModuleEnv, replaceProcessEnv},
301
348
  {sourceCode},
302
- {createTSConfigAliasPlugin},
349
+ {tsconfigAliases},
350
+ {react},
303
351
  {css},
304
352
  {assetManifest, rawAssets, staticAssets},
305
353
  {asyncModules},
@@ -313,6 +361,7 @@ export async function quiltAppBrowser({
313
361
  import('./features/env.ts'),
314
362
  import('./features/source-code.ts'),
315
363
  import('./features/typescript.ts'),
364
+ import('./features/react.ts'),
316
365
  import('./features/css.ts'),
317
366
  import('./features/assets.ts'),
318
367
  import('./features/async.ts'),
@@ -323,7 +372,8 @@ export async function quiltAppBrowser({
323
372
  loadPackageJSON(root),
324
373
  ]);
325
374
 
326
- const plugins: Plugin[] = [
375
+ const plugins: InputPluginOption[] = [
376
+ quiltAppBrowserInput({root, entry}),
327
377
  ...nodePlugins,
328
378
  systemJS({minify}),
329
379
  replaceProcessEnv({mode}),
@@ -345,11 +395,12 @@ export async function quiltAppBrowser({
345
395
  },
346
396
  },
347
397
  }),
398
+ react(),
399
+ css({minify, emit: true}),
348
400
  esnext({
349
401
  mode,
350
402
  targets: browserGroup.browsers,
351
403
  }),
352
- css({minify, emit: true}),
353
404
  rawAssets(),
354
405
  staticAssets({
355
406
  baseURL,
@@ -376,6 +427,7 @@ export async function quiltAppBrowser({
376
427
  chunkFileNames: `[name]${targetFilenamePart}.[hash].js`,
377
428
  },
378
429
  }),
430
+ tsconfigAliases({root}),
379
431
  ];
380
432
 
381
433
  if (assets?.clean ?? true) {
@@ -386,12 +438,6 @@ export async function quiltAppBrowser({
386
438
  );
387
439
  }
388
440
 
389
- const tsconfigAliases = await createTSConfigAliasPlugin();
390
-
391
- if (tsconfigAliases) {
392
- plugins.push(tsconfigAliases);
393
- }
394
-
395
441
  const appEntry = await resolveAppEntry(app, {root, packageJSON});
396
442
 
397
443
  if (appEntry) {
@@ -445,44 +491,63 @@ export async function quiltAppBrowser({
445
491
  }),
446
492
  );
447
493
 
448
- const finalEntry = entry
449
- ? path.resolve(root, entry)
450
- : (await glob('{browser,client,web}.{ts,tsx,mjs,js,jsx}', {
451
- cwd: root,
452
- nodir: true,
453
- absolute: true,
454
- }).then((files) => files[0])) ?? MAGIC_MODULE_ENTRY;
494
+ return plugins;
495
+ }
455
496
 
456
- const isESM = await targetsSupportModules(browserGroup.browsers);
497
+ export function quiltAppBrowserInput({
498
+ root: rootPath = process.cwd(),
499
+ entry,
500
+ }: Pick<AppBrowserOptions, 'root' | 'entry'> = {}) {
501
+ const root = resolveRoot(rootPath);
457
502
 
458
503
  return {
459
- // If we are using the "magic entry", give it an explicit name of `browser`.
460
- // Otherwise, Rollup will use the file name as the output name.
461
- input:
462
- finalEntry === MAGIC_MODULE_ENTRY ? {browser: finalEntry} : finalEntry,
463
- plugins,
464
- onwarn(warning, defaultWarn) {
465
- // Removes annoying warnings for React-focused libraries that
466
- // include 'use client' directives.
467
- if (
468
- warning.code === 'MODULE_LEVEL_DIRECTIVE' &&
469
- /['"]use client['"]/.test(warning.message)
470
- ) {
471
- return;
472
- }
473
-
474
- defaultWarn(warning);
504
+ name: '@quilted/app-browser/input',
505
+ async options(options) {
506
+ const finalEntry =
507
+ normalizeRollupInput(options.input) ??
508
+ (entry
509
+ ? path.resolve(root, entry)
510
+ : await glob('{browser,client,web}.{ts,tsx,mjs,js,jsx}', {
511
+ cwd: root,
512
+ nodir: true,
513
+ absolute: true,
514
+ }).then((files) => files[0])) ??
515
+ MAGIC_MODULE_ENTRY;
516
+
517
+ return {
518
+ ...options,
519
+ // If we are using the "magic entry", give it an explicit name of `browser`.
520
+ // Otherwise, Rollup will use the file name as the output name.
521
+ input:
522
+ finalEntry === MAGIC_MODULE_ENTRY
523
+ ? {browser: finalEntry}
524
+ : finalEntry,
525
+ };
475
526
  },
527
+ } satisfies Plugin;
528
+ }
529
+
530
+ export async function quiltAppServerOptions(options: AppServerOptions = {}) {
531
+ const {root: rootPath = process.cwd(), output} = options;
532
+
533
+ const root = resolveRoot(rootPath);
534
+ const hash = output?.hash ?? 'async-only';
535
+ const outputFormat = output?.format ?? 'esmodules';
536
+
537
+ const plugins = await quiltAppServer(options);
538
+
539
+ return {
540
+ plugins,
476
541
  output: {
477
- format: isESM ? 'esm' : 'systemjs',
478
- dir: path.resolve(root, `build/assets`),
479
- entryFileNames: `[name]${targetFilenamePart}.[hash].js`,
480
- assetFileNames: `[name]${targetFilenamePart}.[hash].[ext]`,
481
- chunkFileNames: `[name]${targetFilenamePart}.[hash].js`,
482
- manualChunks: createManualChunksSorter(),
483
- generatedCode: await rollupGenerateOptionsForBrowsers(
484
- browserGroup.browsers,
485
- ),
542
+ format:
543
+ outputFormat === 'commonjs' || outputFormat === 'cjs' ? 'cjs' : 'esm',
544
+ dir: path.resolve(root, `build/server`),
545
+ entryFileNames: `[name]${hash === true ? `.[hash]` : ''}.js`,
546
+ chunkFileNames: `[name]${
547
+ hash === true || hash === 'async-only' ? `.[hash]` : ''
548
+ }.js`,
549
+ assetFileNames: `[name]${hash === true ? `.[hash]` : ''}.[ext]`,
550
+ generatedCode: 'es2015',
486
551
  },
487
552
  } satisfies RollupOptions;
488
553
  }
@@ -505,14 +570,13 @@ export async function quiltAppServer({
505
570
 
506
571
  const bundle = output?.bundle;
507
572
  const minify = output?.minify ?? false;
508
- const hash = output?.hash ?? 'async-only';
509
- const outputFormat = output?.format ?? 'esmodules';
510
573
 
511
574
  const [
512
575
  {visualizer},
513
576
  {magicModuleEnv, replaceProcessEnv},
514
577
  {sourceCode},
515
- {createTSConfigAliasPlugin},
578
+ {react},
579
+ {tsconfigAliases},
516
580
  {css},
517
581
  {rawAssets, staticAssets},
518
582
  {asyncModules},
@@ -523,6 +587,7 @@ export async function quiltAppServer({
523
587
  import('rollup-plugin-visualizer'),
524
588
  import('./features/env.ts'),
525
589
  import('./features/source-code.ts'),
590
+ import('./features/react.ts'),
526
591
  import('./features/typescript.ts'),
527
592
  import('./features/css.ts'),
528
593
  import('./features/assets.ts'),
@@ -532,7 +597,8 @@ export async function quiltAppServer({
532
597
  loadPackageJSON(root),
533
598
  ]);
534
599
 
535
- const plugins: Plugin[] = [
600
+ const plugins: InputPluginOption[] = [
601
+ quiltAppServerInput({root, entry, format}),
536
602
  ...nodePlugins,
537
603
  replaceProcessEnv({mode}),
538
604
  magicModuleEnv({...resolveEnvOption(env), mode}),
@@ -552,6 +618,7 @@ export async function quiltAppServer({
552
618
  },
553
619
  },
554
620
  }),
621
+ react(),
555
622
  esnext({
556
623
  mode,
557
624
  targets: ['current node'],
@@ -573,14 +640,9 @@ export async function quiltAppServer({
573
640
  moduleID: ({imported}) => path.relative(root, imported),
574
641
  }),
575
642
  removeBuildFiles(['build/server'], {root}),
643
+ tsconfigAliases({root}),
576
644
  ];
577
645
 
578
- const tsconfigAliases = await createTSConfigAliasPlugin();
579
-
580
- if (tsconfigAliases) {
581
- plugins.push(tsconfigAliases);
582
- }
583
-
584
646
  const appEntry = await resolveAppEntry(app, {root, packageJSON});
585
647
 
586
648
  if (appEntry) {
@@ -595,11 +657,6 @@ export async function quiltAppServer({
595
657
  absolute: true,
596
658
  }).then((files) => files[0]);
597
659
 
598
- const finalEntry =
599
- format === 'request-router'
600
- ? MAGIC_MODULE_ENTRY
601
- : serverEntry ?? MAGIC_MODULE_ENTRY;
602
-
603
660
  plugins.push(
604
661
  magicModuleAppServerEntry({
605
662
  assets: {baseURL},
@@ -630,36 +687,45 @@ export async function quiltAppServer({
630
687
  }),
631
688
  );
632
689
 
690
+ return plugins;
691
+ }
692
+
693
+ export function quiltAppServerInput({
694
+ root: rootPath = process.cwd(),
695
+ entry,
696
+ format = 'request-router',
697
+ }: Pick<AppServerOptions, 'root' | 'entry' | 'format'> = {}) {
698
+ const root = resolveRoot(rootPath);
699
+
633
700
  return {
634
- // If we are using the "magic entry", give it an explicit name of `server`.
635
- // Otherwise, Rollup will use the file name as the output name.
636
- input:
637
- finalEntry === MAGIC_MODULE_ENTRY ? {server: finalEntry} : finalEntry,
638
- plugins,
639
- onwarn(warning, defaultWarn) {
640
- // Removes annoying warnings for React-focused libraries that
641
- // include 'use client' directives.
642
- if (
643
- warning.code === 'MODULE_LEVEL_DIRECTIVE' &&
644
- /['"]use client['"]/.test(warning.message)
645
- ) {
646
- return;
701
+ name: '@quilted/app-server/input',
702
+ async options(options) {
703
+ let finalEntry = normalizeRollupInput(options.input);
704
+
705
+ if (!finalEntry) {
706
+ const serverEntry = entry
707
+ ? path.resolve(root, entry)
708
+ : await glob('{server,service,backend}.{ts,tsx,mjs,js,jsx}', {
709
+ cwd: root,
710
+ nodir: true,
711
+ absolute: true,
712
+ }).then((files) => files[0]);
713
+
714
+ finalEntry =
715
+ format === 'request-router'
716
+ ? MAGIC_MODULE_ENTRY
717
+ : serverEntry ?? MAGIC_MODULE_ENTRY;
647
718
  }
648
719
 
649
- defaultWarn(warning);
650
- },
651
- output: {
652
- format:
653
- outputFormat === 'commonjs' || outputFormat === 'cjs' ? 'cjs' : 'esm',
654
- dir: path.resolve(root, `build/server`),
655
- entryFileNames: `[name]${hash === true ? `.[hash]` : ''}.js`,
656
- chunkFileNames: `[name]${
657
- hash === true || hash === 'async-only' ? `.[hash]` : ''
658
- }.js`,
659
- assetFileNames: `[name]${hash === true ? `.[hash]` : ''}.[ext]`,
660
- generatedCode: 'es2015',
720
+ return {
721
+ ...options,
722
+ // If we are using the "magic entry", give it an explicit name of `server`.
723
+ // Otherwise, Rollup will use the file name as the output name.
724
+ input:
725
+ finalEntry === MAGIC_MODULE_ENTRY ? {server: finalEntry} : finalEntry,
726
+ };
661
727
  },
662
- } satisfies RollupOptions;
728
+ } satisfies Plugin;
663
729
  }
664
730
 
665
731
  export function magicModuleAppComponent({entry}: {entry: string}) {
@@ -0,0 +1,26 @@
1
+ import type {Plugin} from 'rollup';
2
+
3
+ export function react() {
4
+ return {
5
+ name: '@quilted/react',
6
+ options(options) {
7
+ return {
8
+ ...options,
9
+ onLog(level, log, handler) {
10
+ if (
11
+ log.code === 'MODULE_LEVEL_DIRECTIVE' &&
12
+ /['"]use client['"]/.test(log.message)
13
+ ) {
14
+ return;
15
+ }
16
+
17
+ if (options.onLog) {
18
+ options.onLog(level, log, handler);
19
+ } else {
20
+ handler(level, log);
21
+ }
22
+ },
23
+ };
24
+ },
25
+ } satisfies Plugin;
26
+ }
@@ -1,7 +1,7 @@
1
1
  import * as path from 'path';
2
2
  import * as fs from 'fs';
3
3
 
4
- export async function createTSConfigAliasPlugin({
4
+ export async function tsconfigAliases({
5
5
  root = process.cwd(),
6
6
  }: {root?: string} = {}) {
7
7
  const [{default: alias}, tsconfig] = await Promise.all([
package/source/index.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  export {
2
- quiltApp,
2
+ quiltAppOptions,
3
3
  quiltAppBrowser,
4
+ quiltAppBrowserOptions,
4
5
  quiltAppServer,
6
+ quiltAppServerOptions,
5
7
  type AppOptions,
6
8
  type AppBaseOptions,
7
9
  type AppBrowserOptions,
package/source/module.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as path from 'path';
2
- import {Plugin, type RollupOptions} from 'rollup';
2
+ import {type InputPluginOption, type RollupOptions} from 'rollup';
3
3
  import {glob} from 'glob';
4
4
 
5
5
  import {resolveRoot} from './shared/path.ts';
@@ -86,6 +86,8 @@ export async function quiltModule({
86
86
  {visualizer},
87
87
  {magicModuleEnv, replaceProcessEnv},
88
88
  {sourceCode},
89
+ {tsconfigAliases},
90
+ {react},
89
91
  {esnext},
90
92
  nodePlugins,
91
93
  packageJSON,
@@ -93,6 +95,8 @@ export async function quiltModule({
93
95
  import('rollup-plugin-visualizer'),
94
96
  import('./features/env.ts'),
95
97
  import('./features/source-code.ts'),
98
+ import('./features/typescript.ts'),
99
+ import('./features/react.ts'),
96
100
  import('./features/esnext.ts'),
97
101
  getNodePlugins({bundle}),
98
102
  loadPackageJSON(root),
@@ -102,12 +106,14 @@ export async function quiltModule({
102
106
  ? path.resolve(root, entry)
103
107
  : await sourceForModule(root, packageJSON);
104
108
 
105
- const plugins: Plugin[] = [
109
+ const plugins: InputPluginOption[] = [
106
110
  ...nodePlugins,
107
111
  replaceProcessEnv({mode}),
108
112
  magicModuleEnv({...resolveEnvOption(env), mode}),
109
113
  sourceCode({mode, targets: browserGroup.browsers}),
114
+ tsconfigAliases({root}),
110
115
  esnext({mode, targets: browserGroup.browsers}),
116
+ react(),
111
117
  removeBuildFiles(['build/assets', 'build/reports'], {root}),
112
118
  ];
113
119
 
@@ -136,18 +142,6 @@ export async function quiltModule({
136
142
  return {
137
143
  input: finalEntry,
138
144
  plugins,
139
- onwarn(warning, defaultWarn) {
140
- // Removes annoying warnings for React-focused libraries that
141
- // include 'use client' directives.
142
- if (
143
- warning.code === 'MODULE_LEVEL_DIRECTIVE' &&
144
- /['"]use client['"]/.test(warning.message)
145
- ) {
146
- return;
147
- }
148
-
149
- defaultWarn(warning);
150
- },
151
145
  output: {
152
146
  format: 'esm',
153
147
  dir: outputDirectory,
package/source/server.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as path from 'path';
2
- import {Plugin, type RollupOptions} from 'rollup';
2
+ import {type InputPluginOption, type RollupOptions} from 'rollup';
3
3
  import {glob} from 'glob';
4
4
 
5
5
  import {
@@ -107,6 +107,8 @@ export interface ServerOutputOptions
107
107
  format?: 'esmodules' | 'esm' | 'es' | 'commonjs' | 'cjs';
108
108
  }
109
109
 
110
+ export {MAGIC_MODULE_ENTRY, MAGIC_MODULE_REQUEST_ROUTER};
111
+
110
112
  export async function quiltServer({
111
113
  root: rootPath = process.cwd(),
112
114
  entry,
@@ -131,6 +133,8 @@ export async function quiltServer({
131
133
  {visualizer},
132
134
  {magicModuleEnv, replaceProcessEnv},
133
135
  {sourceCode},
136
+ {tsconfigAliases},
137
+ {react},
134
138
  {esnext},
135
139
  nodePlugins,
136
140
  packageJSON,
@@ -138,6 +142,8 @@ export async function quiltServer({
138
142
  import('rollup-plugin-visualizer'),
139
143
  import('./features/env.ts'),
140
144
  import('./features/source-code.ts'),
145
+ import('./features/typescript.ts'),
146
+ import('./features/react.ts'),
141
147
  import('./features/esnext.ts'),
142
148
  getNodePlugins({bundle}),
143
149
  loadPackageJSON(root),
@@ -152,11 +158,13 @@ export async function quiltServer({
152
158
  ? MAGIC_MODULE_ENTRY
153
159
  : serverEntry ?? MAGIC_MODULE_ENTRY;
154
160
 
155
- const plugins: Plugin[] = [
161
+ const plugins: InputPluginOption[] = [
156
162
  ...nodePlugins,
157
163
  replaceProcessEnv({mode}),
158
164
  magicModuleEnv({...resolveEnvOption(env), mode}),
159
165
  sourceCode({mode, targets: ['current node']}),
166
+ tsconfigAliases({root}),
167
+ react(),
160
168
  esnext({mode, targets: ['current node']}),
161
169
  removeBuildFiles(['build/server', 'build/reports'], {root}),
162
170
  ];
@@ -30,7 +30,9 @@ export async function getBrowserGroupTargetDetails(
30
30
  return config[targetName] ?? ['defaults'];
31
31
  })());
32
32
 
33
- return {name: targets.name, browsers: browserslist(targetBrowsers)};
33
+ const browsers = browserslist(targetBrowsers);
34
+
35
+ return {name: targets.name, browsers};
34
36
  }
35
37
 
36
38
  export interface BrowserGroups {
@@ -1,7 +1,7 @@
1
1
  import * as fs from 'fs/promises';
2
2
  import {glob} from 'glob';
3
3
 
4
- import type {Plugin, InputOptions} from 'rollup';
4
+ import type {Plugin, InputOption, InputOptions} from 'rollup';
5
5
  import replace, {type RollupReplaceOptions} from '@rollup/plugin-replace';
6
6
 
7
7
  export function smartReplace(
@@ -39,6 +39,10 @@ export function removeBuildFiles(
39
39
  } satisfies Plugin;
40
40
  }
41
41
 
42
+ export function normalizeRollupInput(input?: InputOption) {
43
+ return Array.isArray(input) && input.length === 0 ? undefined : input;
44
+ }
45
+
42
46
  export interface RollupNodeBundle {
43
47
  readonly builtins?: boolean;
44
48
  readonly dependencies?: boolean;