@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.
@@ -0,0 +1,139 @@
1
+ import {dirname} from 'path';
2
+ import {readFile, mkdir, writeFile} from 'fs/promises';
3
+
4
+ import {parse, type DocumentNode} from 'graphql';
5
+ import type {Plugin, TransformPluginContext} from 'rollup';
6
+
7
+ import {
8
+ toGraphQLOperation,
9
+ cleanGraphQLDocument,
10
+ extractGraphQLImports,
11
+ } from './graphql/transform.ts';
12
+
13
+ export interface Options {
14
+ manifest?: string | boolean;
15
+ }
16
+
17
+ export function graphql({manifest}: Options = {}): Plugin {
18
+ const shouldWriteManifest = Boolean(manifest);
19
+ const manifestPath =
20
+ typeof manifest === 'string' ? manifest : `manifests/graphql.json`;
21
+
22
+ return {
23
+ name: '@quilted/graphql',
24
+ async transform(code, id) {
25
+ if (!id.endsWith('.graphql') && !id.endsWith('.gql')) return null;
26
+
27
+ const topLevelDefinitions = new Set<string>();
28
+
29
+ const loadedDocument = await loadDocument(
30
+ code,
31
+ id,
32
+ this,
33
+ (document, level) => {
34
+ if (level !== 0) return;
35
+
36
+ for (const definition of document.definitions) {
37
+ if ('name' in definition && definition.name != null) {
38
+ topLevelDefinitions.add(definition.name.value);
39
+ }
40
+ }
41
+ },
42
+ );
43
+
44
+ const document = toGraphQLOperation(
45
+ cleanGraphQLDocument(loadedDocument, {
46
+ removeUnused: {exclude: topLevelDefinitions},
47
+ }),
48
+ );
49
+
50
+ return {
51
+ code: `export default JSON.parse(${JSON.stringify(
52
+ JSON.stringify(document),
53
+ )})`,
54
+ meta: shouldWriteManifest
55
+ ? {
56
+ quilt: {graphql: document},
57
+ }
58
+ : undefined,
59
+ };
60
+ },
61
+ async generateBundle() {
62
+ if (!shouldWriteManifest) return;
63
+
64
+ const operations: Record<string, string> = {};
65
+
66
+ for (const moduleId of this.getModuleIds()) {
67
+ const operation = this.getModuleInfo(moduleId)?.meta?.quilt?.graphql;
68
+
69
+ if (
70
+ operation != null &&
71
+ typeof operation.id === 'string' &&
72
+ typeof operation.source === 'string'
73
+ ) {
74
+ operations[operation.id] = operation.source;
75
+ }
76
+ }
77
+
78
+ await mkdir(dirname(manifestPath), {recursive: true});
79
+ await writeFile(manifestPath, JSON.stringify(operations, null, 2));
80
+ },
81
+ };
82
+ }
83
+
84
+ async function loadDocument(
85
+ code: string,
86
+ file: string,
87
+ plugin: TransformPluginContext,
88
+ add?: (document: DocumentNode, level: number) => void,
89
+ level = 0,
90
+ seen = new Set<string>(),
91
+ ) {
92
+ const {imports, source} = extractGraphQLImports(code);
93
+ const document = parse(source);
94
+
95
+ add?.(document, level);
96
+
97
+ if (imports.length === 0) {
98
+ return document;
99
+ }
100
+
101
+ const resolvedImports = await Promise.all(
102
+ imports.map(async (imported) => {
103
+ if (seen.has(imported)) return;
104
+
105
+ seen.add(imported);
106
+
107
+ const resolvedId = await plugin.resolve(imported, file);
108
+
109
+ if (resolvedId == null) {
110
+ throw new Error(
111
+ `Could not find ${JSON.stringify(imported)} from ${JSON.stringify(
112
+ file,
113
+ )}`,
114
+ );
115
+ }
116
+
117
+ plugin.addWatchFile(resolvedId.id);
118
+ const contents = await readFile(resolvedId.id, {
119
+ encoding: 'utf8',
120
+ });
121
+
122
+ return loadDocument(
123
+ contents,
124
+ resolvedId.id,
125
+ plugin,
126
+ add,
127
+ level + 1,
128
+ seen,
129
+ );
130
+ }),
131
+ );
132
+
133
+ for (const importedDocument of resolvedImports) {
134
+ if (importedDocument == null) continue;
135
+ (document.definitions as any[]).push(...importedDocument.definitions);
136
+ }
137
+
138
+ return document;
139
+ }
package/source/index.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  export {magicModuleEnv, type MagicModuleEnvOptions} from './env.ts';
2
2
  export {
3
- quiltApp,
4
3
  quiltAppBrowser,
5
4
  quiltAppServer,
6
5
  magicModuleAppComponent,
@@ -0,0 +1,64 @@
1
+ import {createRequire} from 'module';
2
+
3
+ import babel from '@rollup/plugin-babel';
4
+
5
+ const require = createRequire(import.meta.url);
6
+
7
+ export function sourceCode({
8
+ mode,
9
+ targets,
10
+ }: {
11
+ mode?: 'development' | 'production';
12
+ targets?: string[];
13
+ }) {
14
+ return babel({
15
+ configFile: false,
16
+ babelrc: false,
17
+ presets: [
18
+ require.resolve('@babel/preset-typescript'),
19
+ [
20
+ require.resolve('@babel/preset-react'),
21
+ {
22
+ runtime: 'automatic',
23
+ importSource: 'react',
24
+ development: mode === 'development',
25
+ },
26
+ ],
27
+ [
28
+ require.resolve('@babel/preset-env'),
29
+ {
30
+ // @ts-expect-error This is a valid option
31
+ corejs: '3.15',
32
+ useBuiltIns: 'usage',
33
+ bugfixes: true,
34
+ shippedProposals: true,
35
+ // I thought I wanted this on, but if you do this, Babel
36
+ // stops respecting the top-level `targets` option and tries
37
+ // to use the targets passed to the preset directly instead.
38
+ ignoreBrowserslistConfig: true,
39
+ } satisfies import('@babel/preset-env').Options,
40
+ ],
41
+ ],
42
+ plugins: [
43
+ [
44
+ require.resolve('@babel/plugin-proposal-decorators'),
45
+ {version: '2023-01'},
46
+ ],
47
+ ],
48
+ targets,
49
+ extensions: [
50
+ '.ts',
51
+ '.tsx',
52
+ '.mts',
53
+ '.mtsx',
54
+ '.js',
55
+ '.jsx',
56
+ '.es6',
57
+ '.es',
58
+ '.mjs',
59
+ ],
60
+ exclude: 'node_modules/**',
61
+ babelHelpers: 'bundled',
62
+ skipPreflightCheck: true,
63
+ });
64
+ }