@quilted/rollup 0.1.0

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 (114) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +1 -0
  3. package/build/cjs/app.cjs +137 -0
  4. package/build/cjs/constants.cjs +13 -0
  5. package/build/cjs/env.cjs +130 -0
  6. package/build/cjs/index.cjs +16 -0
  7. package/build/cjs/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/TemplateTag/TemplateTag.cjs +168 -0
  8. package/build/cjs/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/commaLists/commaLists.cjs +8 -0
  9. package/build/cjs/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/commaListsAnd/commaListsAnd.cjs +8 -0
  10. package/build/cjs/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/commaListsOr/commaListsOr.cjs +8 -0
  11. package/build/cjs/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/html/html.cjs +10 -0
  12. package/build/cjs/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/inlineArrayTransformer/inlineArrayTransformer.cjs +48 -0
  13. package/build/cjs/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/inlineLists/inlineLists.cjs +8 -0
  14. package/build/cjs/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/oneLine/oneLine.cjs +7 -0
  15. package/build/cjs/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/oneLineCommaLists/oneLineCommaLists.cjs +8 -0
  16. package/build/cjs/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/oneLineCommaListsAnd/oneLineCommaListsAnd.cjs +8 -0
  17. package/build/cjs/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/oneLineCommaListsOr/oneLineCommaListsOr.cjs +8 -0
  18. package/build/cjs/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/oneLineInlineLists/oneLineInlineLists.cjs +8 -0
  19. package/build/cjs/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/oneLineTrim/oneLineTrim.cjs +7 -0
  20. package/build/cjs/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/removeNonPrintingValuesTransformer/removeNonPrintingValuesTransformer.cjs +23 -0
  21. package/build/cjs/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/replaceResultTransformer/replaceResultTransformer.cjs +22 -0
  22. package/build/cjs/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/replaceSubstitutionTransformer/replaceSubstitutionTransformer.cjs +22 -0
  23. package/build/cjs/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/safeHtml/safeHtml.cjs +10 -0
  24. package/build/cjs/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/splitStringTransformer/splitStringTransformer.cjs +20 -0
  25. package/build/cjs/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/stripIndent/stripIndent.cjs +11 -0
  26. package/build/cjs/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/stripIndentTransformer/stripIndentTransformer.cjs +37 -0
  27. package/build/cjs/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/stripIndents/stripIndents.cjs +7 -0
  28. package/build/cjs/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/trimResultTransformer/trimResultTransformer.cjs +33 -0
  29. package/build/cjs/request-router.cjs +30 -0
  30. package/build/cjs/shared/magic-module.cjs +44 -0
  31. package/build/cjs/shared/strings.cjs +16 -0
  32. package/build/esm/app.mjs +130 -0
  33. package/build/esm/constants.mjs +7 -0
  34. package/build/esm/env.mjs +108 -0
  35. package/build/esm/index.mjs +3 -0
  36. package/build/esm/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/TemplateTag/TemplateTag.mjs +164 -0
  37. package/build/esm/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/commaLists/commaLists.mjs +6 -0
  38. package/build/esm/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/commaListsAnd/commaListsAnd.mjs +6 -0
  39. package/build/esm/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/commaListsOr/commaListsOr.mjs +6 -0
  40. package/build/esm/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/html/html.mjs +8 -0
  41. package/build/esm/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/inlineArrayTransformer/inlineArrayTransformer.mjs +44 -0
  42. package/build/esm/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/inlineLists/inlineLists.mjs +6 -0
  43. package/build/esm/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/oneLine/oneLine.mjs +5 -0
  44. package/build/esm/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/oneLineCommaLists/oneLineCommaLists.mjs +6 -0
  45. package/build/esm/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/oneLineCommaListsAnd/oneLineCommaListsAnd.mjs +6 -0
  46. package/build/esm/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/oneLineCommaListsOr/oneLineCommaListsOr.mjs +6 -0
  47. package/build/esm/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/oneLineInlineLists/oneLineInlineLists.mjs +6 -0
  48. package/build/esm/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/oneLineTrim/oneLineTrim.mjs +5 -0
  49. package/build/esm/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/removeNonPrintingValuesTransformer/removeNonPrintingValuesTransformer.mjs +19 -0
  50. package/build/esm/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/replaceResultTransformer/replaceResultTransformer.mjs +18 -0
  51. package/build/esm/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/replaceSubstitutionTransformer/replaceSubstitutionTransformer.mjs +18 -0
  52. package/build/esm/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/safeHtml/safeHtml.mjs +8 -0
  53. package/build/esm/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/splitStringTransformer/splitStringTransformer.mjs +16 -0
  54. package/build/esm/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/stripIndent/stripIndent.mjs +7 -0
  55. package/build/esm/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/stripIndentTransformer/stripIndentTransformer.mjs +33 -0
  56. package/build/esm/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/stripIndents/stripIndents.mjs +5 -0
  57. package/build/esm/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/trimResultTransformer/trimResultTransformer.mjs +29 -0
  58. package/build/esm/request-router.mjs +28 -0
  59. package/build/esm/shared/magic-module.mjs +41 -0
  60. package/build/esm/shared/strings.mjs +14 -0
  61. package/build/esnext/app.esnext +130 -0
  62. package/build/esnext/constants.esnext +7 -0
  63. package/build/esnext/env.esnext +108 -0
  64. package/build/esnext/index.esnext +3 -0
  65. package/build/esnext/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/TemplateTag/TemplateTag.esnext +164 -0
  66. package/build/esnext/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/commaLists/commaLists.esnext +6 -0
  67. package/build/esnext/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/commaListsAnd/commaListsAnd.esnext +6 -0
  68. package/build/esnext/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/commaListsOr/commaListsOr.esnext +6 -0
  69. package/build/esnext/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/html/html.esnext +8 -0
  70. package/build/esnext/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/inlineArrayTransformer/inlineArrayTransformer.esnext +44 -0
  71. package/build/esnext/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/inlineLists/inlineLists.esnext +6 -0
  72. package/build/esnext/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/oneLine/oneLine.esnext +5 -0
  73. package/build/esnext/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/oneLineCommaLists/oneLineCommaLists.esnext +6 -0
  74. package/build/esnext/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/oneLineCommaListsAnd/oneLineCommaListsAnd.esnext +6 -0
  75. package/build/esnext/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/oneLineCommaListsOr/oneLineCommaListsOr.esnext +6 -0
  76. package/build/esnext/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/oneLineInlineLists/oneLineInlineLists.esnext +6 -0
  77. package/build/esnext/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/oneLineTrim/oneLineTrim.esnext +5 -0
  78. package/build/esnext/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/removeNonPrintingValuesTransformer/removeNonPrintingValuesTransformer.esnext +19 -0
  79. package/build/esnext/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/replaceResultTransformer/replaceResultTransformer.esnext +18 -0
  80. package/build/esnext/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/replaceSubstitutionTransformer/replaceSubstitutionTransformer.esnext +18 -0
  81. package/build/esnext/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/safeHtml/safeHtml.esnext +8 -0
  82. package/build/esnext/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/splitStringTransformer/splitStringTransformer.esnext +16 -0
  83. package/build/esnext/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/stripIndent/stripIndent.esnext +7 -0
  84. package/build/esnext/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/stripIndentTransformer/stripIndentTransformer.esnext +33 -0
  85. package/build/esnext/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/stripIndents/stripIndents.esnext +5 -0
  86. package/build/esnext/node_modules/.pnpm/common-tags@1.8.2/node_modules/common-tags/es/trimResultTransformer/trimResultTransformer.esnext +29 -0
  87. package/build/esnext/request-router.esnext +28 -0
  88. package/build/esnext/shared/magic-module.esnext +41 -0
  89. package/build/esnext/shared/strings.esnext +14 -0
  90. package/build/tsconfig.tsbuildinfo +1 -0
  91. package/build/typescript/app.d.ts +163 -0
  92. package/build/typescript/app.d.ts.map +1 -0
  93. package/build/typescript/constants.d.ts +6 -0
  94. package/build/typescript/constants.d.ts.map +1 -0
  95. package/build/typescript/env.d.ts +51 -0
  96. package/build/typescript/env.d.ts.map +1 -0
  97. package/build/typescript/index.d.ts +4 -0
  98. package/build/typescript/index.d.ts.map +1 -0
  99. package/build/typescript/request-router.d.ts +15 -0
  100. package/build/typescript/request-router.d.ts.map +1 -0
  101. package/build/typescript/shared/magic-module.d.ts +32 -0
  102. package/build/typescript/shared/magic-module.d.ts.map +1 -0
  103. package/build/typescript/shared/strings.d.ts +2 -0
  104. package/build/typescript/shared/strings.d.ts.map +1 -0
  105. package/package.json +52 -0
  106. package/quilt.project.ts +5 -0
  107. package/source/app.ts +217 -0
  108. package/source/constants.ts +5 -0
  109. package/source/env.ts +153 -0
  110. package/source/index.ts +13 -0
  111. package/source/request-router.ts +33 -0
  112. package/source/shared/magic-module.ts +53 -0
  113. package/source/shared/strings.ts +17 -0
  114. package/tsconfig.json +10 -0
package/source/app.ts ADDED
@@ -0,0 +1,217 @@
1
+ import type {Plugin} from 'rollup';
2
+
3
+ import {
4
+ MAGIC_MODULE_APP_COMPONENT,
5
+ MAGIC_MODULE_BROWSER_ASSETS,
6
+ MAGIC_MODULE_REQUEST_ROUTER,
7
+ } from './constants.ts';
8
+ import {magicModuleEnv, type MagicModuleEnvOptions} from './env.ts';
9
+ import {magicModuleRequestRouterEntry} from './request-router.ts';
10
+
11
+ import {multiline} from './shared/strings.ts';
12
+ import {
13
+ createMagicModulePlugin,
14
+ createMagicModuleEntryPlugin,
15
+ } from './shared/magic-module.ts';
16
+
17
+ export interface AppOptions {
18
+ /**
19
+ * The entry module for this app. This should be an absolute path, or relative
20
+ * path from the root directory containing your project. This entry should just be
21
+ * for the main `App` component in your project, which Quilt will automatically use
22
+ * to create browser and server-side entries for your project.
23
+ *
24
+ * If you only want to use a custom entry module for the browser build, use the
25
+ * `browser.entry` option instead. If you only want to use a custom entry module
26
+ * for the server-side build, use the `server.entry` option instead.
27
+ *
28
+ * @example './App.tsx'
29
+ */
30
+ entry?: string;
31
+
32
+ /**
33
+ * Whether to include GraphQL-related code transformations.
34
+ *
35
+ * @default true
36
+ */
37
+ graphql?: boolean;
38
+
39
+ /**
40
+ * Customizes the behavior of environment variables for your application. You
41
+ * can further customize the environment variables provided during server-side
42
+ * rendering by passing `server.env`.
43
+ */
44
+ env?: MagicModuleEnvOptions;
45
+ }
46
+
47
+ export function quiltApp({env, entry}: AppOptions = {}) {
48
+ return {
49
+ name: '@quilted/app',
50
+ options(originalOptions) {
51
+ const newPlugins = [
52
+ ...(Array.isArray(originalOptions.plugins)
53
+ ? originalOptions.plugins
54
+ : originalOptions.plugins
55
+ ? [originalOptions.plugins]
56
+ : []),
57
+ ];
58
+
59
+ const newOptions = {...originalOptions, plugins: newPlugins};
60
+
61
+ if (env) {
62
+ newPlugins.push(
63
+ typeof env === 'boolean' ? magicModuleEnv() : magicModuleEnv(env),
64
+ );
65
+ }
66
+
67
+ if (entry) {
68
+ newPlugins.push(magicModuleAppComponent({entry}));
69
+ }
70
+
71
+ return newOptions;
72
+ },
73
+ } satisfies Plugin;
74
+ }
75
+
76
+ export interface AppBrowserOptions {
77
+ /**
78
+ * Whether the app should use hydration or client-side rendering.
79
+ */
80
+ hydrate?: boolean;
81
+
82
+ /**
83
+ * The CSS selector to render or hydrate the application into.
84
+ */
85
+ selector?: string;
86
+ }
87
+
88
+ export function quiltAppBrowser(options: AppBrowserOptions = {}) {
89
+ return {
90
+ name: '@quilted/app/browser',
91
+ options(originalOptions) {
92
+ const newPlugins = [
93
+ ...(Array.isArray(originalOptions.plugins)
94
+ ? originalOptions.plugins
95
+ : originalOptions.plugins
96
+ ? [originalOptions.plugins]
97
+ : []),
98
+ ];
99
+
100
+ const newOptions = {...originalOptions, plugins: newPlugins};
101
+
102
+ newPlugins.push(magicModuleAppBrowserEntry(options));
103
+
104
+ return newOptions;
105
+ },
106
+ } satisfies Plugin;
107
+ }
108
+
109
+ export interface AppServerOptions {
110
+ /**
111
+ * The entry module for the server of this app. This module must export a
112
+ * `RequestRouter` object as its default export, which will be wrapped in
113
+ * the specific server runtime you configure.
114
+ */
115
+ entry?: string;
116
+ }
117
+
118
+ export function quiltAppServer(options: AppServerOptions = {}) {
119
+ return {
120
+ name: '@quilted/app/server',
121
+ options(originalOptions) {
122
+ const newPlugins = [
123
+ ...(Array.isArray(originalOptions.plugins)
124
+ ? originalOptions.plugins
125
+ : originalOptions.plugins
126
+ ? [originalOptions.plugins]
127
+ : []),
128
+ ];
129
+
130
+ const newOptions = {...originalOptions, plugins: newPlugins};
131
+
132
+ newPlugins.push(magicModuleRequestRouterEntry());
133
+ newPlugins.push(magicModuleAppRequestRouter(options));
134
+
135
+ return newOptions;
136
+ },
137
+ } satisfies Plugin;
138
+ }
139
+
140
+ export function magicModuleAppComponent({entry}: {entry: string}) {
141
+ return createMagicModulePlugin({
142
+ name: '@quilted/magic-module/app',
143
+ module: MAGIC_MODULE_APP_COMPONENT,
144
+ alias: entry,
145
+ });
146
+ }
147
+
148
+ export function magicModuleAppRequestRouter({
149
+ entry,
150
+ }: Pick<AppServerOptions, 'entry'> = {}) {
151
+ return createMagicModulePlugin({
152
+ name: '@quilted/magic-module/app-request-router',
153
+ module: MAGIC_MODULE_REQUEST_ROUTER,
154
+ alias: entry,
155
+ source: entry
156
+ ? undefined
157
+ : async function source() {
158
+ return multiline`
159
+ import '@quilted/quilt/globals';
160
+
161
+ import {jsx} from 'react/jsx-runtime';
162
+ import {RequestRouter} from '@quilted/quilt/request-router';
163
+ import {renderToResponse} from '@quilted/quilt/server';
164
+
165
+ import App from ${JSON.stringify(MAGIC_MODULE_APP_COMPONENT)};
166
+ import {BrowserAssets} from ${JSON.stringify(
167
+ MAGIC_MODULE_BROWSER_ASSETS,
168
+ )};
169
+
170
+ const router = new RequestRouter();
171
+ const assets = new BrowserAssets();
172
+
173
+ // For all GET requests, render our React application.
174
+ router.get(async (request) => {
175
+ const response = await renderToResponse(jsx(App), {
176
+ request,
177
+ assets,
178
+ });
179
+
180
+ return response;
181
+ });
182
+
183
+ export default router;
184
+ `;
185
+ },
186
+ });
187
+ }
188
+
189
+ export function magicModuleAppBrowserEntry({
190
+ hydrate = true,
191
+ selector = '#app',
192
+ }: AppBrowserOptions = {}) {
193
+ return createMagicModuleEntryPlugin({
194
+ name: '@quilted/magic-module/app-browser-entry',
195
+ sideEffects: true,
196
+ async source() {
197
+ const reactRootFunction = hydrate ? 'hydrateRoot' : 'createRoot';
198
+
199
+ return multiline`
200
+ import '@quilted/quilt/globals';
201
+
202
+ import {jsx} from 'react/jsx-runtime';
203
+ import {${reactRootFunction}} from 'react-dom/client';
204
+
205
+ import App from ${JSON.stringify(MAGIC_MODULE_APP_COMPONENT)};
206
+
207
+ const element = document.querySelector(${JSON.stringify(selector)});
208
+
209
+ ${
210
+ hydrate
211
+ ? `${reactRootFunction}(element, jsx(App));`
212
+ : `${reactRootFunction}(element).render(jsx(App));`
213
+ }
214
+ `;
215
+ },
216
+ });
217
+ }
@@ -0,0 +1,5 @@
1
+ export const MAGIC_MODULE_ENV = 'quilt:module/env';
2
+ export const MAGIC_MODULE_ENTRY = 'quilt:module/entry';
3
+ export const MAGIC_MODULE_APP_COMPONENT = 'quilt:module/app';
4
+ export const MAGIC_MODULE_BROWSER_ASSETS = 'quilt:module/assets';
5
+ export const MAGIC_MODULE_REQUEST_ROUTER = 'quilt:module/request-router';
package/source/env.ts ADDED
@@ -0,0 +1,153 @@
1
+ import * as path from 'path';
2
+ import * as fs from 'fs';
3
+
4
+ import type {PluginContext} from 'rollup';
5
+ import {stripIndent} from 'common-tags';
6
+
7
+ import {MAGIC_MODULE_ENV} from './constants.ts';
8
+ import {createMagicModulePlugin} from './shared/magic-module.ts';
9
+
10
+ export interface MagicModuleEnvOptions {
11
+ /**
12
+ * The runtime mode for your target environment.
13
+ */
14
+ mode?: 'production' | 'development';
15
+
16
+ /**
17
+ * Environment variables from the build environment to inline into the magic
18
+ * module. Be careful when using this option! Inlining environment variables
19
+ * into your application always comes with the risk of exposing sensitive information
20
+ * to your users. Only use this option for environment variables that are safe
21
+ * for a human to see if they open their browser developer tools.
22
+ */
23
+ inline?: string[];
24
+
25
+ /**
26
+ * A string that will be inlined directly as code to reference a runtime variable
27
+ * that contains environment variables.
28
+ */
29
+ runtime?: string;
30
+
31
+ /**
32
+ * Whether to load environment variables from a `.env` file. The option can
33
+ * be one of the following types:
34
+ *
35
+ * - `false`, which disables loading environment variables from a `.env` file.
36
+ * - An object containing a `roots` field, specifying the directories to search
37
+ * for `.env` files in.
38
+ * - An object containing a `files` field, specifying the directories to search
39
+ * for `.env` files in.
40
+ *
41
+ * @default {roots: ['.', 'configuration']}
42
+ */
43
+ dotenv?:
44
+ | false
45
+ | {roots?: string[]; files?: never}
46
+ | {roots?: never; files?: string[]};
47
+ }
48
+
49
+ export function magicModuleEnv({
50
+ mode,
51
+ dotenv = {roots: ['.', 'configuration']},
52
+ inline = [],
53
+ runtime = '{}',
54
+ }: MagicModuleEnvOptions = {}) {
55
+ return createMagicModulePlugin({
56
+ name: '@quilted/magic-module/env',
57
+ module: MAGIC_MODULE_ENV,
58
+ async source() {
59
+ const inlineEnv: Record<string, string> = {};
60
+
61
+ if (mode) {
62
+ inlineEnv.MODE = mode;
63
+ }
64
+
65
+ const loadedEnv = await loadEnv.call(this, {mode, dotenv});
66
+
67
+ for (const inlineVariable of inline.sort()) {
68
+ if (inlineVariable in inlineEnv) continue;
69
+ const value = process.env[inlineVariable] ?? loadedEnv[inlineVariable];
70
+ if (value == null) continue;
71
+ inlineEnv[inlineVariable] =
72
+ typeof value === 'string' &&
73
+ value[0] === '"' &&
74
+ value[value.length - 1] === '"'
75
+ ? JSON.parse(value)
76
+ : value;
77
+ }
78
+
79
+ return stripIndent`
80
+ const runtime = (${runtime});
81
+ const inline = JSON.parse(${JSON.stringify(JSON.stringify(inlineEnv))});
82
+
83
+ const Env = new Proxy(
84
+ {},
85
+ {
86
+ get(_, property) {
87
+ return runtime[property] ?? inline[property];
88
+ },
89
+ },
90
+ );
91
+
92
+ export default Env;
93
+ `;
94
+ },
95
+ });
96
+ }
97
+
98
+ // Inspired by https://github.com/vitejs/vite/blob/e0a4d810598d1834933ed437ac5a2168cbbbf2f8/packages/vite/source/node/config.ts#L1050-L1113
99
+ async function loadEnv(
100
+ this: PluginContext,
101
+ {
102
+ mode,
103
+ dotenv,
104
+ }: {mode?: string} & Required<Pick<MagicModuleEnvOptions, 'dotenv'>>,
105
+ ): Promise<Record<string, string | undefined>> {
106
+ const env: Record<string, string | undefined> = {...process.env};
107
+
108
+ if (dotenv !== false) {
109
+ const {parse} = await import('dotenv');
110
+
111
+ let files = dotenv.files;
112
+
113
+ if (files == null) {
114
+ const testFiles = [
115
+ // default file
116
+ `.env`,
117
+ // local file
118
+ `.env.local`,
119
+ ];
120
+
121
+ if (mode) {
122
+ testFiles.push(
123
+ // mode file
124
+ `.env.${mode}`,
125
+ // mode local file
126
+ `.env.${mode}.local`,
127
+ );
128
+ }
129
+
130
+ files = testFiles.flatMap((file) =>
131
+ (dotenv.roots ?? ['.', 'configuration']).map((root) =>
132
+ path.resolve(root, file),
133
+ ),
134
+ );
135
+ }
136
+
137
+ const envFileResults = await Promise.all(
138
+ files.map(async (file) => {
139
+ if (fs.existsSync(file)) {
140
+ this.addWatchFile(file);
141
+ return parse(await fs.promises.readFile(file, 'utf-8'));
142
+ }
143
+ }),
144
+ );
145
+
146
+ for (const envFileResult of envFileResults) {
147
+ if (envFileResult == null) continue;
148
+ Object.assign(env, envFileResult);
149
+ }
150
+ }
151
+
152
+ return env;
153
+ }
@@ -0,0 +1,13 @@
1
+ export {magicModuleEnv, type MagicModuleEnvOptions} from './env.ts';
2
+ export {
3
+ quiltApp,
4
+ quiltAppBrowser,
5
+ quiltAppServer,
6
+ magicModuleAppComponent,
7
+ magicModuleAppBrowserEntry,
8
+ magicModuleAppRequestRouter,
9
+ type AppOptions,
10
+ type AppBrowserOptions,
11
+ type AppServerOptions,
12
+ } from './app.ts';
13
+ export {magicModuleRequestRouterEntry} from './request-router.ts';
@@ -0,0 +1,33 @@
1
+ import {MAGIC_MODULE_REQUEST_ROUTER} from './constants.ts';
2
+
3
+ import {createMagicModuleEntryPlugin} from './shared/magic-module.ts';
4
+ import {multiline} from './shared/strings.ts';
5
+
6
+ export function magicModuleRequestRouterEntry({
7
+ host,
8
+ port,
9
+ }: {
10
+ host?: string;
11
+ port?: number;
12
+ } = {}) {
13
+ return createMagicModuleEntryPlugin({
14
+ name: '@quilted/request-router',
15
+ sideEffects: true,
16
+ async source() {
17
+ const initialContent = multiline`
18
+ import requestRouter from ${JSON.stringify(
19
+ MAGIC_MODULE_REQUEST_ROUTER,
20
+ )};
21
+
22
+ import {createHttpServer} from '@quilted/quilt/request-router/node';
23
+
24
+ const port = ${port ?? 'Number.parseInt(process.env.PORT, 10)'};
25
+ const host = ${host ? JSON.stringify(host) : 'process.env.HOST'};
26
+
27
+ createHttpServer(requestRouter).listen(port, host);
28
+ `;
29
+
30
+ return initialContent;
31
+ },
32
+ });
33
+ }
@@ -0,0 +1,53 @@
1
+ import type {Plugin, PluginContext} from 'rollup';
2
+
3
+ import {MAGIC_MODULE_ENTRY} from '../constants.ts';
4
+
5
+ const VIRTUAL_MODULE_PREFIX = '\0';
6
+ const VIRTUAL_MODULE_POSTFIX = '/module.js';
7
+
8
+ export function createMagicModulePlugin({
9
+ name,
10
+ module,
11
+ alias = `${VIRTUAL_MODULE_PREFIX}${module}${VIRTUAL_MODULE_POSTFIX}`,
12
+ source: getSource,
13
+ sideEffects = false,
14
+ }: {
15
+ readonly name: string;
16
+ readonly alias?: string;
17
+ readonly module: string;
18
+ readonly sideEffects?: boolean;
19
+ source?(this: PluginContext): string | Promise<string>;
20
+ }) {
21
+ return {
22
+ name,
23
+ resolveId(id) {
24
+ if (id !== module) return null;
25
+
26
+ return {
27
+ id: alias,
28
+ moduleSideEffects: sideEffects ? 'no-treeshake' : undefined,
29
+ };
30
+ },
31
+ load: getSource
32
+ ? async function load(source) {
33
+ if (source !== alias) return null;
34
+
35
+ const code = await getSource.call(this);
36
+
37
+ return {
38
+ code,
39
+ moduleSideEffects: sideEffects ? 'no-treeshake' : undefined,
40
+ };
41
+ }
42
+ : undefined,
43
+ } satisfies Plugin;
44
+ }
45
+
46
+ export function createMagicModuleEntryPlugin({
47
+ module = MAGIC_MODULE_ENTRY,
48
+ ...options
49
+ }: Omit<Parameters<typeof createMagicModulePlugin>[0], 'module' | 'alias'> & {
50
+ module?: string;
51
+ }) {
52
+ return createMagicModulePlugin({...options, module});
53
+ }
@@ -0,0 +1,17 @@
1
+ export function multiline(strings: TemplateStringsArray, ...values: any[]) {
2
+ let result = strings.reduce(
3
+ (combined, string, index) => `${combined}${string}${values[index] ?? ''}`,
4
+ '',
5
+ );
6
+
7
+ // Inspired by https://github.com/zspecza/common-tags/blob/master/src/stripIndentTransformer/stripIndentTransformer.js#L8
8
+ const match = result.match(/^[^\S\n]*(?=\S)/gm);
9
+ const indent = match && Math.min(...match.map((indent) => indent.length));
10
+
11
+ if (indent) {
12
+ const regexp = new RegExp(`^.{${indent}}`, 'gm');
13
+ result = result.replace(regexp, '');
14
+ }
15
+
16
+ return result.trim();
17
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "@quilted/typescript/project.json",
3
+ "compilerOptions": {
4
+ "rootDir": "source",
5
+ "outDir": "build/typescript"
6
+ },
7
+ "include": ["source"],
8
+ "exclude": ["quilt.project.ts", "**/*.test.ts", "**/*.test.tsx"],
9
+ "references": []
10
+ }