@quilted/rollup 0.1.9 → 0.1.11

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.
@@ -1,7 +1,13 @@
1
- import type { InputOptions } from 'rollup';
1
+ import type { Plugin, InputOptions } from 'rollup';
2
2
  import { type RollupReplaceOptions } from '@rollup/plugin-replace';
3
- export declare function smartReplace(values: NonNullable<RollupReplaceOptions['values']>, options?: Omit<RollupReplaceOptions, 'values'>): import("rollup").Plugin<any>;
4
- export declare function getNodePlugins(): Promise<import("rollup").Plugin<any>[]>;
3
+ export declare function smartReplace(values: NonNullable<RollupReplaceOptions['values']>, options?: Omit<RollupReplaceOptions, 'values'>): Plugin<any>;
4
+ export declare function removeBuildFiles(patterns: string | string[], { root }?: {
5
+ root?: string;
6
+ }): {
7
+ name: string;
8
+ buildStart(this: import("rollup").PluginContext): Promise<void>;
9
+ };
10
+ export declare function getNodePlugins(): Promise<Plugin<any>[]>;
5
11
  export declare function rollupPluginsToArray(plugins?: InputOptions['plugins']): import("rollup").InputPluginOption[];
6
12
  export declare function addRollupOnWarn(options: InputOptions, warn: NonNullable<InputOptions['onwarn']>): InputOptions;
7
13
  //# sourceMappingURL=rollup.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"rollup.d.ts","sourceRoot":"","sources":["../../../source/shared/rollup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,QAAQ,CAAC;AACzC,OAAgB,EAAC,KAAK,oBAAoB,EAAC,MAAM,wBAAwB,CAAC;AAE1E,wBAAgB,YAAY,CAC1B,MAAM,EAAE,WAAW,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC,EACnD,OAAO,CAAC,EAAE,IAAI,CAAC,oBAAoB,EAAE,QAAQ,CAAC,gCAY/C;AAED,wBAAsB,cAAc,4CAwBnC;AAED,wBAAgB,oBAAoB,CAAC,OAAO,CAAC,EAAE,YAAY,CAAC,SAAS,CAAC,wCAErE;AAED,wBAAgB,eAAe,CAC7B,OAAO,EAAE,YAAY,EACrB,IAAI,EAAE,WAAW,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,GACxC,YAAY,CAed"}
1
+ {"version":3,"file":"rollup.d.ts","sourceRoot":"","sources":["../../../source/shared/rollup.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,MAAM,EAAE,YAAY,EAAC,MAAM,QAAQ,CAAC;AACjD,OAAgB,EAAC,KAAK,oBAAoB,EAAC,MAAM,wBAAwB,CAAC;AAE1E,wBAAgB,YAAY,CAC1B,MAAM,EAAE,WAAW,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC,EACnD,OAAO,CAAC,EAAE,IAAI,CAAC,oBAAoB,EAAE,QAAQ,CAAC,eAY/C;AAED,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,EAC3B,EAAC,IAAoB,EAAC,GAAE;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAM;;;EAe7C;AAED,wBAAsB,cAAc,2BAwBnC;AAED,wBAAgB,oBAAoB,CAAC,OAAO,CAAC,EAAE,YAAY,CAAC,SAAS,CAAC,wCAErE;AAED,wBAAgB,eAAe,CAC7B,OAAO,EAAE,YAAY,EACrB,IAAI,EAAE,WAAW,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,GACxC,YAAY,CAed"}
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "access": "public",
7
7
  "@quilted/registry": "https://registry.npmjs.org"
8
8
  },
9
- "version": "0.1.9",
9
+ "version": "0.1.11",
10
10
  "engines": {
11
11
  "node": ">=14.0.0"
12
12
  },
@@ -43,6 +43,7 @@
43
43
  "@quilted/assets": "^0.0.4",
44
44
  "@quilted/graphql": "^2.0.0",
45
45
  "@types/babel__preset-env": "^7.9.0",
46
+ "browserslist": "^4.22.1",
46
47
  "dotenv": "^16.0.0",
47
48
  "esbuild": "^0.19.4",
48
49
  "glob": "^10.3.10",
package/source/app.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import * as path from 'path';
2
2
  import * as fs from 'fs/promises';
3
3
  import {glob} from 'glob';
4
+ import {fileURLToPath} from 'url';
4
5
 
5
6
  import type {Plugin, RollupOptions, GetManualChunk} from 'rollup';
6
7
  import type {AssetsBuildManifest} from '@quilted/assets';
@@ -14,10 +15,15 @@ import {
14
15
  import type {MagicModuleEnvOptions} from './features/env.ts';
15
16
 
16
17
  import {multiline} from './shared/strings.ts';
17
- import {getNodePlugins} from './shared/rollup.ts';
18
+ import {getNodePlugins, removeBuildFiles} from './shared/rollup.ts';
18
19
  import {createMagicModulePlugin} from './shared/magic-module.ts';
19
20
 
20
21
  export interface AppOptions {
22
+ /**
23
+ * The root directory containing the source code for your application.
24
+ */
25
+ root?: string | URL;
26
+
21
27
  /**
22
28
  * The entry module for this app. This should be an absolute path, or relative
23
29
  * path from the root directory containing your project. This entry should just be
@@ -96,9 +102,17 @@ export interface AppBrowserAssetsOptions {
96
102
  minify?: boolean;
97
103
 
98
104
  baseURL?: string;
105
+ targets?:
106
+ | string[]
107
+ | {
108
+ name?: string;
109
+ browsers?: string[];
110
+ };
111
+ priority?: number;
99
112
  }
100
113
 
101
114
  export async function quiltAppBrowser({
115
+ root: rootPath = process.cwd(),
102
116
  app,
103
117
  entry,
104
118
  env,
@@ -106,12 +120,35 @@ export async function quiltAppBrowser({
106
120
  module,
107
121
  graphql = true,
108
122
  }: AppBrowserOptions = {}) {
109
- const root = process.cwd();
123
+ const root = fileURLToPath(rootPath);
110
124
  const mode =
111
125
  (typeof env === 'object' ? env?.mode : undefined) ?? 'production';
112
126
  const minify = assets?.minify ?? mode === 'production';
113
127
  const baseURL = assets?.baseURL ?? '/assets/';
114
128
 
129
+ const assetTargets = assets?.targets ?? {};
130
+ const targets = Array.isArray(assetTargets)
131
+ ? {
132
+ browsers: assetTargets,
133
+ }
134
+ : assetTargets;
135
+ const targetBrowsers =
136
+ targets.browsers ??
137
+ (await (async () => {
138
+ const {default: browserslist} = await import('browserslist');
139
+ const config = browserslist.findConfig(root);
140
+
141
+ if (config == null) return ['defaults'];
142
+
143
+ const targetName = targets.name ?? 'defaults';
144
+ return config[targetName] ?? ['defaults'];
145
+ })());
146
+ const normalizedTargetName =
147
+ targets.name === 'defaults' ? 'default' : targets.name;
148
+ const targetFilenamePart = normalizedTargetName
149
+ ? `.${normalizedTargetName}`
150
+ : '';
151
+
115
152
  const [
116
153
  {visualizer},
117
154
  {assetManifest},
@@ -135,10 +172,13 @@ export async function quiltAppBrowser({
135
172
  const plugins: Plugin[] = [
136
173
  ...nodePlugins,
137
174
  systemJS({minify}),
138
- sourceCode({mode}),
175
+ sourceCode({mode, targets: targetBrowsers}),
139
176
  css({minify, emit: true}),
140
177
  rawAssets(),
141
178
  staticAssets({baseURL, emit: true}),
179
+ removeBuildFiles(['build/assets', 'build/manifests', 'build/reports'], {
180
+ root,
181
+ }),
142
182
  ];
143
183
 
144
184
  const tsconfigAliases = await createTSConfigAliasPlugin();
@@ -177,31 +217,45 @@ export async function quiltAppBrowser({
177
217
 
178
218
  if (graphql) {
179
219
  const {graphql} = await import('./features/graphql.ts');
180
- plugins.push(graphql({manifest: path.resolve(`manifests/graphql.json`)}));
220
+
221
+ plugins.push(
222
+ graphql({
223
+ manifest: path.resolve(`manifests/graphql${targetFilenamePart}.json`),
224
+ }),
225
+ );
181
226
  }
182
227
 
183
228
  if (minify) {
184
229
  const {minify} = await import('rollup-plugin-esbuild');
230
+
185
231
  plugins.push(minify());
186
232
  }
187
233
 
234
+ const cacheKey = targets.name ? {browserTarget: targets.name} : undefined;
235
+ const id = targets.name ? targets.name : undefined;
236
+
188
237
  plugins.push(
189
238
  // @ts-expect-error The plugin still depends on Rollup 3
190
239
  assetManifest({
240
+ id,
241
+ cacheKey,
191
242
  baseUrl: baseURL,
192
- path: path.resolve(`build/manifests/assets.json`),
243
+ path: path.resolve(`build/manifests/assets${targetFilenamePart}.json`),
244
+ priority: assets?.priority,
193
245
  }),
194
246
  visualizer({
195
247
  template: 'treemap',
196
248
  open: false,
197
249
  brotliSize: true,
198
- filename: path.resolve(`build/reports/bundle-visualizer.html`),
250
+ filename: path.resolve(
251
+ `build/reports/bundle-visualizer${targetFilenamePart}.html`,
252
+ ),
199
253
  }),
200
254
  );
201
255
 
202
256
  const finalEntry =
203
257
  entry ??
204
- (await glob('browser.{ts,tsx,mjs,js,jsx}', {
258
+ (await glob('{browser,client}.{ts,tsx,mjs,js,jsx}', {
205
259
  cwd: root,
206
260
  nodir: true,
207
261
  absolute: true,
@@ -227,9 +281,9 @@ export async function quiltAppBrowser({
227
281
  // format: isESM ? 'esm' : 'systemjs',
228
282
  format: 'esm',
229
283
  dir: path.resolve(`build/assets`),
230
- entryFileNames: `app.[hash].js`,
231
- assetFileNames: `[name].[hash].[ext]`,
232
- chunkFileNames: `[name].[hash].js`,
284
+ entryFileNames: `app${targetFilenamePart}.[hash].js`,
285
+ assetFileNames: `[name]${targetFilenamePart}.[hash].[ext]`,
286
+ chunkFileNames: `[name]${targetFilenamePart}.[hash].js`,
233
287
  manualChunks: createManualChunksSorter(),
234
288
  },
235
289
  } satisfies RollupOptions;
@@ -282,10 +336,11 @@ export async function quiltAppServer({
282
336
 
283
337
  const plugins: Plugin[] = [
284
338
  ...nodePlugins,
285
- sourceCode({mode}),
339
+ sourceCode({mode, targets: ['current node']}),
286
340
  css({emit: false, minify}),
287
341
  rawAssets(),
288
342
  staticAssets({emit: false}),
343
+ removeBuildFiles(['build/server'], {root}),
289
344
  ];
290
345
 
291
346
  const tsconfigAliases = await createTSConfigAliasPlugin();
@@ -338,14 +393,14 @@ export async function quiltAppServer({
338
393
  visualizer({
339
394
  template: 'treemap',
340
395
  open: false,
341
- brotliSize: true,
342
- filename: path.resolve(`build/reports/bundle-visualizer.html`),
396
+ brotliSize: false,
397
+ filename: path.resolve(`build/reports/bundle-visualizer.server.html`),
343
398
  }),
344
399
  );
345
400
 
346
401
  const finalEntry =
347
402
  entry ??
348
- (await glob('server.{ts,tsx,mjs,js,jsx}', {
403
+ (await glob('{server,service,backend}.{ts,tsx,mjs,js,jsx}', {
349
404
  cwd: root,
350
405
  nodir: true,
351
406
  absolute: true,
package/source/index.ts CHANGED
@@ -5,3 +5,4 @@ export {
5
5
  type AppBrowserOptions,
6
6
  type AppServerOptions,
7
7
  } from './app.ts';
8
+ export {quiltPackageESModules, type PackageOptions} from './package.ts';
@@ -0,0 +1,143 @@
1
+ import * as path from 'path';
2
+ import {Plugin, type RollupOptions} from 'rollup';
3
+ import {glob} from 'glob';
4
+ import {fileURLToPath} from 'url';
5
+
6
+ import {getNodePlugins, removeBuildFiles} from './shared/rollup.ts';
7
+ import {loadPackageJSON, type PackageJSON} from './shared/package-json.ts';
8
+
9
+ export interface PackageOptions {
10
+ /**
11
+ * The root directory containing the source code for your application.
12
+ */
13
+ root?: string | URL;
14
+ }
15
+
16
+ export async function quiltPackageESModules({
17
+ root: rootPath = process.cwd(),
18
+ }: PackageOptions = {}) {
19
+ const root = fileURLToPath(rootPath);
20
+ const outputDirectory = path.join(root, 'build/esm');
21
+
22
+ const [{sourceCode}, nodePlugins, packageJSON] = await Promise.all([
23
+ import('./features/source-code.ts'),
24
+ getNodePlugins(),
25
+ loadPackageJSON(root),
26
+ ]);
27
+
28
+ const [entries] = await Promise.all([
29
+ sourceEntriesForPackage(root, packageJSON),
30
+ ]);
31
+
32
+ let sourceRoot = root;
33
+
34
+ for (const entry of Object.values(entries)) {
35
+ if (!entry.startsWith(root)) continue;
36
+
37
+ sourceRoot = path.resolve(
38
+ root,
39
+ path.relative(root, entry).split(path.sep)[0] ?? '.',
40
+ );
41
+ break;
42
+ }
43
+
44
+ const plugins: Plugin[] = [
45
+ ...nodePlugins,
46
+ sourceCode({mode: 'production'}),
47
+ removeBuildFiles(['build/esm'], {root}),
48
+ ];
49
+
50
+ return {
51
+ input: entries,
52
+ plugins,
53
+ onwarn(warning, defaultWarn) {
54
+ // Removes annoying warnings for React-focused libraries that
55
+ // include 'use client' directives.
56
+ if (
57
+ warning.code === 'MODULE_LEVEL_DIRECTIVE' &&
58
+ /['"]use client['"]/.test(warning.message)
59
+ ) {
60
+ return;
61
+ }
62
+
63
+ defaultWarn(warning);
64
+ },
65
+ output: {
66
+ preserveModules: true,
67
+ preserveModulesRoot: sourceRoot,
68
+ format: 'esm',
69
+ dir: outputDirectory,
70
+ entryFileNames: `[name].mjs`,
71
+ assetFileNames: `[name].[ext]`,
72
+ // chunkFileNames: createChunkNamer({
73
+ // extension: ESM_EXTENSION,
74
+ // sourceRoot: sourceRootDirectory,
75
+ // }),
76
+ },
77
+ } satisfies RollupOptions;
78
+ }
79
+
80
+ async function sourceEntriesForPackage(root: string, packageJSON: PackageJSON) {
81
+ const {main, exports} = packageJSON;
82
+
83
+ const entries: Record<string, string> = {};
84
+
85
+ if (typeof main === 'string') {
86
+ entries['.'] = await resolveTargetFileAsSource(main, root);
87
+ }
88
+
89
+ if (typeof exports === 'string') {
90
+ entries['.'] = await resolveTargetFileAsSource(exports, root);
91
+ return entries;
92
+ } else if (exports == null || typeof exports !== 'object') {
93
+ return entries;
94
+ }
95
+
96
+ for (const [exportPath, exportCondition] of Object.entries(
97
+ exports as Record<string, null | string | Record<string, string>>,
98
+ )) {
99
+ let targetFile: string | null | undefined = null;
100
+
101
+ if (exportCondition == null) continue;
102
+
103
+ if (typeof exportCondition === 'string') {
104
+ targetFile = exportCondition;
105
+ } else {
106
+ targetFile ??=
107
+ exportCondition['source'] ??
108
+ exportCondition['quilt:source'] ??
109
+ exportCondition['quilt:esnext'] ??
110
+ Object.values(exportCondition).find(
111
+ (condition) =>
112
+ typeof condition === 'string' && condition.startsWith('./build/'),
113
+ );
114
+ }
115
+
116
+ if (targetFile == null) continue;
117
+
118
+ const sourceFile = await resolveTargetFileAsSource(targetFile, root);
119
+
120
+ entries[exportPath] = sourceFile;
121
+ }
122
+
123
+ return entries;
124
+ }
125
+
126
+ async function resolveTargetFileAsSource(file: string, root: string) {
127
+ const sourceFile = file.includes('/build/')
128
+ ? (
129
+ await glob(
130
+ file
131
+ .replace(/[/]build[/][^/]+[/]/, '/*/')
132
+ .replace(/(\.d\.ts|\.[\w]+)$/, '.*'),
133
+ {
134
+ cwd: root,
135
+ absolute: true,
136
+ ignore: [path.resolve(root, file)],
137
+ },
138
+ )
139
+ )[0]!
140
+ : path.resolve(root, file);
141
+
142
+ return sourceFile;
143
+ }
@@ -0,0 +1,17 @@
1
+ import * as path from 'path';
2
+ import {fileURLToPath} from 'url';
3
+ import {readFile} from 'fs/promises';
4
+
5
+ export interface PackageJSON {
6
+ name?: string;
7
+ [key: string]: unknown;
8
+ }
9
+
10
+ export async function loadPackageJSON(root: string | URL) {
11
+ const file = await readFile(
12
+ path.join(fileURLToPath(root), 'package.json'),
13
+ 'utf8',
14
+ );
15
+
16
+ return JSON.parse(file) as PackageJSON;
17
+ }
@@ -1,4 +1,7 @@
1
- import type {InputOptions} from 'rollup';
1
+ import * as fs from 'fs/promises';
2
+ import {glob} from 'glob';
3
+
4
+ import type {Plugin, InputOptions} from 'rollup';
2
5
  import replace, {type RollupReplaceOptions} from '@rollup/plugin-replace';
3
6
 
4
7
  export function smartReplace(
@@ -17,6 +20,25 @@ export function smartReplace(
17
20
  });
18
21
  }
19
22
 
23
+ export function removeBuildFiles(
24
+ patterns: string | string[],
25
+ {root = process.cwd()}: {root?: string} = {},
26
+ ) {
27
+ return {
28
+ name: '@quilt/remove-build-files',
29
+ async buildStart() {
30
+ const matches = await glob(patterns, {
31
+ cwd: root,
32
+ absolute: true,
33
+ });
34
+
35
+ await Promise.all(
36
+ matches.map((file) => fs.rm(file, {recursive: true, force: true})),
37
+ );
38
+ },
39
+ } satisfies Plugin;
40
+ }
41
+
20
42
  export async function getNodePlugins() {
21
43
  const [
22
44
  {default: commonjs},