@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
@@ -0,0 +1,245 @@
1
+ import * as path from 'path';
2
+ import {Plugin, type RollupOptions} from 'rollup';
3
+ import {glob} from 'glob';
4
+
5
+ import {
6
+ RollupNodePluginOptions,
7
+ getNodePlugins,
8
+ removeBuildFiles,
9
+ } from './shared/rollup.ts';
10
+ import {resolveRoot} from './shared/path.ts';
11
+ import {loadPackageJSON, type PackageJSON} from './shared/package-json.ts';
12
+ import {magicModuleRequestRouterEntry} from './features/request-router.ts';
13
+ import {resolveEnvOption, type MagicModuleEnvOptions} from './features/env.ts';
14
+ import {MAGIC_MODULE_ENTRY, MAGIC_MODULE_REQUEST_ROUTER} from './constants.ts';
15
+ import {createMagicModulePlugin} from './shared/magic-module.ts';
16
+
17
+ export interface ServerOptions {
18
+ /**
19
+ * The root directory containing the source code for your application.
20
+ */
21
+ root?: string | URL;
22
+
23
+ /**
24
+ * The entry module for this server. By default, this module must export
25
+ * a `RequestRouter` object as its default export, which will be wrapped in
26
+ * the specific server runtime you configure. If you set the format to `'custom'`,
27
+ * this entry can be any content — it will be bundled as-is.
28
+ *
29
+ * If not provided, this will default to a file named `server`, `service`,
30
+ * or `backend` in your server’s root directory.
31
+ */
32
+ entry?: string;
33
+
34
+ /**
35
+ * Whether this server code uses the `request-router` library to
36
+ * define itself in a generic way, which can be adapted to a variety
37
+ * of environments. By default, this is `'request-router'`, and when `'request-router'`,
38
+ * the `entry` you specified must export an `RequestRouter` object as
39
+ * its default export. When set to `false`, the app server will be built
40
+ * as a basic server-side JavaScript project, without the special
41
+ * `request-router` adaptor.
42
+ *
43
+ * @default 'request-router'
44
+ */
45
+ format?: 'request-router' | 'custom';
46
+
47
+ /**
48
+ * Whether to include GraphQL-related code transformations.
49
+ *
50
+ * @default true
51
+ */
52
+ graphql?: boolean;
53
+
54
+ /**
55
+ * Customizes the behavior of environment variables for your module.
56
+ */
57
+ env?: MagicModuleEnvOptions | MagicModuleEnvOptions['mode'];
58
+
59
+ /**
60
+ * Controls how the server outputs are generated.
61
+ */
62
+ output?: ServerOutputOptions;
63
+
64
+ /**
65
+ * The port that the server will listen on when it runs. This only applies
66
+ * when you use the `request-router` format — if you use the `custom` format,
67
+ * you are responsible for starting the server yourself.
68
+ *
69
+ * If you do not provide a value here, the server will listen for requests on
70
+ * the port specified by `process.env.NODE_ENV`.
71
+ */
72
+ port?: number | string;
73
+
74
+ /**
75
+ * The host that the server will listen on when it runs. This only applies
76
+ * when you use the `request-router` format — if you use the `custom` format,
77
+ * you are responsible for starting the server yourself.
78
+ */
79
+ host?: string;
80
+ }
81
+
82
+ export interface ServerOutputOptions
83
+ extends Pick<RollupNodePluginOptions, 'bundle'> {
84
+ /**
85
+ * Whether to minify assets created for this server.
86
+ *
87
+ * @default false
88
+ */
89
+ minify?: boolean;
90
+
91
+ /**
92
+ * Whether to add a hash to the output files for your server. You can set
93
+ * this to `true`, which includes a hash for all files, `false`, which never
94
+ * includes a hash, or `'async-only'`, which only includes a hash for files
95
+ * that are loaded asynchronously (that is, your entry file will not have a
96
+ * hash, but any files it loads will).
97
+ *
98
+ * @default 'async-only'
99
+ */
100
+ hash?: boolean | 'async-only';
101
+
102
+ /**
103
+ * What module format to use for the server output.
104
+ *
105
+ * @default 'esmodules'
106
+ */
107
+ format?: 'esmodules' | 'esm' | 'es' | 'commonjs' | 'cjs';
108
+ }
109
+
110
+ export async function quiltServer({
111
+ root: rootPath = process.cwd(),
112
+ entry,
113
+ format = 'request-router',
114
+ env,
115
+ graphql = true,
116
+ output,
117
+ port,
118
+ host,
119
+ }: ServerOptions = {}) {
120
+ const root = resolveRoot(rootPath);
121
+ const mode =
122
+ (typeof env === 'object' ? env?.mode : undefined) ?? 'production';
123
+ const outputDirectory = path.join(root, 'build/server');
124
+
125
+ const minify = output?.minify ?? false;
126
+ const bundle = output?.bundle;
127
+ const hash = output?.hash ?? 'async-only';
128
+ const outputFormat = output?.format ?? 'esmodules';
129
+
130
+ const [
131
+ {visualizer},
132
+ {magicModuleEnv, replaceProcessEnv},
133
+ {sourceCode},
134
+ {esnext},
135
+ nodePlugins,
136
+ packageJSON,
137
+ ] = await Promise.all([
138
+ import('rollup-plugin-visualizer'),
139
+ import('./features/env.ts'),
140
+ import('./features/source-code.ts'),
141
+ import('./features/esnext.ts'),
142
+ getNodePlugins({bundle}),
143
+ loadPackageJSON(root),
144
+ ]);
145
+
146
+ const serverEntry = entry
147
+ ? path.resolve(root, entry)
148
+ : await sourceForServer(root, packageJSON);
149
+
150
+ const finalEntry =
151
+ format === 'request-router'
152
+ ? MAGIC_MODULE_ENTRY
153
+ : serverEntry ?? MAGIC_MODULE_ENTRY;
154
+
155
+ const plugins: Plugin[] = [
156
+ ...nodePlugins,
157
+ replaceProcessEnv({mode}),
158
+ magicModuleEnv({...resolveEnvOption(env), mode}),
159
+ sourceCode({mode, targets: ['current node']}),
160
+ esnext({mode, targets: ['current node']}),
161
+ removeBuildFiles(['build/server', 'build/reports'], {root}),
162
+ ];
163
+
164
+ if (format === 'request-router') {
165
+ plugins.push(
166
+ createMagicModulePlugin({
167
+ name: '@quilted/magic-module/server-request-router',
168
+ module: MAGIC_MODULE_REQUEST_ROUTER,
169
+ alias: serverEntry,
170
+ }),
171
+ magicModuleRequestRouterEntry({
172
+ host,
173
+ port: typeof port === 'string' ? Number.parseInt(port, 10) : port,
174
+ }),
175
+ );
176
+ }
177
+
178
+ if (graphql) {
179
+ const {graphql} = await import('./features/graphql.ts');
180
+ plugins.push(graphql({manifest: false}));
181
+ }
182
+
183
+ if (minify) {
184
+ const {minify} = await import('rollup-plugin-esbuild');
185
+ plugins.push(minify());
186
+ }
187
+
188
+ plugins.push(
189
+ visualizer({
190
+ template: 'treemap',
191
+ open: false,
192
+ brotliSize: true,
193
+ filename: path.resolve(root, `build/reports/bundle-visualizer.html`),
194
+ }),
195
+ );
196
+
197
+ return {
198
+ input: finalEntry,
199
+ plugins,
200
+ onwarn(warning, defaultWarn) {
201
+ // Removes annoying warnings for React-focused libraries that
202
+ // include 'use client' directives.
203
+ if (
204
+ warning.code === 'MODULE_LEVEL_DIRECTIVE' &&
205
+ /['"]use client['"]/.test(warning.message)
206
+ ) {
207
+ return;
208
+ }
209
+
210
+ defaultWarn(warning);
211
+ },
212
+ output: {
213
+ format:
214
+ outputFormat === 'commonjs' || outputFormat === 'cjs' ? 'cjs' : 'esm',
215
+ dir: outputDirectory,
216
+ entryFileNames: `server${hash === true ? `.[hash]` : ''}.js`,
217
+ chunkFileNames: `[name]${
218
+ hash === true || hash === 'async-only' ? `.[hash]` : ''
219
+ }.js`,
220
+ assetFileNames: `[name]${hash === true ? `.[hash]` : ''}.[ext]`,
221
+ generatedCode: 'es2015',
222
+ },
223
+ } satisfies RollupOptions;
224
+ }
225
+
226
+ async function sourceForServer(root: string, packageJSON: PackageJSON) {
227
+ const {main, exports} = packageJSON;
228
+
229
+ const entryFromPackageJSON = main ?? (exports as any)?.['.'];
230
+
231
+ if (entryFromPackageJSON) {
232
+ return path.resolve(root, entryFromPackageJSON);
233
+ }
234
+
235
+ const possibleSourceFiles = await glob(
236
+ '{index,server,service,backend,entry,input}.{ts,tsx,mjs,js,jsx}',
237
+ {
238
+ cwd: root,
239
+ nodir: true,
240
+ absolute: true,
241
+ },
242
+ );
243
+
244
+ return possibleSourceFiles[0]!;
245
+ }
@@ -1,32 +1,222 @@
1
- export type BrowserTargetSelection =
2
- | string[]
1
+ export type BrowserGroupTargetSelection =
2
+ | readonly string[]
3
3
  | {
4
4
  name?: string;
5
- browsers?: string[];
5
+ browsers?: readonly string[];
6
6
  };
7
7
 
8
- export async function getBrowserTargetDetails(
9
- targetSelection: BrowserTargetSelection = {},
8
+ export async function getBrowserGroupTargetDetails(
9
+ targetSelection: BrowserGroupTargetSelection = {},
10
10
  {root}: {root?: string} = {},
11
11
  ) {
12
- const targets = Array.isArray(targetSelection)
13
- ? {
14
- browsers: targetSelection,
15
- }
16
- : targetSelection;
12
+ const {default: browserslist} = await import('browserslist');
13
+
14
+ const targets: {
15
+ name?: string;
16
+ browsers?: readonly string[];
17
+ } = (
18
+ Array.isArray(targetSelection)
19
+ ? {
20
+ browsers: targetSelection,
21
+ }
22
+ : targetSelection
23
+ ) as any;
24
+
17
25
  const targetBrowsers =
18
26
  targets.browsers ??
19
27
  (await (async () => {
20
- const {default: browserslist} = await import('browserslist');
21
- const config = browserslist.findConfig(root!);
22
-
23
- if (config == null) return ['defaults'];
24
-
25
- const targetName = targets.name ?? 'defaults';
28
+ const config = await getBrowserGroups({root});
29
+ const targetName = targets.name ?? 'default';
26
30
  return config[targetName] ?? ['defaults'];
27
31
  })());
28
32
 
29
- const name = targets.name === 'defaults' ? 'default' : targets.name;
33
+ return {name: targets.name, browsers: browserslist(targetBrowsers)};
34
+ }
35
+
36
+ export interface BrowserGroups {
37
+ default: readonly string[];
38
+ [name: string]: readonly string[];
39
+ }
40
+
41
+ export async function getBrowserGroups({
42
+ root = process.cwd(),
43
+ }: {root?: string} = {}): Promise<BrowserGroups> {
44
+ const {default: browserslist} = await import('browserslist');
45
+ const config = browserslist.findConfig(root);
46
+
47
+ if (config == null) return {default: browserslist(['defaults'])};
48
+
49
+ const {defaults, ...rest} = config;
50
+
51
+ const browserGroups: BrowserGroups = {} as any;
52
+
53
+ const groupsWithFullList = Object.entries(rest)
54
+ .map(([name, browsers]) => ({
55
+ name,
56
+ browsers: browserslist(browsers),
57
+ }))
58
+ .sort((first, second) => first.browsers.length - second.browsers.length);
59
+
60
+ for (const {name, browsers} of groupsWithFullList) {
61
+ browserGroups[name] = browsers;
62
+ }
63
+
64
+ browserGroups.default = defaults;
65
+
66
+ return browserGroups;
67
+ }
68
+
69
+ export async function getBrowserGroupRegularExpressions(
70
+ groups?: BrowserGroups,
71
+ ): Promise<Record<string, RegExp>> {
72
+ const [{default: browserslist}, {getUserAgentRegex}] = await Promise.all([
73
+ import('browserslist'),
74
+ import('browserslist-useragent-regexp'),
75
+ ]);
76
+
77
+ // Expand the browserslist queries into the full list of supported browsers,
78
+ // and sort by the number of browsers in each group (with the last item having
79
+ // the largest browser support)
80
+ const groupsWithFullList = Object.entries(
81
+ groups ?? (await getBrowserGroups()),
82
+ )
83
+ .map(([name, browsers]) => ({
84
+ name,
85
+ browsers: browserslist(browsers),
86
+ }))
87
+ .sort((first, second) => first.browsers.length - second.browsers.length);
88
+
89
+ if (groupsWithFullList.length === 0) return {};
90
+
91
+ const lastGroup = groupsWithFullList.pop()!;
92
+
93
+ const regexes: Record<string, RegExp> = {};
94
+
95
+ for (const {name, browsers} of groupsWithFullList) {
96
+ const regex = getUserAgentRegex({
97
+ browsers,
98
+ ignoreMinor: true,
99
+ ignorePatch: true,
100
+ allowHigherVersions: true,
101
+ });
102
+
103
+ regexes[name] = regex;
104
+ }
105
+
106
+ // The last group is the default group, so it should match everything
107
+ regexes[lastGroup.name] = new RegExp('');
108
+
109
+ return regexes;
110
+ }
111
+
112
+ let esmBrowserslist: Promise<Set<string>>;
113
+
114
+ export async function targetsSupportModules(targets: readonly string[]) {
115
+ esmBrowserslist ??= (async () => {
116
+ const {default: browserslist} = await import('browserslist');
117
+
118
+ return new Set(
119
+ browserslist(
120
+ 'defaults and fully supports es6-module and fully supports es6-module-dynamic-import',
121
+ ),
122
+ );
123
+ })();
124
+
125
+ const esmBrowsers = await esmBrowserslist;
126
+
127
+ return targets.every((target) => esmBrowsers.has(target));
128
+ }
129
+
130
+ const BROWSESLIST_BROWSER_TO_MDN_BROWSER = new Map([
131
+ ['and_chr', 'chrome_android'],
132
+ ['and_ff', 'firefox_android'],
133
+ ['and_qq', 'qq_android'],
134
+ ['and_uc', 'uc_android'],
135
+ ['android', 'webview_android'],
136
+ ['chrome', 'chrome'],
137
+ ['edge', 'edge'],
138
+ ['edge_mob', 'edge_mobile'],
139
+ ['firefox', 'firefox'],
140
+ ['ie', 'ie'],
141
+ ['ios_saf', 'safari_ios'],
142
+ ['node', 'nodejs'],
143
+ ['opera', 'opera'],
144
+ ['safari', 'safari'],
145
+ ['samsung', 'samsunginternet_android'],
146
+ ]);
147
+
148
+ // Roughly adapted from https://github.com/webhintio/hint/blob/main/packages/utils-compat-data/src/browsers.ts
149
+ export async function rollupGenerateOptionsForBrowsers(
150
+ browsers: readonly string[],
151
+ ) {
152
+ const [{default: semver}, {default: mdn}] = await Promise.all([
153
+ import('semver'),
154
+ import('@mdn/browser-compat-data', {
155
+ assert: {type: 'json'},
156
+ }) as Promise<any>,
157
+ ]);
158
+
159
+ const arrowFunctionsSupport =
160
+ mdn.javascript.functions.arrow_functions.__compat.support;
161
+ const constBindingsSupport = mdn.javascript.statements.const.__compat.support;
162
+ const objectShorthandSupport =
163
+ mdn.javascript.grammar.shorthand_object_literals.__compat.support;
164
+ const symbolsSupport = mdn.javascript.builtins.Symbol.__compat.support;
165
+
166
+ let arrowFunctions = true;
167
+ let constBindings = true;
168
+ let objectShorthand = true;
169
+ let symbols = true;
170
+
171
+ const isSupported = (
172
+ browser: string,
173
+ version: import('semver').SemVer,
174
+ supportList: any,
175
+ ) => {
176
+ const supportedVersionDetails = supportList[browser];
177
+ if (supportedVersionDetails == null) return false;
178
+
179
+ const supportedVersion = semver.coerce(
180
+ supportedVersionDetails.version_added,
181
+ );
182
+ if (supportedVersion == null) return false;
183
+
184
+ return semver.gte(version, supportedVersion);
185
+ };
186
+
187
+ for (const browser of browsers) {
188
+ const [name, version] = browser.split(' ');
189
+
190
+ const semverVersion = semver.coerce(version);
191
+ if (semverVersion == null) continue;
192
+
193
+ const mdnBrowser = BROWSESLIST_BROWSER_TO_MDN_BROWSER.get(name!);
194
+ if (mdnBrowser == null) continue;
195
+
196
+ arrowFunctions &&= isSupported(
197
+ mdnBrowser,
198
+ semverVersion,
199
+ arrowFunctionsSupport,
200
+ );
201
+ constBindings &&= isSupported(
202
+ mdnBrowser,
203
+ semverVersion,
204
+ constBindingsSupport,
205
+ );
206
+ objectShorthand &&= isSupported(
207
+ mdnBrowser,
208
+ semverVersion,
209
+ objectShorthandSupport,
210
+ );
211
+ symbols &&= isSupported(mdnBrowser, semverVersion, symbolsSupport);
212
+ }
30
213
 
31
- return {name, browsers: targetBrowsers};
214
+ return {
215
+ preset: 'es2015',
216
+ arrowFunctions,
217
+ constBindings,
218
+ objectShorthand,
219
+ reservedNamesAsProps: objectShorthand,
220
+ symbols,
221
+ } satisfies import('rollup').GeneratedCodeOptions;
32
222
  }
@@ -0,0 +1,5 @@
1
+ import {fileURLToPath} from 'url';
2
+
3
+ export function resolveRoot(root: string | URL) {
4
+ return typeof root === 'string' ? root : fileURLToPath(root);
5
+ }
@@ -39,7 +39,37 @@ export function removeBuildFiles(
39
39
  } satisfies Plugin;
40
40
  }
41
41
 
42
- export async function getNodePlugins() {
42
+ export interface RollupNodeBundle {
43
+ readonly builtins?: boolean;
44
+ readonly dependencies?: boolean;
45
+ readonly devDependencies?: boolean;
46
+ readonly peerDependencies?: boolean;
47
+ readonly exclude?: (string | RegExp)[];
48
+ readonly include?: (string | RegExp)[];
49
+ }
50
+
51
+ export interface RollupNodePluginOptions {
52
+ /**
53
+ * Controls how dependencies from node_modules will be bundled into
54
+ * your rollup build. This can either be `true`, indicating that all
55
+ * dependencies (except node builtins, like `fs`) will be bundled;
56
+ * `false`, indicating that all node dependencies should be treated as
57
+ * external in the resulting build; or a `RollupNodeBundle` object
58
+ * that gives fine-grained control over how node dependencies are
59
+ * bundled. The options in the `RollupNodeBundle` object indicate
60
+ * which dependencies to bundle into your project; this is similar to
61
+ * the options provided to [`rollup-plugin-node-externals`](https://github.com/Septh/rollup-plugin-node-externals),
62
+ * except that those options are inverted (e.g., they indicate which
63
+ * modules to externalize, rather than which modules to bundle).
64
+ *
65
+ * @see https://github.com/Septh/rollup-plugin-node-externals
66
+ */
67
+ bundle?: boolean | RollupNodeBundle;
68
+ }
69
+
70
+ export async function getNodePlugins({
71
+ bundle = {},
72
+ }: RollupNodePluginOptions = {}) {
43
73
  const [
44
74
  {default: commonjs},
45
75
  {default: json},
@@ -52,13 +82,81 @@ export async function getNodePlugins() {
52
82
  import('rollup-plugin-node-externals'),
53
83
  ]);
54
84
 
85
+ let nodeExternalsOptions: Parameters<typeof nodeExternals>[0];
86
+
87
+ if (bundle === true) {
88
+ // If the consumer wants to bundle node dependencies, we use our
89
+ // default bundling config, which inlines all node dependencies
90
+ // other than node builtins.
91
+ nodeExternalsOptions = {
92
+ builtins: true,
93
+ builtinsPrefix: 'strip',
94
+ deps: false,
95
+ devDeps: false,
96
+ peerDeps: false,
97
+ optDeps: false,
98
+ };
99
+ } else if (bundle === false) {
100
+ // If the consumer does not want to bundle node dependencies,
101
+ // we mark all dependencies as external.
102
+ nodeExternalsOptions = {
103
+ builtins: true,
104
+ builtinsPrefix: 'add',
105
+ deps: true,
106
+ devDeps: true,
107
+ peerDeps: true,
108
+ optDeps: true,
109
+ };
110
+ } else {
111
+ // Use the customized bundling configuration. Because this option
112
+ // is framed as what you bundle, rather than what you externalize,
113
+ // we need to invert all their options. For options that aren’t set,
114
+ // we default to bundling only development dependencies — production
115
+ // dependencies and node built-ins are not bundled.
116
+ const {
117
+ builtins: bundleBuiltins = false,
118
+ dependencies: bundleDependencies = false,
119
+ devDependencies: bundleDevDependencies = true,
120
+ peerDependencies: bundlePeerDependencies = false,
121
+ include: alwaysBundleDependencies,
122
+ exclude: neverBundleDependencies,
123
+ } = bundle;
124
+
125
+ nodeExternalsOptions = {
126
+ builtins: !bundleBuiltins,
127
+ builtinsPrefix: bundleBuiltins ? 'strip' : 'add',
128
+ deps: !bundleDependencies,
129
+ devDeps: !bundleDevDependencies,
130
+ peerDeps: !bundlePeerDependencies,
131
+ optDeps: !bundlePeerDependencies,
132
+ include: neverBundleDependencies,
133
+ exclude: alwaysBundleDependencies,
134
+ };
135
+ }
136
+
55
137
  return [
56
- nodeExternals({}),
138
+ nodeExternals(nodeExternalsOptions),
57
139
  nodeResolve({
58
140
  preferBuiltins: true,
59
141
  dedupe: [],
60
- // extensions,
61
- // exportConditions,
142
+ extensions: [
143
+ '.ts',
144
+ '.tsx',
145
+ '.mts',
146
+ '.mtsx',
147
+ '.js',
148
+ '.jsx',
149
+ '.es6',
150
+ '.es',
151
+ '.mjs',
152
+ ],
153
+ exportConditions: [
154
+ 'esnext',
155
+ 'quilt:esnext',
156
+ 'default',
157
+ 'module',
158
+ 'import',
159
+ ],
62
160
  }),
63
161
  commonjs(),
64
162
  json(),
package/tsconfig.json CHANGED
@@ -5,6 +5,10 @@
5
5
  "outDir": "build/typescript"
6
6
  },
7
7
  "include": ["source"],
8
- "exclude": ["quilt.project.ts", "**/*.test.ts", "**/*.test.tsx"],
9
- "references": [{"path": "../assets"}, {"path": "../graphql"}]
8
+ "exclude": ["**/*.test.ts", "**/*.test.tsx"],
9
+ "references": [
10
+ {"path": "../assets"},
11
+ {"path": "../babel"},
12
+ {"path": "../graphql"}
13
+ ]
10
14
  }