@quilted/rollup 0.1.4 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/build/cjs/app.cjs +144 -142
  3. package/build/cjs/features/assets.cjs +130 -0
  4. package/build/cjs/{env.cjs → features/env.cjs} +4 -4
  5. package/build/cjs/{request-router.cjs → features/request-router.cjs} +3 -3
  6. package/build/cjs/{shared → features}/source-code.cjs +1 -1
  7. package/build/cjs/features/system-js.cjs +35 -0
  8. package/build/cjs/index.cjs +0 -7
  9. package/build/cjs/shared/rollup.cjs +0 -4
  10. package/build/esm/app.mjs +146 -144
  11. package/build/esm/features/assets.mjs +107 -0
  12. package/build/esm/{env.mjs → features/env.mjs} +4 -4
  13. package/build/esm/{request-router.mjs → features/request-router.mjs} +3 -3
  14. package/build/esm/features/system-js.mjs +33 -0
  15. package/build/esm/index.mjs +1 -3
  16. package/build/esm/shared/rollup.mjs +1 -4
  17. package/build/esnext/app.esnext +146 -144
  18. package/build/esnext/features/assets.esnext +107 -0
  19. package/build/esnext/{env.esnext → features/env.esnext} +4 -4
  20. package/build/esnext/{request-router.esnext → features/request-router.esnext} +3 -3
  21. package/build/esnext/features/system-js.esnext +33 -0
  22. package/build/esnext/index.esnext +1 -3
  23. package/build/esnext/shared/rollup.esnext +1 -4
  24. package/build/tsconfig.tsbuildinfo +1 -1
  25. package/build/typescript/app.d.ts +32 -144
  26. package/build/typescript/app.d.ts.map +1 -1
  27. package/build/typescript/features/assets.d.ts +13 -0
  28. package/build/typescript/features/assets.d.ts.map +1 -0
  29. package/build/typescript/features/css.d.ts +16 -0
  30. package/build/typescript/features/css.d.ts.map +1 -0
  31. package/build/typescript/features/env.d.ts +57 -0
  32. package/build/typescript/features/env.d.ts.map +1 -0
  33. package/build/typescript/features/graphql/transform.d.ts +17 -0
  34. package/build/typescript/features/graphql/transform.d.ts.map +1 -0
  35. package/build/typescript/features/graphql.d.ts +6 -0
  36. package/build/typescript/features/graphql.d.ts.map +1 -0
  37. package/build/typescript/features/request-router.d.ts +15 -0
  38. package/build/typescript/features/request-router.d.ts.map +1 -0
  39. package/build/typescript/features/source-code.d.ts +5 -0
  40. package/build/typescript/features/source-code.d.ts.map +1 -0
  41. package/build/typescript/features/system-js.d.ts +7 -0
  42. package/build/typescript/features/system-js.d.ts.map +1 -0
  43. package/build/typescript/index.d.ts +1 -3
  44. package/build/typescript/index.d.ts.map +1 -1
  45. package/package.json +5 -2
  46. package/source/app.ts +168 -124
  47. package/source/features/assets.ts +183 -0
  48. package/source/features/css.ts +91 -0
  49. package/source/{env.ts → features/env.ts} +4 -4
  50. package/source/{request-router.ts → features/request-router.ts} +3 -3
  51. package/source/features/system-js.ts +36 -0
  52. package/source/index.ts +0 -5
  53. /package/build/cjs/{graphql → features/graphql}/transform.cjs +0 -0
  54. /package/build/cjs/{graphql.cjs → features/graphql.cjs} +0 -0
  55. /package/build/esm/{graphql → features/graphql}/transform.mjs +0 -0
  56. /package/build/esm/{graphql.mjs → features/graphql.mjs} +0 -0
  57. /package/build/esm/{shared → features}/source-code.mjs +0 -0
  58. /package/build/esnext/{graphql → features/graphql}/transform.esnext +0 -0
  59. /package/build/esnext/{graphql.esnext → features/graphql.esnext} +0 -0
  60. /package/build/esnext/{shared → features}/source-code.esnext +0 -0
  61. /package/source/{graphql → features/graphql}/transform.ts +0 -0
  62. /package/source/{graphql.ts → features/graphql.ts} +0 -0
  63. /package/source/{shared → features}/source-code.ts +0 -0
@@ -1,172 +1,174 @@
1
1
  import * as path from 'node:path';
2
- import { MAGIC_MODULE_APP_COMPONENT, MAGIC_MODULE_REQUEST_ROUTER, MAGIC_MODULE_BROWSER_ASSETS, MAGIC_MODULE_ENTRY } from './constants.esnext';
2
+ import { MAGIC_MODULE_ENTRY, MAGIC_MODULE_APP_COMPONENT, MAGIC_MODULE_REQUEST_ROUTER, MAGIC_MODULE_BROWSER_ASSETS } from './constants.esnext';
3
3
  import { multiline } from './shared/strings.esnext';
4
- import { rollupPluginsToArray, getNodePlugins } from './shared/rollup.esnext';
4
+ import { getNodePlugins } from './shared/rollup.esnext';
5
5
  import { createMagicModulePlugin } from './shared/magic-module.esnext';
6
6
 
7
- function quiltAppBrowser({
7
+ async function quiltAppBrowser({
8
8
  app,
9
+ entry = MAGIC_MODULE_ENTRY,
9
10
  env,
10
11
  assets,
11
12
  module,
12
13
  graphql = true
13
14
  } = {}) {
14
15
  const mode = (typeof env === 'object' ? env?.mode : undefined) ?? 'production';
15
- return {
16
- name: '@quilted/app/browser',
17
- async options(originalOptions) {
18
- const newPlugins = rollupPluginsToArray(originalOptions.plugins);
19
- const newOptions = {
20
- ...originalOptions,
21
- plugins: newPlugins
22
- };
23
- const [{
24
- visualizer
25
- }, {
26
- sourceCode
27
- }, nodePlugins] = await Promise.all([import('rollup-plugin-visualizer'), import('./shared/source-code.esnext'), getNodePlugins()]);
28
- newPlugins.push(...nodePlugins);
29
- newPlugins.push(sourceCode({
16
+ const minify = assets?.minify ?? true;
17
+ const [{
18
+ visualizer
19
+ }, {
20
+ sourceCode
21
+ }, {
22
+ rawAssets,
23
+ staticAssets
24
+ }, {
25
+ systemJS
26
+ }, nodePlugins] = await Promise.all([import('rollup-plugin-visualizer'), import('./features/source-code.esnext'), import('./features/assets.esnext'), import('./features/system-js.esnext'), getNodePlugins()]);
27
+ const plugins = [...nodePlugins, systemJS(), sourceCode({
28
+ mode
29
+ }), rawAssets(), staticAssets()];
30
+ if (env) {
31
+ const {
32
+ magicModuleEnv,
33
+ replaceProcessEnv
34
+ } = await import('./features/env.esnext');
35
+ if (typeof env === 'boolean') {
36
+ plugins.push(replaceProcessEnv({
30
37
  mode
31
38
  }));
32
- if (env) {
33
- const {
34
- magicModuleEnv,
35
- replaceProcessEnv
36
- } = await import('./env.esnext');
37
- if (typeof env === 'boolean') {
38
- newPlugins.push(replaceProcessEnv({
39
- mode: 'production'
40
- }));
41
- newPlugins.push(magicModuleEnv({
42
- mode: 'production'
43
- }));
44
- } else {
45
- newPlugins.push(replaceProcessEnv({
46
- mode: env.mode ?? 'production'
47
- }));
48
- newPlugins.push(magicModuleEnv({
49
- mode: 'production',
50
- ...env
51
- }));
52
- }
53
- }
54
- if (app) {
55
- newPlugins.push(magicModuleAppComponent({
56
- entry: app
57
- }));
58
- }
59
- newPlugins.push(magicModuleAppBrowserEntry(module));
60
- if (graphql) {
61
- const {
62
- graphql
63
- } = await import('./graphql.esnext');
64
- newPlugins.push(graphql({
65
- manifest: path.resolve(`manifests/graphql.json`)
66
- }));
67
- }
68
- const minify = assets?.minify ?? true;
69
- if (minify) {
70
- const {
71
- minify
72
- } = await import('rollup-plugin-esbuild');
73
- newPlugins.push(minify());
74
- }
75
- newPlugins.push(visualizer({
76
- template: 'treemap',
77
- open: false,
78
- brotliSize: true,
79
- filename: path.resolve(`reports/bundle-visualizer.html`)
39
+ plugins.push(magicModuleEnv({
40
+ mode
80
41
  }));
81
- return newOptions;
82
- },
83
- outputOptions(originalOptions) {
84
- return {
85
- ...originalOptions,
86
- // format: isESM ? 'esm' : 'systemjs',
87
- format: 'esm',
88
- dir: path.resolve(`build/assets`),
89
- entryFileNames: `app.[hash].js`,
90
- assetFileNames: `[name].[hash].[ext]`,
91
- chunkFileNames: `[name].[hash].js`,
92
- manualChunks: createManualChunksSorter()
93
- };
42
+ } else {
43
+ plugins.push(replaceProcessEnv({
44
+ mode
45
+ }));
46
+ plugins.push(magicModuleEnv({
47
+ mode
48
+ }));
49
+ }
50
+ }
51
+ if (app) {
52
+ plugins.push(magicModuleAppComponent({
53
+ entry: app
54
+ }));
55
+ }
56
+ plugins.push(magicModuleAppBrowserEntry(module));
57
+ if (graphql) {
58
+ const {
59
+ graphql
60
+ } = await import('./features/graphql.esnext');
61
+ plugins.push(graphql({
62
+ manifest: path.resolve(`manifests/graphql.json`)
63
+ }));
64
+ }
65
+ if (minify) {
66
+ const {
67
+ minify
68
+ } = await import('rollup-plugin-esbuild');
69
+ plugins.push(minify());
70
+ }
71
+ plugins.push(visualizer({
72
+ template: 'treemap',
73
+ open: false,
74
+ brotliSize: true,
75
+ filename: path.resolve(`reports/bundle-visualizer.html`)
76
+ }));
77
+ return {
78
+ input: entry,
79
+ plugins,
80
+ output: {
81
+ // format: isESM ? 'esm' : 'systemjs',
82
+ format: 'esm',
83
+ dir: path.resolve(`build/assets`),
84
+ entryFileNames: `app.[hash].js`,
85
+ assetFileNames: `[name].[hash].[ext]`,
86
+ chunkFileNames: `[name].[hash].js`,
87
+ manualChunks: createManualChunksSorter()
94
88
  }
95
89
  };
96
90
  }
97
- function quiltAppServer({
91
+ async function quiltAppServer({
98
92
  app,
99
93
  env,
100
94
  graphql,
101
- entry
95
+ entry = MAGIC_MODULE_ENTRY,
96
+ minify = false
102
97
  } = {}) {
103
98
  const mode = (typeof env === 'object' ? env?.mode : undefined) ?? 'production';
104
- return {
105
- name: '@quilted/app/server',
106
- async options(originalOptions) {
107
- const newPlugins = rollupPluginsToArray(originalOptions.plugins);
108
- const newOptions = {
109
- ...originalOptions,
110
- plugins: newPlugins
111
- };
112
- const [{
113
- magicModuleRequestRouterEntry
114
- }, {
115
- sourceCode
116
- }, nodePlugins] = await Promise.all([import('./request-router.esnext'), import('./shared/source-code.esnext'), getNodePlugins()]);
117
- newPlugins.push(...nodePlugins);
118
- newPlugins.push(sourceCode({
99
+ const [{
100
+ visualizer
101
+ }, {
102
+ sourceCode
103
+ }, {
104
+ rawAssets,
105
+ staticAssets
106
+ }, {
107
+ magicModuleRequestRouterEntry
108
+ }, nodePlugins] = await Promise.all([import('rollup-plugin-visualizer'), import('./features/source-code.esnext'), import('./features/assets.esnext'), import('./features/request-router.esnext'), getNodePlugins()]);
109
+ const plugins = [...nodePlugins, sourceCode({
110
+ mode
111
+ }), rawAssets(), staticAssets({
112
+ emit: false
113
+ })];
114
+ if (env) {
115
+ const {
116
+ magicModuleEnv,
117
+ replaceProcessEnv
118
+ } = await import('./features/env.esnext');
119
+ if (typeof env === 'boolean') {
120
+ plugins.push(replaceProcessEnv({
119
121
  mode
120
122
  }));
121
- if (env) {
122
- const {
123
- magicModuleEnv,
124
- replaceProcessEnv
125
- } = await import('./env.esnext');
126
- if (typeof env === 'boolean') {
127
- newPlugins.push(replaceProcessEnv({
128
- mode
129
- }));
130
- newPlugins.push(magicModuleEnv({
131
- mode
132
- }));
133
- } else {
134
- newPlugins.push(replaceProcessEnv({
135
- mode
136
- }));
137
- newPlugins.push(magicModuleEnv({
138
- mode,
139
- ...env
140
- }));
141
- }
142
- }
143
- if (app) {
144
- newPlugins.push(magicModuleAppComponent({
145
- entry: app
146
- }));
147
- }
148
- newPlugins.push(magicModuleRequestRouterEntry());
149
- newPlugins.push(magicModuleAppRequestRouter({
150
- entry
123
+ plugins.push(magicModuleEnv({
124
+ mode
151
125
  }));
152
- if (graphql) {
153
- const {
154
- graphql
155
- } = await import('./graphql.esnext');
156
- newPlugins.push(graphql({
157
- manifest: false
158
- }));
159
- }
160
- return newOptions;
161
- },
162
- outputOptions(originalOptions) {
163
- return {
164
- ...originalOptions,
165
- // format,
166
- format: 'esm',
167
- dir: path.resolve(`build/server`),
168
- entryFileNames: 'server.js'
169
- };
126
+ } else {
127
+ plugins.push(replaceProcessEnv({
128
+ mode
129
+ }));
130
+ plugins.push(magicModuleEnv({
131
+ mode
132
+ }));
133
+ }
134
+ }
135
+ if (app) {
136
+ plugins.push(magicModuleAppComponent({
137
+ entry: app
138
+ }));
139
+ }
140
+ plugins.push(magicModuleRequestRouterEntry());
141
+ plugins.push(magicModuleAppRequestRouter({
142
+ entry
143
+ }));
144
+ if (graphql) {
145
+ const {
146
+ graphql
147
+ } = await import('./features/graphql.esnext');
148
+ plugins.push(graphql({
149
+ manifest: false
150
+ }));
151
+ }
152
+ if (minify) {
153
+ const {
154
+ minify
155
+ } = await import('rollup-plugin-esbuild');
156
+ plugins.push(minify());
157
+ }
158
+ plugins.push(visualizer({
159
+ template: 'treemap',
160
+ open: false,
161
+ brotliSize: true,
162
+ filename: path.resolve(`reports/bundle-visualizer.html`)
163
+ }));
164
+ return {
165
+ input: entry,
166
+ plugins,
167
+ output: {
168
+ // format: isESM ? 'esm' : 'systemjs',
169
+ format: 'esm',
170
+ dir: path.resolve(`build/server`),
171
+ entryFileNames: 'server.js'
170
172
  }
171
173
  };
172
174
  }
@@ -0,0 +1,107 @@
1
+ import * as path from 'node:path';
2
+ import { readFile } from 'node:fs/promises';
3
+ import { createHash } from 'node:crypto';
4
+ import * as mime from 'mrmime';
5
+
6
+ const QUERY_PATTERN = /\?.*$/s;
7
+ const HASH_PATTERN = /#.*$/s;
8
+ const RAW_PATTERN = /(\?|&)raw(?:&|$)/;
9
+ const DEFAULT_INLINE_LIMIT = 4096;
10
+ const DEFAULT_OUTPUT_PATTERN = '[name].[hash].[ext]';
11
+ const DEFAULT_STATIC_ASSET_EXTENSIONS = [
12
+ // images
13
+ '.png', '.jpg', '.jpeg', '.gif', '.svg', '.ico', '.webp', '.avif',
14
+ // media
15
+ '.mp4', '.webm', '.ogg', '.mp3', '.wav', '.flac', '.aac',
16
+ // fonts
17
+ '.woff', '.woff2', '.eot', '.ttf', '.otf',
18
+ // other
19
+ '.webmanifest', '.pdf', '.txt'];
20
+ function rawAssets() {
21
+ return {
22
+ name: '@quilted/raw-assets',
23
+ async load(id) {
24
+ if (id.startsWith('\0') || !RAW_PATTERN.test(id)) {
25
+ return null;
26
+ }
27
+ const moduleId = cleanModuleIdentifier(id);
28
+ this.addWatchFile(moduleId);
29
+ const file = await readFile(moduleId, {
30
+ encoding: 'utf-8'
31
+ });
32
+ return `export default ${JSON.stringify(file)}`;
33
+ }
34
+ };
35
+ }
36
+ function staticAssets({
37
+ emit = true,
38
+ baseURL = '/',
39
+ extensions = DEFAULT_STATIC_ASSET_EXTENSIONS,
40
+ inlineLimit = DEFAULT_INLINE_LIMIT,
41
+ outputPattern = DEFAULT_OUTPUT_PATTERN
42
+ } = {}) {
43
+ const assetCache = new Map();
44
+ const assetMatcher = new RegExp(`\\.(` + extensions.map(extension => extension.startsWith('.') ? extension.slice(1) : extension).join('|') + `)(\\?.*)?$`);
45
+ return {
46
+ name: '@quilted/static-assets',
47
+ async load(id) {
48
+ if (id.startsWith('\0') || !assetMatcher.test(id)) {
49
+ return null;
50
+ }
51
+ const cached = assetCache.get(id);
52
+ if (cached) {
53
+ return cached;
54
+ }
55
+ const file = cleanModuleIdentifier(id);
56
+ const content = await readFile(file);
57
+ let url;
58
+ if (!file.endsWith('.svg') && content.length < inlineLimit) {
59
+ // base64 inlined as a string
60
+ url = `data:${mime.lookup(file)};base64,${content.toString('base64')}`;
61
+ } else {
62
+ const contentHash = getHash(content);
63
+ const filename = assetFileNamesToFileName(outputPattern, file, contentHash);
64
+ url = `${baseURL.endsWith('/') ? baseURL.slice(0, -1) : baseURL}/${filename}`;
65
+ if (emit) {
66
+ this.emitFile({
67
+ name: file,
68
+ type: 'asset',
69
+ fileName: filename,
70
+ source: content
71
+ });
72
+ }
73
+ }
74
+ const source = `export default ${JSON.stringify(url)};`;
75
+ assetCache.set(id, source);
76
+ return source;
77
+ }
78
+ };
79
+ }
80
+ function assetFileNamesToFileName(pattern, file, contentHash) {
81
+ const basename = path.basename(file);
82
+ const extname = path.extname(basename);
83
+ const ext = extname.substring(1);
84
+ const name = basename.slice(0, -extname.length);
85
+ const hash = contentHash;
86
+ return pattern.replace(/\[\w+\]/g, placeholder => {
87
+ switch (placeholder) {
88
+ case '[ext]':
89
+ return ext;
90
+ case '[extname]':
91
+ return extname;
92
+ case '[hash]':
93
+ return hash;
94
+ case '[name]':
95
+ return name;
96
+ }
97
+ throw new Error(`invalid placeholder ${placeholder} in assetFileNames "${pattern}"`);
98
+ });
99
+ }
100
+ function getHash(text) {
101
+ return createHash('sha256').update(text).digest('hex').substring(0, 8);
102
+ }
103
+ function cleanModuleIdentifier(url) {
104
+ return url.replace(HASH_PATTERN, '').replace(QUERY_PATTERN, '');
105
+ }
106
+
107
+ export { rawAssets, staticAssets };
@@ -1,9 +1,9 @@
1
1
  import * as path from 'node:path';
2
2
  import * as fs from 'node:fs';
3
- import { MAGIC_MODULE_ENV } from './constants.esnext';
4
- import { multiline } from './shared/strings.esnext';
5
- import { smartReplace } from './shared/rollup.esnext';
6
- import { createMagicModulePlugin } from './shared/magic-module.esnext';
3
+ import { MAGIC_MODULE_ENV } from '../constants.esnext';
4
+ import { multiline } from '../shared/strings.esnext';
5
+ import { smartReplace } from '../shared/rollup.esnext';
6
+ import { createMagicModulePlugin } from '../shared/magic-module.esnext';
7
7
 
8
8
  const EMPTY_PROCESS_ENV_OBJECT = {
9
9
  'globalThis.process.env.': `({}).`,
@@ -1,6 +1,6 @@
1
- import { MAGIC_MODULE_ENTRY, MAGIC_MODULE_REQUEST_ROUTER } from './constants.esnext';
2
- import { createMagicModulePlugin } from './shared/magic-module.esnext';
3
- import { multiline } from './shared/strings.esnext';
1
+ import { MAGIC_MODULE_ENTRY, MAGIC_MODULE_REQUEST_ROUTER } from '../constants.esnext';
2
+ import { createMagicModulePlugin } from '../shared/magic-module.esnext';
3
+ import { multiline } from '../shared/strings.esnext';
4
4
 
5
5
  function magicModuleRequestRouterEntry({
6
6
  host,
@@ -0,0 +1,33 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { createRequire } from 'node:module';
3
+
4
+ function systemJS({
5
+ minify = false
6
+ } = {}) {
7
+ return {
8
+ name: '@quilted/system-js',
9
+ async renderChunk(_, chunk, options) {
10
+ if (options.format !== 'system' || !chunk.isEntry) return null;
11
+ const require = createRequire(import.meta.url);
12
+ const systemjs = minify ? require.resolve('systemjs/dist/s.min.js') : require.resolve('systemjs/dist/s.js');
13
+
14
+ // We write the systemjs loader to a dedicated file, and we make it the
15
+ // "first import" of the chunk so that it is the first file listed in
16
+ // the manifest.
17
+ const fileHandle = this.emitFile({
18
+ type: 'asset',
19
+ name: 'loader.js',
20
+ source: (await readFile(systemjs, {
21
+ encoding: 'utf8'
22
+ })).replace(
23
+ // Remove the source map comment, if it is present, because we don’t upload the
24
+ // sourcemap for this file.
25
+ /\n?[/][/]# sourceMappingURL=s.*\.map\n?$/, '')
26
+ });
27
+ chunk.imports.unshift(this.getFileName(fileHandle));
28
+ return null;
29
+ }
30
+ };
31
+ }
32
+
33
+ export { systemJS };
@@ -1,3 +1 @@
1
- export { magicModuleEnv } from './env.esnext';
2
- export { magicModuleAppBrowserEntry, magicModuleAppComponent, magicModuleAppRequestRouter, quiltAppBrowser, quiltAppServer } from './app.esnext';
3
- export { magicModuleRequestRouterEntry } from './request-router.esnext';
1
+ export { quiltAppBrowser, quiltAppServer } from './app.esnext';
@@ -26,8 +26,5 @@ async function getNodePlugins() {
26
26
  // exportConditions,
27
27
  }), commonjs(), json()];
28
28
  }
29
- function rollupPluginsToArray(plugins) {
30
- return Array.isArray(plugins) ? [...plugins] : plugins ? [plugins] : [];
31
- }
32
29
 
33
- export { getNodePlugins, rollupPluginsToArray, smartReplace };
30
+ export { getNodePlugins, smartReplace };