@rindo/core 3.0.1 → 3.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 (111) hide show
  1. package/cli/config-flags.d.ts +122 -122
  2. package/cli/index.cjs +2301 -2432
  3. package/cli/index.d.ts +19 -19
  4. package/cli/index.js +2302 -2433
  5. package/cli/package.json +1 -1
  6. package/compiler/package.json +1 -1
  7. package/compiler/rindo.d.ts +73 -73
  8. package/compiler/rindo.js +66137 -62907
  9. package/compiler/rindo.min.js +2 -2
  10. package/compiler/sys/in-memory-fs.d.ts +218 -218
  11. package/compiler/transpile.d.ts +32 -32
  12. package/dev-server/client/app-error.d.ts +18 -18
  13. package/dev-server/client/events.d.ts +6 -6
  14. package/dev-server/client/hmr-components.d.ts +1 -1
  15. package/dev-server/client/hmr-external-styles.d.ts +1 -1
  16. package/dev-server/client/hmr-images.d.ts +1 -1
  17. package/dev-server/client/hmr-inline-styles.d.ts +1 -1
  18. package/dev-server/client/hmr-util.d.ts +9 -9
  19. package/dev-server/client/hmr-window.d.ts +10 -10
  20. package/dev-server/client/index.d.ts +6 -6
  21. package/dev-server/client/index.js +781 -781
  22. package/dev-server/client/logger.d.ts +5 -5
  23. package/dev-server/client/package.json +1 -1
  24. package/dev-server/client/progress.d.ts +3 -3
  25. package/dev-server/client/status.d.ts +4 -4
  26. package/dev-server/connector.html +2 -2
  27. package/dev-server/index.d.ts +3 -3
  28. package/dev-server/index.js +228 -228
  29. package/dev-server/open-in-editor-api.js +1 -1
  30. package/dev-server/package.json +1 -1
  31. package/dev-server/server-process.js +1300 -1281
  32. package/dev-server/ws.js +1 -1
  33. package/dev-server/xdg-open +0 -0
  34. package/internal/app-data/index.cjs +88 -88
  35. package/internal/app-data/index.d.ts +4 -4
  36. package/internal/app-data/index.js +88 -88
  37. package/internal/app-data/package.json +1 -1
  38. package/internal/client/css-shim.js +1 -1
  39. package/internal/client/dom.js +1 -1
  40. package/internal/client/index.js +3380 -3380
  41. package/internal/client/package.json +1 -1
  42. package/internal/client/patch-browser.js +155 -155
  43. package/internal/client/patch-esm.js +25 -25
  44. package/internal/client/shadow-css.js +382 -382
  45. package/internal/hydrate/package.json +1 -1
  46. package/internal/index.d.ts +2 -2
  47. package/internal/index.js +1 -1
  48. package/internal/package.json +1 -1
  49. package/internal/rindo-private.d.ts +2272 -2268
  50. package/internal/rindo-public-compiler.d.ts +2377 -2356
  51. package/internal/rindo-public-docs.d.ts +139 -139
  52. package/internal/rindo-public-runtime.d.ts +1636 -1636
  53. package/internal/testing/package.json +1 -1
  54. package/mock-doc/index.cjs +4766 -4766
  55. package/mock-doc/index.d.ts +1006 -1006
  56. package/mock-doc/index.js +4766 -4766
  57. package/mock-doc/package.json +1 -1
  58. package/package.json +9 -9
  59. package/screenshot/connector-base.d.ts +42 -42
  60. package/screenshot/connector-local.d.ts +7 -7
  61. package/screenshot/index.d.ts +3 -3
  62. package/screenshot/index.js +615 -615
  63. package/screenshot/package.json +1 -1
  64. package/screenshot/pixel-match.d.ts +1 -1
  65. package/screenshot/pixel-match.js +14 -14
  66. package/screenshot/screenshot-compare.d.ts +3 -3
  67. package/screenshot/screenshot-fs.d.ts +15 -15
  68. package/sys/node/autoprefixer.js +2 -2
  69. package/sys/node/glob.js +1 -1
  70. package/sys/node/graceful-fs.js +1 -1
  71. package/sys/node/index.d.ts +22 -22
  72. package/sys/node/index.js +6 -3
  73. package/sys/node/node-fetch.js +1 -1
  74. package/sys/node/package.json +1 -1
  75. package/sys/node/prompts.js +1 -1
  76. package/sys/node/worker.js +1 -1
  77. package/testing/index.d.ts +12 -12
  78. package/testing/index.js +7 -3
  79. package/testing/jest/jest-config.d.ts +16 -16
  80. package/testing/jest/jest-environment.d.ts +15 -15
  81. package/testing/jest/jest-preprocessor.d.ts +59 -59
  82. package/testing/jest/jest-runner.d.ts +10 -10
  83. package/testing/jest/jest-screenshot.d.ts +2 -2
  84. package/testing/jest/jest-serializer.d.ts +4 -4
  85. package/testing/jest/jest-setup-test-framework.d.ts +1 -1
  86. package/testing/matchers/attributes.d.ts +14 -14
  87. package/testing/matchers/class-list.d.ts +12 -12
  88. package/testing/matchers/events.d.ts +21 -21
  89. package/testing/matchers/html.d.ts +12 -12
  90. package/testing/matchers/index.d.ts +23 -23
  91. package/testing/matchers/screenshot.d.ts +5 -5
  92. package/testing/matchers/text.d.ts +4 -4
  93. package/testing/mock-fetch.d.ts +11 -11
  94. package/testing/mocks.d.ts +56 -56
  95. package/testing/package.json +1 -1
  96. package/testing/puppeteer/index.d.ts +2 -2
  97. package/testing/puppeteer/puppeteer-browser.d.ts +6 -6
  98. package/testing/puppeteer/puppeteer-declarations.d.ts +403 -403
  99. package/testing/puppeteer/puppeteer-element.d.ts +67 -67
  100. package/testing/puppeteer/puppeteer-emulate.d.ts +2 -2
  101. package/testing/puppeteer/puppeteer-events.d.ts +21 -21
  102. package/testing/puppeteer/puppeteer-page.d.ts +2 -2
  103. package/testing/puppeteer/puppeteer-screenshot.d.ts +4 -4
  104. package/testing/reset-build-conditionals.d.ts +2 -2
  105. package/testing/spec-page.d.ts +2 -2
  106. package/testing/test-transpile.d.ts +2 -2
  107. package/testing/testing-logger.d.ts +25 -25
  108. package/testing/testing-sys.d.ts +6 -6
  109. package/testing/testing-utils.d.ts +79 -79
  110. package/testing/testing.d.ts +2 -2
  111. package/dependencies.json +0 -120
@@ -1,5 +1,5 @@
1
1
  /*!
2
- Rindo Dev Server Process v3.0.1 | MIT Licensed | https://rindojs.web.app
2
+ Rindo Dev Server Process v3.1.0 | MIT Licensed | https://rindojs.web.app
3
3
  */
4
4
  'use strict';
5
5
 
@@ -53,324 +53,324 @@ const openInEditorApi__default = /*#__PURE__*/_interopDefaultLegacy(openInEditor
53
53
  const zlib__namespace = /*#__PURE__*/_interopNamespace(zlib);
54
54
  const ws__namespace = /*#__PURE__*/_interopNamespace(ws);
55
55
 
56
- /**
57
- * This is just a no-op, don't expect it to do anything.
58
- */
59
- const noop = () => {
60
- /* noop*/
61
- };
62
- const isFunction = (v) => typeof v === 'function';
56
+ /**
57
+ * This is just a no-op, don't expect it to do anything.
58
+ */
59
+ const noop = () => {
60
+ /* noop*/
61
+ };
62
+ const isFunction = (v) => typeof v === 'function';
63
63
  const isString = (v) => typeof v === 'string';
64
64
 
65
- /**
66
- * Builds a diagnostic from an `Error`, appends it to the `diagnostics` parameter, and returns the created diagnostic
67
- * @param diagnostics the series of diagnostics the newly created diagnostics should be added to
68
- * @param err the error to derive information from in generating the diagnostic
69
- * @param msg an optional message to use in place of `err` to generate the diagnostic
70
- * @returns the generated diagnostic
71
- */
72
- const catchError = (diagnostics, err, msg) => {
73
- const diagnostic = {
74
- level: 'error',
75
- type: 'build',
76
- header: 'Build Error',
77
- messageText: 'build error',
78
- relFilePath: null,
79
- absFilePath: null,
80
- lines: [],
81
- };
82
- if (isString(msg)) {
83
- diagnostic.messageText = msg.length ? msg : 'UNKNOWN ERROR';
84
- }
85
- else if (err != null) {
86
- if (err.stack != null) {
87
- diagnostic.messageText = err.stack.toString();
88
- }
89
- else {
90
- if (err.message != null) {
91
- diagnostic.messageText = err.message.length ? err.message : 'UNKNOWN ERROR';
92
- }
93
- else {
94
- diagnostic.messageText = err.toString();
95
- }
96
- }
97
- }
98
- if (diagnostics != null && !shouldIgnoreError(diagnostic.messageText)) {
99
- diagnostics.push(diagnostic);
100
- }
101
- return diagnostic;
102
- };
103
- const shouldIgnoreError = (msg) => {
104
- return msg === TASK_CANCELED_MSG;
105
- };
65
+ /**
66
+ * Builds a diagnostic from an `Error`, appends it to the `diagnostics` parameter, and returns the created diagnostic
67
+ * @param diagnostics the series of diagnostics the newly created diagnostics should be added to
68
+ * @param err the error to derive information from in generating the diagnostic
69
+ * @param msg an optional message to use in place of `err` to generate the diagnostic
70
+ * @returns the generated diagnostic
71
+ */
72
+ const catchError = (diagnostics, err, msg) => {
73
+ const diagnostic = {
74
+ level: 'error',
75
+ type: 'build',
76
+ header: 'Build Error',
77
+ messageText: 'build error',
78
+ relFilePath: null,
79
+ absFilePath: null,
80
+ lines: [],
81
+ };
82
+ if (isString(msg)) {
83
+ diagnostic.messageText = msg.length ? msg : 'UNKNOWN ERROR';
84
+ }
85
+ else if (err != null) {
86
+ if (err.stack != null) {
87
+ diagnostic.messageText = err.stack.toString();
88
+ }
89
+ else {
90
+ if (err.message != null) {
91
+ diagnostic.messageText = err.message.length ? err.message : 'UNKNOWN ERROR';
92
+ }
93
+ else {
94
+ diagnostic.messageText = err.toString();
95
+ }
96
+ }
97
+ }
98
+ if (diagnostics != null && !shouldIgnoreError(diagnostic.messageText)) {
99
+ diagnostics.push(diagnostic);
100
+ }
101
+ return diagnostic;
102
+ };
103
+ const shouldIgnoreError = (msg) => {
104
+ return msg === TASK_CANCELED_MSG;
105
+ };
106
106
  const TASK_CANCELED_MSG = `task canceled`;
107
107
 
108
- /**
109
- * Convert Windows backslash paths to slash paths: foo\\bar ➔ foo/bar
110
- * Forward-slash paths can be used in Windows as long as they're not
111
- * extended-length paths and don't contain any non-ascii characters.
112
- * This was created since the path methods in Node.js outputs \\ paths on Windows.
113
- * @param path the Windows-based path to convert
114
- * @returns the converted path
115
- */
116
- const normalizePath = (path) => {
117
- if (typeof path !== 'string') {
118
- throw new Error(`invalid path to normalize`);
119
- }
120
- path = normalizeSlashes(path.trim());
121
- const components = pathComponents(path, getRootLength(path));
122
- const reducedComponents = reducePathComponents(components);
123
- const rootPart = reducedComponents[0];
124
- const secondPart = reducedComponents[1];
125
- const normalized = rootPart + reducedComponents.slice(1).join('/');
126
- if (normalized === '') {
127
- return '.';
128
- }
129
- if (rootPart === '' &&
130
- secondPart &&
131
- path.includes('/') &&
132
- !secondPart.startsWith('.') &&
133
- !secondPart.startsWith('@')) {
134
- return './' + normalized;
135
- }
136
- return normalized;
137
- };
138
- const normalizeSlashes = (path) => path.replace(backslashRegExp, '/');
139
- const altDirectorySeparator = '\\';
140
- const urlSchemeSeparator = '://';
141
- const backslashRegExp = /\\/g;
142
- const reducePathComponents = (components) => {
143
- if (!Array.isArray(components) || components.length === 0) {
144
- return [];
145
- }
146
- const reduced = [components[0]];
147
- for (let i = 1; i < components.length; i++) {
148
- const component = components[i];
149
- if (!component)
150
- continue;
151
- if (component === '.')
152
- continue;
153
- if (component === '..') {
154
- if (reduced.length > 1) {
155
- if (reduced[reduced.length - 1] !== '..') {
156
- reduced.pop();
157
- continue;
158
- }
159
- }
160
- else if (reduced[0])
161
- continue;
162
- }
163
- reduced.push(component);
164
- }
165
- return reduced;
166
- };
167
- const getRootLength = (path) => {
168
- const rootLength = getEncodedRootLength(path);
169
- return rootLength < 0 ? ~rootLength : rootLength;
170
- };
171
- const getEncodedRootLength = (path) => {
172
- if (!path)
173
- return 0;
174
- const ch0 = path.charCodeAt(0);
175
- // POSIX or UNC
176
- if (ch0 === 47 /* CharacterCodes.slash */ || ch0 === 92 /* CharacterCodes.backslash */) {
177
- if (path.charCodeAt(1) !== ch0)
178
- return 1; // POSIX: "/" (or non-normalized "\")
179
- const p1 = path.indexOf(ch0 === 47 /* CharacterCodes.slash */ ? '/' : altDirectorySeparator, 2);
180
- if (p1 < 0)
181
- return path.length; // UNC: "//server" or "\\server"
182
- return p1 + 1; // UNC: "//server/" or "\\server\"
183
- }
184
- // DOS
185
- if (isVolumeCharacter(ch0) && path.charCodeAt(1) === 58 /* CharacterCodes.colon */) {
186
- const ch2 = path.charCodeAt(2);
187
- if (ch2 === 47 /* CharacterCodes.slash */ || ch2 === 92 /* CharacterCodes.backslash */)
188
- return 3; // DOS: "c:/" or "c:\"
189
- if (path.length === 2)
190
- return 2; // DOS: "c:" (but not "c:d")
191
- }
192
- // URL
193
- const schemeEnd = path.indexOf(urlSchemeSeparator);
194
- if (schemeEnd !== -1) {
195
- const authorityStart = schemeEnd + urlSchemeSeparator.length;
196
- const authorityEnd = path.indexOf('/', authorityStart);
197
- if (authorityEnd !== -1) {
198
- // URL: "file:///", "file://server/", "file://server/path"
199
- // For local "file" URLs, include the leading DOS volume (if present).
200
- // Per https://www.ietf.org/rfc/rfc1738.txt, a host of "" or "localhost" is a
201
- // special case interpreted as "the machine from which the URL is being interpreted".
202
- const scheme = path.slice(0, schemeEnd);
203
- const authority = path.slice(authorityStart, authorityEnd);
204
- if (scheme === 'file' &&
205
- (authority === '' || authority === 'localhost') &&
206
- isVolumeCharacter(path.charCodeAt(authorityEnd + 1))) {
207
- const volumeSeparatorEnd = getFileUrlVolumeSeparatorEnd(path, authorityEnd + 2);
208
- if (volumeSeparatorEnd !== -1) {
209
- if (path.charCodeAt(volumeSeparatorEnd) === 47 /* CharacterCodes.slash */) {
210
- // URL: "file:///c:/", "file://localhost/c:/", "file:///c%3a/", "file://localhost/c%3a/"
211
- return ~(volumeSeparatorEnd + 1);
212
- }
213
- if (volumeSeparatorEnd === path.length) {
214
- // URL: "file:///c:", "file://localhost/c:", "file:///c$3a", "file://localhost/c%3a"
215
- // but not "file:///c:d" or "file:///c%3ad"
216
- return ~volumeSeparatorEnd;
217
- }
218
- }
219
- }
220
- return ~(authorityEnd + 1); // URL: "file://server/", "http://server/"
221
- }
222
- return ~path.length; // URL: "file://server", "http://server"
223
- }
224
- // relative
225
- return 0;
226
- };
227
- const isVolumeCharacter = (charCode) => (charCode >= 97 /* CharacterCodes.a */ && charCode <= 122 /* CharacterCodes.z */) ||
228
- (charCode >= 65 /* CharacterCodes.A */ && charCode <= 90 /* CharacterCodes.Z */);
229
- const getFileUrlVolumeSeparatorEnd = (url, start) => {
230
- const ch0 = url.charCodeAt(start);
231
- if (ch0 === 58 /* CharacterCodes.colon */)
232
- return start + 1;
233
- if (ch0 === 37 /* CharacterCodes.percent */ && url.charCodeAt(start + 1) === 51 /* CharacterCodes._3 */) {
234
- const ch2 = url.charCodeAt(start + 2);
235
- if (ch2 === 97 /* CharacterCodes.a */ || ch2 === 65 /* CharacterCodes.A */)
236
- return start + 3;
237
- }
238
- return -1;
239
- };
240
- const pathComponents = (path, rootLength) => {
241
- const root = path.substring(0, rootLength);
242
- const rest = path.substring(rootLength).split('/');
243
- const restLen = rest.length;
244
- if (restLen > 0 && !rest[restLen - 1]) {
245
- rest.pop();
246
- }
247
- return [root, ...rest];
108
+ /**
109
+ * Convert Windows backslash paths to slash paths: foo\\bar ➔ foo/bar
110
+ * Forward-slash paths can be used in Windows as long as they're not
111
+ * extended-length paths and don't contain any non-ascii characters.
112
+ * This was created since the path methods in Node.js outputs \\ paths on Windows.
113
+ * @param path the Windows-based path to convert
114
+ * @returns the converted path
115
+ */
116
+ const normalizePath = (path) => {
117
+ if (typeof path !== 'string') {
118
+ throw new Error(`invalid path to normalize`);
119
+ }
120
+ path = normalizeSlashes(path.trim());
121
+ const components = pathComponents(path, getRootLength(path));
122
+ const reducedComponents = reducePathComponents(components);
123
+ const rootPart = reducedComponents[0];
124
+ const secondPart = reducedComponents[1];
125
+ const normalized = rootPart + reducedComponents.slice(1).join('/');
126
+ if (normalized === '') {
127
+ return '.';
128
+ }
129
+ if (rootPart === '' &&
130
+ secondPart &&
131
+ path.includes('/') &&
132
+ !secondPart.startsWith('.') &&
133
+ !secondPart.startsWith('@')) {
134
+ return './' + normalized;
135
+ }
136
+ return normalized;
137
+ };
138
+ const normalizeSlashes = (path) => path.replace(backslashRegExp, '/');
139
+ const altDirectorySeparator = '\\';
140
+ const urlSchemeSeparator = '://';
141
+ const backslashRegExp = /\\/g;
142
+ const reducePathComponents = (components) => {
143
+ if (!Array.isArray(components) || components.length === 0) {
144
+ return [];
145
+ }
146
+ const reduced = [components[0]];
147
+ for (let i = 1; i < components.length; i++) {
148
+ const component = components[i];
149
+ if (!component)
150
+ continue;
151
+ if (component === '.')
152
+ continue;
153
+ if (component === '..') {
154
+ if (reduced.length > 1) {
155
+ if (reduced[reduced.length - 1] !== '..') {
156
+ reduced.pop();
157
+ continue;
158
+ }
159
+ }
160
+ else if (reduced[0])
161
+ continue;
162
+ }
163
+ reduced.push(component);
164
+ }
165
+ return reduced;
166
+ };
167
+ const getRootLength = (path) => {
168
+ const rootLength = getEncodedRootLength(path);
169
+ return rootLength < 0 ? ~rootLength : rootLength;
170
+ };
171
+ const getEncodedRootLength = (path) => {
172
+ if (!path)
173
+ return 0;
174
+ const ch0 = path.charCodeAt(0);
175
+ // POSIX or UNC
176
+ if (ch0 === 47 /* CharacterCodes.slash */ || ch0 === 92 /* CharacterCodes.backslash */) {
177
+ if (path.charCodeAt(1) !== ch0)
178
+ return 1; // POSIX: "/" (or non-normalized "\")
179
+ const p1 = path.indexOf(ch0 === 47 /* CharacterCodes.slash */ ? '/' : altDirectorySeparator, 2);
180
+ if (p1 < 0)
181
+ return path.length; // UNC: "//server" or "\\server"
182
+ return p1 + 1; // UNC: "//server/" or "\\server\"
183
+ }
184
+ // DOS
185
+ if (isVolumeCharacter(ch0) && path.charCodeAt(1) === 58 /* CharacterCodes.colon */) {
186
+ const ch2 = path.charCodeAt(2);
187
+ if (ch2 === 47 /* CharacterCodes.slash */ || ch2 === 92 /* CharacterCodes.backslash */)
188
+ return 3; // DOS: "c:/" or "c:\"
189
+ if (path.length === 2)
190
+ return 2; // DOS: "c:" (but not "c:d")
191
+ }
192
+ // URL
193
+ const schemeEnd = path.indexOf(urlSchemeSeparator);
194
+ if (schemeEnd !== -1) {
195
+ const authorityStart = schemeEnd + urlSchemeSeparator.length;
196
+ const authorityEnd = path.indexOf('/', authorityStart);
197
+ if (authorityEnd !== -1) {
198
+ // URL: "file:///", "file://server/", "file://server/path"
199
+ // For local "file" URLs, include the leading DOS volume (if present).
200
+ // Per https://www.ietf.org/rfc/rfc1738.txt, a host of "" or "localhost" is a
201
+ // special case interpreted as "the machine from which the URL is being interpreted".
202
+ const scheme = path.slice(0, schemeEnd);
203
+ const authority = path.slice(authorityStart, authorityEnd);
204
+ if (scheme === 'file' &&
205
+ (authority === '' || authority === 'localhost') &&
206
+ isVolumeCharacter(path.charCodeAt(authorityEnd + 1))) {
207
+ const volumeSeparatorEnd = getFileUrlVolumeSeparatorEnd(path, authorityEnd + 2);
208
+ if (volumeSeparatorEnd !== -1) {
209
+ if (path.charCodeAt(volumeSeparatorEnd) === 47 /* CharacterCodes.slash */) {
210
+ // URL: "file:///c:/", "file://localhost/c:/", "file:///c%3a/", "file://localhost/c%3a/"
211
+ return ~(volumeSeparatorEnd + 1);
212
+ }
213
+ if (volumeSeparatorEnd === path.length) {
214
+ // URL: "file:///c:", "file://localhost/c:", "file:///c$3a", "file://localhost/c%3a"
215
+ // but not "file:///c:d" or "file:///c%3ad"
216
+ return ~volumeSeparatorEnd;
217
+ }
218
+ }
219
+ }
220
+ return ~(authorityEnd + 1); // URL: "file://server/", "http://server/"
221
+ }
222
+ return ~path.length; // URL: "file://server", "http://server"
223
+ }
224
+ // relative
225
+ return 0;
226
+ };
227
+ const isVolumeCharacter = (charCode) => (charCode >= 97 /* CharacterCodes.a */ && charCode <= 122 /* CharacterCodes.z */) ||
228
+ (charCode >= 65 /* CharacterCodes.A */ && charCode <= 90 /* CharacterCodes.Z */);
229
+ const getFileUrlVolumeSeparatorEnd = (url, start) => {
230
+ const ch0 = url.charCodeAt(start);
231
+ if (ch0 === 58 /* CharacterCodes.colon */)
232
+ return start + 1;
233
+ if (ch0 === 37 /* CharacterCodes.percent */ && url.charCodeAt(start + 1) === 51 /* CharacterCodes._3 */) {
234
+ const ch2 = url.charCodeAt(start + 2);
235
+ if (ch2 === 97 /* CharacterCodes.a */ || ch2 === 65 /* CharacterCodes.A */)
236
+ return start + 3;
237
+ }
238
+ return -1;
239
+ };
240
+ const pathComponents = (path, rootLength) => {
241
+ const root = path.substring(0, rootLength);
242
+ const rest = path.substring(rootLength).split('/');
243
+ const restLen = rest.length;
244
+ if (restLen > 0 && !rest[restLen - 1]) {
245
+ rest.pop();
246
+ }
247
+ return [root, ...rest];
248
248
  };
249
249
 
250
- const DEV_SERVER_URL = '/~dev-server';
251
- const DEV_MODULE_URL = '/~dev-module';
252
- const DEV_SERVER_INIT_URL = `${DEV_SERVER_URL}-init`;
250
+ const DEV_SERVER_URL = '/~dev-server';
251
+ const DEV_MODULE_URL = '/~dev-module';
252
+ const DEV_SERVER_INIT_URL = `${DEV_SERVER_URL}-init`;
253
253
  const OPEN_IN_EDITOR_URL = `${DEV_SERVER_URL}-open-in-editor`;
254
254
 
255
- const version = '3.0.1';
255
+ const version = '3.1.0';
256
256
 
257
257
  const contentTypes = {"123":"application/vnd.lotus-1-2-3","1km":"application/vnd.1000minds.decision-model+xml","3dml":"text/vnd.in3d.3dml","3ds":"image/x-3ds","3g2":"video/3gpp2","3gp":"video/3gpp","3gpp":"video/3gpp","3mf":"model/3mf","7z":"application/x-7z-compressed","aab":"application/x-authorware-bin","aac":"audio/x-aac","aam":"application/x-authorware-map","aas":"application/x-authorware-seg","abw":"application/x-abiword","ac":"application/vnd.nokia.n-gage.ac+xml","acc":"application/vnd.americandynamics.acc","ace":"application/x-ace-compressed","acu":"application/vnd.acucobol","acutc":"application/vnd.acucorp","adp":"audio/adpcm","aep":"application/vnd.audiograph","afm":"application/x-font-type1","afp":"application/vnd.ibm.modcap","age":"application/vnd.age","ahead":"application/vnd.ahead.space","ai":"application/postscript","aif":"audio/x-aiff","aifc":"audio/x-aiff","aiff":"audio/x-aiff","air":"application/vnd.adobe.air-application-installer-package+zip","ait":"application/vnd.dvb.ait","ami":"application/vnd.amiga.ami","amr":"audio/amr","apk":"application/vnd.android.package-archive","apng":"image/apng","appcache":"text/cache-manifest","application":"application/x-ms-application","apr":"application/vnd.lotus-approach","arc":"application/x-freearc","arj":"application/x-arj","asc":"application/pgp-signature","asf":"video/x-ms-asf","asm":"text/x-asm","aso":"application/vnd.accpac.simply.aso","asx":"video/x-ms-asf","atc":"application/vnd.acucorp","atom":"application/atom+xml","atomcat":"application/atomcat+xml","atomdeleted":"application/atomdeleted+xml","atomsvc":"application/atomsvc+xml","atx":"application/vnd.antix.game-component","au":"audio/basic","avci":"image/avci","avcs":"image/avcs","avi":"video/x-msvideo","avif":"image/avif","aw":"application/applixware","azf":"application/vnd.airzip.filesecure.azf","azs":"application/vnd.airzip.filesecure.azs","azv":"image/vnd.airzip.accelerator.azv","azw":"application/vnd.amazon.ebook","b16":"image/vnd.pco.b16","bat":"application/x-msdownload","bcpio":"application/x-bcpio","bdf":"application/x-font-bdf","bdm":"application/vnd.syncml.dm+wbxml","bdoc":"application/x-bdoc","bed":"application/vnd.realvnc.bed","bh2":"application/vnd.fujitsu.oasysprs","bin":"application/octet-stream","blb":"application/x-blorb","blorb":"application/x-blorb","bmi":"application/vnd.bmi","bmml":"application/vnd.balsamiq.bmml+xml","bmp":"image/x-ms-bmp","book":"application/vnd.framemaker","box":"application/vnd.previewsystems.box","boz":"application/x-bzip2","bpk":"application/octet-stream","bsp":"model/vnd.valve.source.compiled-map","btif":"image/prs.btif","buffer":"application/octet-stream","bz":"application/x-bzip","bz2":"application/x-bzip2","c":"text/x-c","c11amc":"application/vnd.cluetrust.cartomobile-config","c11amz":"application/vnd.cluetrust.cartomobile-config-pkg","c4d":"application/vnd.clonk.c4group","c4f":"application/vnd.clonk.c4group","c4g":"application/vnd.clonk.c4group","c4p":"application/vnd.clonk.c4group","c4u":"application/vnd.clonk.c4group","cab":"application/vnd.ms-cab-compressed","caf":"audio/x-caf","cap":"application/vnd.tcpdump.pcap","car":"application/vnd.curl.car","cat":"application/vnd.ms-pki.seccat","cb7":"application/x-cbr","cba":"application/x-cbr","cbr":"application/x-cbr","cbt":"application/x-cbr","cbz":"application/x-cbr","cc":"text/x-c","cco":"application/x-cocoa","cct":"application/x-director","ccxml":"application/ccxml+xml","cdbcmsg":"application/vnd.contact.cmsg","cdf":"application/x-netcdf","cdfx":"application/cdfx+xml","cdkey":"application/vnd.mediastation.cdkey","cdmia":"application/cdmi-capability","cdmic":"application/cdmi-container","cdmid":"application/cdmi-domain","cdmio":"application/cdmi-object","cdmiq":"application/cdmi-queue","cdx":"chemical/x-cdx","cdxml":"application/vnd.chemdraw+xml","cdy":"application/vnd.cinderella","cer":"application/pkix-cert","cfs":"application/x-cfs-compressed","cgm":"image/cgm","chat":"application/x-chat","chm":"application/vnd.ms-htmlhelp","chrt":"application/vnd.kde.kchart","cif":"chemical/x-cif","cii":"application/vnd.anser-web-certificate-issue-initiation","cil":"application/vnd.ms-artgalry","cjs":"application/node","cla":"application/vnd.claymore","class":"application/java-vm","clkk":"application/vnd.crick.clicker.keyboard","clkp":"application/vnd.crick.clicker.palette","clkt":"application/vnd.crick.clicker.template","clkw":"application/vnd.crick.clicker.wordbank","clkx":"application/vnd.crick.clicker","clp":"application/x-msclip","cmc":"application/vnd.cosmocaller","cmdf":"chemical/x-cmdf","cml":"chemical/x-cml","cmp":"application/vnd.yellowriver-custom-menu","cmx":"image/x-cmx","cod":"application/vnd.rim.cod","coffee":"text/coffeescript","com":"application/x-msdownload","conf":"text/plain","cpio":"application/x-cpio","cpl":"application/cpl+xml","cpp":"text/x-c","cpt":"application/mac-compactpro","crd":"application/x-mscardfile","crl":"application/pkix-crl","crt":"application/x-x509-ca-cert","crx":"application/x-chrome-extension","cryptonote":"application/vnd.rig.cryptonote","csh":"application/x-csh","csl":"application/vnd.citationstyles.style+xml","csml":"chemical/x-csml","csp":"application/vnd.commonspace","css":"text/css","cst":"application/x-director","csv":"text/csv","cu":"application/cu-seeme","curl":"text/vnd.curl","cww":"application/prs.cww","cxt":"application/x-director","cxx":"text/x-c","dae":"model/vnd.collada+xml","daf":"application/vnd.mobius.daf","dart":"application/vnd.dart","dataless":"application/vnd.fdsn.seed","davmount":"application/davmount+xml","dbf":"application/vnd.dbf","dbk":"application/docbook+xml","dcr":"application/x-director","dcurl":"text/vnd.curl.dcurl","dd2":"application/vnd.oma.dd2+xml","ddd":"application/vnd.fujixerox.ddd","ddf":"application/vnd.syncml.dmddf+xml","dds":"image/vnd.ms-dds","deb":"application/x-debian-package","def":"text/plain","deploy":"application/octet-stream","der":"application/x-x509-ca-cert","dfac":"application/vnd.dreamfactory","dgc":"application/x-dgc-compressed","dic":"text/x-c","dir":"application/x-director","dis":"application/vnd.mobius.dis","disposition-notification":"message/disposition-notification","dist":"application/octet-stream","distz":"application/octet-stream","djv":"image/vnd.djvu","djvu":"image/vnd.djvu","dll":"application/x-msdownload","dmg":"application/x-apple-diskimage","dmp":"application/vnd.tcpdump.pcap","dms":"application/octet-stream","dna":"application/vnd.dna","doc":"application/msword","docm":"application/vnd.ms-word.document.macroenabled.12","docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document","dot":"application/msword","dotm":"application/vnd.ms-word.template.macroenabled.12","dotx":"application/vnd.openxmlformats-officedocument.wordprocessingml.template","dp":"application/vnd.osgi.dp","dpg":"application/vnd.dpgraph","dra":"audio/vnd.dra","drle":"image/dicom-rle","dsc":"text/prs.lines.tag","dssc":"application/dssc+der","dtb":"application/x-dtbook+xml","dtd":"application/xml-dtd","dts":"audio/vnd.dts","dtshd":"audio/vnd.dts.hd","dump":"application/octet-stream","dvb":"video/vnd.dvb.file","dvi":"application/x-dvi","dwd":"application/atsc-dwd+xml","dwf":"model/vnd.dwf","dwg":"image/vnd.dwg","dxf":"image/vnd.dxf","dxp":"application/vnd.spotfire.dxp","dxr":"application/x-director","ear":"application/java-archive","ecelp4800":"audio/vnd.nuera.ecelp4800","ecelp7470":"audio/vnd.nuera.ecelp7470","ecelp9600":"audio/vnd.nuera.ecelp9600","ecma":"application/ecmascript","edm":"application/vnd.novadigm.edm","edx":"application/vnd.novadigm.edx","efif":"application/vnd.picsel","ei6":"application/vnd.pg.osasli","elc":"application/octet-stream","emf":"image/emf","eml":"message/rfc822","emma":"application/emma+xml","emotionml":"application/emotionml+xml","emz":"application/x-msmetafile","eol":"audio/vnd.digital-winds","eot":"application/vnd.ms-fontobject","eps":"application/postscript","epub":"application/epub+zip","es":"application/ecmascript","es3":"application/vnd.eszigno3+xml","esa":"application/vnd.osgi.subsystem","esf":"application/vnd.epson.esf","et3":"application/vnd.eszigno3+xml","etx":"text/x-setext","eva":"application/x-eva","evy":"application/x-envoy","exe":"application/x-msdownload","exi":"application/exi","exp":"application/express","exr":"image/aces","ext":"application/vnd.novadigm.ext","ez":"application/andrew-inset","ez2":"application/vnd.ezpix-album","ez3":"application/vnd.ezpix-package","f":"text/x-fortran","f4v":"video/x-f4v","f77":"text/x-fortran","f90":"text/x-fortran","fbs":"image/vnd.fastbidsheet","fcdt":"application/vnd.adobe.formscentral.fcdt","fcs":"application/vnd.isac.fcs","fdf":"application/vnd.fdf","fdt":"application/fdt+xml","fe_launch":"application/vnd.denovo.fcselayout-link","fg5":"application/vnd.fujitsu.oasysgp","fgd":"application/x-director","fh":"image/x-freehand","fh4":"image/x-freehand","fh5":"image/x-freehand","fh7":"image/x-freehand","fhc":"image/x-freehand","fig":"application/x-xfig","fits":"image/fits","flac":"audio/x-flac","fli":"video/x-fli","flo":"application/vnd.micrografx.flo","flv":"video/x-flv","flw":"application/vnd.kde.kivio","flx":"text/vnd.fmi.flexstor","fly":"text/vnd.fly","fm":"application/vnd.framemaker","fnc":"application/vnd.frogans.fnc","fo":"application/vnd.software602.filler.form+xml","for":"text/x-fortran","fpx":"image/vnd.fpx","frame":"application/vnd.framemaker","fsc":"application/vnd.fsc.weblaunch","fst":"image/vnd.fst","ftc":"application/vnd.fluxtime.clip","fti":"application/vnd.anser-web-funds-transfer-initiation","fvt":"video/vnd.fvt","fxp":"application/vnd.adobe.fxp","fxpl":"application/vnd.adobe.fxp","fzs":"application/vnd.fuzzysheet","g2w":"application/vnd.geoplan","g3":"image/g3fax","g3w":"application/vnd.geospace","gac":"application/vnd.groove-account","gam":"application/x-tads","gbr":"application/rpki-ghostbusters","gca":"application/x-gca-compressed","gdl":"model/vnd.gdl","gdoc":"application/vnd.google-apps.document","ged":"text/vnd.familysearch.gedcom","geo":"application/vnd.dynageo","geojson":"application/geo+json","gex":"application/vnd.geometry-explorer","ggb":"application/vnd.geogebra.file","ggt":"application/vnd.geogebra.tool","ghf":"application/vnd.groove-help","gif":"image/gif","gim":"application/vnd.groove-identity-message","glb":"model/gltf-binary","gltf":"model/gltf+json","gml":"application/gml+xml","gmx":"application/vnd.gmx","gnumeric":"application/x-gnumeric","gph":"application/vnd.flographit","gpx":"application/gpx+xml","gqf":"application/vnd.grafeq","gqs":"application/vnd.grafeq","gram":"application/srgs","gramps":"application/x-gramps-xml","gre":"application/vnd.geometry-explorer","grv":"application/vnd.groove-injector","grxml":"application/srgs+xml","gsf":"application/x-font-ghostscript","gsheet":"application/vnd.google-apps.spreadsheet","gslides":"application/vnd.google-apps.presentation","gtar":"application/x-gtar","gtm":"application/vnd.groove-tool-message","gtw":"model/vnd.gtw","gv":"text/vnd.graphviz","gxf":"application/gxf","gxt":"application/vnd.geonext","gz":"application/gzip","h":"text/x-c","h261":"video/h261","h263":"video/h263","h264":"video/h264","hal":"application/vnd.hal+xml","hbci":"application/vnd.hbci","hbs":"text/x-handlebars-template","hdd":"application/x-virtualbox-hdd","hdf":"application/x-hdf","heic":"image/heic","heics":"image/heic-sequence","heif":"image/heif","heifs":"image/heif-sequence","hej2":"image/hej2k","held":"application/atsc-held+xml","hh":"text/x-c","hjson":"application/hjson","hlp":"application/winhlp","hpgl":"application/vnd.hp-hpgl","hpid":"application/vnd.hp-hpid","hps":"application/vnd.hp-hps","hqx":"application/mac-binhex40","hsj2":"image/hsj2","htc":"text/x-component","htke":"application/vnd.kenameaapp","htm":"text/html","html":"text/html","hvd":"application/vnd.yamaha.hv-dic","hvp":"application/vnd.yamaha.hv-voice","hvs":"application/vnd.yamaha.hv-script","i2g":"application/vnd.intergeo","icc":"application/vnd.iccprofile","ice":"x-conference/x-cooltalk","icm":"application/vnd.iccprofile","ico":"image/x-icon","ics":"text/calendar","ief":"image/ief","ifb":"text/calendar","ifm":"application/vnd.shana.informed.formdata","iges":"model/iges","igl":"application/vnd.igloader","igm":"application/vnd.insors.igm","igs":"model/iges","igx":"application/vnd.micrografx.igx","iif":"application/vnd.shana.informed.interchange","img":"application/octet-stream","imp":"application/vnd.accpac.simply.imp","ims":"application/vnd.ms-ims","in":"text/plain","ini":"text/plain","ink":"application/inkml+xml","inkml":"application/inkml+xml","install":"application/x-install-instructions","iota":"application/vnd.astraea-software.iota","ipfix":"application/ipfix","ipk":"application/vnd.shana.informed.package","irm":"application/vnd.ibm.rights-management","irp":"application/vnd.irepository.package+xml","iso":"application/x-iso9660-image","itp":"application/vnd.shana.informed.formtemplate","its":"application/its+xml","ivp":"application/vnd.immervision-ivp","ivu":"application/vnd.immervision-ivu","jad":"text/vnd.sun.j2me.app-descriptor","jade":"text/jade","jam":"application/vnd.jam","jar":"application/java-archive","jardiff":"application/x-java-archive-diff","java":"text/x-java-source","jhc":"image/jphc","jisp":"application/vnd.jisp","jls":"image/jls","jlt":"application/vnd.hp-jlyt","jng":"image/x-jng","jnlp":"application/x-java-jnlp-file","joda":"application/vnd.joost.joda-archive","jp2":"image/jp2","jpe":"image/jpeg","jpeg":"image/jpeg","jpf":"image/jpx","jpg":"image/jpeg","jpg2":"image/jp2","jpgm":"video/jpm","jpgv":"video/jpeg","jph":"image/jph","jpm":"video/jpm","jpx":"image/jpx","js":"application/javascript","json":"application/json","json5":"application/json5","jsonld":"application/ld+json","jsonml":"application/jsonml+json","jsx":"text/jsx","jxr":"image/jxr","jxra":"image/jxra","jxrs":"image/jxrs","jxs":"image/jxs","jxsc":"image/jxsc","jxsi":"image/jxsi","jxss":"image/jxss","kar":"audio/midi","karbon":"application/vnd.kde.karbon","kdbx":"application/x-keepass2","key":"application/x-iwork-keynote-sffkey","kfo":"application/vnd.kde.kformula","kia":"application/vnd.kidspiration","kml":"application/vnd.google-earth.kml+xml","kmz":"application/vnd.google-earth.kmz","kne":"application/vnd.kinar","knp":"application/vnd.kinar","kon":"application/vnd.kde.kontour","kpr":"application/vnd.kde.kpresenter","kpt":"application/vnd.kde.kpresenter","kpxx":"application/vnd.ds-keypoint","ksp":"application/vnd.kde.kspread","ktr":"application/vnd.kahootz","ktx":"image/ktx","ktx2":"image/ktx2","ktz":"application/vnd.kahootz","kwd":"application/vnd.kde.kword","kwt":"application/vnd.kde.kword","lasxml":"application/vnd.las.las+xml","latex":"application/x-latex","lbd":"application/vnd.llamagraphics.life-balance.desktop","lbe":"application/vnd.llamagraphics.life-balance.exchange+xml","les":"application/vnd.hhe.lesson-player","less":"text/less","lgr":"application/lgr+xml","lha":"application/x-lzh-compressed","link66":"application/vnd.route66.link66+xml","list":"text/plain","list3820":"application/vnd.ibm.modcap","listafp":"application/vnd.ibm.modcap","litcoffee":"text/coffeescript","lnk":"application/x-ms-shortcut","log":"text/plain","lostxml":"application/lost+xml","lrf":"application/octet-stream","lrm":"application/vnd.ms-lrm","ltf":"application/vnd.frogans.ltf","lua":"text/x-lua","luac":"application/x-lua-bytecode","lvp":"audio/vnd.lucent.voice","lwp":"application/vnd.lotus-wordpro","lzh":"application/x-lzh-compressed","m13":"application/x-msmediaview","m14":"application/x-msmediaview","m1v":"video/mpeg","m21":"application/mp21","m2a":"audio/mpeg","m2v":"video/mpeg","m3a":"audio/mpeg","m3u":"audio/x-mpegurl","m3u8":"application/vnd.apple.mpegurl","m4a":"audio/x-m4a","m4p":"application/mp4","m4s":"video/iso.segment","m4u":"video/vnd.mpegurl","m4v":"video/x-m4v","ma":"application/mathematica","mads":"application/mads+xml","maei":"application/mmt-aei+xml","mag":"application/vnd.ecowin.chart","maker":"application/vnd.framemaker","man":"text/troff","manifest":"text/cache-manifest","map":"application/json","mar":"application/octet-stream","markdown":"text/markdown","mathml":"application/mathml+xml","mb":"application/mathematica","mbk":"application/vnd.mobius.mbk","mbox":"application/mbox","mc1":"application/vnd.medcalcdata","mcd":"application/vnd.mcd","mcurl":"text/vnd.curl.mcurl","md":"text/markdown","mdb":"application/x-msaccess","mdi":"image/vnd.ms-modi","mdx":"text/mdx","me":"text/troff","mesh":"model/mesh","meta4":"application/metalink4+xml","metalink":"application/metalink+xml","mets":"application/mets+xml","mfm":"application/vnd.mfmp","mft":"application/rpki-manifest","mgp":"application/vnd.osgeo.mapguide.package","mgz":"application/vnd.proteus.magazine","mid":"audio/midi","midi":"audio/midi","mie":"application/x-mie","mif":"application/vnd.mif","mime":"message/rfc822","mj2":"video/mj2","mjp2":"video/mj2","mjs":"application/javascript","mk3d":"video/x-matroska","mka":"audio/x-matroska","mkd":"text/x-markdown","mks":"video/x-matroska","mkv":"video/x-matroska","mlp":"application/vnd.dolby.mlp","mmd":"application/vnd.chipnuts.karaoke-mmd","mmf":"application/vnd.smaf","mml":"text/mathml","mmr":"image/vnd.fujixerox.edmics-mmr","mng":"video/x-mng","mny":"application/x-msmoney","mobi":"application/x-mobipocket-ebook","mods":"application/mods+xml","mov":"video/quicktime","movie":"video/x-sgi-movie","mp2":"audio/mpeg","mp21":"application/mp21","mp2a":"audio/mpeg","mp3":"audio/mpeg","mp4":"video/mp4","mp4a":"audio/mp4","mp4s":"application/mp4","mp4v":"video/mp4","mpc":"application/vnd.mophun.certificate","mpd":"application/dash+xml","mpe":"video/mpeg","mpeg":"video/mpeg","mpf":"application/media-policy-dataset+xml","mpg":"video/mpeg","mpg4":"video/mp4","mpga":"audio/mpeg","mpkg":"application/vnd.apple.installer+xml","mpm":"application/vnd.blueice.multipass","mpn":"application/vnd.mophun.application","mpp":"application/vnd.ms-project","mpt":"application/vnd.ms-project","mpy":"application/vnd.ibm.minipay","mqy":"application/vnd.mobius.mqy","mrc":"application/marc","mrcx":"application/marcxml+xml","ms":"text/troff","mscml":"application/mediaservercontrol+xml","mseed":"application/vnd.fdsn.mseed","mseq":"application/vnd.mseq","msf":"application/vnd.epson.msf","msg":"application/vnd.ms-outlook","msh":"model/mesh","msi":"application/x-msdownload","msl":"application/vnd.mobius.msl","msm":"application/octet-stream","msp":"application/octet-stream","msty":"application/vnd.muvee.style","mtl":"model/mtl","mts":"model/vnd.mts","mus":"application/vnd.musician","musd":"application/mmt-usd+xml","musicxml":"application/vnd.recordare.musicxml+xml","mvb":"application/x-msmediaview","mvt":"application/vnd.mapbox-vector-tile","mwf":"application/vnd.mfer","mxf":"application/mxf","mxl":"application/vnd.recordare.musicxml","mxmf":"audio/mobile-xmf","mxml":"application/xv+xml","mxs":"application/vnd.triscape.mxs","mxu":"video/vnd.mpegurl","n-gage":"application/vnd.nokia.n-gage.symbian.install","n3":"text/n3","nb":"application/mathematica","nbp":"application/vnd.wolfram.player","nc":"application/x-netcdf","ncx":"application/x-dtbncx+xml","nfo":"text/x-nfo","ngdat":"application/vnd.nokia.n-gage.data","nitf":"application/vnd.nitf","nlu":"application/vnd.neurolanguage.nlu","nml":"application/vnd.enliven","nnd":"application/vnd.noblenet-directory","nns":"application/vnd.noblenet-sealer","nnw":"application/vnd.noblenet-web","npx":"image/vnd.net-fpx","nq":"application/n-quads","nsc":"application/x-conference","nsf":"application/vnd.lotus-notes","nt":"application/n-triples","ntf":"application/vnd.nitf","numbers":"application/x-iwork-numbers-sffnumbers","nzb":"application/x-nzb","oa2":"application/vnd.fujitsu.oasys2","oa3":"application/vnd.fujitsu.oasys3","oas":"application/vnd.fujitsu.oasys","obd":"application/x-msbinder","obgx":"application/vnd.openblox.game+xml","obj":"model/obj","oda":"application/oda","odb":"application/vnd.oasis.opendocument.database","odc":"application/vnd.oasis.opendocument.chart","odf":"application/vnd.oasis.opendocument.formula","odft":"application/vnd.oasis.opendocument.formula-template","odg":"application/vnd.oasis.opendocument.graphics","odi":"application/vnd.oasis.opendocument.image","odm":"application/vnd.oasis.opendocument.text-master","odp":"application/vnd.oasis.opendocument.presentation","ods":"application/vnd.oasis.opendocument.spreadsheet","odt":"application/vnd.oasis.opendocument.text","oga":"audio/ogg","ogex":"model/vnd.opengex","ogg":"audio/ogg","ogv":"video/ogg","ogx":"application/ogg","omdoc":"application/omdoc+xml","onepkg":"application/onenote","onetmp":"application/onenote","onetoc":"application/onenote","onetoc2":"application/onenote","opf":"application/oebps-package+xml","opml":"text/x-opml","oprc":"application/vnd.palm","opus":"audio/ogg","org":"text/x-org","osf":"application/vnd.yamaha.openscoreformat","osfpvg":"application/vnd.yamaha.openscoreformat.osfpvg+xml","osm":"application/vnd.openstreetmap.data+xml","otc":"application/vnd.oasis.opendocument.chart-template","otf":"font/otf","otg":"application/vnd.oasis.opendocument.graphics-template","oth":"application/vnd.oasis.opendocument.text-web","oti":"application/vnd.oasis.opendocument.image-template","otp":"application/vnd.oasis.opendocument.presentation-template","ots":"application/vnd.oasis.opendocument.spreadsheet-template","ott":"application/vnd.oasis.opendocument.text-template","ova":"application/x-virtualbox-ova","ovf":"application/x-virtualbox-ovf","owl":"application/rdf+xml","oxps":"application/oxps","oxt":"application/vnd.openofficeorg.extension","p":"text/x-pascal","p10":"application/pkcs10","p12":"application/x-pkcs12","p7b":"application/x-pkcs7-certificates","p7c":"application/pkcs7-mime","p7m":"application/pkcs7-mime","p7r":"application/x-pkcs7-certreqresp","p7s":"application/pkcs7-signature","p8":"application/pkcs8","pac":"application/x-ns-proxy-autoconfig","pages":"application/x-iwork-pages-sffpages","pas":"text/x-pascal","paw":"application/vnd.pawaafile","pbd":"application/vnd.powerbuilder6","pbm":"image/x-portable-bitmap","pcap":"application/vnd.tcpdump.pcap","pcf":"application/x-font-pcf","pcl":"application/vnd.hp-pcl","pclxl":"application/vnd.hp-pclxl","pct":"image/x-pict","pcurl":"application/vnd.curl.pcurl","pcx":"image/x-pcx","pdb":"application/x-pilot","pde":"text/x-processing","pdf":"application/pdf","pem":"application/x-x509-ca-cert","pfa":"application/x-font-type1","pfb":"application/x-font-type1","pfm":"application/x-font-type1","pfr":"application/font-tdpfr","pfx":"application/x-pkcs12","pgm":"image/x-portable-graymap","pgn":"application/x-chess-pgn","pgp":"application/pgp-encrypted","php":"application/x-httpd-php","pic":"image/x-pict","pkg":"application/octet-stream","pki":"application/pkixcmp","pkipath":"application/pkix-pkipath","pkpass":"application/vnd.apple.pkpass","pl":"application/x-perl","plb":"application/vnd.3gpp.pic-bw-large","plc":"application/vnd.mobius.plc","plf":"application/vnd.pocketlearn","pls":"application/pls+xml","pm":"application/x-perl","pml":"application/vnd.ctc-posml","png":"image/png","pnm":"image/x-portable-anymap","portpkg":"application/vnd.macports.portpkg","pot":"application/vnd.ms-powerpoint","potm":"application/vnd.ms-powerpoint.template.macroenabled.12","potx":"application/vnd.openxmlformats-officedocument.presentationml.template","ppam":"application/vnd.ms-powerpoint.addin.macroenabled.12","ppd":"application/vnd.cups-ppd","ppm":"image/x-portable-pixmap","pps":"application/vnd.ms-powerpoint","ppsm":"application/vnd.ms-powerpoint.slideshow.macroenabled.12","ppsx":"application/vnd.openxmlformats-officedocument.presentationml.slideshow","ppt":"application/vnd.ms-powerpoint","pptm":"application/vnd.ms-powerpoint.presentation.macroenabled.12","pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation","pqa":"application/vnd.palm","prc":"application/x-pilot","pre":"application/vnd.lotus-freelance","prf":"application/pics-rules","provx":"application/provenance+xml","ps":"application/postscript","psb":"application/vnd.3gpp.pic-bw-small","psd":"image/vnd.adobe.photoshop","psf":"application/x-font-linux-psf","pskcxml":"application/pskc+xml","pti":"image/prs.pti","ptid":"application/vnd.pvi.ptid1","pub":"application/x-mspublisher","pvb":"application/vnd.3gpp.pic-bw-var","pwn":"application/vnd.3m.post-it-notes","pya":"audio/vnd.ms-playready.media.pya","pyv":"video/vnd.ms-playready.media.pyv","qam":"application/vnd.epson.quickanime","qbo":"application/vnd.intu.qbo","qfx":"application/vnd.intu.qfx","qps":"application/vnd.publishare-delta-tree","qt":"video/quicktime","qwd":"application/vnd.quark.quarkxpress","qwt":"application/vnd.quark.quarkxpress","qxb":"application/vnd.quark.quarkxpress","qxd":"application/vnd.quark.quarkxpress","qxl":"application/vnd.quark.quarkxpress","qxt":"application/vnd.quark.quarkxpress","ra":"audio/x-realaudio","ram":"audio/x-pn-realaudio","raml":"application/raml+yaml","rapd":"application/route-apd+xml","rar":"application/x-rar-compressed","ras":"image/x-cmu-raster","rcprofile":"application/vnd.ipunplugged.rcprofile","rdf":"application/rdf+xml","rdz":"application/vnd.data-vision.rdz","relo":"application/p2p-overlay+xml","rep":"application/vnd.businessobjects","res":"application/x-dtbresource+xml","rgb":"image/x-rgb","rif":"application/reginfo+xml","rip":"audio/vnd.rip","ris":"application/x-research-info-systems","rl":"application/resource-lists+xml","rlc":"image/vnd.fujixerox.edmics-rlc","rld":"application/resource-lists-diff+xml","rm":"application/vnd.rn-realmedia","rmi":"audio/midi","rmp":"audio/x-pn-realaudio-plugin","rms":"application/vnd.jcp.javame.midlet-rms","rmvb":"application/vnd.rn-realmedia-vbr","rnc":"application/relax-ng-compact-syntax","rng":"application/xml","roa":"application/rpki-roa","roff":"text/troff","rp9":"application/vnd.cloanto.rp9","rpm":"application/x-redhat-package-manager","rpss":"application/vnd.nokia.radio-presets","rpst":"application/vnd.nokia.radio-preset","rq":"application/sparql-query","rs":"application/rls-services+xml","rsat":"application/atsc-rsat+xml","rsd":"application/rsd+xml","rsheet":"application/urc-ressheet+xml","rss":"application/rss+xml","rtf":"text/rtf","rtx":"text/richtext","run":"application/x-makeself","rusd":"application/route-usd+xml","s":"text/x-asm","s3m":"audio/s3m","saf":"application/vnd.yamaha.smaf-audio","sass":"text/x-sass","sbml":"application/sbml+xml","sc":"application/vnd.ibm.secure-container","scd":"application/x-msschedule","scm":"application/vnd.lotus-screencam","scq":"application/scvp-cv-request","scs":"application/scvp-cv-response","scss":"text/x-scss","scurl":"text/vnd.curl.scurl","sda":"application/vnd.stardivision.draw","sdc":"application/vnd.stardivision.calc","sdd":"application/vnd.stardivision.impress","sdkd":"application/vnd.solent.sdkm+xml","sdkm":"application/vnd.solent.sdkm+xml","sdp":"application/sdp","sdw":"application/vnd.stardivision.writer","sea":"application/x-sea","see":"application/vnd.seemail","seed":"application/vnd.fdsn.seed","sema":"application/vnd.sema","semd":"application/vnd.semd","semf":"application/vnd.semf","senmlx":"application/senml+xml","sensmlx":"application/sensml+xml","ser":"application/java-serialized-object","setpay":"application/set-payment-initiation","setreg":"application/set-registration-initiation","sfd-hdstx":"application/vnd.hydrostatix.sof-data","sfs":"application/vnd.spotfire.sfs","sfv":"text/x-sfv","sgi":"image/sgi","sgl":"application/vnd.stardivision.writer-global","sgm":"text/sgml","sgml":"text/sgml","sh":"application/x-sh","shar":"application/x-shar","shex":"text/shex","shf":"application/shf+xml","shtml":"text/html","sid":"image/x-mrsid-image","sieve":"application/sieve","sig":"application/pgp-signature","sil":"audio/silk","silo":"model/mesh","sis":"application/vnd.symbian.install","sisx":"application/vnd.symbian.install","sit":"application/x-stuffit","sitx":"application/x-stuffitx","siv":"application/sieve","skd":"application/vnd.koan","skm":"application/vnd.koan","skp":"application/vnd.koan","skt":"application/vnd.koan","sldm":"application/vnd.ms-powerpoint.slide.macroenabled.12","sldx":"application/vnd.openxmlformats-officedocument.presentationml.slide","slim":"text/slim","slm":"text/slim","sls":"application/route-s-tsid+xml","slt":"application/vnd.epson.salt","sm":"application/vnd.stepmania.stepchart","smf":"application/vnd.stardivision.math","smi":"application/smil+xml","smil":"application/smil+xml","smv":"video/x-smv","smzip":"application/vnd.stepmania.package","snd":"audio/basic","snf":"application/x-font-snf","so":"application/octet-stream","spc":"application/x-pkcs7-certificates","spdx":"text/spdx","spf":"application/vnd.yamaha.smaf-phrase","spl":"application/x-futuresplash","spot":"text/vnd.in3d.spot","spp":"application/scvp-vp-response","spq":"application/scvp-vp-request","spx":"audio/ogg","sql":"application/x-sql","src":"application/x-wais-source","srt":"application/x-subrip","sru":"application/sru+xml","srx":"application/sparql-results+xml","ssdl":"application/ssdl+xml","sse":"application/vnd.kodak-descriptor","ssf":"application/vnd.epson.ssf","ssml":"application/ssml+xml","st":"application/vnd.sailingtracker.track","stc":"application/vnd.sun.xml.calc.template","std":"application/vnd.sun.xml.draw.template","stf":"application/vnd.wt.stf","sti":"application/vnd.sun.xml.impress.template","stk":"application/hyperstudio","stl":"model/stl","stpx":"model/step+xml","stpxz":"model/step-xml+zip","stpz":"model/step+zip","str":"application/vnd.pg.format","stw":"application/vnd.sun.xml.writer.template","styl":"text/stylus","stylus":"text/stylus","sub":"text/vnd.dvb.subtitle","sus":"application/vnd.sus-calendar","susp":"application/vnd.sus-calendar","sv4cpio":"application/x-sv4cpio","sv4crc":"application/x-sv4crc","svc":"application/vnd.dvb.service","svd":"application/vnd.svd","svg":"image/svg+xml","svgz":"image/svg+xml","swa":"application/x-director","swf":"application/x-shockwave-flash","swi":"application/vnd.aristanetworks.swi","swidtag":"application/swid+xml","sxc":"application/vnd.sun.xml.calc","sxd":"application/vnd.sun.xml.draw","sxg":"application/vnd.sun.xml.writer.global","sxi":"application/vnd.sun.xml.impress","sxm":"application/vnd.sun.xml.math","sxw":"application/vnd.sun.xml.writer","t":"text/troff","t3":"application/x-t3vm-image","t38":"image/t38","taglet":"application/vnd.mynfc","tao":"application/vnd.tao.intent-module-archive","tap":"image/vnd.tencent.tap","tar":"application/x-tar","tcap":"application/vnd.3gpp2.tcap","tcl":"application/x-tcl","td":"application/urc-targetdesc+xml","teacher":"application/vnd.smart.teacher","tei":"application/tei+xml","teicorpus":"application/tei+xml","tex":"application/x-tex","texi":"application/x-texinfo","texinfo":"application/x-texinfo","text":"text/plain","tfi":"application/thraud+xml","tfm":"application/x-tex-tfm","tfx":"image/tiff-fx","tga":"image/x-tga","thmx":"application/vnd.ms-officetheme","tif":"image/tiff","tiff":"image/tiff","tk":"application/x-tcl","tmo":"application/vnd.tmobile-livetv","toml":"application/toml","torrent":"application/x-bittorrent","tpl":"application/vnd.groove-tool-template","tpt":"application/vnd.trid.tpt","tr":"text/troff","tra":"application/vnd.trueapp","trig":"application/trig","trm":"application/x-msterminal","ts":"video/mp2t","tsd":"application/timestamped-data","tsv":"text/tab-separated-values","ttc":"font/collection","ttf":"font/ttf","ttl":"text/turtle","ttml":"application/ttml+xml","twd":"application/vnd.simtech-mindmapper","twds":"application/vnd.simtech-mindmapper","txd":"application/vnd.genomatix.tuxedo","txf":"application/vnd.mobius.txf","txt":"text/plain","u32":"application/x-authorware-bin","u8dsn":"message/global-delivery-status","u8hdr":"message/global-headers","u8mdn":"message/global-disposition-notification","u8msg":"message/global","ubj":"application/ubjson","udeb":"application/x-debian-package","ufd":"application/vnd.ufdl","ufdl":"application/vnd.ufdl","ulx":"application/x-glulx","umj":"application/vnd.umajin","unityweb":"application/vnd.unity","uoml":"application/vnd.uoml+xml","uri":"text/uri-list","uris":"text/uri-list","urls":"text/uri-list","usdz":"model/vnd.usdz+zip","ustar":"application/x-ustar","utz":"application/vnd.uiq.theme","uu":"text/x-uuencode","uva":"audio/vnd.dece.audio","uvd":"application/vnd.dece.data","uvf":"application/vnd.dece.data","uvg":"image/vnd.dece.graphic","uvh":"video/vnd.dece.hd","uvi":"image/vnd.dece.graphic","uvm":"video/vnd.dece.mobile","uvp":"video/vnd.dece.pd","uvs":"video/vnd.dece.sd","uvt":"application/vnd.dece.ttml+xml","uvu":"video/vnd.uvvu.mp4","uvv":"video/vnd.dece.video","uvva":"audio/vnd.dece.audio","uvvd":"application/vnd.dece.data","uvvf":"application/vnd.dece.data","uvvg":"image/vnd.dece.graphic","uvvh":"video/vnd.dece.hd","uvvi":"image/vnd.dece.graphic","uvvm":"video/vnd.dece.mobile","uvvp":"video/vnd.dece.pd","uvvs":"video/vnd.dece.sd","uvvt":"application/vnd.dece.ttml+xml","uvvu":"video/vnd.uvvu.mp4","uvvv":"video/vnd.dece.video","uvvx":"application/vnd.dece.unspecified","uvvz":"application/vnd.dece.zip","uvx":"application/vnd.dece.unspecified","uvz":"application/vnd.dece.zip","vbox":"application/x-virtualbox-vbox","vbox-extpack":"application/x-virtualbox-vbox-extpack","vcard":"text/vcard","vcd":"application/x-cdlink","vcf":"text/x-vcard","vcg":"application/vnd.groove-vcard","vcs":"text/x-vcalendar","vcx":"application/vnd.vcx","vdi":"application/x-virtualbox-vdi","vds":"model/vnd.sap.vds","vhd":"application/x-virtualbox-vhd","vis":"application/vnd.visionary","viv":"video/vnd.vivo","vmdk":"application/x-virtualbox-vmdk","vob":"video/x-ms-vob","vor":"application/vnd.stardivision.writer","vox":"application/x-authorware-bin","vrml":"model/vrml","vsd":"application/vnd.visio","vsf":"application/vnd.vsf","vss":"application/vnd.visio","vst":"application/vnd.visio","vsw":"application/vnd.visio","vtf":"image/vnd.valve.source.texture","vtt":"text/vtt","vtu":"model/vnd.vtu","vxml":"application/voicexml+xml","w3d":"application/x-director","wad":"application/x-doom","wadl":"application/vnd.sun.wadl+xml","war":"application/java-archive","wasm":"application/wasm","wav":"audio/x-wav","wax":"audio/x-ms-wax","wbmp":"image/vnd.wap.wbmp","wbs":"application/vnd.criticaltools.wbs+xml","wbxml":"application/vnd.wap.wbxml","wcm":"application/vnd.ms-works","wdb":"application/vnd.ms-works","wdp":"image/vnd.ms-photo","weba":"audio/webm","webapp":"application/x-web-app-manifest+json","webm":"video/webm","webmanifest":"application/manifest+json","webp":"image/webp","wg":"application/vnd.pmi.widget","wgt":"application/widget","wif":"application/watcherinfo+xml","wks":"application/vnd.ms-works","wm":"video/x-ms-wm","wma":"audio/x-ms-wma","wmd":"application/x-ms-wmd","wmf":"image/wmf","wml":"text/vnd.wap.wml","wmlc":"application/vnd.wap.wmlc","wmls":"text/vnd.wap.wmlscript","wmlsc":"application/vnd.wap.wmlscriptc","wmv":"video/x-ms-wmv","wmx":"video/x-ms-wmx","wmz":"application/x-msmetafile","woff":"font/woff","woff2":"font/woff2","wpd":"application/vnd.wordperfect","wpl":"application/vnd.ms-wpl","wps":"application/vnd.ms-works","wqd":"application/vnd.wqd","wri":"application/x-mswrite","wrl":"model/vrml","wsc":"message/vnd.wfa.wsc","wsdl":"application/wsdl+xml","wspolicy":"application/wspolicy+xml","wtb":"application/vnd.webturbo","wvx":"video/x-ms-wvx","x32":"application/x-authorware-bin","x3d":"model/x3d+xml","x3db":"model/x3d+fastinfoset","x3dbz":"model/x3d+binary","x3dv":"model/x3d-vrml","x3dvz":"model/x3d+vrml","x3dz":"model/x3d+xml","x_b":"model/vnd.parasolid.transmit.binary","x_t":"model/vnd.parasolid.transmit.text","xaml":"application/xaml+xml","xap":"application/x-silverlight-app","xar":"application/vnd.xara","xav":"application/xcap-att+xml","xbap":"application/x-ms-xbap","xbd":"application/vnd.fujixerox.docuworks.binder","xbm":"image/x-xbitmap","xca":"application/xcap-caps+xml","xcs":"application/calendar+xml","xdf":"application/xcap-diff+xml","xdm":"application/vnd.syncml.dm+xml","xdp":"application/vnd.adobe.xdp+xml","xdssc":"application/dssc+xml","xdw":"application/vnd.fujixerox.docuworks","xel":"application/xcap-el+xml","xenc":"application/xenc+xml","xer":"application/patch-ops-error+xml","xfdf":"application/vnd.adobe.xfdf","xfdl":"application/vnd.xfdl","xht":"application/xhtml+xml","xhtml":"application/xhtml+xml","xhvml":"application/xv+xml","xif":"image/vnd.xiff","xla":"application/vnd.ms-excel","xlam":"application/vnd.ms-excel.addin.macroenabled.12","xlc":"application/vnd.ms-excel","xlf":"application/xliff+xml","xlm":"application/vnd.ms-excel","xls":"application/vnd.ms-excel","xlsb":"application/vnd.ms-excel.sheet.binary.macroenabled.12","xlsm":"application/vnd.ms-excel.sheet.macroenabled.12","xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","xlt":"application/vnd.ms-excel","xltm":"application/vnd.ms-excel.template.macroenabled.12","xltx":"application/vnd.openxmlformats-officedocument.spreadsheetml.template","xlw":"application/vnd.ms-excel","xm":"audio/xm","xml":"text/xml","xns":"application/xcap-ns+xml","xo":"application/vnd.olpc-sugar","xop":"application/xop+xml","xpi":"application/x-xpinstall","xpl":"application/xproc+xml","xpm":"image/x-xpixmap","xpr":"application/vnd.is-xpr","xps":"application/vnd.ms-xpsdocument","xpw":"application/vnd.intercon.formnet","xpx":"application/vnd.intercon.formnet","xsd":"application/xml","xsl":"application/xslt+xml","xslt":"application/xslt+xml","xsm":"application/vnd.syncml+xml","xspf":"application/xspf+xml","xul":"application/vnd.mozilla.xul+xml","xvm":"application/xv+xml","xvml":"application/xv+xml","xwd":"image/x-xwindowdump","xyz":"chemical/x-xyz","xz":"application/x-xz","yaml":"text/yaml","yang":"application/yang","yin":"application/yin+xml","yml":"text/yaml","ymp":"text/x-suse-ymp","z1":"application/x-zmachine","z2":"application/x-zmachine","z3":"application/x-zmachine","z4":"application/x-zmachine","z5":"application/x-zmachine","z6":"application/x-zmachine","z7":"application/x-zmachine","z8":"application/x-zmachine","zaz":"application/vnd.zzazz.deck+xml","zip":"application/zip","zir":"application/vnd.zul","zirz":"application/vnd.zul","zmm":"application/vnd.handheld-entertainment+xml"};
258
258
 
259
- function responseHeaders(headers, httpCache = false) {
260
- headers = { ...DEFAULT_HEADERS, ...headers };
261
- if (httpCache) {
262
- headers['cache-control'] = 'max-age=3600';
263
- delete headers['date'];
264
- delete headers['expires'];
265
- }
266
- return headers;
267
- }
268
- const DEFAULT_HEADERS = {
269
- 'cache-control': 'no-cache, no-store, must-revalidate, max-age=0',
270
- expires: '0',
271
- date: 'Wed, 1 Jan 2000 00:00:00 GMT',
272
- server: 'Rindo Dev Server ' + version,
273
- 'access-control-allow-origin': '*',
274
- 'access-control-expose-headers': '*',
275
- };
276
- function getBrowserUrl(protocol, address, port, basePath, pathname) {
277
- address = address === `0.0.0.0` ? `localhost` : address;
278
- const portSuffix = !port || port === 80 || port === 443 ? '' : ':' + port;
279
- let path = basePath;
280
- if (pathname.startsWith('/')) {
281
- pathname = pathname.substring(1);
282
- }
283
- path += pathname;
284
- protocol = protocol.replace(/\:/g, '');
285
- return `${protocol}://${address}${portSuffix}${path}`;
286
- }
287
- function getDevServerClientUrl(devServerConfig, host, protocol) {
288
- let address = devServerConfig.address;
289
- let port = devServerConfig.port;
290
- if (host) {
291
- address = host;
292
- port = null;
293
- }
294
- return getBrowserUrl(protocol !== null && protocol !== void 0 ? protocol : devServerConfig.protocol, address, port, devServerConfig.basePath, DEV_SERVER_URL);
295
- }
296
- function getContentType(filePath) {
297
- const last = filePath.replace(/^.*[/\\]/, '').toLowerCase();
298
- const ext = last.replace(/^.*\./, '').toLowerCase();
299
- const hasPath = last.length < filePath.length;
300
- const hasDot = ext.length < last.length - 1;
301
- return ((hasDot || !hasPath) && contentTypes[ext]) || 'application/octet-stream';
302
- }
303
- function isHtmlFile(filePath) {
304
- filePath = filePath.toLowerCase().trim();
305
- return filePath.endsWith('.html') || filePath.endsWith('.htm');
306
- }
307
- function isCssFile(filePath) {
308
- filePath = filePath.toLowerCase().trim();
309
- return filePath.endsWith('.css');
310
- }
311
- const TXT_EXT = ['css', 'html', 'htm', 'js', 'json', 'svg', 'xml'];
312
- function isSimpleText(filePath) {
313
- const ext = filePath.toLowerCase().trim().split('.').pop();
314
- return TXT_EXT.includes(ext);
315
- }
316
- function isExtensionLessPath(pathname) {
317
- const parts = pathname.split('/');
318
- const lastPart = parts[parts.length - 1];
319
- return !lastPart.includes('.');
320
- }
321
- function isSsrStaticDataPath(pathname) {
322
- const parts = pathname.split('/');
323
- const fileName = parts[parts.length - 1].split('?')[0];
324
- return fileName === 'page.state.json';
325
- }
326
- function getSsrStaticDataPath(req) {
327
- const parts = req.url.href.split('/');
328
- const fileName = parts[parts.length - 1];
329
- const fileNameParts = fileName.split('?');
330
- parts.pop();
331
- let ssrPath = new URL(parts.join('/')).href;
332
- if (!ssrPath.endsWith('/') && req.headers) {
333
- const h = new Headers(req.headers);
334
- if (h.get('referer').endsWith('/')) {
335
- ssrPath += '/';
336
- }
337
- }
338
- return {
339
- ssrPath,
340
- fileName: fileNameParts[0],
341
- hasQueryString: typeof fileNameParts[1] === 'string' && fileNameParts[1].length > 0,
342
- };
343
- }
344
- function isDevClient(pathname) {
345
- return pathname.startsWith(DEV_SERVER_URL);
346
- }
347
- function isDevModule(pathname) {
348
- return pathname.includes(DEV_MODULE_URL);
349
- }
350
- function isOpenInEditor(pathname) {
351
- return pathname === OPEN_IN_EDITOR_URL;
352
- }
353
- function isInitialDevServerLoad(pathname) {
354
- return pathname === DEV_SERVER_INIT_URL;
355
- }
356
- function isDevServerClient(pathname) {
357
- return pathname === DEV_SERVER_URL;
358
- }
359
- function shouldCompress(devServerConfig, req) {
360
- if (!devServerConfig.gzip) {
361
- return false;
362
- }
363
- if (req.method !== 'GET') {
364
- return false;
365
- }
366
- const acceptEncoding = req.headers && req.headers['accept-encoding'];
367
- if (typeof acceptEncoding !== 'string') {
368
- return false;
369
- }
370
- if (!acceptEncoding.includes('gzip')) {
371
- return false;
372
- }
373
- return true;
259
+ function responseHeaders(headers, httpCache = false) {
260
+ headers = { ...DEFAULT_HEADERS, ...headers };
261
+ if (httpCache) {
262
+ headers['cache-control'] = 'max-age=3600';
263
+ delete headers['date'];
264
+ delete headers['expires'];
265
+ }
266
+ return headers;
267
+ }
268
+ const DEFAULT_HEADERS = {
269
+ 'cache-control': 'no-cache, no-store, must-revalidate, max-age=0',
270
+ expires: '0',
271
+ date: 'Wed, 1 Jan 2000 00:00:00 GMT',
272
+ server: 'Rindo Dev Server ' + version,
273
+ 'access-control-allow-origin': '*',
274
+ 'access-control-expose-headers': '*',
275
+ };
276
+ function getBrowserUrl(protocol, address, port, basePath, pathname) {
277
+ address = address === `0.0.0.0` ? `localhost` : address;
278
+ const portSuffix = !port || port === 80 || port === 443 ? '' : ':' + port;
279
+ let path = basePath;
280
+ if (pathname.startsWith('/')) {
281
+ pathname = pathname.substring(1);
282
+ }
283
+ path += pathname;
284
+ protocol = protocol.replace(/\:/g, '');
285
+ return `${protocol}://${address}${portSuffix}${path}`;
286
+ }
287
+ function getDevServerClientUrl(devServerConfig, host, protocol) {
288
+ let address = devServerConfig.address;
289
+ let port = devServerConfig.port;
290
+ if (host) {
291
+ address = host;
292
+ port = null;
293
+ }
294
+ return getBrowserUrl(protocol !== null && protocol !== void 0 ? protocol : devServerConfig.protocol, address, port, devServerConfig.basePath, DEV_SERVER_URL);
295
+ }
296
+ function getContentType(filePath) {
297
+ const last = filePath.replace(/^.*[/\\]/, '').toLowerCase();
298
+ const ext = last.replace(/^.*\./, '').toLowerCase();
299
+ const hasPath = last.length < filePath.length;
300
+ const hasDot = ext.length < last.length - 1;
301
+ return ((hasDot || !hasPath) && contentTypes[ext]) || 'application/octet-stream';
302
+ }
303
+ function isHtmlFile(filePath) {
304
+ filePath = filePath.toLowerCase().trim();
305
+ return filePath.endsWith('.html') || filePath.endsWith('.htm');
306
+ }
307
+ function isCssFile(filePath) {
308
+ filePath = filePath.toLowerCase().trim();
309
+ return filePath.endsWith('.css');
310
+ }
311
+ const TXT_EXT = ['css', 'html', 'htm', 'js', 'json', 'svg', 'xml'];
312
+ function isSimpleText(filePath) {
313
+ const ext = filePath.toLowerCase().trim().split('.').pop();
314
+ return TXT_EXT.includes(ext);
315
+ }
316
+ function isExtensionLessPath(pathname) {
317
+ const parts = pathname.split('/');
318
+ const lastPart = parts[parts.length - 1];
319
+ return !lastPart.includes('.');
320
+ }
321
+ function isSsrStaticDataPath(pathname) {
322
+ const parts = pathname.split('/');
323
+ const fileName = parts[parts.length - 1].split('?')[0];
324
+ return fileName === 'page.state.json';
325
+ }
326
+ function getSsrStaticDataPath(req) {
327
+ const parts = req.url.href.split('/');
328
+ const fileName = parts[parts.length - 1];
329
+ const fileNameParts = fileName.split('?');
330
+ parts.pop();
331
+ let ssrPath = new URL(parts.join('/')).href;
332
+ if (!ssrPath.endsWith('/') && req.headers) {
333
+ const h = new Headers(req.headers);
334
+ if (h.get('referer').endsWith('/')) {
335
+ ssrPath += '/';
336
+ }
337
+ }
338
+ return {
339
+ ssrPath,
340
+ fileName: fileNameParts[0],
341
+ hasQueryString: typeof fileNameParts[1] === 'string' && fileNameParts[1].length > 0,
342
+ };
343
+ }
344
+ function isDevClient(pathname) {
345
+ return pathname.startsWith(DEV_SERVER_URL);
346
+ }
347
+ function isDevModule(pathname) {
348
+ return pathname.includes(DEV_MODULE_URL);
349
+ }
350
+ function isOpenInEditor(pathname) {
351
+ return pathname === OPEN_IN_EDITOR_URL;
352
+ }
353
+ function isInitialDevServerLoad(pathname) {
354
+ return pathname === DEV_SERVER_INIT_URL;
355
+ }
356
+ function isDevServerClient(pathname) {
357
+ return pathname === DEV_SERVER_URL;
358
+ }
359
+ function shouldCompress(devServerConfig, req) {
360
+ if (!devServerConfig.gzip) {
361
+ return false;
362
+ }
363
+ if (req.method !== 'GET') {
364
+ return false;
365
+ }
366
+ const acceptEncoding = req.headers && req.headers['accept-encoding'];
367
+ if (typeof acceptEncoding !== 'string') {
368
+ return false;
369
+ }
370
+ if (!acceptEncoding.includes('gzip')) {
371
+ return false;
372
+ }
373
+ return true;
374
374
  }
375
375
 
376
376
  function createCommonjsModule(fn, basedir, module) {
@@ -476,6 +476,25 @@ const localXdgOpenPath = path__default['default'].join(__dirname, 'xdg-open');
476
476
 
477
477
  const {platform, arch} = process;
478
478
 
479
+ // Podman detection
480
+ const hasContainerEnv = () => {
481
+ try {
482
+ fs.statSync('/run/.containerenv');
483
+ return true;
484
+ } catch {
485
+ return false;
486
+ }
487
+ };
488
+
489
+ let cachedResult;
490
+ function isInsideContainer() {
491
+ if (cachedResult === undefined) {
492
+ cachedResult = hasContainerEnv() || isDocker_1();
493
+ }
494
+
495
+ return cachedResult;
496
+ }
497
+
479
498
  /**
480
499
  Get the mount point for fixed drives in WSL.
481
500
 
@@ -586,7 +605,7 @@ const baseOpen = async options => {
586
605
  if (app) {
587
606
  cliArguments.push('-a', app);
588
607
  }
589
- } else if (platform === 'win32' || (isWsl_1 && !isDocker_1() && !app)) {
608
+ } else if (platform === 'win32' || (isWsl_1 && !isInsideContainer() && !app)) {
590
609
  const mountPoint = await getWslDrivesMountPoint();
591
610
 
592
611
  command = isWsl_1 ?
@@ -780,682 +799,682 @@ open.openApp = openApp;
780
799
 
781
800
  var open_1 = open;
782
801
 
783
- async function openInBrowser(opts) {
784
- // await open(opts.url, { app: ['google chrome', '--auto-open-devtools-for-tabs'] });
785
- await open_1(opts.url);
802
+ async function openInBrowser(opts) {
803
+ // await open(opts.url, { app: ['google chrome', '--auto-open-devtools-for-tabs'] });
804
+ await open_1(opts.url);
786
805
  }
787
806
 
788
- function createServerContext(sys, sendMsg, devServerConfig, buildResultsResolves, compilerRequestResolves) {
789
- const logRequest = (req, status) => {
790
- if (devServerConfig) {
791
- sendMsg({
792
- requestLog: {
793
- method: req.method || '?',
794
- url: req.pathname || '?',
795
- status,
796
- },
797
- });
798
- }
799
- };
800
- const serve500 = (req, res, error, xSource) => {
801
- try {
802
- res.writeHead(500, responseHeaders({
803
- 'content-type': 'text/plain; charset=utf-8',
804
- 'x-source': xSource,
805
- }));
806
- res.write(util__default['default'].inspect(error));
807
- res.end();
808
- logRequest(req, 500);
809
- }
810
- catch (e) {
811
- sendMsg({ error: { message: 'serve500: ' + e } });
812
- }
813
- };
814
- const serve404 = (req, res, xSource, content = null) => {
815
- try {
816
- if (req.pathname === '/favicon.ico') {
817
- const defaultFavicon = path__default['default'].join(devServerConfig.devServerDir, 'static', 'favicon.ico');
818
- res.writeHead(200, responseHeaders({
819
- 'content-type': 'image/x-icon',
820
- 'x-source': `favicon: ${xSource}`,
821
- }));
822
- const rs = fs__default$1['default'].createReadStream(defaultFavicon);
823
- rs.on('error', (err) => {
824
- res.writeHead(404, responseHeaders({
825
- 'content-type': 'text/plain; charset=utf-8',
826
- 'x-source': `createReadStream error: ${err}, ${xSource}`,
827
- }));
828
- res.write(util__default['default'].inspect(err));
829
- res.end();
830
- });
831
- rs.pipe(res);
832
- return;
833
- }
834
- if (content == null) {
835
- content = ['404 File Not Found', 'Url: ' + req.pathname, 'File: ' + req.filePath].join('\n');
836
- }
837
- res.writeHead(404, responseHeaders({
838
- 'content-type': 'text/plain; charset=utf-8',
839
- 'x-source': xSource,
840
- }));
841
- res.write(content);
842
- res.end();
843
- logRequest(req, 400);
844
- }
845
- catch (e) {
846
- serve500(req, res, e, xSource);
847
- }
848
- };
849
- const serve302 = (req, res, pathname = null) => {
850
- logRequest(req, 302);
851
- res.writeHead(302, { location: pathname || devServerConfig.basePath || '/' });
852
- res.end();
853
- };
854
- const getBuildResults = () => new Promise((resolve, reject) => {
855
- if (serverCtx.isServerListening) {
856
- buildResultsResolves.push({ resolve, reject });
857
- sendMsg({ requestBuildResults: true });
858
- }
859
- else {
860
- reject('dev server closed');
861
- }
862
- });
863
- const getCompilerRequest = (compilerRequestPath) => new Promise((resolve, reject) => {
864
- if (serverCtx.isServerListening) {
865
- compilerRequestResolves.push({
866
- path: compilerRequestPath,
867
- resolve,
868
- reject,
869
- });
870
- sendMsg({ compilerRequestPath });
871
- }
872
- else {
873
- reject('dev server closed');
874
- }
875
- });
876
- const serverCtx = {
877
- connectorHtml: null,
878
- dirTemplate: null,
879
- getBuildResults,
880
- getCompilerRequest,
881
- isServerListening: false,
882
- logRequest,
883
- prerenderConfig: null,
884
- serve302,
885
- serve404,
886
- serve500,
887
- sys,
888
- };
889
- return serverCtx;
807
+ function createServerContext(sys, sendMsg, devServerConfig, buildResultsResolves, compilerRequestResolves) {
808
+ const logRequest = (req, status) => {
809
+ if (devServerConfig) {
810
+ sendMsg({
811
+ requestLog: {
812
+ method: req.method || '?',
813
+ url: req.pathname || '?',
814
+ status,
815
+ },
816
+ });
817
+ }
818
+ };
819
+ const serve500 = (req, res, error, xSource) => {
820
+ try {
821
+ res.writeHead(500, responseHeaders({
822
+ 'content-type': 'text/plain; charset=utf-8',
823
+ 'x-source': xSource,
824
+ }));
825
+ res.write(util__default['default'].inspect(error));
826
+ res.end();
827
+ logRequest(req, 500);
828
+ }
829
+ catch (e) {
830
+ sendMsg({ error: { message: 'serve500: ' + e } });
831
+ }
832
+ };
833
+ const serve404 = (req, res, xSource, content = null) => {
834
+ try {
835
+ if (req.pathname === '/favicon.ico') {
836
+ const defaultFavicon = path__default['default'].join(devServerConfig.devServerDir, 'static', 'favicon.ico');
837
+ res.writeHead(200, responseHeaders({
838
+ 'content-type': 'image/x-icon',
839
+ 'x-source': `favicon: ${xSource}`,
840
+ }));
841
+ const rs = fs__default$1['default'].createReadStream(defaultFavicon);
842
+ rs.on('error', (err) => {
843
+ res.writeHead(404, responseHeaders({
844
+ 'content-type': 'text/plain; charset=utf-8',
845
+ 'x-source': `createReadStream error: ${err}, ${xSource}`,
846
+ }));
847
+ res.write(util__default['default'].inspect(err));
848
+ res.end();
849
+ });
850
+ rs.pipe(res);
851
+ return;
852
+ }
853
+ if (content == null) {
854
+ content = ['404 File Not Found', 'Url: ' + req.pathname, 'File: ' + req.filePath].join('\n');
855
+ }
856
+ res.writeHead(404, responseHeaders({
857
+ 'content-type': 'text/plain; charset=utf-8',
858
+ 'x-source': xSource,
859
+ }));
860
+ res.write(content);
861
+ res.end();
862
+ logRequest(req, 400);
863
+ }
864
+ catch (e) {
865
+ serve500(req, res, e, xSource);
866
+ }
867
+ };
868
+ const serve302 = (req, res, pathname = null) => {
869
+ logRequest(req, 302);
870
+ res.writeHead(302, { location: pathname || devServerConfig.basePath || '/' });
871
+ res.end();
872
+ };
873
+ const getBuildResults = () => new Promise((resolve, reject) => {
874
+ if (serverCtx.isServerListening) {
875
+ buildResultsResolves.push({ resolve, reject });
876
+ sendMsg({ requestBuildResults: true });
877
+ }
878
+ else {
879
+ reject('dev server closed');
880
+ }
881
+ });
882
+ const getCompilerRequest = (compilerRequestPath) => new Promise((resolve, reject) => {
883
+ if (serverCtx.isServerListening) {
884
+ compilerRequestResolves.push({
885
+ path: compilerRequestPath,
886
+ resolve,
887
+ reject,
888
+ });
889
+ sendMsg({ compilerRequestPath });
890
+ }
891
+ else {
892
+ reject('dev server closed');
893
+ }
894
+ });
895
+ const serverCtx = {
896
+ connectorHtml: null,
897
+ dirTemplate: null,
898
+ getBuildResults,
899
+ getCompilerRequest,
900
+ isServerListening: false,
901
+ logRequest,
902
+ prerenderConfig: null,
903
+ serve302,
904
+ serve404,
905
+ serve500,
906
+ sys,
907
+ };
908
+ return serverCtx;
890
909
  }
891
910
 
892
- async function serveOpenInEditor(serverCtx, req, res) {
893
- let status = 200;
894
- const data = {};
895
- try {
896
- const editors = await getEditors();
897
- if (editors.length > 0) {
898
- await parseData(editors, serverCtx.sys, req, data);
899
- await openDataInEditor(data);
900
- }
901
- else {
902
- data.error = `no editors available`;
903
- }
904
- }
905
- catch (e) {
906
- data.error = e + '';
907
- status = 500;
908
- }
909
- serverCtx.logRequest(req, status);
910
- res.writeHead(status, responseHeaders({
911
- 'content-type': 'application/json; charset=utf-8',
912
- }));
913
- res.write(JSON.stringify(data, null, 2));
914
- res.end();
915
- }
916
- async function parseData(editors, sys, req, data) {
917
- const qs = req.searchParams;
918
- if (!qs.has('file')) {
919
- data.error = `missing file`;
920
- return;
921
- }
922
- data.file = qs.get('file');
923
- if (qs.has('line') && !isNaN(qs.get('line'))) {
924
- data.line = parseInt(qs.get('line'), 10);
925
- }
926
- if (typeof data.line !== 'number' || data.line < 1) {
927
- data.line = 1;
928
- }
929
- if (qs.has('column') && !isNaN(qs.get('column'))) {
930
- data.column = parseInt(qs.get('column'), 10);
931
- }
932
- if (typeof data.column !== 'number' || data.column < 1) {
933
- data.column = 1;
934
- }
935
- let editor = qs.get('editor');
936
- if (typeof editor === 'string') {
937
- editor = editor.trim().toLowerCase();
938
- if (editors.some((e) => e.id === editor)) {
939
- data.editor = editor;
940
- }
941
- else {
942
- data.error = `invalid editor: ${editor}`;
943
- return;
944
- }
945
- }
946
- else {
947
- data.editor = editors[0].id;
948
- }
949
- const stat = await sys.stat(data.file);
950
- data.exists = stat.isFile;
951
- }
952
- async function openDataInEditor(data) {
953
- if (!data.exists || data.error) {
954
- return;
955
- }
956
- try {
957
- const opts = {
958
- editor: data.editor,
959
- };
960
- const editor = openInEditorApi__default['default'].configure(opts, (err) => (data.error = err + ''));
961
- if (data.error) {
962
- return;
963
- }
964
- data.open = `${data.file}:${data.line}:${data.column}`;
965
- await editor.open(data.open);
966
- }
967
- catch (e) {
968
- data.error = e + '';
969
- }
970
- }
971
- let editors = null;
972
- function getEditors() {
973
- if (!editors) {
974
- editors = new Promise(async (resolve) => {
975
- const editors = [];
976
- try {
977
- await Promise.all(Object.keys(openInEditorApi__default['default'].editors).map(async (editorId) => {
978
- const isSupported = await isEditorSupported(editorId);
979
- editors.push({
980
- id: editorId,
981
- priority: EDITOR_PRIORITY[editorId],
982
- supported: isSupported,
983
- });
984
- }));
985
- }
986
- catch (e) { }
987
- resolve(editors
988
- .filter((e) => e.supported)
989
- .sort((a, b) => {
990
- if (a.priority < b.priority)
991
- return -1;
992
- if (a.priority > b.priority)
993
- return 1;
994
- return 0;
995
- })
996
- .map((e) => {
997
- return {
998
- id: e.id,
999
- name: EDITORS[e.id],
1000
- };
1001
- }));
1002
- });
1003
- }
1004
- return editors;
1005
- }
1006
- async function isEditorSupported(editorId) {
1007
- let isSupported = false;
1008
- try {
1009
- await openInEditorApi__default['default'].editors[editorId].detect();
1010
- isSupported = true;
1011
- }
1012
- catch (e) { }
1013
- return isSupported;
1014
- }
1015
- const EDITORS = {
1016
- atom: 'Atom',
1017
- code: 'Code',
1018
- emacs: 'Emacs',
1019
- idea14ce: 'IDEA 14 Community Edition',
1020
- phpstorm: 'PhpStorm',
1021
- sublime: 'Sublime',
1022
- webstorm: 'WebStorm',
1023
- vim: 'Vim',
1024
- visualstudio: 'Visual Studio',
1025
- };
1026
- const EDITOR_PRIORITY = {
1027
- code: 1,
1028
- atom: 2,
1029
- sublime: 3,
1030
- visualstudio: 4,
1031
- idea14ce: 5,
1032
- webstorm: 6,
1033
- phpstorm: 7,
1034
- vim: 8,
1035
- emacs: 9,
911
+ async function serveOpenInEditor(serverCtx, req, res) {
912
+ let status = 200;
913
+ const data = {};
914
+ try {
915
+ const editors = await getEditors();
916
+ if (editors.length > 0) {
917
+ await parseData(editors, serverCtx.sys, req, data);
918
+ await openDataInEditor(data);
919
+ }
920
+ else {
921
+ data.error = `no editors available`;
922
+ }
923
+ }
924
+ catch (e) {
925
+ data.error = e + '';
926
+ status = 500;
927
+ }
928
+ serverCtx.logRequest(req, status);
929
+ res.writeHead(status, responseHeaders({
930
+ 'content-type': 'application/json; charset=utf-8',
931
+ }));
932
+ res.write(JSON.stringify(data, null, 2));
933
+ res.end();
934
+ }
935
+ async function parseData(editors, sys, req, data) {
936
+ const qs = req.searchParams;
937
+ if (!qs.has('file')) {
938
+ data.error = `missing file`;
939
+ return;
940
+ }
941
+ data.file = qs.get('file');
942
+ if (qs.has('line') && !isNaN(qs.get('line'))) {
943
+ data.line = parseInt(qs.get('line'), 10);
944
+ }
945
+ if (typeof data.line !== 'number' || data.line < 1) {
946
+ data.line = 1;
947
+ }
948
+ if (qs.has('column') && !isNaN(qs.get('column'))) {
949
+ data.column = parseInt(qs.get('column'), 10);
950
+ }
951
+ if (typeof data.column !== 'number' || data.column < 1) {
952
+ data.column = 1;
953
+ }
954
+ let editor = qs.get('editor');
955
+ if (typeof editor === 'string') {
956
+ editor = editor.trim().toLowerCase();
957
+ if (editors.some((e) => e.id === editor)) {
958
+ data.editor = editor;
959
+ }
960
+ else {
961
+ data.error = `invalid editor: ${editor}`;
962
+ return;
963
+ }
964
+ }
965
+ else {
966
+ data.editor = editors[0].id;
967
+ }
968
+ const stat = await sys.stat(data.file);
969
+ data.exists = stat.isFile;
970
+ }
971
+ async function openDataInEditor(data) {
972
+ if (!data.exists || data.error) {
973
+ return;
974
+ }
975
+ try {
976
+ const opts = {
977
+ editor: data.editor,
978
+ };
979
+ const editor = openInEditorApi__default['default'].configure(opts, (err) => (data.error = err + ''));
980
+ if (data.error) {
981
+ return;
982
+ }
983
+ data.open = `${data.file}:${data.line}:${data.column}`;
984
+ await editor.open(data.open);
985
+ }
986
+ catch (e) {
987
+ data.error = e + '';
988
+ }
989
+ }
990
+ let editors = null;
991
+ function getEditors() {
992
+ if (!editors) {
993
+ editors = new Promise(async (resolve) => {
994
+ const editors = [];
995
+ try {
996
+ await Promise.all(Object.keys(openInEditorApi__default['default'].editors).map(async (editorId) => {
997
+ const isSupported = await isEditorSupported(editorId);
998
+ editors.push({
999
+ id: editorId,
1000
+ priority: EDITOR_PRIORITY[editorId],
1001
+ supported: isSupported,
1002
+ });
1003
+ }));
1004
+ }
1005
+ catch (e) { }
1006
+ resolve(editors
1007
+ .filter((e) => e.supported)
1008
+ .sort((a, b) => {
1009
+ if (a.priority < b.priority)
1010
+ return -1;
1011
+ if (a.priority > b.priority)
1012
+ return 1;
1013
+ return 0;
1014
+ })
1015
+ .map((e) => {
1016
+ return {
1017
+ id: e.id,
1018
+ name: EDITORS[e.id],
1019
+ };
1020
+ }));
1021
+ });
1022
+ }
1023
+ return editors;
1024
+ }
1025
+ async function isEditorSupported(editorId) {
1026
+ let isSupported = false;
1027
+ try {
1028
+ await openInEditorApi__default['default'].editors[editorId].detect();
1029
+ isSupported = true;
1030
+ }
1031
+ catch (e) { }
1032
+ return isSupported;
1033
+ }
1034
+ const EDITORS = {
1035
+ atom: 'Atom',
1036
+ code: 'Code',
1037
+ emacs: 'Emacs',
1038
+ idea14ce: 'IDEA 14 Community Edition',
1039
+ phpstorm: 'PhpStorm',
1040
+ sublime: 'Sublime',
1041
+ webstorm: 'WebStorm',
1042
+ vim: 'Vim',
1043
+ visualstudio: 'Visual Studio',
1044
+ };
1045
+ const EDITOR_PRIORITY = {
1046
+ code: 1,
1047
+ atom: 2,
1048
+ sublime: 3,
1049
+ visualstudio: 4,
1050
+ idea14ce: 5,
1051
+ webstorm: 6,
1052
+ phpstorm: 7,
1053
+ vim: 8,
1054
+ emacs: 9,
1036
1055
  };
1037
1056
 
1038
- async function serveFile(devServerConfig, serverCtx, req, res) {
1039
- try {
1040
- if (isSimpleText(req.filePath)) {
1041
- // easy text file, use the internal cache
1042
- let content = await serverCtx.sys.readFile(req.filePath, 'utf8');
1043
- if (devServerConfig.websocket && isHtmlFile(req.filePath) && !isDevServerClient(req.pathname)) {
1044
- // auto inject our dev server script
1045
- content = appendDevServerClientScript(devServerConfig, req, content);
1046
- }
1047
- else if (isCssFile(req.filePath)) {
1048
- content = updateStyleUrls(req.url, content);
1049
- }
1050
- if (shouldCompress(devServerConfig, req)) {
1051
- // let's gzip this well known web dev text file
1052
- res.writeHead(200, responseHeaders({
1053
- 'content-type': getContentType(req.filePath) + '; charset=utf-8',
1054
- 'content-encoding': 'gzip',
1055
- vary: 'Accept-Encoding',
1056
- }));
1057
- zlib__namespace.gzip(content, { level: 9 }, (_, data) => {
1058
- res.end(data);
1059
- });
1060
- }
1061
- else {
1062
- // let's not gzip this file
1063
- res.writeHead(200, responseHeaders({
1064
- 'content-type': getContentType(req.filePath) + '; charset=utf-8',
1065
- 'content-length': buffer.Buffer.byteLength(content, 'utf8'),
1066
- }));
1067
- res.write(content);
1068
- res.end();
1069
- }
1070
- }
1071
- else {
1072
- // non-well-known text file or other file, probably best we use a stream
1073
- // but don't bother trying to gzip this file for the dev server
1074
- res.writeHead(200, responseHeaders({
1075
- 'content-type': getContentType(req.filePath),
1076
- 'content-length': req.stats.size,
1077
- }));
1078
- fs__default$1['default'].createReadStream(req.filePath).pipe(res);
1079
- }
1080
- serverCtx.logRequest(req, 200);
1081
- }
1082
- catch (e) {
1083
- serverCtx.serve500(req, res, e, 'serveFile');
1084
- }
1085
- }
1086
- function updateStyleUrls(url, oldCss) {
1087
- const versionId = url.searchParams.get('s-hmr');
1088
- const hmrUrls = url.searchParams.get('s-hmr-urls');
1089
- if (versionId && hmrUrls) {
1090
- hmrUrls.split(',').forEach((hmrUrl) => {
1091
- urlVersionIds.set(hmrUrl, versionId);
1092
- });
1093
- }
1094
- const reg = /url\((['"]?)(.*)\1\)/gi;
1095
- let result;
1096
- let newCss = oldCss;
1097
- while ((result = reg.exec(oldCss)) !== null) {
1098
- const oldUrl = result[2];
1099
- const parsedUrl = new URL(oldUrl, url);
1100
- const fileName = path__default['default'].basename(parsedUrl.pathname);
1101
- const versionId = urlVersionIds.get(fileName);
1102
- if (!versionId) {
1103
- continue;
1104
- }
1105
- parsedUrl.searchParams.set('s-hmr', versionId);
1106
- newCss = newCss.replace(oldUrl, parsedUrl.pathname);
1107
- }
1108
- return newCss;
1109
- }
1110
- const urlVersionIds = new Map();
1111
- function appendDevServerClientScript(devServerConfig, req, content) {
1112
- var _a, _b, _c;
1113
- const devServerClientUrl = getDevServerClientUrl(devServerConfig, (_b = (_a = req.headers) === null || _a === void 0 ? void 0 : _a['x-forwarded-host']) !== null && _b !== void 0 ? _b : req.host, (_c = req.headers) === null || _c === void 0 ? void 0 : _c['x-forwarded-proto']);
1114
- const iframe = `<iframe title="Rindo Dev Server Connector ${version} &#9889;" src="${devServerClientUrl}" style="display:block;width:0;height:0;border:0;visibility:hidden" aria-hidden="true"></iframe>`;
1115
- return appendDevServerClientIframe(content, iframe);
1116
- }
1117
- function appendDevServerClientIframe(content, iframe) {
1118
- if (content.includes('</body>')) {
1119
- return content.replace('</body>', `${iframe}</body>`);
1120
- }
1121
- if (content.includes('</html>')) {
1122
- return content.replace('</html>', `${iframe}</html>`);
1123
- }
1124
- return `${content}${iframe}`;
1057
+ async function serveFile(devServerConfig, serverCtx, req, res) {
1058
+ try {
1059
+ if (isSimpleText(req.filePath)) {
1060
+ // easy text file, use the internal cache
1061
+ let content = await serverCtx.sys.readFile(req.filePath, 'utf8');
1062
+ if (devServerConfig.websocket && isHtmlFile(req.filePath) && !isDevServerClient(req.pathname)) {
1063
+ // auto inject our dev server script
1064
+ content = appendDevServerClientScript(devServerConfig, req, content);
1065
+ }
1066
+ else if (isCssFile(req.filePath)) {
1067
+ content = updateStyleUrls(req.url, content);
1068
+ }
1069
+ if (shouldCompress(devServerConfig, req)) {
1070
+ // let's gzip this well known web dev text file
1071
+ res.writeHead(200, responseHeaders({
1072
+ 'content-type': getContentType(req.filePath) + '; charset=utf-8',
1073
+ 'content-encoding': 'gzip',
1074
+ vary: 'Accept-Encoding',
1075
+ }));
1076
+ zlib__namespace.gzip(content, { level: 9 }, (_, data) => {
1077
+ res.end(data);
1078
+ });
1079
+ }
1080
+ else {
1081
+ // let's not gzip this file
1082
+ res.writeHead(200, responseHeaders({
1083
+ 'content-type': getContentType(req.filePath) + '; charset=utf-8',
1084
+ 'content-length': buffer.Buffer.byteLength(content, 'utf8'),
1085
+ }));
1086
+ res.write(content);
1087
+ res.end();
1088
+ }
1089
+ }
1090
+ else {
1091
+ // non-well-known text file or other file, probably best we use a stream
1092
+ // but don't bother trying to gzip this file for the dev server
1093
+ res.writeHead(200, responseHeaders({
1094
+ 'content-type': getContentType(req.filePath),
1095
+ 'content-length': req.stats.size,
1096
+ }));
1097
+ fs__default$1['default'].createReadStream(req.filePath).pipe(res);
1098
+ }
1099
+ serverCtx.logRequest(req, 200);
1100
+ }
1101
+ catch (e) {
1102
+ serverCtx.serve500(req, res, e, 'serveFile');
1103
+ }
1104
+ }
1105
+ function updateStyleUrls(url, oldCss) {
1106
+ const versionId = url.searchParams.get('s-hmr');
1107
+ const hmrUrls = url.searchParams.get('s-hmr-urls');
1108
+ if (versionId && hmrUrls) {
1109
+ hmrUrls.split(',').forEach((hmrUrl) => {
1110
+ urlVersionIds.set(hmrUrl, versionId);
1111
+ });
1112
+ }
1113
+ const reg = /url\((['"]?)(.*)\1\)/gi;
1114
+ let result;
1115
+ let newCss = oldCss;
1116
+ while ((result = reg.exec(oldCss)) !== null) {
1117
+ const oldUrl = result[2];
1118
+ const parsedUrl = new URL(oldUrl, url);
1119
+ const fileName = path__default['default'].basename(parsedUrl.pathname);
1120
+ const versionId = urlVersionIds.get(fileName);
1121
+ if (!versionId) {
1122
+ continue;
1123
+ }
1124
+ parsedUrl.searchParams.set('s-hmr', versionId);
1125
+ newCss = newCss.replace(oldUrl, parsedUrl.pathname);
1126
+ }
1127
+ return newCss;
1128
+ }
1129
+ const urlVersionIds = new Map();
1130
+ function appendDevServerClientScript(devServerConfig, req, content) {
1131
+ var _a, _b, _c;
1132
+ const devServerClientUrl = getDevServerClientUrl(devServerConfig, (_b = (_a = req.headers) === null || _a === void 0 ? void 0 : _a['x-forwarded-host']) !== null && _b !== void 0 ? _b : req.host, (_c = req.headers) === null || _c === void 0 ? void 0 : _c['x-forwarded-proto']);
1133
+ const iframe = `<iframe title="Rindo Dev Server Connector ${version} &#9889;" src="${devServerClientUrl}" style="display:block;width:0;height:0;border:0;visibility:hidden" aria-hidden="true"></iframe>`;
1134
+ return appendDevServerClientIframe(content, iframe);
1135
+ }
1136
+ function appendDevServerClientIframe(content, iframe) {
1137
+ if (content.includes('</body>')) {
1138
+ return content.replace('</body>', `${iframe}</body>`);
1139
+ }
1140
+ if (content.includes('</html>')) {
1141
+ return content.replace('</html>', `${iframe}</html>`);
1142
+ }
1143
+ return `${content}${iframe}`;
1125
1144
  }
1126
1145
 
1127
- async function serveDevClient(devServerConfig, serverCtx, req, res) {
1128
- try {
1129
- if (isOpenInEditor(req.pathname)) {
1130
- return serveOpenInEditor(serverCtx, req, res);
1131
- }
1132
- if (isDevServerClient(req.pathname)) {
1133
- return serveDevClientScript(devServerConfig, serverCtx, req, res);
1134
- }
1135
- if (isInitialDevServerLoad(req.pathname)) {
1136
- req.filePath = path__default['default'].join(devServerConfig.devServerDir, 'templates', 'initial-load.html');
1137
- }
1138
- else {
1139
- const staticFile = req.pathname.replace(DEV_SERVER_URL + '/', '');
1140
- req.filePath = path__default['default'].join(devServerConfig.devServerDir, 'static', staticFile);
1141
- }
1142
- try {
1143
- req.stats = await serverCtx.sys.stat(req.filePath);
1144
- if (req.stats.isFile) {
1145
- return serveFile(devServerConfig, serverCtx, req, res);
1146
- }
1147
- return serverCtx.serve404(req, res, 'serveDevClient not file');
1148
- }
1149
- catch (e) {
1150
- return serverCtx.serve404(req, res, `serveDevClient stats error ${e}`);
1151
- }
1152
- }
1153
- catch (e) {
1154
- return serverCtx.serve500(req, res, e, 'serveDevClient');
1155
- }
1156
- }
1157
- async function serveDevClientScript(devServerConfig, serverCtx, req, res) {
1158
- try {
1159
- if (serverCtx.connectorHtml == null) {
1160
- const filePath = path__default['default'].join(devServerConfig.devServerDir, 'connector.html');
1161
- serverCtx.connectorHtml = serverCtx.sys.readFileSync(filePath, 'utf8');
1162
- if (typeof serverCtx.connectorHtml !== 'string') {
1163
- return serverCtx.serve404(req, res, `serveDevClientScript`);
1164
- }
1165
- const devClientConfig = {
1166
- basePath: devServerConfig.basePath,
1167
- editors: await getEditors(),
1168
- reloadStrategy: devServerConfig.reloadStrategy,
1169
- };
1170
- serverCtx.connectorHtml = serverCtx.connectorHtml.replace('window.__DEV_CLIENT_CONFIG__', JSON.stringify(devClientConfig));
1171
- }
1172
- res.writeHead(200, responseHeaders({
1173
- 'content-type': 'text/html; charset=utf-8',
1174
- }));
1175
- res.write(serverCtx.connectorHtml);
1176
- res.end();
1177
- }
1178
- catch (e) {
1179
- return serverCtx.serve500(req, res, e, `serveDevClientScript`);
1180
- }
1146
+ async function serveDevClient(devServerConfig, serverCtx, req, res) {
1147
+ try {
1148
+ if (isOpenInEditor(req.pathname)) {
1149
+ return serveOpenInEditor(serverCtx, req, res);
1150
+ }
1151
+ if (isDevServerClient(req.pathname)) {
1152
+ return serveDevClientScript(devServerConfig, serverCtx, req, res);
1153
+ }
1154
+ if (isInitialDevServerLoad(req.pathname)) {
1155
+ req.filePath = path__default['default'].join(devServerConfig.devServerDir, 'templates', 'initial-load.html');
1156
+ }
1157
+ else {
1158
+ const staticFile = req.pathname.replace(DEV_SERVER_URL + '/', '');
1159
+ req.filePath = path__default['default'].join(devServerConfig.devServerDir, 'static', staticFile);
1160
+ }
1161
+ try {
1162
+ req.stats = await serverCtx.sys.stat(req.filePath);
1163
+ if (req.stats.isFile) {
1164
+ return serveFile(devServerConfig, serverCtx, req, res);
1165
+ }
1166
+ return serverCtx.serve404(req, res, 'serveDevClient not file');
1167
+ }
1168
+ catch (e) {
1169
+ return serverCtx.serve404(req, res, `serveDevClient stats error ${e}`);
1170
+ }
1171
+ }
1172
+ catch (e) {
1173
+ return serverCtx.serve500(req, res, e, 'serveDevClient');
1174
+ }
1175
+ }
1176
+ async function serveDevClientScript(devServerConfig, serverCtx, req, res) {
1177
+ try {
1178
+ if (serverCtx.connectorHtml == null) {
1179
+ const filePath = path__default['default'].join(devServerConfig.devServerDir, 'connector.html');
1180
+ serverCtx.connectorHtml = serverCtx.sys.readFileSync(filePath, 'utf8');
1181
+ if (typeof serverCtx.connectorHtml !== 'string') {
1182
+ return serverCtx.serve404(req, res, `serveDevClientScript`);
1183
+ }
1184
+ const devClientConfig = {
1185
+ basePath: devServerConfig.basePath,
1186
+ editors: await getEditors(),
1187
+ reloadStrategy: devServerConfig.reloadStrategy,
1188
+ };
1189
+ serverCtx.connectorHtml = serverCtx.connectorHtml.replace('window.__DEV_CLIENT_CONFIG__', JSON.stringify(devClientConfig));
1190
+ }
1191
+ res.writeHead(200, responseHeaders({
1192
+ 'content-type': 'text/html; charset=utf-8',
1193
+ }));
1194
+ res.write(serverCtx.connectorHtml);
1195
+ res.end();
1196
+ }
1197
+ catch (e) {
1198
+ return serverCtx.serve500(req, res, e, `serveDevClientScript`);
1199
+ }
1181
1200
  }
1182
1201
 
1183
- async function serveDevNodeModule(serverCtx, req, res) {
1184
- try {
1185
- const results = await serverCtx.getCompilerRequest(req.pathname);
1186
- const headers = {
1187
- 'content-type': 'application/javascript; charset=utf-8',
1188
- 'content-length': Buffer.byteLength(results.content, 'utf8'),
1189
- 'x-dev-node-module-id': results.nodeModuleId,
1190
- 'x-dev-node-module-version': results.nodeModuleVersion,
1191
- 'x-dev-node-module-resolved-path': results.nodeResolvedPath,
1192
- 'x-dev-node-module-cache-path': results.cachePath,
1193
- 'x-dev-node-module-cache-hit': results.cacheHit,
1194
- };
1195
- res.writeHead(results.status, responseHeaders(headers));
1196
- res.write(results.content);
1197
- res.end();
1198
- }
1199
- catch (e) {
1200
- serverCtx.serve500(req, res, e, `serveDevNodeModule`);
1201
- }
1202
+ async function serveDevNodeModule(serverCtx, req, res) {
1203
+ try {
1204
+ const results = await serverCtx.getCompilerRequest(req.pathname);
1205
+ const headers = {
1206
+ 'content-type': 'application/javascript; charset=utf-8',
1207
+ 'content-length': Buffer.byteLength(results.content, 'utf8'),
1208
+ 'x-dev-node-module-id': results.nodeModuleId,
1209
+ 'x-dev-node-module-version': results.nodeModuleVersion,
1210
+ 'x-dev-node-module-resolved-path': results.nodeResolvedPath,
1211
+ 'x-dev-node-module-cache-path': results.cachePath,
1212
+ 'x-dev-node-module-cache-hit': results.cacheHit,
1213
+ };
1214
+ res.writeHead(results.status, responseHeaders(headers));
1215
+ res.write(results.content);
1216
+ res.end();
1217
+ }
1218
+ catch (e) {
1219
+ serverCtx.serve500(req, res, e, `serveDevNodeModule`);
1220
+ }
1202
1221
  }
1203
1222
 
1204
- async function serveDirectoryIndex(devServerConfig, serverCtx, req, res) {
1205
- const indexFilePath = path__default['default'].join(req.filePath, 'index.html');
1206
- req.stats = await serverCtx.sys.stat(indexFilePath);
1207
- if (req.stats.isFile) {
1208
- req.filePath = indexFilePath;
1209
- return serveFile(devServerConfig, serverCtx, req, res);
1210
- }
1211
- if (!req.pathname.endsWith('/')) {
1212
- return serverCtx.serve302(req, res, req.pathname + '/');
1213
- }
1214
- try {
1215
- const dirFilePaths = await serverCtx.sys.readDir(req.filePath);
1216
- try {
1217
- if (serverCtx.dirTemplate == null) {
1218
- const dirTemplatePath = path__default['default'].join(devServerConfig.devServerDir, 'templates', 'directory-index.html');
1219
- serverCtx.dirTemplate = serverCtx.sys.readFileSync(dirTemplatePath);
1220
- }
1221
- const files = await getFiles(serverCtx.sys, req.url, dirFilePaths);
1222
- const templateHtml = serverCtx.dirTemplate
1223
- .replace('{{title}}', getTitle(req.pathname))
1224
- .replace('{{nav}}', getName(req.pathname))
1225
- .replace('{{files}}', files);
1226
- serverCtx.logRequest(req, 200);
1227
- res.writeHead(200, responseHeaders({
1228
- 'content-type': 'text/html; charset=utf-8',
1229
- 'x-directory-index': req.pathname,
1230
- }));
1231
- res.write(templateHtml);
1232
- res.end();
1233
- }
1234
- catch (e) {
1235
- return serverCtx.serve500(req, res, e, 'serveDirectoryIndex');
1236
- }
1237
- }
1238
- catch (e) {
1239
- return serverCtx.serve404(req, res, 'serveDirectoryIndex');
1240
- }
1241
- }
1242
- async function getFiles(sys, baseUrl, dirItemNames) {
1243
- const items = await getDirectoryItems(sys, baseUrl, dirItemNames);
1244
- if (baseUrl.pathname !== '/') {
1245
- items.unshift({
1246
- isDirectory: true,
1247
- pathname: '../',
1248
- name: '..',
1249
- });
1250
- }
1251
- return items
1252
- .map((item) => {
1223
+ async function serveDirectoryIndex(devServerConfig, serverCtx, req, res) {
1224
+ const indexFilePath = path__default['default'].join(req.filePath, 'index.html');
1225
+ req.stats = await serverCtx.sys.stat(indexFilePath);
1226
+ if (req.stats.isFile) {
1227
+ req.filePath = indexFilePath;
1228
+ return serveFile(devServerConfig, serverCtx, req, res);
1229
+ }
1230
+ if (!req.pathname.endsWith('/')) {
1231
+ return serverCtx.serve302(req, res, req.pathname + '/');
1232
+ }
1233
+ try {
1234
+ const dirFilePaths = await serverCtx.sys.readDir(req.filePath);
1235
+ try {
1236
+ if (serverCtx.dirTemplate == null) {
1237
+ const dirTemplatePath = path__default['default'].join(devServerConfig.devServerDir, 'templates', 'directory-index.html');
1238
+ serverCtx.dirTemplate = serverCtx.sys.readFileSync(dirTemplatePath);
1239
+ }
1240
+ const files = await getFiles(serverCtx.sys, req.url, dirFilePaths);
1241
+ const templateHtml = serverCtx.dirTemplate
1242
+ .replace('{{title}}', getTitle(req.pathname))
1243
+ .replace('{{nav}}', getName(req.pathname))
1244
+ .replace('{{files}}', files);
1245
+ serverCtx.logRequest(req, 200);
1246
+ res.writeHead(200, responseHeaders({
1247
+ 'content-type': 'text/html; charset=utf-8',
1248
+ 'x-directory-index': req.pathname,
1249
+ }));
1250
+ res.write(templateHtml);
1251
+ res.end();
1252
+ }
1253
+ catch (e) {
1254
+ return serverCtx.serve500(req, res, e, 'serveDirectoryIndex');
1255
+ }
1256
+ }
1257
+ catch (e) {
1258
+ return serverCtx.serve404(req, res, 'serveDirectoryIndex');
1259
+ }
1260
+ }
1261
+ async function getFiles(sys, baseUrl, dirItemNames) {
1262
+ const items = await getDirectoryItems(sys, baseUrl, dirItemNames);
1263
+ if (baseUrl.pathname !== '/') {
1264
+ items.unshift({
1265
+ isDirectory: true,
1266
+ pathname: '../',
1267
+ name: '..',
1268
+ });
1269
+ }
1270
+ return items
1271
+ .map((item) => {
1253
1272
  return `
1254
1273
  <li class="${item.isDirectory ? 'directory' : 'file'}">
1255
1274
  <a href="${item.pathname}">
1256
1275
  <span class="icon"></span>
1257
1276
  <span>${item.name}</span>
1258
1277
  </a>
1259
- </li>`;
1260
- })
1261
- .join('');
1262
- }
1263
- async function getDirectoryItems(sys, baseUrl, dirFilePaths) {
1264
- const items = await Promise.all(dirFilePaths.map(async (dirFilePath) => {
1265
- const fileName = path__default['default'].basename(dirFilePath);
1266
- const url = new URL(fileName, baseUrl);
1267
- const stats = await sys.stat(dirFilePath);
1268
- const item = {
1269
- name: fileName,
1270
- pathname: url.pathname,
1271
- isDirectory: stats.isDirectory,
1272
- };
1273
- return item;
1274
- }));
1275
- return items;
1276
- }
1277
- function getTitle(pathName) {
1278
- return pathName;
1279
- }
1280
- function getName(pathName) {
1281
- const dirs = pathName.split('/');
1282
- dirs.pop();
1283
- let url = '';
1284
- return (dirs
1285
- .map((dir, index) => {
1286
- url += dir + '/';
1287
- const text = index === 0 ? `~` : dir;
1288
- return `<a href="${url}">${text}</a>`;
1289
- })
1290
- .join('<span>/</span>') + '<span>/</span>');
1278
+ </li>`;
1279
+ })
1280
+ .join('');
1281
+ }
1282
+ async function getDirectoryItems(sys, baseUrl, dirFilePaths) {
1283
+ const items = await Promise.all(dirFilePaths.map(async (dirFilePath) => {
1284
+ const fileName = path__default['default'].basename(dirFilePath);
1285
+ const url = new URL(fileName, baseUrl);
1286
+ const stats = await sys.stat(dirFilePath);
1287
+ const item = {
1288
+ name: fileName,
1289
+ pathname: url.pathname,
1290
+ isDirectory: stats.isDirectory,
1291
+ };
1292
+ return item;
1293
+ }));
1294
+ return items;
1295
+ }
1296
+ function getTitle(pathName) {
1297
+ return pathName;
1298
+ }
1299
+ function getName(pathName) {
1300
+ const dirs = pathName.split('/');
1301
+ dirs.pop();
1302
+ let url = '';
1303
+ return (dirs
1304
+ .map((dir, index) => {
1305
+ url += dir + '/';
1306
+ const text = index === 0 ? `~` : dir;
1307
+ return `<a href="${url}">${text}</a>`;
1308
+ })
1309
+ .join('<span>/</span>') + '<span>/</span>');
1291
1310
  }
1292
1311
 
1293
- async function ssrPageRequest(devServerConfig, serverCtx, req, res) {
1294
- try {
1295
- let status = 500;
1296
- let content = '';
1297
- const { hydrateApp, srcIndexHtml, diagnostics } = await setupHydrateApp(devServerConfig, serverCtx);
1298
- if (!diagnostics.some((diagnostic) => diagnostic.level === 'error')) {
1299
- try {
1300
- const opts = getSsrHydrateOptions(devServerConfig, serverCtx, req.url);
1301
- const ssrResults = await hydrateApp.renderToString(srcIndexHtml, opts);
1302
- diagnostics.push(...ssrResults.diagnostics);
1303
- status = ssrResults.httpStatus;
1304
- content = ssrResults.html;
1305
- }
1306
- catch (e) {
1307
- catchError(diagnostics, e);
1308
- }
1309
- }
1310
- if (diagnostics.some((diagnostic) => diagnostic.level === 'error')) {
1311
- content = getSsrErrorContent(diagnostics);
1312
- status = 500;
1313
- }
1314
- if (devServerConfig.websocket) {
1315
- content = appendDevServerClientScript(devServerConfig, req, content);
1316
- }
1317
- serverCtx.logRequest(req, status);
1318
- res.writeHead(status, responseHeaders({
1319
- 'content-type': 'text/html; charset=utf-8',
1320
- 'content-length': Buffer.byteLength(content, 'utf8'),
1321
- }));
1322
- res.write(content);
1323
- res.end();
1324
- }
1325
- catch (e) {
1326
- serverCtx.serve500(req, res, e, `ssrPageRequest`);
1327
- }
1328
- }
1329
- async function ssrStaticDataRequest(devServerConfig, serverCtx, req, res) {
1330
- try {
1331
- const data = {};
1332
- let httpCache = false;
1333
- const { hydrateApp, srcIndexHtml, diagnostics } = await setupHydrateApp(devServerConfig, serverCtx);
1334
- if (!diagnostics.some((diagnostic) => diagnostic.level === 'error')) {
1335
- try {
1336
- const { ssrPath, hasQueryString } = getSsrStaticDataPath(req);
1337
- const url = new URL(ssrPath, req.url);
1338
- const opts = getSsrHydrateOptions(devServerConfig, serverCtx, url);
1339
- const ssrResults = await hydrateApp.renderToString(srcIndexHtml, opts);
1340
- diagnostics.push(...ssrResults.diagnostics);
1341
- ssrResults.staticData.forEach((s) => {
1342
- if (s.type === 'application/json') {
1343
- data[s.id] = JSON.parse(s.content);
1344
- }
1345
- else {
1346
- data[s.id] = s.content;
1347
- }
1348
- });
1349
- data.components = ssrResults.components.map((c) => c.tag).sort();
1350
- httpCache = hasQueryString;
1351
- }
1352
- catch (e) {
1353
- catchError(diagnostics, e);
1354
- }
1355
- }
1356
- if (diagnostics.length > 0) {
1357
- data.diagnostics = diagnostics;
1358
- }
1359
- const status = diagnostics.some((diagnostic) => diagnostic.level === 'error') ? 500 : 200;
1360
- const content = JSON.stringify(data);
1361
- serverCtx.logRequest(req, status);
1362
- res.writeHead(status, responseHeaders({
1363
- 'content-type': 'application/json; charset=utf-8',
1364
- 'content-length': Buffer.byteLength(content, 'utf8'),
1365
- }, httpCache && status === 200));
1366
- res.write(content);
1367
- res.end();
1368
- }
1369
- catch (e) {
1370
- serverCtx.serve500(req, res, e, `ssrStaticDataRequest`);
1371
- }
1372
- }
1373
- async function setupHydrateApp(devServerConfig, serverCtx) {
1374
- let srcIndexHtml = null;
1375
- let hydrateApp = null;
1376
- const buildResults = await serverCtx.getBuildResults();
1377
- const diagnostics = [];
1378
- if (serverCtx.prerenderConfig == null && isString(devServerConfig.prerenderConfig)) {
1379
- const compilerPath = path__default['default'].join(devServerConfig.devServerDir, '..', 'compiler', 'rindo.js');
1380
- const compiler = require(compilerPath);
1381
- const prerenderConfigResults = compiler.nodeRequire(devServerConfig.prerenderConfig);
1382
- diagnostics.push(...prerenderConfigResults.diagnostics);
1383
- if (prerenderConfigResults.module && prerenderConfigResults.module.config) {
1384
- serverCtx.prerenderConfig = prerenderConfigResults.module.config;
1385
- }
1386
- }
1387
- if (!isString(buildResults.hydrateAppFilePath)) {
1388
- diagnostics.push({ messageText: `Missing hydrateAppFilePath`, level: `error`, type: `ssr`, lines: [] });
1389
- }
1390
- else if (!isString(devServerConfig.srcIndexHtml)) {
1391
- diagnostics.push({ messageText: `Missing srcIndexHtml`, level: `error`, type: `ssr`, lines: [] });
1392
- }
1393
- else {
1394
- srcIndexHtml = await serverCtx.sys.readFile(devServerConfig.srcIndexHtml);
1395
- if (!isString(srcIndexHtml)) {
1396
- diagnostics.push({
1397
- level: `error`,
1398
- lines: [],
1399
- messageText: `Unable to load src index html: ${devServerConfig.srcIndexHtml}`,
1400
- type: `ssr`,
1401
- });
1402
- }
1403
- else {
1404
- // ensure we cleared out node's internal require() cache for this file
1405
- const hydrateAppFilePath = path__default['default'].resolve(buildResults.hydrateAppFilePath);
1406
- // brute force way of clearning node's module cache
1407
- // not using `delete require.cache[id]` since it'll cause memory leaks
1408
- require.cache = {};
1409
- const Module = require('module');
1410
- Module._cache[hydrateAppFilePath] = undefined;
1411
- hydrateApp = require(hydrateAppFilePath);
1412
- }
1413
- }
1414
- return {
1415
- hydrateApp,
1416
- srcIndexHtml,
1417
- diagnostics,
1418
- };
1419
- }
1420
- function getSsrHydrateOptions(devServerConfig, serverCtx, url) {
1421
- const opts = {
1422
- url: url.href,
1423
- addModulePreloads: false,
1424
- approximateLineWidth: 120,
1425
- inlineExternalStyleSheets: false,
1426
- minifyScriptElements: false,
1427
- minifyStyleElements: false,
1428
- removeAttributeQuotes: false,
1429
- removeBooleanAttributeQuotes: false,
1430
- removeEmptyAttributes: false,
1431
- removeHtmlComments: false,
1432
- prettyHtml: true,
1433
- };
1434
- const prerenderConfig = serverCtx === null || serverCtx === void 0 ? void 0 : serverCtx.prerenderConfig;
1435
- if (isFunction(prerenderConfig === null || prerenderConfig === void 0 ? void 0 : prerenderConfig.hydrateOptions)) {
1436
- const userOpts = prerenderConfig.hydrateOptions(url);
1437
- if (userOpts) {
1438
- Object.assign(opts, userOpts);
1439
- }
1440
- }
1441
- if (isFunction(serverCtx.sys.applyPrerenderGlobalPatch)) {
1442
- const orgBeforeHydrate = opts.beforeHydrate;
1443
- opts.beforeHydrate = (document) => {
1444
- // patch this new window with the fetch global from node-fetch
1445
- const devServerBaseUrl = new URL(devServerConfig.browserUrl);
1446
- const devServerHostUrl = devServerBaseUrl.origin;
1447
- serverCtx.sys.applyPrerenderGlobalPatch({
1448
- devServerHostUrl: devServerHostUrl,
1449
- window: document.defaultView,
1450
- });
1451
- if (typeof orgBeforeHydrate === 'function') {
1452
- return orgBeforeHydrate(document);
1453
- }
1454
- };
1455
- }
1456
- return opts;
1457
- }
1458
- function getSsrErrorContent(diagnostics) {
1312
+ async function ssrPageRequest(devServerConfig, serverCtx, req, res) {
1313
+ try {
1314
+ let status = 500;
1315
+ let content = '';
1316
+ const { hydrateApp, srcIndexHtml, diagnostics } = await setupHydrateApp(devServerConfig, serverCtx);
1317
+ if (!diagnostics.some((diagnostic) => diagnostic.level === 'error')) {
1318
+ try {
1319
+ const opts = getSsrHydrateOptions(devServerConfig, serverCtx, req.url);
1320
+ const ssrResults = await hydrateApp.renderToString(srcIndexHtml, opts);
1321
+ diagnostics.push(...ssrResults.diagnostics);
1322
+ status = ssrResults.httpStatus;
1323
+ content = ssrResults.html;
1324
+ }
1325
+ catch (e) {
1326
+ catchError(diagnostics, e);
1327
+ }
1328
+ }
1329
+ if (diagnostics.some((diagnostic) => diagnostic.level === 'error')) {
1330
+ content = getSsrErrorContent(diagnostics);
1331
+ status = 500;
1332
+ }
1333
+ if (devServerConfig.websocket) {
1334
+ content = appendDevServerClientScript(devServerConfig, req, content);
1335
+ }
1336
+ serverCtx.logRequest(req, status);
1337
+ res.writeHead(status, responseHeaders({
1338
+ 'content-type': 'text/html; charset=utf-8',
1339
+ 'content-length': Buffer.byteLength(content, 'utf8'),
1340
+ }));
1341
+ res.write(content);
1342
+ res.end();
1343
+ }
1344
+ catch (e) {
1345
+ serverCtx.serve500(req, res, e, `ssrPageRequest`);
1346
+ }
1347
+ }
1348
+ async function ssrStaticDataRequest(devServerConfig, serverCtx, req, res) {
1349
+ try {
1350
+ const data = {};
1351
+ let httpCache = false;
1352
+ const { hydrateApp, srcIndexHtml, diagnostics } = await setupHydrateApp(devServerConfig, serverCtx);
1353
+ if (!diagnostics.some((diagnostic) => diagnostic.level === 'error')) {
1354
+ try {
1355
+ const { ssrPath, hasQueryString } = getSsrStaticDataPath(req);
1356
+ const url = new URL(ssrPath, req.url);
1357
+ const opts = getSsrHydrateOptions(devServerConfig, serverCtx, url);
1358
+ const ssrResults = await hydrateApp.renderToString(srcIndexHtml, opts);
1359
+ diagnostics.push(...ssrResults.diagnostics);
1360
+ ssrResults.staticData.forEach((s) => {
1361
+ if (s.type === 'application/json') {
1362
+ data[s.id] = JSON.parse(s.content);
1363
+ }
1364
+ else {
1365
+ data[s.id] = s.content;
1366
+ }
1367
+ });
1368
+ data.components = ssrResults.components.map((c) => c.tag).sort();
1369
+ httpCache = hasQueryString;
1370
+ }
1371
+ catch (e) {
1372
+ catchError(diagnostics, e);
1373
+ }
1374
+ }
1375
+ if (diagnostics.length > 0) {
1376
+ data.diagnostics = diagnostics;
1377
+ }
1378
+ const status = diagnostics.some((diagnostic) => diagnostic.level === 'error') ? 500 : 200;
1379
+ const content = JSON.stringify(data);
1380
+ serverCtx.logRequest(req, status);
1381
+ res.writeHead(status, responseHeaders({
1382
+ 'content-type': 'application/json; charset=utf-8',
1383
+ 'content-length': Buffer.byteLength(content, 'utf8'),
1384
+ }, httpCache && status === 200));
1385
+ res.write(content);
1386
+ res.end();
1387
+ }
1388
+ catch (e) {
1389
+ serverCtx.serve500(req, res, e, `ssrStaticDataRequest`);
1390
+ }
1391
+ }
1392
+ async function setupHydrateApp(devServerConfig, serverCtx) {
1393
+ let srcIndexHtml = null;
1394
+ let hydrateApp = null;
1395
+ const buildResults = await serverCtx.getBuildResults();
1396
+ const diagnostics = [];
1397
+ if (serverCtx.prerenderConfig == null && isString(devServerConfig.prerenderConfig)) {
1398
+ const compilerPath = path__default['default'].join(devServerConfig.devServerDir, '..', 'compiler', 'rindo.js');
1399
+ const compiler = require(compilerPath);
1400
+ const prerenderConfigResults = compiler.nodeRequire(devServerConfig.prerenderConfig);
1401
+ diagnostics.push(...prerenderConfigResults.diagnostics);
1402
+ if (prerenderConfigResults.module && prerenderConfigResults.module.config) {
1403
+ serverCtx.prerenderConfig = prerenderConfigResults.module.config;
1404
+ }
1405
+ }
1406
+ if (!isString(buildResults.hydrateAppFilePath)) {
1407
+ diagnostics.push({ messageText: `Missing hydrateAppFilePath`, level: `error`, type: `ssr`, lines: [] });
1408
+ }
1409
+ else if (!isString(devServerConfig.srcIndexHtml)) {
1410
+ diagnostics.push({ messageText: `Missing srcIndexHtml`, level: `error`, type: `ssr`, lines: [] });
1411
+ }
1412
+ else {
1413
+ srcIndexHtml = await serverCtx.sys.readFile(devServerConfig.srcIndexHtml);
1414
+ if (!isString(srcIndexHtml)) {
1415
+ diagnostics.push({
1416
+ level: `error`,
1417
+ lines: [],
1418
+ messageText: `Unable to load src index html: ${devServerConfig.srcIndexHtml}`,
1419
+ type: `ssr`,
1420
+ });
1421
+ }
1422
+ else {
1423
+ // ensure we cleared out node's internal require() cache for this file
1424
+ const hydrateAppFilePath = path__default['default'].resolve(buildResults.hydrateAppFilePath);
1425
+ // brute force way of clearning node's module cache
1426
+ // not using `delete require.cache[id]` since it'll cause memory leaks
1427
+ require.cache = {};
1428
+ const Module = require('module');
1429
+ Module._cache[hydrateAppFilePath] = undefined;
1430
+ hydrateApp = require(hydrateAppFilePath);
1431
+ }
1432
+ }
1433
+ return {
1434
+ hydrateApp,
1435
+ srcIndexHtml,
1436
+ diagnostics,
1437
+ };
1438
+ }
1439
+ function getSsrHydrateOptions(devServerConfig, serverCtx, url) {
1440
+ const opts = {
1441
+ url: url.href,
1442
+ addModulePreloads: false,
1443
+ approximateLineWidth: 120,
1444
+ inlineExternalStyleSheets: false,
1445
+ minifyScriptElements: false,
1446
+ minifyStyleElements: false,
1447
+ removeAttributeQuotes: false,
1448
+ removeBooleanAttributeQuotes: false,
1449
+ removeEmptyAttributes: false,
1450
+ removeHtmlComments: false,
1451
+ prettyHtml: true,
1452
+ };
1453
+ const prerenderConfig = serverCtx === null || serverCtx === void 0 ? void 0 : serverCtx.prerenderConfig;
1454
+ if (isFunction(prerenderConfig === null || prerenderConfig === void 0 ? void 0 : prerenderConfig.hydrateOptions)) {
1455
+ const userOpts = prerenderConfig.hydrateOptions(url);
1456
+ if (userOpts) {
1457
+ Object.assign(opts, userOpts);
1458
+ }
1459
+ }
1460
+ if (isFunction(serverCtx.sys.applyPrerenderGlobalPatch)) {
1461
+ const orgBeforeHydrate = opts.beforeHydrate;
1462
+ opts.beforeHydrate = (document) => {
1463
+ // patch this new window with the fetch global from node-fetch
1464
+ const devServerBaseUrl = new URL(devServerConfig.browserUrl);
1465
+ const devServerHostUrl = devServerBaseUrl.origin;
1466
+ serverCtx.sys.applyPrerenderGlobalPatch({
1467
+ devServerHostUrl: devServerHostUrl,
1468
+ window: document.defaultView,
1469
+ });
1470
+ if (typeof orgBeforeHydrate === 'function') {
1471
+ return orgBeforeHydrate(document);
1472
+ }
1473
+ };
1474
+ }
1475
+ return opts;
1476
+ }
1477
+ function getSsrErrorContent(diagnostics) {
1459
1478
  return `<!doctype html>
1460
1479
  <html>
1461
1480
  <head>
@@ -1474,330 +1493,330 @@ function getSsrErrorContent(diagnostics) {
1474
1493
  </p>
1475
1494
  `)}
1476
1495
  </body>
1477
- </html>`;
1496
+ </html>`;
1478
1497
  }
1479
1498
 
1480
- function createRequestHandler(devServerConfig, serverCtx) {
1481
- let userRequestHandler = null;
1482
- if (typeof devServerConfig.requestListenerPath === 'string') {
1483
- userRequestHandler = require(devServerConfig.requestListenerPath);
1484
- }
1485
- return async function (incomingReq, res) {
1486
- async function defaultHandler() {
1487
- try {
1488
- const req = normalizeHttpRequest(devServerConfig, incomingReq);
1489
- if (!req.url) {
1490
- return serverCtx.serve302(req, res);
1491
- }
1492
- if (isDevClient(req.pathname) && devServerConfig.websocket) {
1493
- return serveDevClient(devServerConfig, serverCtx, req, res);
1494
- }
1495
- if (isDevModule(req.pathname)) {
1496
- return serveDevNodeModule(serverCtx, req, res);
1497
- }
1498
- if (!isValidUrlBasePath(devServerConfig.basePath, req.url)) {
1499
- return serverCtx.serve404(req, res, `invalid basePath`, `404 File Not Found, base path: ${devServerConfig.basePath}`);
1500
- }
1501
- if (devServerConfig.ssr) {
1502
- if (isExtensionLessPath(req.url.pathname)) {
1503
- return ssrPageRequest(devServerConfig, serverCtx, req, res);
1504
- }
1505
- if (isSsrStaticDataPath(req.url.pathname)) {
1506
- return ssrStaticDataRequest(devServerConfig, serverCtx, req, res);
1507
- }
1508
- }
1509
- req.stats = await serverCtx.sys.stat(req.filePath);
1510
- if (req.stats.isFile) {
1511
- return serveFile(devServerConfig, serverCtx, req, res);
1512
- }
1513
- if (req.stats.isDirectory) {
1514
- return serveDirectoryIndex(devServerConfig, serverCtx, req, res);
1515
- }
1516
- const xSource = ['notfound'];
1517
- const validHistoryApi = isValidHistoryApi(devServerConfig, req);
1518
- xSource.push(`validHistoryApi: ${validHistoryApi}`);
1519
- if (validHistoryApi) {
1520
- try {
1521
- const indexFilePath = path__default['default'].join(devServerConfig.root, devServerConfig.historyApiFallback.index);
1522
- xSource.push(`indexFilePath: ${indexFilePath}`);
1523
- req.stats = await serverCtx.sys.stat(indexFilePath);
1524
- if (req.stats.isFile) {
1525
- req.filePath = indexFilePath;
1526
- return serveFile(devServerConfig, serverCtx, req, res);
1527
- }
1528
- }
1529
- catch (e) {
1530
- xSource.push(`notfound error: ${e}`);
1531
- }
1532
- }
1533
- return serverCtx.serve404(req, res, xSource.join(', '));
1534
- }
1535
- catch (e) {
1536
- return serverCtx.serve500(incomingReq, res, e, `not found error`);
1537
- }
1538
- }
1539
- if (typeof userRequestHandler === 'function') {
1540
- await userRequestHandler(incomingReq, res, defaultHandler);
1541
- }
1542
- else {
1543
- await defaultHandler();
1544
- }
1545
- };
1546
- }
1547
- function isValidUrlBasePath(basePath, url) {
1548
- // normalize the paths to always end with a slash for the check
1549
- let pathname = url.pathname;
1550
- if (!pathname.endsWith('/')) {
1551
- pathname += '/';
1552
- }
1553
- if (!basePath.endsWith('/')) {
1554
- basePath += '/';
1555
- }
1556
- return pathname.startsWith(basePath);
1557
- }
1558
- function normalizeHttpRequest(devServerConfig, incomingReq) {
1559
- const req = {
1560
- method: (incomingReq.method || 'GET').toUpperCase(),
1561
- headers: incomingReq.headers,
1562
- acceptHeader: (incomingReq.headers && typeof incomingReq.headers.accept === 'string' && incomingReq.headers.accept) || '',
1563
- host: (incomingReq.headers && typeof incomingReq.headers.host === 'string' && incomingReq.headers.host) || null,
1564
- url: null,
1565
- searchParams: null,
1566
- };
1567
- const incomingUrl = (incomingReq.url || '').trim() || null;
1568
- if (incomingUrl) {
1569
- if (req.host) {
1570
- req.url = new URL(incomingReq.url, `http://${req.host}`);
1571
- }
1572
- else {
1573
- req.url = new URL(incomingReq.url, `http://rindojs-dev.web.app`);
1574
- }
1575
- req.searchParams = req.url.searchParams;
1576
- }
1577
- if (req.url) {
1578
- const parts = req.url.pathname.replace(/\\/g, '/').split('/');
1579
- req.pathname = parts.map((part) => decodeURIComponent(part)).join('/');
1580
- if (req.pathname.length > 0 && !isDevClient(req.pathname)) {
1581
- req.pathname = '/' + req.pathname.substring(devServerConfig.basePath.length);
1582
- }
1583
- req.filePath = normalizePath(path__default['default'].normalize(path__default['default'].join(devServerConfig.root, path__default['default'].relative('/', req.pathname))));
1584
- }
1585
- return req;
1586
- }
1587
- function isValidHistoryApi(devServerConfig, req) {
1588
- if (!devServerConfig.historyApiFallback) {
1589
- return false;
1590
- }
1591
- if (req.method !== 'GET') {
1592
- return false;
1593
- }
1594
- if (!req.acceptHeader.includes('text/html')) {
1595
- return false;
1596
- }
1597
- if (!devServerConfig.historyApiFallback.disableDotRule && req.pathname.includes('.')) {
1598
- return false;
1599
- }
1600
- return true;
1499
+ function createRequestHandler(devServerConfig, serverCtx) {
1500
+ let userRequestHandler = null;
1501
+ if (typeof devServerConfig.requestListenerPath === 'string') {
1502
+ userRequestHandler = require(devServerConfig.requestListenerPath);
1503
+ }
1504
+ return async function (incomingReq, res) {
1505
+ async function defaultHandler() {
1506
+ try {
1507
+ const req = normalizeHttpRequest(devServerConfig, incomingReq);
1508
+ if (!req.url) {
1509
+ return serverCtx.serve302(req, res);
1510
+ }
1511
+ if (isDevClient(req.pathname) && devServerConfig.websocket) {
1512
+ return serveDevClient(devServerConfig, serverCtx, req, res);
1513
+ }
1514
+ if (isDevModule(req.pathname)) {
1515
+ return serveDevNodeModule(serverCtx, req, res);
1516
+ }
1517
+ if (!isValidUrlBasePath(devServerConfig.basePath, req.url)) {
1518
+ return serverCtx.serve404(req, res, `invalid basePath`, `404 File Not Found, base path: ${devServerConfig.basePath}`);
1519
+ }
1520
+ if (devServerConfig.ssr) {
1521
+ if (isExtensionLessPath(req.url.pathname)) {
1522
+ return ssrPageRequest(devServerConfig, serverCtx, req, res);
1523
+ }
1524
+ if (isSsrStaticDataPath(req.url.pathname)) {
1525
+ return ssrStaticDataRequest(devServerConfig, serverCtx, req, res);
1526
+ }
1527
+ }
1528
+ req.stats = await serverCtx.sys.stat(req.filePath);
1529
+ if (req.stats.isFile) {
1530
+ return serveFile(devServerConfig, serverCtx, req, res);
1531
+ }
1532
+ if (req.stats.isDirectory) {
1533
+ return serveDirectoryIndex(devServerConfig, serverCtx, req, res);
1534
+ }
1535
+ const xSource = ['notfound'];
1536
+ const validHistoryApi = isValidHistoryApi(devServerConfig, req);
1537
+ xSource.push(`validHistoryApi: ${validHistoryApi}`);
1538
+ if (validHistoryApi) {
1539
+ try {
1540
+ const indexFilePath = path__default['default'].join(devServerConfig.root, devServerConfig.historyApiFallback.index);
1541
+ xSource.push(`indexFilePath: ${indexFilePath}`);
1542
+ req.stats = await serverCtx.sys.stat(indexFilePath);
1543
+ if (req.stats.isFile) {
1544
+ req.filePath = indexFilePath;
1545
+ return serveFile(devServerConfig, serverCtx, req, res);
1546
+ }
1547
+ }
1548
+ catch (e) {
1549
+ xSource.push(`notfound error: ${e}`);
1550
+ }
1551
+ }
1552
+ return serverCtx.serve404(req, res, xSource.join(', '));
1553
+ }
1554
+ catch (e) {
1555
+ return serverCtx.serve500(incomingReq, res, e, `not found error`);
1556
+ }
1557
+ }
1558
+ if (typeof userRequestHandler === 'function') {
1559
+ await userRequestHandler(incomingReq, res, defaultHandler);
1560
+ }
1561
+ else {
1562
+ await defaultHandler();
1563
+ }
1564
+ };
1565
+ }
1566
+ function isValidUrlBasePath(basePath, url) {
1567
+ // normalize the paths to always end with a slash for the check
1568
+ let pathname = url.pathname;
1569
+ if (!pathname.endsWith('/')) {
1570
+ pathname += '/';
1571
+ }
1572
+ if (!basePath.endsWith('/')) {
1573
+ basePath += '/';
1574
+ }
1575
+ return pathname.startsWith(basePath);
1576
+ }
1577
+ function normalizeHttpRequest(devServerConfig, incomingReq) {
1578
+ const req = {
1579
+ method: (incomingReq.method || 'GET').toUpperCase(),
1580
+ headers: incomingReq.headers,
1581
+ acceptHeader: (incomingReq.headers && typeof incomingReq.headers.accept === 'string' && incomingReq.headers.accept) || '',
1582
+ host: (incomingReq.headers && typeof incomingReq.headers.host === 'string' && incomingReq.headers.host) || null,
1583
+ url: null,
1584
+ searchParams: null,
1585
+ };
1586
+ const incomingUrl = (incomingReq.url || '').trim() || null;
1587
+ if (incomingUrl) {
1588
+ if (req.host) {
1589
+ req.url = new URL(incomingReq.url, `http://${req.host}`);
1590
+ }
1591
+ else {
1592
+ req.url = new URL(incomingReq.url, `http://rindojs-dev.web.app`);
1593
+ }
1594
+ req.searchParams = req.url.searchParams;
1595
+ }
1596
+ if (req.url) {
1597
+ const parts = req.url.pathname.replace(/\\/g, '/').split('/');
1598
+ req.pathname = parts.map((part) => decodeURIComponent(part)).join('/');
1599
+ if (req.pathname.length > 0 && !isDevClient(req.pathname)) {
1600
+ req.pathname = '/' + req.pathname.substring(devServerConfig.basePath.length);
1601
+ }
1602
+ req.filePath = normalizePath(path__default['default'].normalize(path__default['default'].join(devServerConfig.root, path__default['default'].relative('/', req.pathname))));
1603
+ }
1604
+ return req;
1605
+ }
1606
+ function isValidHistoryApi(devServerConfig, req) {
1607
+ if (!devServerConfig.historyApiFallback) {
1608
+ return false;
1609
+ }
1610
+ if (req.method !== 'GET') {
1611
+ return false;
1612
+ }
1613
+ if (!req.acceptHeader.includes('text/html')) {
1614
+ return false;
1615
+ }
1616
+ if (!devServerConfig.historyApiFallback.disableDotRule && req.pathname.includes('.')) {
1617
+ return false;
1618
+ }
1619
+ return true;
1601
1620
  }
1602
1621
 
1603
- function createHttpServer(devServerConfig, serverCtx) {
1604
- // create our request handler
1605
- const reqHandler = createRequestHandler(devServerConfig, serverCtx);
1606
- const credentials = devServerConfig.https;
1607
- return credentials ? https__namespace.createServer(credentials, reqHandler) : http__namespace.createServer(reqHandler);
1608
- }
1609
- async function findClosestOpenPort(host, port) {
1610
- async function t(portToCheck) {
1611
- const isTaken = await isPortTaken(host, portToCheck);
1612
- if (!isTaken) {
1613
- return portToCheck;
1614
- }
1615
- return t(portToCheck + 1);
1616
- }
1617
- return t(port);
1618
- }
1619
- function isPortTaken(host, port) {
1620
- return new Promise((resolve, reject) => {
1621
- const tester = net__namespace
1622
- .createServer()
1623
- .once('error', () => {
1624
- resolve(true);
1625
- })
1626
- .once('listening', () => {
1627
- tester
1628
- .once('close', () => {
1629
- resolve(false);
1630
- })
1631
- .close();
1632
- })
1633
- .on('error', (err) => {
1634
- reject(err);
1635
- })
1636
- .listen(port, host);
1637
- });
1622
+ function createHttpServer(devServerConfig, serverCtx) {
1623
+ // create our request handler
1624
+ const reqHandler = createRequestHandler(devServerConfig, serverCtx);
1625
+ const credentials = devServerConfig.https;
1626
+ return credentials ? https__namespace.createServer(credentials, reqHandler) : http__namespace.createServer(reqHandler);
1627
+ }
1628
+ async function findClosestOpenPort(host, port) {
1629
+ async function t(portToCheck) {
1630
+ const isTaken = await isPortTaken(host, portToCheck);
1631
+ if (!isTaken) {
1632
+ return portToCheck;
1633
+ }
1634
+ return t(portToCheck + 1);
1635
+ }
1636
+ return t(port);
1637
+ }
1638
+ function isPortTaken(host, port) {
1639
+ return new Promise((resolve, reject) => {
1640
+ const tester = net__namespace
1641
+ .createServer()
1642
+ .once('error', () => {
1643
+ resolve(true);
1644
+ })
1645
+ .once('listening', () => {
1646
+ tester
1647
+ .once('close', () => {
1648
+ resolve(false);
1649
+ })
1650
+ .close();
1651
+ })
1652
+ .on('error', (err) => {
1653
+ reject(err);
1654
+ })
1655
+ .listen(port, host);
1656
+ });
1638
1657
  }
1639
1658
 
1640
- function createWebSocket(httpServer, onMessageFromClient) {
1641
- const wsConfig = {
1642
- server: httpServer,
1643
- };
1644
- const wsServer = new ws__namespace.Server(wsConfig);
1645
- function heartbeat() {
1646
- // we need to coerce the `ws` type to our custom `DevWS` type here, since
1647
- // this function is going to be passed in to `ws.on('pong'` which expects
1648
- // to be passed a functon where `this` is bound to `ws`.
1649
- this.isAlive = true;
1650
- }
1651
- wsServer.on('connection', (ws) => {
1652
- ws.on('message', (data) => {
1653
- // the server process has received a message from the browser
1654
- // pass the message received from the browser to the main cli process
1655
- try {
1656
- onMessageFromClient(JSON.parse(data.toString()));
1657
- }
1658
- catch (e) {
1659
- console.error(e);
1660
- }
1661
- });
1662
- ws.isAlive = true;
1663
- ws.on('pong', heartbeat);
1664
- // ignore invalid close frames sent by Safari 15
1665
- ws.on('error', console.error);
1666
- });
1667
- const pingInternval = setInterval(() => {
1668
- wsServer.clients.forEach((ws) => {
1669
- if (!ws.isAlive) {
1670
- return ws.close(1000);
1671
- }
1672
- ws.isAlive = false;
1673
- ws.ping(noop);
1674
- });
1675
- }, 10000);
1676
- return {
1677
- sendToBrowser: (msg) => {
1678
- if (msg && wsServer && wsServer.clients) {
1679
- const data = JSON.stringify(msg);
1680
- wsServer.clients.forEach((ws) => {
1681
- if (ws.readyState === ws.OPEN) {
1682
- ws.send(data);
1683
- }
1684
- });
1685
- }
1686
- },
1687
- close: () => {
1688
- return new Promise((resolve, reject) => {
1689
- clearInterval(pingInternval);
1690
- wsServer.clients.forEach((ws) => {
1691
- ws.close(1000);
1692
- });
1693
- wsServer.close((err) => {
1694
- if (err) {
1695
- reject(err);
1696
- }
1697
- else {
1698
- resolve();
1699
- }
1700
- });
1701
- });
1702
- },
1703
- };
1659
+ function createWebSocket(httpServer, onMessageFromClient) {
1660
+ const wsConfig = {
1661
+ server: httpServer,
1662
+ };
1663
+ const wsServer = new ws__namespace.Server(wsConfig);
1664
+ function heartbeat() {
1665
+ // we need to coerce the `ws` type to our custom `DevWS` type here, since
1666
+ // this function is going to be passed in to `ws.on('pong'` which expects
1667
+ // to be passed a functon where `this` is bound to `ws`.
1668
+ this.isAlive = true;
1669
+ }
1670
+ wsServer.on('connection', (ws) => {
1671
+ ws.on('message', (data) => {
1672
+ // the server process has received a message from the browser
1673
+ // pass the message received from the browser to the main cli process
1674
+ try {
1675
+ onMessageFromClient(JSON.parse(data.toString()));
1676
+ }
1677
+ catch (e) {
1678
+ console.error(e);
1679
+ }
1680
+ });
1681
+ ws.isAlive = true;
1682
+ ws.on('pong', heartbeat);
1683
+ // ignore invalid close frames sent by Safari 15
1684
+ ws.on('error', console.error);
1685
+ });
1686
+ const pingInternval = setInterval(() => {
1687
+ wsServer.clients.forEach((ws) => {
1688
+ if (!ws.isAlive) {
1689
+ return ws.close(1000);
1690
+ }
1691
+ ws.isAlive = false;
1692
+ ws.ping(noop);
1693
+ });
1694
+ }, 10000);
1695
+ return {
1696
+ sendToBrowser: (msg) => {
1697
+ if (msg && wsServer && wsServer.clients) {
1698
+ const data = JSON.stringify(msg);
1699
+ wsServer.clients.forEach((ws) => {
1700
+ if (ws.readyState === ws.OPEN) {
1701
+ ws.send(data);
1702
+ }
1703
+ });
1704
+ }
1705
+ },
1706
+ close: () => {
1707
+ return new Promise((resolve, reject) => {
1708
+ clearInterval(pingInternval);
1709
+ wsServer.clients.forEach((ws) => {
1710
+ ws.close(1000);
1711
+ });
1712
+ wsServer.close((err) => {
1713
+ if (err) {
1714
+ reject(err);
1715
+ }
1716
+ else {
1717
+ resolve();
1718
+ }
1719
+ });
1720
+ });
1721
+ },
1722
+ };
1704
1723
  }
1705
1724
 
1706
- function initServerProcess(sendMsg) {
1707
- let server = null;
1708
- let webSocket = null;
1709
- let serverCtx = null;
1710
- const buildResultsResolves = [];
1711
- const compilerRequestResolves = [];
1712
- const startServer = async (msg) => {
1713
- const devServerConfig = msg.startServer;
1714
- devServerConfig.port = await findClosestOpenPort(devServerConfig.address, devServerConfig.port);
1715
- devServerConfig.browserUrl = getBrowserUrl(devServerConfig.protocol, devServerConfig.address, devServerConfig.port, devServerConfig.basePath, '/');
1716
- devServerConfig.root = normalizePath(devServerConfig.root);
1717
- const sys = index_js.createNodeSys({ process });
1718
- serverCtx = createServerContext(sys, sendMsg, devServerConfig, buildResultsResolves, compilerRequestResolves);
1719
- server = createHttpServer(devServerConfig, serverCtx);
1720
- webSocket = devServerConfig.websocket ? createWebSocket(server, sendMsg) : null;
1721
- server.listen(devServerConfig.port, devServerConfig.address);
1722
- serverCtx.isServerListening = true;
1723
- if (devServerConfig.openBrowser) {
1724
- const initialLoadUrl = getBrowserUrl(devServerConfig.protocol, devServerConfig.address, devServerConfig.port, devServerConfig.basePath, devServerConfig.initialLoadUrl || DEV_SERVER_INIT_URL);
1725
- openInBrowser({ url: initialLoadUrl });
1726
- }
1727
- sendMsg({ serverStarted: devServerConfig });
1728
- };
1729
- const closeServer = () => {
1730
- const promises = [];
1731
- buildResultsResolves.forEach((r) => r.reject('dev server closed'));
1732
- buildResultsResolves.length = 0;
1733
- compilerRequestResolves.forEach((r) => r.reject('dev server closed'));
1734
- compilerRequestResolves.length = 0;
1735
- if (serverCtx) {
1736
- if (serverCtx.sys) {
1737
- promises.push(serverCtx.sys.destroy());
1738
- }
1739
- }
1740
- if (webSocket) {
1741
- promises.push(webSocket.close());
1742
- webSocket = null;
1743
- }
1744
- if (server) {
1745
- promises.push(new Promise((resolve) => {
1746
- server.close((err) => {
1747
- if (err) {
1748
- console.error(`close error: ${err}`);
1749
- }
1750
- resolve();
1751
- });
1752
- }));
1753
- }
1754
- Promise.all(promises).finally(() => {
1755
- sendMsg({
1756
- serverClosed: true,
1757
- });
1758
- });
1759
- };
1760
- const receiveMessageFromMain = (msg) => {
1761
- // the server process received a message from main thread
1762
- try {
1763
- if (msg) {
1764
- if (msg.startServer) {
1765
- startServer(msg);
1766
- }
1767
- else if (msg.closeServer) {
1768
- closeServer();
1769
- }
1770
- else if (msg.compilerRequestResults) {
1771
- for (let i = compilerRequestResolves.length - 1; i >= 0; i--) {
1772
- const r = compilerRequestResolves[i];
1773
- if (r.path === msg.compilerRequestResults.path) {
1774
- r.resolve(msg.compilerRequestResults);
1775
- compilerRequestResolves.splice(i, 1);
1776
- }
1777
- }
1778
- }
1779
- else if (serverCtx) {
1780
- if (msg.buildResults && !msg.isActivelyBuilding) {
1781
- buildResultsResolves.forEach((r) => r.resolve(msg.buildResults));
1782
- buildResultsResolves.length = 0;
1783
- }
1784
- if (webSocket) {
1785
- webSocket.sendToBrowser(msg);
1786
- }
1787
- }
1788
- }
1789
- }
1790
- catch (e) {
1791
- let stack = null;
1792
- if (e instanceof Error) {
1793
- stack = e.stack;
1794
- }
1795
- sendMsg({
1796
- error: { message: e + '', stack },
1797
- });
1798
- }
1799
- };
1800
- return receiveMessageFromMain;
1725
+ function initServerProcess(sendMsg) {
1726
+ let server = null;
1727
+ let webSocket = null;
1728
+ let serverCtx = null;
1729
+ const buildResultsResolves = [];
1730
+ const compilerRequestResolves = [];
1731
+ const startServer = async (msg) => {
1732
+ const devServerConfig = msg.startServer;
1733
+ devServerConfig.port = await findClosestOpenPort(devServerConfig.address, devServerConfig.port);
1734
+ devServerConfig.browserUrl = getBrowserUrl(devServerConfig.protocol, devServerConfig.address, devServerConfig.port, devServerConfig.basePath, '/');
1735
+ devServerConfig.root = normalizePath(devServerConfig.root);
1736
+ const sys = index_js.createNodeSys({ process });
1737
+ serverCtx = createServerContext(sys, sendMsg, devServerConfig, buildResultsResolves, compilerRequestResolves);
1738
+ server = createHttpServer(devServerConfig, serverCtx);
1739
+ webSocket = devServerConfig.websocket ? createWebSocket(server, sendMsg) : null;
1740
+ server.listen(devServerConfig.port, devServerConfig.address);
1741
+ serverCtx.isServerListening = true;
1742
+ if (devServerConfig.openBrowser) {
1743
+ const initialLoadUrl = getBrowserUrl(devServerConfig.protocol, devServerConfig.address, devServerConfig.port, devServerConfig.basePath, devServerConfig.initialLoadUrl || DEV_SERVER_INIT_URL);
1744
+ openInBrowser({ url: initialLoadUrl });
1745
+ }
1746
+ sendMsg({ serverStarted: devServerConfig });
1747
+ };
1748
+ const closeServer = () => {
1749
+ const promises = [];
1750
+ buildResultsResolves.forEach((r) => r.reject('dev server closed'));
1751
+ buildResultsResolves.length = 0;
1752
+ compilerRequestResolves.forEach((r) => r.reject('dev server closed'));
1753
+ compilerRequestResolves.length = 0;
1754
+ if (serverCtx) {
1755
+ if (serverCtx.sys) {
1756
+ promises.push(serverCtx.sys.destroy());
1757
+ }
1758
+ }
1759
+ if (webSocket) {
1760
+ promises.push(webSocket.close());
1761
+ webSocket = null;
1762
+ }
1763
+ if (server) {
1764
+ promises.push(new Promise((resolve) => {
1765
+ server.close((err) => {
1766
+ if (err) {
1767
+ console.error(`close error: ${err}`);
1768
+ }
1769
+ resolve();
1770
+ });
1771
+ }));
1772
+ }
1773
+ Promise.all(promises).finally(() => {
1774
+ sendMsg({
1775
+ serverClosed: true,
1776
+ });
1777
+ });
1778
+ };
1779
+ const receiveMessageFromMain = (msg) => {
1780
+ // the server process received a message from main thread
1781
+ try {
1782
+ if (msg) {
1783
+ if (msg.startServer) {
1784
+ startServer(msg);
1785
+ }
1786
+ else if (msg.closeServer) {
1787
+ closeServer();
1788
+ }
1789
+ else if (msg.compilerRequestResults) {
1790
+ for (let i = compilerRequestResolves.length - 1; i >= 0; i--) {
1791
+ const r = compilerRequestResolves[i];
1792
+ if (r.path === msg.compilerRequestResults.path) {
1793
+ r.resolve(msg.compilerRequestResults);
1794
+ compilerRequestResolves.splice(i, 1);
1795
+ }
1796
+ }
1797
+ }
1798
+ else if (serverCtx) {
1799
+ if (msg.buildResults && !msg.isActivelyBuilding) {
1800
+ buildResultsResolves.forEach((r) => r.resolve(msg.buildResults));
1801
+ buildResultsResolves.length = 0;
1802
+ }
1803
+ if (webSocket) {
1804
+ webSocket.sendToBrowser(msg);
1805
+ }
1806
+ }
1807
+ }
1808
+ }
1809
+ catch (e) {
1810
+ let stack = null;
1811
+ if (e instanceof Error) {
1812
+ stack = e.stack;
1813
+ }
1814
+ sendMsg({
1815
+ error: { message: e + '', stack },
1816
+ });
1817
+ }
1818
+ };
1819
+ return receiveMessageFromMain;
1801
1820
  }
1802
1821
 
1803
1822
  exports.initServerProcess = initServerProcess;