@quilted/rollup 0.1.2 → 0.1.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/CHANGELOG.md +14 -0
- package/build/cjs/app.cjs +166 -38
- package/build/cjs/graphql/transform.cjs +186 -0
- package/build/cjs/graphql.cjs +86 -0
- package/build/cjs/index.cjs +0 -1
- package/build/cjs/shared/source-code.cjs +40 -0
- package/build/esm/app.mjs +167 -38
- package/build/esm/graphql/transform.mjs +181 -0
- package/build/esm/graphql.mjs +84 -0
- package/build/esm/index.mjs +1 -1
- package/build/esm/shared/source-code.mjs +38 -0
- package/build/esnext/app.esnext +167 -38
- package/build/esnext/graphql/transform.esnext +181 -0
- package/build/esnext/graphql.esnext +84 -0
- package/build/esnext/index.esnext +1 -1
- package/build/esnext/shared/source-code.esnext +38 -0
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/typescript/app.d.ts +101 -31
- package/build/typescript/app.d.ts.map +1 -1
- package/build/typescript/graphql/transform.d.ts +17 -0
- package/build/typescript/graphql/transform.d.ts.map +1 -0
- package/build/typescript/graphql.d.ts +6 -0
- package/build/typescript/graphql.d.ts.map +1 -0
- package/build/typescript/index.d.ts +1 -1
- package/build/typescript/index.d.ts.map +1 -1
- package/build/typescript/shared/source-code.d.ts +5 -0
- package/build/typescript/shared/source-code.d.ts.map +1 -0
- package/package.json +13 -1
- package/source/app.ts +197 -41
- package/source/graphql/transform.ts +283 -0
- package/source/graphql.ts +139 -0
- package/source/index.ts +0 -1
- package/source/shared/source-code.ts +64 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @quilted/rollup
|
|
2
2
|
|
|
3
|
+
## 0.1.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`2a36d5b8`](https://github.com/lemonmade/quilt/commit/2a36d5b8cb5178c3a51d441f754526f0b3b58571) Thanks [@lemonmade](https://github.com/lemonmade)! - Add source code plugin
|
|
8
|
+
|
|
9
|
+
## 0.1.3
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [`4841dca5`](https://github.com/lemonmade/quilt/commit/4841dca5fb9817c8873b06c1790b3f4a05bc62d6) Thanks [@lemonmade](https://github.com/lemonmade)! - Add GraphQL plugins
|
|
14
|
+
|
|
15
|
+
- [`34b06933`](https://github.com/lemonmade/quilt/commit/34b06933ea46eedace0caef682ae6aadea3f4ea8) Thanks [@lemonmade](https://github.com/lemonmade)! - Add output options
|
|
16
|
+
|
|
3
17
|
## 0.1.2
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
package/build/cjs/app.cjs
CHANGED
|
@@ -25,18 +25,31 @@ function _interopNamespaceDefault(e) {
|
|
|
25
25
|
|
|
26
26
|
var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
|
|
27
27
|
|
|
28
|
-
function
|
|
28
|
+
function quiltAppBrowser({
|
|
29
|
+
app,
|
|
29
30
|
env,
|
|
30
|
-
|
|
31
|
+
assets,
|
|
32
|
+
module,
|
|
33
|
+
graphql = true
|
|
31
34
|
} = {}) {
|
|
35
|
+
const mode = (typeof env === 'object' ? env?.mode : undefined) ?? 'production';
|
|
32
36
|
return {
|
|
33
|
-
name: '@quilted/app',
|
|
37
|
+
name: '@quilted/app/browser',
|
|
34
38
|
async options(originalOptions) {
|
|
35
39
|
const newPlugins = rollup.rollupPluginsToArray(originalOptions.plugins);
|
|
36
40
|
const newOptions = {
|
|
37
41
|
...originalOptions,
|
|
38
42
|
plugins: newPlugins
|
|
39
43
|
};
|
|
44
|
+
const [{
|
|
45
|
+
visualizer
|
|
46
|
+
}, {
|
|
47
|
+
sourceCode
|
|
48
|
+
}, nodePlugins] = await Promise.all([import('rollup-plugin-visualizer'), Promise.resolve().then(function () { return require('./shared/source-code.cjs'); }), rollup.getNodePlugins()]);
|
|
49
|
+
newPlugins.push(...nodePlugins);
|
|
50
|
+
newPlugins.push(sourceCode({
|
|
51
|
+
mode
|
|
52
|
+
}));
|
|
40
53
|
if (env) {
|
|
41
54
|
const {
|
|
42
55
|
magicModuleEnv,
|
|
@@ -59,40 +72,20 @@ function quiltApp({
|
|
|
59
72
|
}));
|
|
60
73
|
}
|
|
61
74
|
}
|
|
62
|
-
if (
|
|
75
|
+
if (app) {
|
|
63
76
|
newPlugins.push(magicModuleAppComponent({
|
|
64
|
-
entry
|
|
77
|
+
entry: app
|
|
65
78
|
}));
|
|
66
79
|
}
|
|
67
|
-
return newOptions;
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
function quiltAppBrowser({
|
|
72
|
-
entry,
|
|
73
|
-
env,
|
|
74
|
-
graphql,
|
|
75
|
-
assets,
|
|
76
|
-
module
|
|
77
|
-
} = {}) {
|
|
78
|
-
return {
|
|
79
|
-
name: '@quilted/app/browser',
|
|
80
|
-
async options(originalOptions) {
|
|
81
|
-
const newPlugins = rollup.rollupPluginsToArray(originalOptions.plugins);
|
|
82
|
-
const newOptions = {
|
|
83
|
-
...originalOptions,
|
|
84
|
-
plugins: newPlugins
|
|
85
|
-
};
|
|
86
|
-
const [{
|
|
87
|
-
visualizer
|
|
88
|
-
}, nodePlugins] = await Promise.all([import('rollup-plugin-visualizer'), rollup.getNodePlugins()]);
|
|
89
|
-
newPlugins.push(quiltApp({
|
|
90
|
-
env,
|
|
91
|
-
entry,
|
|
92
|
-
graphql
|
|
93
|
-
}));
|
|
94
|
-
newPlugins.push(...nodePlugins);
|
|
95
80
|
newPlugins.push(magicModuleAppBrowserEntry(module));
|
|
81
|
+
if (graphql) {
|
|
82
|
+
const {
|
|
83
|
+
graphql
|
|
84
|
+
} = await Promise.resolve().then(function () { return require('./graphql.cjs'); });
|
|
85
|
+
newPlugins.push(graphql({
|
|
86
|
+
manifest: path__namespace.resolve(`manifests/graphql.json`)
|
|
87
|
+
}));
|
|
88
|
+
}
|
|
96
89
|
const minify = assets?.minify ?? true;
|
|
97
90
|
if (minify) {
|
|
98
91
|
const {
|
|
@@ -104,13 +97,31 @@ function quiltAppBrowser({
|
|
|
104
97
|
template: 'treemap',
|
|
105
98
|
open: false,
|
|
106
99
|
brotliSize: true,
|
|
107
|
-
filename: path__namespace.resolve(
|
|
100
|
+
filename: path__namespace.resolve(`reports/bundle-visualizer.html`)
|
|
108
101
|
}));
|
|
109
102
|
return newOptions;
|
|
103
|
+
},
|
|
104
|
+
outputOptions(originalOptions) {
|
|
105
|
+
return {
|
|
106
|
+
...originalOptions,
|
|
107
|
+
// format: isESM ? 'esm' : 'systemjs',
|
|
108
|
+
format: 'esm',
|
|
109
|
+
dir: path__namespace.resolve(`build/assets`),
|
|
110
|
+
entryFileNames: `app.[hash].js`,
|
|
111
|
+
assetFileNames: `[name].[hash].[ext]`,
|
|
112
|
+
chunkFileNames: `[name].[hash].js`,
|
|
113
|
+
manualChunks: createManualChunksSorter()
|
|
114
|
+
};
|
|
110
115
|
}
|
|
111
116
|
};
|
|
112
117
|
}
|
|
113
|
-
function quiltAppServer(
|
|
118
|
+
function quiltAppServer({
|
|
119
|
+
app,
|
|
120
|
+
env,
|
|
121
|
+
graphql,
|
|
122
|
+
entry
|
|
123
|
+
} = {}) {
|
|
124
|
+
const mode = (typeof env === 'object' ? env?.mode : undefined) ?? 'production';
|
|
114
125
|
return {
|
|
115
126
|
name: '@quilted/app/server',
|
|
116
127
|
async options(originalOptions) {
|
|
@@ -121,10 +132,62 @@ function quiltAppServer(options = {}) {
|
|
|
121
132
|
};
|
|
122
133
|
const [{
|
|
123
134
|
magicModuleRequestRouterEntry
|
|
124
|
-
}
|
|
135
|
+
}, {
|
|
136
|
+
sourceCode
|
|
137
|
+
}, nodePlugins] = await Promise.all([Promise.resolve().then(function () { return require('./request-router.cjs'); }), Promise.resolve().then(function () { return require('./shared/source-code.cjs'); }), rollup.getNodePlugins()]);
|
|
138
|
+
newPlugins.push(...nodePlugins);
|
|
139
|
+
newPlugins.push(sourceCode({
|
|
140
|
+
mode
|
|
141
|
+
}));
|
|
142
|
+
if (env) {
|
|
143
|
+
const {
|
|
144
|
+
magicModuleEnv,
|
|
145
|
+
replaceProcessEnv
|
|
146
|
+
} = await Promise.resolve().then(function () { return require('./env.cjs'); });
|
|
147
|
+
if (typeof env === 'boolean') {
|
|
148
|
+
newPlugins.push(replaceProcessEnv({
|
|
149
|
+
mode
|
|
150
|
+
}));
|
|
151
|
+
newPlugins.push(magicModuleEnv({
|
|
152
|
+
mode
|
|
153
|
+
}));
|
|
154
|
+
} else {
|
|
155
|
+
newPlugins.push(replaceProcessEnv({
|
|
156
|
+
mode
|
|
157
|
+
}));
|
|
158
|
+
newPlugins.push(magicModuleEnv({
|
|
159
|
+
mode,
|
|
160
|
+
...env
|
|
161
|
+
}));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (app) {
|
|
165
|
+
newPlugins.push(magicModuleAppComponent({
|
|
166
|
+
entry: app
|
|
167
|
+
}));
|
|
168
|
+
}
|
|
125
169
|
newPlugins.push(magicModuleRequestRouterEntry());
|
|
126
|
-
newPlugins.push(magicModuleAppRequestRouter(
|
|
170
|
+
newPlugins.push(magicModuleAppRequestRouter({
|
|
171
|
+
entry
|
|
172
|
+
}));
|
|
173
|
+
if (graphql) {
|
|
174
|
+
const {
|
|
175
|
+
graphql
|
|
176
|
+
} = await Promise.resolve().then(function () { return require('./graphql.cjs'); });
|
|
177
|
+
newPlugins.push(graphql({
|
|
178
|
+
manifest: false
|
|
179
|
+
}));
|
|
180
|
+
}
|
|
127
181
|
return newOptions;
|
|
182
|
+
},
|
|
183
|
+
outputOptions(originalOptions) {
|
|
184
|
+
return {
|
|
185
|
+
...originalOptions,
|
|
186
|
+
// format,
|
|
187
|
+
format: 'esm',
|
|
188
|
+
dir: path__namespace.resolve(`build/server`),
|
|
189
|
+
entryFileNames: 'server.js'
|
|
190
|
+
};
|
|
128
191
|
}
|
|
129
192
|
};
|
|
130
193
|
}
|
|
@@ -198,10 +261,75 @@ function magicModuleAppBrowserEntry({
|
|
|
198
261
|
}
|
|
199
262
|
});
|
|
200
263
|
}
|
|
264
|
+
const FRAMEWORK_CHUNK_NAME = 'framework';
|
|
265
|
+
const POLYFILLS_CHUNK_NAME = 'polyfills';
|
|
266
|
+
const VENDOR_CHUNK_NAME = 'vendor';
|
|
267
|
+
const INTERNALS_CHUNK_NAME = 'internals';
|
|
268
|
+
const SHARED_CHUNK_NAME = 'shared';
|
|
269
|
+
const PACKAGES_CHUNK_NAME = 'packages';
|
|
270
|
+
const GLOBAL_CHUNK_NAME = 'global';
|
|
271
|
+
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/',
|
|
272
|
+
// TODO I should turn this into an allowlist
|
|
273
|
+
/node_modules[/]@quilted[/](?!react-query|swr)/];
|
|
274
|
+
const POLYFILL_TEST_STRINGS = ['/node_modules/@quilted/polyfills/', '/node_modules/core-js/', '/node_modules/whatwg-fetch/', '/node_modules/regenerator-runtime/', '/node_modules/abort-controller/'];
|
|
275
|
+
const INTERNALS_TEST_STRINGS = ['\x00commonjsHelpers.js', '/node_modules/@babel/runtime/'];
|
|
276
|
+
|
|
277
|
+
// When building from source, quilt packages are not in node_modules,
|
|
278
|
+
// so we instead add their repo paths to the list of framework test strings.
|
|
279
|
+
if (process.env.QUILT_FROM_SOURCE) {
|
|
280
|
+
FRAMEWORK_TEST_STRINGS.push('/quilt/packages/');
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Inspired by Vite: https://github.com/vitejs/vite/blob/c69f83615292953d40f07b1178d1ed1d72abe695/packages/vite/source/node/build.ts#L567
|
|
284
|
+
function createManualChunksSorter() {
|
|
285
|
+
// TODO: make this more configurable, and make it so that we bundle more intelligently
|
|
286
|
+
// for split entries
|
|
287
|
+
const packagesPath = path__namespace.resolve('packages') + path__namespace.sep;
|
|
288
|
+
const globalPath = path__namespace.resolve('global') + path__namespace.sep;
|
|
289
|
+
const sharedPath = path__namespace.resolve('shared') + path__namespace.sep;
|
|
290
|
+
return (id, {
|
|
291
|
+
getModuleInfo
|
|
292
|
+
}) => {
|
|
293
|
+
if (INTERNALS_TEST_STRINGS.some(test => id.includes(test))) {
|
|
294
|
+
return INTERNALS_CHUNK_NAME;
|
|
295
|
+
}
|
|
296
|
+
if (FRAMEWORK_TEST_STRINGS.some(test => typeof test === 'string' ? id.includes(test) : test.test(id))) {
|
|
297
|
+
return FRAMEWORK_CHUNK_NAME;
|
|
298
|
+
}
|
|
299
|
+
if (POLYFILL_TEST_STRINGS.some(test => id.includes(test))) {
|
|
300
|
+
return POLYFILLS_CHUNK_NAME;
|
|
301
|
+
}
|
|
302
|
+
let bundleBaseName;
|
|
303
|
+
let relativeId;
|
|
304
|
+
if (id.includes('/node_modules/')) {
|
|
305
|
+
const moduleInfo = getModuleInfo(id);
|
|
306
|
+
|
|
307
|
+
// If the only dependency is another vendor, let Rollup handle the naming
|
|
308
|
+
if (moduleInfo == null) return;
|
|
309
|
+
if (moduleInfo.importers.length > 0 && moduleInfo.importers.every(importer => importer.includes('/node_modules/'))) {
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
bundleBaseName = VENDOR_CHUNK_NAME;
|
|
313
|
+
relativeId = id.replace(/^.*[/]node_modules[/]/, '');
|
|
314
|
+
} else if (id.startsWith(packagesPath)) {
|
|
315
|
+
bundleBaseName = PACKAGES_CHUNK_NAME;
|
|
316
|
+
relativeId = id.replace(packagesPath, '');
|
|
317
|
+
} else if (id.startsWith(globalPath)) {
|
|
318
|
+
bundleBaseName = GLOBAL_CHUNK_NAME;
|
|
319
|
+
relativeId = id.replace(globalPath, '');
|
|
320
|
+
} else if (id.startsWith(sharedPath)) {
|
|
321
|
+
bundleBaseName = SHARED_CHUNK_NAME;
|
|
322
|
+
relativeId = id.replace(sharedPath, '');
|
|
323
|
+
}
|
|
324
|
+
if (bundleBaseName == null || relativeId == null) {
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
return `${bundleBaseName}-${relativeId.split(path__namespace.sep)[0]?.split('.')[0]}`;
|
|
328
|
+
};
|
|
329
|
+
}
|
|
201
330
|
|
|
202
331
|
exports.magicModuleAppBrowserEntry = magicModuleAppBrowserEntry;
|
|
203
332
|
exports.magicModuleAppComponent = magicModuleAppComponent;
|
|
204
333
|
exports.magicModuleAppRequestRouter = magicModuleAppRequestRouter;
|
|
205
|
-
exports.quiltApp = quiltApp;
|
|
206
334
|
exports.quiltAppBrowser = quiltAppBrowser;
|
|
207
335
|
exports.quiltAppServer = quiltAppServer;
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var node_crypto = require('node:crypto');
|
|
4
|
+
var graphql = require('graphql');
|
|
5
|
+
|
|
6
|
+
const IMPORT_REGEX = /^#import\s+['"]([^'"]*)['"];?[\s\n]*/gm;
|
|
7
|
+
const DEFAULT_NAME = 'Operation';
|
|
8
|
+
function cleanGraphQLDocument(document, {
|
|
9
|
+
removeUnused = true
|
|
10
|
+
} = {}) {
|
|
11
|
+
if (removeUnused) {
|
|
12
|
+
removeUnusedDefinitions(document, {
|
|
13
|
+
exclude: removeUnused === true ? new Set() : removeUnused.exclude
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
for (const definition of document.definitions) {
|
|
17
|
+
addTypename(definition);
|
|
18
|
+
}
|
|
19
|
+
const normalizedSource = minifyGraphQLSource(graphql.print(document));
|
|
20
|
+
const normalizedDocument = graphql.parse(normalizedSource);
|
|
21
|
+
for (const definition of normalizedDocument.definitions) {
|
|
22
|
+
stripLoc(definition);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// This ID is a hash of the full file contents that are part of the document,
|
|
26
|
+
// including other documents that are injected in, but excluding any unused
|
|
27
|
+
// fragments. This is useful for things like persisted queries.
|
|
28
|
+
const id = node_crypto.createHash('sha256').update(normalizedSource).digest('hex');
|
|
29
|
+
Reflect.defineProperty(normalizedDocument, 'id', {
|
|
30
|
+
value: id,
|
|
31
|
+
enumerable: true,
|
|
32
|
+
writable: false,
|
|
33
|
+
configurable: false
|
|
34
|
+
});
|
|
35
|
+
Reflect.defineProperty(normalizedDocument, 'loc', {
|
|
36
|
+
value: stripDocumentLoc(normalizedDocument.loc),
|
|
37
|
+
enumerable: true,
|
|
38
|
+
writable: false,
|
|
39
|
+
configurable: false
|
|
40
|
+
});
|
|
41
|
+
return normalizedDocument;
|
|
42
|
+
}
|
|
43
|
+
function extractGraphQLImports(rawSource) {
|
|
44
|
+
const imports = new Set();
|
|
45
|
+
const source = rawSource.replace(IMPORT_REGEX, (_, imported) => {
|
|
46
|
+
imports.add(imported);
|
|
47
|
+
return '';
|
|
48
|
+
});
|
|
49
|
+
return {
|
|
50
|
+
imports: [...imports],
|
|
51
|
+
source
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function toGraphQLOperation(documentOrSource) {
|
|
55
|
+
const document = typeof documentOrSource === 'string' ? cleanGraphQLDocument(graphql.parse(documentOrSource)) : documentOrSource;
|
|
56
|
+
return {
|
|
57
|
+
id: document.id,
|
|
58
|
+
name: operationNameForDocument(document),
|
|
59
|
+
source: document.loc.source.body
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function operationNameForDocument(document) {
|
|
63
|
+
return document.definitions.find(definition => definition.kind === 'OperationDefinition')?.name?.value;
|
|
64
|
+
}
|
|
65
|
+
function removeUnusedDefinitions(document, {
|
|
66
|
+
exclude
|
|
67
|
+
}) {
|
|
68
|
+
const usedDefinitions = new Set();
|
|
69
|
+
const dependencies = definitionDependencies(document.definitions);
|
|
70
|
+
const markAsUsed = definition => {
|
|
71
|
+
if (usedDefinitions.has(definition)) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
usedDefinitions.add(definition);
|
|
75
|
+
for (const dependency of dependencies.get(definition) || []) {
|
|
76
|
+
markAsUsed(dependency);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
for (const definition of document.definitions) {
|
|
80
|
+
if (definition.kind === 'FragmentDefinition') {
|
|
81
|
+
if (exclude.has(definition.name.value)) {
|
|
82
|
+
markAsUsed(definition);
|
|
83
|
+
}
|
|
84
|
+
} else {
|
|
85
|
+
markAsUsed(definition);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
document.definitions = [...usedDefinitions];
|
|
89
|
+
}
|
|
90
|
+
function definitionDependencies(definitions) {
|
|
91
|
+
const executableDefinitions = definitions.filter(definition => definition.kind === 'OperationDefinition' || definition.kind === 'FragmentDefinition');
|
|
92
|
+
const definitionsByName = new Map(executableDefinitions.map(definition => [definition.name ? definition.name.value : DEFAULT_NAME, definition]));
|
|
93
|
+
return new Map(executableDefinitions.map(executableNode => [executableNode, [...collectUsedFragmentSpreads(executableNode, new Set())].map(usedFragment => {
|
|
94
|
+
const definition = definitionsByName.get(usedFragment);
|
|
95
|
+
if (definition == null) {
|
|
96
|
+
throw new Error(`You attempted to use the fragment '${usedFragment}' (in '${executableNode.name ? executableNode.name.value : DEFAULT_NAME}'), but it does not exist. Maybe you forgot to import it from another document?`);
|
|
97
|
+
}
|
|
98
|
+
return definition;
|
|
99
|
+
})]));
|
|
100
|
+
}
|
|
101
|
+
const TYPENAME_FIELD = {
|
|
102
|
+
kind: 'Field',
|
|
103
|
+
alias: null,
|
|
104
|
+
name: {
|
|
105
|
+
kind: 'Name',
|
|
106
|
+
value: '__typename'
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
function addTypename(definition) {
|
|
110
|
+
for (const {
|
|
111
|
+
selections
|
|
112
|
+
} of selectionSetsForDefinition(definition)) {
|
|
113
|
+
const hasTypename = selections.some(selection => selection.kind === 'Field' && selection.name.value === '__typename');
|
|
114
|
+
if (!hasTypename) {
|
|
115
|
+
selections.push(TYPENAME_FIELD);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function collectUsedFragmentSpreads(definition, usedSpreads) {
|
|
120
|
+
for (const selection of selectionsForDefinition(definition)) {
|
|
121
|
+
if (selection.kind === 'FragmentSpread') {
|
|
122
|
+
usedSpreads.add(selection.name.value);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return usedSpreads;
|
|
126
|
+
}
|
|
127
|
+
function selectionsForDefinition(definition) {
|
|
128
|
+
if (!('selectionSet' in definition) || definition.selectionSet == null) {
|
|
129
|
+
return [][Symbol.iterator]();
|
|
130
|
+
}
|
|
131
|
+
return selectionsForSelectionSet(definition.selectionSet);
|
|
132
|
+
}
|
|
133
|
+
function* selectionSetsForDefinition(definition) {
|
|
134
|
+
if (!('selectionSet' in definition) || definition.selectionSet == null) {
|
|
135
|
+
return [][Symbol.iterator]();
|
|
136
|
+
}
|
|
137
|
+
if (definition.kind !== 'OperationDefinition') {
|
|
138
|
+
yield definition.selectionSet;
|
|
139
|
+
}
|
|
140
|
+
for (const nestedSelection of selectionsForDefinition(definition)) {
|
|
141
|
+
if ('selectionSet' in nestedSelection && nestedSelection.selectionSet != null) {
|
|
142
|
+
yield nestedSelection.selectionSet;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function* selectionsForSelectionSet({
|
|
147
|
+
selections
|
|
148
|
+
}) {
|
|
149
|
+
for (const selection of selections) {
|
|
150
|
+
yield selection;
|
|
151
|
+
if ('selectionSet' in selection && selection.selectionSet != null) {
|
|
152
|
+
yield* selectionsForSelectionSet(selection.selectionSet);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
function stripDocumentLoc(loc) {
|
|
157
|
+
const normalizedLoc = {
|
|
158
|
+
...loc
|
|
159
|
+
};
|
|
160
|
+
delete normalizedLoc.endToken;
|
|
161
|
+
delete normalizedLoc.startToken;
|
|
162
|
+
return normalizedLoc;
|
|
163
|
+
}
|
|
164
|
+
function stripLoc(value) {
|
|
165
|
+
if (Array.isArray(value)) {
|
|
166
|
+
value.forEach(stripLoc);
|
|
167
|
+
} else if (typeof value === 'object') {
|
|
168
|
+
if (value == null) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
if ('loc' in value) {
|
|
172
|
+
delete value.loc;
|
|
173
|
+
}
|
|
174
|
+
for (const key of Object.keys(value)) {
|
|
175
|
+
stripLoc(value[key]);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function minifyGraphQLSource(source) {
|
|
180
|
+
return source.replace(/#.*/g, '').replace(/\\n/g, ' ').replace(/\s\s+/g, ' ').replace(/\s*({|}|\(|\)|\.|:|,)\s*/g, '$1');
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
exports.cleanGraphQLDocument = cleanGraphQLDocument;
|
|
184
|
+
exports.extractGraphQLImports = extractGraphQLImports;
|
|
185
|
+
exports.minifyGraphQLSource = minifyGraphQLSource;
|
|
186
|
+
exports.toGraphQLOperation = toGraphQLOperation;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var path = require('node:path');
|
|
4
|
+
var promises = require('node:fs/promises');
|
|
5
|
+
var graphql$1 = require('graphql');
|
|
6
|
+
var transform = require('./graphql/transform.cjs');
|
|
7
|
+
|
|
8
|
+
function graphql({
|
|
9
|
+
manifest
|
|
10
|
+
} = {}) {
|
|
11
|
+
const shouldWriteManifest = Boolean(manifest);
|
|
12
|
+
const manifestPath = typeof manifest === 'string' ? manifest : `manifests/graphql.json`;
|
|
13
|
+
return {
|
|
14
|
+
name: '@quilted/graphql',
|
|
15
|
+
async transform(code, id) {
|
|
16
|
+
if (!id.endsWith('.graphql') && !id.endsWith('.gql')) return null;
|
|
17
|
+
const topLevelDefinitions = new Set();
|
|
18
|
+
const loadedDocument = await loadDocument(code, id, this, (document, level) => {
|
|
19
|
+
if (level !== 0) return;
|
|
20
|
+
for (const definition of document.definitions) {
|
|
21
|
+
if ('name' in definition && definition.name != null) {
|
|
22
|
+
topLevelDefinitions.add(definition.name.value);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
const document = transform.toGraphQLOperation(transform.cleanGraphQLDocument(loadedDocument, {
|
|
27
|
+
removeUnused: {
|
|
28
|
+
exclude: topLevelDefinitions
|
|
29
|
+
}
|
|
30
|
+
}));
|
|
31
|
+
return {
|
|
32
|
+
code: `export default JSON.parse(${JSON.stringify(JSON.stringify(document))})`,
|
|
33
|
+
meta: shouldWriteManifest ? {
|
|
34
|
+
quilt: {
|
|
35
|
+
graphql: document
|
|
36
|
+
}
|
|
37
|
+
} : undefined
|
|
38
|
+
};
|
|
39
|
+
},
|
|
40
|
+
async generateBundle() {
|
|
41
|
+
if (!shouldWriteManifest) return;
|
|
42
|
+
const operations = {};
|
|
43
|
+
for (const moduleId of this.getModuleIds()) {
|
|
44
|
+
const operation = this.getModuleInfo(moduleId)?.meta?.quilt?.graphql;
|
|
45
|
+
if (operation != null && typeof operation.id === 'string' && typeof operation.source === 'string') {
|
|
46
|
+
operations[operation.id] = operation.source;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
await promises.mkdir(path.dirname(manifestPath), {
|
|
50
|
+
recursive: true
|
|
51
|
+
});
|
|
52
|
+
await promises.writeFile(manifestPath, JSON.stringify(operations, null, 2));
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
async function loadDocument(code, file, plugin, add, level = 0, seen = new Set()) {
|
|
57
|
+
const {
|
|
58
|
+
imports,
|
|
59
|
+
source
|
|
60
|
+
} = transform.extractGraphQLImports(code);
|
|
61
|
+
const document = graphql$1.parse(source);
|
|
62
|
+
add?.(document, level);
|
|
63
|
+
if (imports.length === 0) {
|
|
64
|
+
return document;
|
|
65
|
+
}
|
|
66
|
+
const resolvedImports = await Promise.all(imports.map(async imported => {
|
|
67
|
+
if (seen.has(imported)) return;
|
|
68
|
+
seen.add(imported);
|
|
69
|
+
const resolvedId = await plugin.resolve(imported, file);
|
|
70
|
+
if (resolvedId == null) {
|
|
71
|
+
throw new Error(`Could not find ${JSON.stringify(imported)} from ${JSON.stringify(file)}`);
|
|
72
|
+
}
|
|
73
|
+
plugin.addWatchFile(resolvedId.id);
|
|
74
|
+
const contents = await promises.readFile(resolvedId.id, {
|
|
75
|
+
encoding: 'utf8'
|
|
76
|
+
});
|
|
77
|
+
return loadDocument(contents, resolvedId.id, plugin, add, level + 1, seen);
|
|
78
|
+
}));
|
|
79
|
+
for (const importedDocument of resolvedImports) {
|
|
80
|
+
if (importedDocument == null) continue;
|
|
81
|
+
document.definitions.push(...importedDocument.definitions);
|
|
82
|
+
}
|
|
83
|
+
return document;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
exports.graphql = graphql;
|
package/build/cjs/index.cjs
CHANGED
|
@@ -10,7 +10,6 @@ exports.magicModuleEnv = env.magicModuleEnv;
|
|
|
10
10
|
exports.magicModuleAppBrowserEntry = app.magicModuleAppBrowserEntry;
|
|
11
11
|
exports.magicModuleAppComponent = app.magicModuleAppComponent;
|
|
12
12
|
exports.magicModuleAppRequestRouter = app.magicModuleAppRequestRouter;
|
|
13
|
-
exports.quiltApp = app.quiltApp;
|
|
14
13
|
exports.quiltAppBrowser = app.quiltAppBrowser;
|
|
15
14
|
exports.quiltAppServer = app.quiltAppServer;
|
|
16
15
|
exports.magicModuleRequestRouterEntry = requestRouter.magicModuleRequestRouterEntry;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var node_module = require('node:module');
|
|
4
|
+
var babel = require('@rollup/plugin-babel');
|
|
5
|
+
|
|
6
|
+
const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (document.currentScript && document.currentScript.src || new URL('shared/source-code.cjs', document.baseURI).href)));
|
|
7
|
+
function sourceCode({
|
|
8
|
+
mode,
|
|
9
|
+
targets
|
|
10
|
+
}) {
|
|
11
|
+
return babel({
|
|
12
|
+
configFile: false,
|
|
13
|
+
babelrc: false,
|
|
14
|
+
presets: [require$1.resolve('@babel/preset-typescript'), [require$1.resolve('@babel/preset-react'), {
|
|
15
|
+
runtime: 'automatic',
|
|
16
|
+
importSource: 'react',
|
|
17
|
+
development: mode === 'development'
|
|
18
|
+
}], [require$1.resolve('@babel/preset-env'), {
|
|
19
|
+
// @ts-expect-error This is a valid option
|
|
20
|
+
corejs: '3.15',
|
|
21
|
+
useBuiltIns: 'usage',
|
|
22
|
+
bugfixes: true,
|
|
23
|
+
shippedProposals: true,
|
|
24
|
+
// I thought I wanted this on, but if you do this, Babel
|
|
25
|
+
// stops respecting the top-level `targets` option and tries
|
|
26
|
+
// to use the targets passed to the preset directly instead.
|
|
27
|
+
ignoreBrowserslistConfig: true
|
|
28
|
+
}]],
|
|
29
|
+
plugins: [[require$1.resolve('@babel/plugin-proposal-decorators'), {
|
|
30
|
+
version: '2023-01'
|
|
31
|
+
}]],
|
|
32
|
+
targets,
|
|
33
|
+
extensions: ['.ts', '.tsx', '.mts', '.mtsx', '.js', '.jsx', '.es6', '.es', '.mjs'],
|
|
34
|
+
exclude: 'node_modules/**',
|
|
35
|
+
babelHelpers: 'bundled',
|
|
36
|
+
skipPreflightCheck: true
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
exports.sourceCode = sourceCode;
|