@rindo/core 3.0.0 → 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 -62812
  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 +1301 -1279
  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 -3373
  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 -2353
  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 +10 -10
  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.0 | 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,321 +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
- const noop = () => {
57
- /* noop*/
58
- };
59
- 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';
60
63
  const isString = (v) => typeof v === 'string';
61
64
 
62
- /**
63
- * Builds a diagnostic from an `Error`, appends it to the `diagnostics` parameter, and returns the created diagnostic
64
- * @param diagnostics the series of diagnostics the newly created diagnostics should be added to
65
- * @param err the error to derive information from in generating the diagnostic
66
- * @param msg an optional message to use in place of `err` to generate the diagnostic
67
- * @returns the generated diagnostic
68
- */
69
- const catchError = (diagnostics, err, msg) => {
70
- const diagnostic = {
71
- level: 'error',
72
- type: 'build',
73
- header: 'Build Error',
74
- messageText: 'build error',
75
- relFilePath: null,
76
- absFilePath: null,
77
- lines: [],
78
- };
79
- if (isString(msg)) {
80
- diagnostic.messageText = msg.length ? msg : 'UNKNOWN ERROR';
81
- }
82
- else if (err != null) {
83
- if (err.stack != null) {
84
- diagnostic.messageText = err.stack.toString();
85
- }
86
- else {
87
- if (err.message != null) {
88
- diagnostic.messageText = err.message.length ? err.message : 'UNKNOWN ERROR';
89
- }
90
- else {
91
- diagnostic.messageText = err.toString();
92
- }
93
- }
94
- }
95
- if (diagnostics != null && !shouldIgnoreError(diagnostic.messageText)) {
96
- diagnostics.push(diagnostic);
97
- }
98
- return diagnostic;
99
- };
100
- const shouldIgnoreError = (msg) => {
101
- return msg === TASK_CANCELED_MSG;
102
- };
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
+ };
103
106
  const TASK_CANCELED_MSG = `task canceled`;
104
107
 
105
- /**
106
- * Convert Windows backslash paths to slash paths: foo\\bar ➔ foo/bar
107
- * Forward-slash paths can be used in Windows as long as they're not
108
- * extended-length paths and don't contain any non-ascii characters.
109
- * This was created since the path methods in Node.js outputs \\ paths on Windows.
110
- * @param path the Windows-based path to convert
111
- * @returns the converted path
112
- */
113
- const normalizePath = (path) => {
114
- if (typeof path !== 'string') {
115
- throw new Error(`invalid path to normalize`);
116
- }
117
- path = normalizeSlashes(path.trim());
118
- const components = pathComponents(path, getRootLength(path));
119
- const reducedComponents = reducePathComponents(components);
120
- const rootPart = reducedComponents[0];
121
- const secondPart = reducedComponents[1];
122
- const normalized = rootPart + reducedComponents.slice(1).join('/');
123
- if (normalized === '') {
124
- return '.';
125
- }
126
- if (rootPart === '' &&
127
- secondPart &&
128
- path.includes('/') &&
129
- !secondPart.startsWith('.') &&
130
- !secondPart.startsWith('@')) {
131
- return './' + normalized;
132
- }
133
- return normalized;
134
- };
135
- const normalizeSlashes = (path) => path.replace(backslashRegExp, '/');
136
- const altDirectorySeparator = '\\';
137
- const urlSchemeSeparator = '://';
138
- const backslashRegExp = /\\/g;
139
- const reducePathComponents = (components) => {
140
- if (!Array.isArray(components) || components.length === 0) {
141
- return [];
142
- }
143
- const reduced = [components[0]];
144
- for (let i = 1; i < components.length; i++) {
145
- const component = components[i];
146
- if (!component)
147
- continue;
148
- if (component === '.')
149
- continue;
150
- if (component === '..') {
151
- if (reduced.length > 1) {
152
- if (reduced[reduced.length - 1] !== '..') {
153
- reduced.pop();
154
- continue;
155
- }
156
- }
157
- else if (reduced[0])
158
- continue;
159
- }
160
- reduced.push(component);
161
- }
162
- return reduced;
163
- };
164
- const getRootLength = (path) => {
165
- const rootLength = getEncodedRootLength(path);
166
- return rootLength < 0 ? ~rootLength : rootLength;
167
- };
168
- const getEncodedRootLength = (path) => {
169
- if (!path)
170
- return 0;
171
- const ch0 = path.charCodeAt(0);
172
- // POSIX or UNC
173
- if (ch0 === 47 /* CharacterCodes.slash */ || ch0 === 92 /* CharacterCodes.backslash */) {
174
- if (path.charCodeAt(1) !== ch0)
175
- return 1; // POSIX: "/" (or non-normalized "\")
176
- const p1 = path.indexOf(ch0 === 47 /* CharacterCodes.slash */ ? '/' : altDirectorySeparator, 2);
177
- if (p1 < 0)
178
- return path.length; // UNC: "//server" or "\\server"
179
- return p1 + 1; // UNC: "//server/" or "\\server\"
180
- }
181
- // DOS
182
- if (isVolumeCharacter(ch0) && path.charCodeAt(1) === 58 /* CharacterCodes.colon */) {
183
- const ch2 = path.charCodeAt(2);
184
- if (ch2 === 47 /* CharacterCodes.slash */ || ch2 === 92 /* CharacterCodes.backslash */)
185
- return 3; // DOS: "c:/" or "c:\"
186
- if (path.length === 2)
187
- return 2; // DOS: "c:" (but not "c:d")
188
- }
189
- // URL
190
- const schemeEnd = path.indexOf(urlSchemeSeparator);
191
- if (schemeEnd !== -1) {
192
- const authorityStart = schemeEnd + urlSchemeSeparator.length;
193
- const authorityEnd = path.indexOf('/', authorityStart);
194
- if (authorityEnd !== -1) {
195
- // URL: "file:///", "file://server/", "file://server/path"
196
- // For local "file" URLs, include the leading DOS volume (if present).
197
- // Per https://www.ietf.org/rfc/rfc1738.txt, a host of "" or "localhost" is a
198
- // special case interpreted as "the machine from which the URL is being interpreted".
199
- const scheme = path.slice(0, schemeEnd);
200
- const authority = path.slice(authorityStart, authorityEnd);
201
- if (scheme === 'file' &&
202
- (authority === '' || authority === 'localhost') &&
203
- isVolumeCharacter(path.charCodeAt(authorityEnd + 1))) {
204
- const volumeSeparatorEnd = getFileUrlVolumeSeparatorEnd(path, authorityEnd + 2);
205
- if (volumeSeparatorEnd !== -1) {
206
- if (path.charCodeAt(volumeSeparatorEnd) === 47 /* CharacterCodes.slash */) {
207
- // URL: "file:///c:/", "file://localhost/c:/", "file:///c%3a/", "file://localhost/c%3a/"
208
- return ~(volumeSeparatorEnd + 1);
209
- }
210
- if (volumeSeparatorEnd === path.length) {
211
- // URL: "file:///c:", "file://localhost/c:", "file:///c$3a", "file://localhost/c%3a"
212
- // but not "file:///c:d" or "file:///c%3ad"
213
- return ~volumeSeparatorEnd;
214
- }
215
- }
216
- }
217
- return ~(authorityEnd + 1); // URL: "file://server/", "http://server/"
218
- }
219
- return ~path.length; // URL: "file://server", "http://server"
220
- }
221
- // relative
222
- return 0;
223
- };
224
- const isVolumeCharacter = (charCode) => (charCode >= 97 /* CharacterCodes.a */ && charCode <= 122 /* CharacterCodes.z */) ||
225
- (charCode >= 65 /* CharacterCodes.A */ && charCode <= 90 /* CharacterCodes.Z */);
226
- const getFileUrlVolumeSeparatorEnd = (url, start) => {
227
- const ch0 = url.charCodeAt(start);
228
- if (ch0 === 58 /* CharacterCodes.colon */)
229
- return start + 1;
230
- if (ch0 === 37 /* CharacterCodes.percent */ && url.charCodeAt(start + 1) === 51 /* CharacterCodes._3 */) {
231
- const ch2 = url.charCodeAt(start + 2);
232
- if (ch2 === 97 /* CharacterCodes.a */ || ch2 === 65 /* CharacterCodes.A */)
233
- return start + 3;
234
- }
235
- return -1;
236
- };
237
- const pathComponents = (path, rootLength) => {
238
- const root = path.substring(0, rootLength);
239
- const rest = path.substring(rootLength).split('/');
240
- const restLen = rest.length;
241
- if (restLen > 0 && !rest[restLen - 1]) {
242
- rest.pop();
243
- }
244
- 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];
245
248
  };
246
249
 
247
- const DEV_SERVER_URL = '/~dev-server';
248
- const DEV_MODULE_URL = '/~dev-module';
249
- 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`;
250
253
  const OPEN_IN_EDITOR_URL = `${DEV_SERVER_URL}-open-in-editor`;
251
254
 
252
- const version = '3.0.0';
255
+ const version = '3.1.0';
253
256
 
254
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"};
255
258
 
256
- function responseHeaders(headers, httpCache = false) {
257
- headers = { ...DEFAULT_HEADERS, ...headers };
258
- if (httpCache) {
259
- headers['cache-control'] = 'max-age=3600';
260
- delete headers['date'];
261
- delete headers['expires'];
262
- }
263
- return headers;
264
- }
265
- const DEFAULT_HEADERS = {
266
- 'cache-control': 'no-cache, no-store, must-revalidate, max-age=0',
267
- expires: '0',
268
- date: 'Wed, 1 Jan 2000 00:00:00 GMT',
269
- server: 'Rindo Dev Server ' + version,
270
- 'access-control-allow-origin': '*',
271
- 'access-control-expose-headers': '*',
272
- };
273
- function getBrowserUrl(protocol, address, port, basePath, pathname) {
274
- address = address === `0.0.0.0` ? `localhost` : address;
275
- const portSuffix = !port || port === 80 || port === 443 ? '' : ':' + port;
276
- let path = basePath;
277
- if (pathname.startsWith('/')) {
278
- pathname = pathname.substring(1);
279
- }
280
- path += pathname;
281
- protocol = protocol.replace(/\:/g, '');
282
- return `${protocol}://${address}${portSuffix}${path}`;
283
- }
284
- function getDevServerClientUrl(devServerConfig, host, protocol) {
285
- let address = devServerConfig.address;
286
- let port = devServerConfig.port;
287
- if (host) {
288
- address = host;
289
- port = null;
290
- }
291
- return getBrowserUrl(protocol !== null && protocol !== void 0 ? protocol : devServerConfig.protocol, address, port, devServerConfig.basePath, DEV_SERVER_URL);
292
- }
293
- function getContentType(filePath) {
294
- const last = filePath.replace(/^.*[/\\]/, '').toLowerCase();
295
- const ext = last.replace(/^.*\./, '').toLowerCase();
296
- const hasPath = last.length < filePath.length;
297
- const hasDot = ext.length < last.length - 1;
298
- return ((hasDot || !hasPath) && contentTypes[ext]) || 'application/octet-stream';
299
- }
300
- function isHtmlFile(filePath) {
301
- filePath = filePath.toLowerCase().trim();
302
- return filePath.endsWith('.html') || filePath.endsWith('.htm');
303
- }
304
- function isCssFile(filePath) {
305
- filePath = filePath.toLowerCase().trim();
306
- return filePath.endsWith('.css');
307
- }
308
- const TXT_EXT = ['css', 'html', 'htm', 'js', 'json', 'svg', 'xml'];
309
- function isSimpleText(filePath) {
310
- const ext = filePath.toLowerCase().trim().split('.').pop();
311
- return TXT_EXT.includes(ext);
312
- }
313
- function isExtensionLessPath(pathname) {
314
- const parts = pathname.split('/');
315
- const lastPart = parts[parts.length - 1];
316
- return !lastPart.includes('.');
317
- }
318
- function isSsrStaticDataPath(pathname) {
319
- const parts = pathname.split('/');
320
- const fileName = parts[parts.length - 1].split('?')[0];
321
- return fileName === 'page.state.json';
322
- }
323
- function getSsrStaticDataPath(req) {
324
- const parts = req.url.href.split('/');
325
- const fileName = parts[parts.length - 1];
326
- const fileNameParts = fileName.split('?');
327
- parts.pop();
328
- let ssrPath = new URL(parts.join('/')).href;
329
- if (!ssrPath.endsWith('/') && req.headers) {
330
- const h = new Headers(req.headers);
331
- if (h.get('referer').endsWith('/')) {
332
- ssrPath += '/';
333
- }
334
- }
335
- return {
336
- ssrPath,
337
- fileName: fileNameParts[0],
338
- hasQueryString: typeof fileNameParts[1] === 'string' && fileNameParts[1].length > 0,
339
- };
340
- }
341
- function isDevClient(pathname) {
342
- return pathname.startsWith(DEV_SERVER_URL);
343
- }
344
- function isDevModule(pathname) {
345
- return pathname.includes(DEV_MODULE_URL);
346
- }
347
- function isOpenInEditor(pathname) {
348
- return pathname === OPEN_IN_EDITOR_URL;
349
- }
350
- function isInitialDevServerLoad(pathname) {
351
- return pathname === DEV_SERVER_INIT_URL;
352
- }
353
- function isDevServerClient(pathname) {
354
- return pathname === DEV_SERVER_URL;
355
- }
356
- function shouldCompress(devServerConfig, req) {
357
- if (!devServerConfig.gzip) {
358
- return false;
359
- }
360
- if (req.method !== 'GET') {
361
- return false;
362
- }
363
- const acceptEncoding = req.headers && req.headers['accept-encoding'];
364
- if (typeof acceptEncoding !== 'string') {
365
- return false;
366
- }
367
- if (!acceptEncoding.includes('gzip')) {
368
- return false;
369
- }
370
- 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;
371
374
  }
372
375
 
373
376
  function createCommonjsModule(fn, basedir, module) {
@@ -473,6 +476,25 @@ const localXdgOpenPath = path__default['default'].join(__dirname, 'xdg-open');
473
476
 
474
477
  const {platform, arch} = process;
475
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
+
476
498
  /**
477
499
  Get the mount point for fixed drives in WSL.
478
500
 
@@ -583,7 +605,7 @@ const baseOpen = async options => {
583
605
  if (app) {
584
606
  cliArguments.push('-a', app);
585
607
  }
586
- } else if (platform === 'win32' || (isWsl_1 && !isDocker_1())) {
608
+ } else if (platform === 'win32' || (isWsl_1 && !isInsideContainer() && !app)) {
587
609
  const mountPoint = await getWslDrivesMountPoint();
588
610
 
589
611
  command = isWsl_1 ?
@@ -672,7 +694,7 @@ const baseOpen = async options => {
672
694
  subprocess.once('error', reject);
673
695
 
674
696
  subprocess.once('close', exitCode => {
675
- if (options.allowNonzeroExitCode && exitCode > 0) {
697
+ if (!options.allowNonzeroExitCode && exitCode > 0) {
676
698
  reject(new Error(`Exited with code ${exitCode}`));
677
699
  return;
678
700
  }
@@ -777,682 +799,682 @@ open.openApp = openApp;
777
799
 
778
800
  var open_1 = open;
779
801
 
780
- async function openInBrowser(opts) {
781
- // await open(opts.url, { app: ['google chrome', '--auto-open-devtools-for-tabs'] });
782
- 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);
783
805
  }
784
806
 
785
- function createServerContext(sys, sendMsg, devServerConfig, buildResultsResolves, compilerRequestResolves) {
786
- const logRequest = (req, status) => {
787
- if (devServerConfig) {
788
- sendMsg({
789
- requestLog: {
790
- method: req.method || '?',
791
- url: req.pathname || '?',
792
- status,
793
- },
794
- });
795
- }
796
- };
797
- const serve500 = (req, res, error, xSource) => {
798
- try {
799
- res.writeHead(500, responseHeaders({
800
- 'content-type': 'text/plain; charset=utf-8',
801
- 'x-source': xSource,
802
- }));
803
- res.write(util__default['default'].inspect(error));
804
- res.end();
805
- logRequest(req, 500);
806
- }
807
- catch (e) {
808
- sendMsg({ error: { message: 'serve500: ' + e } });
809
- }
810
- };
811
- const serve404 = (req, res, xSource, content = null) => {
812
- try {
813
- if (req.pathname === '/favicon.ico') {
814
- const defaultFavicon = path__default['default'].join(devServerConfig.devServerDir, 'static', 'favicon.ico');
815
- res.writeHead(200, responseHeaders({
816
- 'content-type': 'image/x-icon',
817
- 'x-source': `favicon: ${xSource}`,
818
- }));
819
- const rs = fs__default$1['default'].createReadStream(defaultFavicon);
820
- rs.on('error', (err) => {
821
- res.writeHead(404, responseHeaders({
822
- 'content-type': 'text/plain; charset=utf-8',
823
- 'x-source': `createReadStream error: ${err}, ${xSource}`,
824
- }));
825
- res.write(util__default['default'].inspect(err));
826
- res.end();
827
- });
828
- rs.pipe(res);
829
- return;
830
- }
831
- if (content == null) {
832
- content = ['404 File Not Found', 'Url: ' + req.pathname, 'File: ' + req.filePath].join('\n');
833
- }
834
- res.writeHead(404, responseHeaders({
835
- 'content-type': 'text/plain; charset=utf-8',
836
- 'x-source': xSource,
837
- }));
838
- res.write(content);
839
- res.end();
840
- logRequest(req, 400);
841
- }
842
- catch (e) {
843
- serve500(req, res, e, xSource);
844
- }
845
- };
846
- const serve302 = (req, res, pathname = null) => {
847
- logRequest(req, 302);
848
- res.writeHead(302, { location: pathname || devServerConfig.basePath || '/' });
849
- res.end();
850
- };
851
- const getBuildResults = () => new Promise((resolve, reject) => {
852
- if (serverCtx.isServerListening) {
853
- buildResultsResolves.push({ resolve, reject });
854
- sendMsg({ requestBuildResults: true });
855
- }
856
- else {
857
- reject('dev server closed');
858
- }
859
- });
860
- const getCompilerRequest = (compilerRequestPath) => new Promise((resolve, reject) => {
861
- if (serverCtx.isServerListening) {
862
- compilerRequestResolves.push({
863
- path: compilerRequestPath,
864
- resolve,
865
- reject,
866
- });
867
- sendMsg({ compilerRequestPath });
868
- }
869
- else {
870
- reject('dev server closed');
871
- }
872
- });
873
- const serverCtx = {
874
- connectorHtml: null,
875
- dirTemplate: null,
876
- getBuildResults,
877
- getCompilerRequest,
878
- isServerListening: false,
879
- logRequest,
880
- prerenderConfig: null,
881
- serve302,
882
- serve404,
883
- serve500,
884
- sys,
885
- };
886
- 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;
887
909
  }
888
910
 
889
- async function serveOpenInEditor(serverCtx, req, res) {
890
- let status = 200;
891
- const data = {};
892
- try {
893
- const editors = await getEditors();
894
- if (editors.length > 0) {
895
- await parseData(editors, serverCtx.sys, req, data);
896
- await openDataInEditor(data);
897
- }
898
- else {
899
- data.error = `no editors available`;
900
- }
901
- }
902
- catch (e) {
903
- data.error = e + '';
904
- status = 500;
905
- }
906
- serverCtx.logRequest(req, status);
907
- res.writeHead(status, responseHeaders({
908
- 'content-type': 'application/json; charset=utf-8',
909
- }));
910
- res.write(JSON.stringify(data, null, 2));
911
- res.end();
912
- }
913
- async function parseData(editors, sys, req, data) {
914
- const qs = req.searchParams;
915
- if (!qs.has('file')) {
916
- data.error = `missing file`;
917
- return;
918
- }
919
- data.file = qs.get('file');
920
- if (qs.has('line') && !isNaN(qs.get('line'))) {
921
- data.line = parseInt(qs.get('line'), 10);
922
- }
923
- if (typeof data.line !== 'number' || data.line < 1) {
924
- data.line = 1;
925
- }
926
- if (qs.has('column') && !isNaN(qs.get('column'))) {
927
- data.column = parseInt(qs.get('column'), 10);
928
- }
929
- if (typeof data.column !== 'number' || data.column < 1) {
930
- data.column = 1;
931
- }
932
- let editor = qs.get('editor');
933
- if (typeof editor === 'string') {
934
- editor = editor.trim().toLowerCase();
935
- if (editors.some((e) => e.id === editor)) {
936
- data.editor = editor;
937
- }
938
- else {
939
- data.error = `invalid editor: ${editor}`;
940
- return;
941
- }
942
- }
943
- else {
944
- data.editor = editors[0].id;
945
- }
946
- const stat = await sys.stat(data.file);
947
- data.exists = stat.isFile;
948
- }
949
- async function openDataInEditor(data) {
950
- if (!data.exists || data.error) {
951
- return;
952
- }
953
- try {
954
- const opts = {
955
- editor: data.editor,
956
- };
957
- const editor = openInEditorApi__default['default'].configure(opts, (err) => (data.error = err + ''));
958
- if (data.error) {
959
- return;
960
- }
961
- data.open = `${data.file}:${data.line}:${data.column}`;
962
- await editor.open(data.open);
963
- }
964
- catch (e) {
965
- data.error = e + '';
966
- }
967
- }
968
- let editors = null;
969
- function getEditors() {
970
- if (!editors) {
971
- editors = new Promise(async (resolve) => {
972
- const editors = [];
973
- try {
974
- await Promise.all(Object.keys(openInEditorApi__default['default'].editors).map(async (editorId) => {
975
- const isSupported = await isEditorSupported(editorId);
976
- editors.push({
977
- id: editorId,
978
- priority: EDITOR_PRIORITY[editorId],
979
- supported: isSupported,
980
- });
981
- }));
982
- }
983
- catch (e) { }
984
- resolve(editors
985
- .filter((e) => e.supported)
986
- .sort((a, b) => {
987
- if (a.priority < b.priority)
988
- return -1;
989
- if (a.priority > b.priority)
990
- return 1;
991
- return 0;
992
- })
993
- .map((e) => {
994
- return {
995
- id: e.id,
996
- name: EDITORS[e.id],
997
- };
998
- }));
999
- });
1000
- }
1001
- return editors;
1002
- }
1003
- async function isEditorSupported(editorId) {
1004
- let isSupported = false;
1005
- try {
1006
- await openInEditorApi__default['default'].editors[editorId].detect();
1007
- isSupported = true;
1008
- }
1009
- catch (e) { }
1010
- return isSupported;
1011
- }
1012
- const EDITORS = {
1013
- atom: 'Atom',
1014
- code: 'Code',
1015
- emacs: 'Emacs',
1016
- idea14ce: 'IDEA 14 Community Edition',
1017
- phpstorm: 'PhpStorm',
1018
- sublime: 'Sublime',
1019
- webstorm: 'WebStorm',
1020
- vim: 'Vim',
1021
- visualstudio: 'Visual Studio',
1022
- };
1023
- const EDITOR_PRIORITY = {
1024
- code: 1,
1025
- atom: 2,
1026
- sublime: 3,
1027
- visualstudio: 4,
1028
- idea14ce: 5,
1029
- webstorm: 6,
1030
- phpstorm: 7,
1031
- vim: 8,
1032
- 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,
1033
1055
  };
1034
1056
 
1035
- async function serveFile(devServerConfig, serverCtx, req, res) {
1036
- try {
1037
- if (isSimpleText(req.filePath)) {
1038
- // easy text file, use the internal cache
1039
- let content = await serverCtx.sys.readFile(req.filePath, 'utf8');
1040
- if (devServerConfig.websocket && isHtmlFile(req.filePath) && !isDevServerClient(req.pathname)) {
1041
- // auto inject our dev server script
1042
- content = appendDevServerClientScript(devServerConfig, req, content);
1043
- }
1044
- else if (isCssFile(req.filePath)) {
1045
- content = updateStyleUrls(req.url, content);
1046
- }
1047
- if (shouldCompress(devServerConfig, req)) {
1048
- // let's gzip this well known web dev text file
1049
- res.writeHead(200, responseHeaders({
1050
- 'content-type': getContentType(req.filePath) + '; charset=utf-8',
1051
- 'content-encoding': 'gzip',
1052
- vary: 'Accept-Encoding',
1053
- }));
1054
- zlib__namespace.gzip(content, { level: 9 }, (_, data) => {
1055
- res.end(data);
1056
- });
1057
- }
1058
- else {
1059
- // let's not gzip this file
1060
- res.writeHead(200, responseHeaders({
1061
- 'content-type': getContentType(req.filePath) + '; charset=utf-8',
1062
- 'content-length': buffer.Buffer.byteLength(content, 'utf8'),
1063
- }));
1064
- res.write(content);
1065
- res.end();
1066
- }
1067
- }
1068
- else {
1069
- // non-well-known text file or other file, probably best we use a stream
1070
- // but don't bother trying to gzip this file for the dev server
1071
- res.writeHead(200, responseHeaders({
1072
- 'content-type': getContentType(req.filePath),
1073
- 'content-length': req.stats.size,
1074
- }));
1075
- fs__default$1['default'].createReadStream(req.filePath).pipe(res);
1076
- }
1077
- serverCtx.logRequest(req, 200);
1078
- }
1079
- catch (e) {
1080
- serverCtx.serve500(req, res, e, 'serveFile');
1081
- }
1082
- }
1083
- function updateStyleUrls(url, oldCss) {
1084
- const versionId = url.searchParams.get('s-hmr');
1085
- const hmrUrls = url.searchParams.get('s-hmr-urls');
1086
- if (versionId && hmrUrls) {
1087
- hmrUrls.split(',').forEach((hmrUrl) => {
1088
- urlVersionIds.set(hmrUrl, versionId);
1089
- });
1090
- }
1091
- const reg = /url\((['"]?)(.*)\1\)/gi;
1092
- let result;
1093
- let newCss = oldCss;
1094
- while ((result = reg.exec(oldCss)) !== null) {
1095
- const oldUrl = result[2];
1096
- const parsedUrl = new URL(oldUrl, url);
1097
- const fileName = path__default['default'].basename(parsedUrl.pathname);
1098
- const versionId = urlVersionIds.get(fileName);
1099
- if (!versionId) {
1100
- continue;
1101
- }
1102
- parsedUrl.searchParams.set('s-hmr', versionId);
1103
- newCss = newCss.replace(oldUrl, parsedUrl.pathname);
1104
- }
1105
- return newCss;
1106
- }
1107
- const urlVersionIds = new Map();
1108
- function appendDevServerClientScript(devServerConfig, req, content) {
1109
- var _a, _b, _c;
1110
- 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']);
1111
- 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>`;
1112
- return appendDevServerClientIframe(content, iframe);
1113
- }
1114
- function appendDevServerClientIframe(content, iframe) {
1115
- if (content.includes('</body>')) {
1116
- return content.replace('</body>', `${iframe}</body>`);
1117
- }
1118
- if (content.includes('</html>')) {
1119
- return content.replace('</html>', `${iframe}</html>`);
1120
- }
1121
- 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}`;
1122
1144
  }
1123
1145
 
1124
- async function serveDevClient(devServerConfig, serverCtx, req, res) {
1125
- try {
1126
- if (isOpenInEditor(req.pathname)) {
1127
- return serveOpenInEditor(serverCtx, req, res);
1128
- }
1129
- if (isDevServerClient(req.pathname)) {
1130
- return serveDevClientScript(devServerConfig, serverCtx, req, res);
1131
- }
1132
- if (isInitialDevServerLoad(req.pathname)) {
1133
- req.filePath = path__default['default'].join(devServerConfig.devServerDir, 'templates', 'initial-load.html');
1134
- }
1135
- else {
1136
- const staticFile = req.pathname.replace(DEV_SERVER_URL + '/', '');
1137
- req.filePath = path__default['default'].join(devServerConfig.devServerDir, 'static', staticFile);
1138
- }
1139
- try {
1140
- req.stats = await serverCtx.sys.stat(req.filePath);
1141
- if (req.stats.isFile) {
1142
- return serveFile(devServerConfig, serverCtx, req, res);
1143
- }
1144
- return serverCtx.serve404(req, res, 'serveDevClient not file');
1145
- }
1146
- catch (e) {
1147
- return serverCtx.serve404(req, res, `serveDevClient stats error ${e}`);
1148
- }
1149
- }
1150
- catch (e) {
1151
- return serverCtx.serve500(req, res, e, 'serveDevClient');
1152
- }
1153
- }
1154
- async function serveDevClientScript(devServerConfig, serverCtx, req, res) {
1155
- try {
1156
- if (serverCtx.connectorHtml == null) {
1157
- const filePath = path__default['default'].join(devServerConfig.devServerDir, 'connector.html');
1158
- serverCtx.connectorHtml = serverCtx.sys.readFileSync(filePath, 'utf8');
1159
- if (typeof serverCtx.connectorHtml !== 'string') {
1160
- return serverCtx.serve404(req, res, `serveDevClientScript`);
1161
- }
1162
- const devClientConfig = {
1163
- basePath: devServerConfig.basePath,
1164
- editors: await getEditors(),
1165
- reloadStrategy: devServerConfig.reloadStrategy,
1166
- };
1167
- serverCtx.connectorHtml = serverCtx.connectorHtml.replace('window.__DEV_CLIENT_CONFIG__', JSON.stringify(devClientConfig));
1168
- }
1169
- res.writeHead(200, responseHeaders({
1170
- 'content-type': 'text/html; charset=utf-8',
1171
- }));
1172
- res.write(serverCtx.connectorHtml);
1173
- res.end();
1174
- }
1175
- catch (e) {
1176
- return serverCtx.serve500(req, res, e, `serveDevClientScript`);
1177
- }
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
+ }
1178
1200
  }
1179
1201
 
1180
- async function serveDevNodeModule(serverCtx, req, res) {
1181
- try {
1182
- const results = await serverCtx.getCompilerRequest(req.pathname);
1183
- const headers = {
1184
- 'content-type': 'application/javascript; charset=utf-8',
1185
- 'content-length': Buffer.byteLength(results.content, 'utf8'),
1186
- 'x-dev-node-module-id': results.nodeModuleId,
1187
- 'x-dev-node-module-version': results.nodeModuleVersion,
1188
- 'x-dev-node-module-resolved-path': results.nodeResolvedPath,
1189
- 'x-dev-node-module-cache-path': results.cachePath,
1190
- 'x-dev-node-module-cache-hit': results.cacheHit,
1191
- };
1192
- res.writeHead(results.status, responseHeaders(headers));
1193
- res.write(results.content);
1194
- res.end();
1195
- }
1196
- catch (e) {
1197
- serverCtx.serve500(req, res, e, `serveDevNodeModule`);
1198
- }
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
+ }
1199
1221
  }
1200
1222
 
1201
- async function serveDirectoryIndex(devServerConfig, serverCtx, req, res) {
1202
- const indexFilePath = path__default['default'].join(req.filePath, 'index.html');
1203
- req.stats = await serverCtx.sys.stat(indexFilePath);
1204
- if (req.stats.isFile) {
1205
- req.filePath = indexFilePath;
1206
- return serveFile(devServerConfig, serverCtx, req, res);
1207
- }
1208
- if (!req.pathname.endsWith('/')) {
1209
- return serverCtx.serve302(req, res, req.pathname + '/');
1210
- }
1211
- try {
1212
- const dirFilePaths = await serverCtx.sys.readDir(req.filePath);
1213
- try {
1214
- if (serverCtx.dirTemplate == null) {
1215
- const dirTemplatePath = path__default['default'].join(devServerConfig.devServerDir, 'templates', 'directory-index.html');
1216
- serverCtx.dirTemplate = serverCtx.sys.readFileSync(dirTemplatePath);
1217
- }
1218
- const files = await getFiles(serverCtx.sys, req.url, dirFilePaths);
1219
- const templateHtml = serverCtx.dirTemplate
1220
- .replace('{{title}}', getTitle(req.pathname))
1221
- .replace('{{nav}}', getName(req.pathname))
1222
- .replace('{{files}}', files);
1223
- serverCtx.logRequest(req, 200);
1224
- res.writeHead(200, responseHeaders({
1225
- 'content-type': 'text/html; charset=utf-8',
1226
- 'x-directory-index': req.pathname,
1227
- }));
1228
- res.write(templateHtml);
1229
- res.end();
1230
- }
1231
- catch (e) {
1232
- return serverCtx.serve500(req, res, e, 'serveDirectoryIndex');
1233
- }
1234
- }
1235
- catch (e) {
1236
- return serverCtx.serve404(req, res, 'serveDirectoryIndex');
1237
- }
1238
- }
1239
- async function getFiles(sys, baseUrl, dirItemNames) {
1240
- const items = await getDirectoryItems(sys, baseUrl, dirItemNames);
1241
- if (baseUrl.pathname !== '/') {
1242
- items.unshift({
1243
- isDirectory: true,
1244
- pathname: '../',
1245
- name: '..',
1246
- });
1247
- }
1248
- return items
1249
- .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) => {
1250
1272
  return `
1251
1273
  <li class="${item.isDirectory ? 'directory' : 'file'}">
1252
1274
  <a href="${item.pathname}">
1253
1275
  <span class="icon"></span>
1254
1276
  <span>${item.name}</span>
1255
1277
  </a>
1256
- </li>`;
1257
- })
1258
- .join('');
1259
- }
1260
- async function getDirectoryItems(sys, baseUrl, dirFilePaths) {
1261
- const items = await Promise.all(dirFilePaths.map(async (dirFilePath) => {
1262
- const fileName = path__default['default'].basename(dirFilePath);
1263
- const url = new URL(fileName, baseUrl);
1264
- const stats = await sys.stat(dirFilePath);
1265
- const item = {
1266
- name: fileName,
1267
- pathname: url.pathname,
1268
- isDirectory: stats.isDirectory,
1269
- };
1270
- return item;
1271
- }));
1272
- return items;
1273
- }
1274
- function getTitle(pathName) {
1275
- return pathName;
1276
- }
1277
- function getName(pathName) {
1278
- const dirs = pathName.split('/');
1279
- dirs.pop();
1280
- let url = '';
1281
- return (dirs
1282
- .map((dir, index) => {
1283
- url += dir + '/';
1284
- const text = index === 0 ? `~` : dir;
1285
- return `<a href="${url}">${text}</a>`;
1286
- })
1287
- .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>');
1288
1310
  }
1289
1311
 
1290
- async function ssrPageRequest(devServerConfig, serverCtx, req, res) {
1291
- try {
1292
- let status = 500;
1293
- let content = '';
1294
- const { hydrateApp, srcIndexHtml, diagnostics } = await setupHydrateApp(devServerConfig, serverCtx);
1295
- if (!diagnostics.some((diagnostic) => diagnostic.level === 'error')) {
1296
- try {
1297
- const opts = getSsrHydrateOptions(devServerConfig, serverCtx, req.url);
1298
- const ssrResults = await hydrateApp.renderToString(srcIndexHtml, opts);
1299
- diagnostics.push(...ssrResults.diagnostics);
1300
- status = ssrResults.httpStatus;
1301
- content = ssrResults.html;
1302
- }
1303
- catch (e) {
1304
- catchError(diagnostics, e);
1305
- }
1306
- }
1307
- if (diagnostics.some((diagnostic) => diagnostic.level === 'error')) {
1308
- content = getSsrErrorContent(diagnostics);
1309
- status = 500;
1310
- }
1311
- if (devServerConfig.websocket) {
1312
- content = appendDevServerClientScript(devServerConfig, req, content);
1313
- }
1314
- serverCtx.logRequest(req, status);
1315
- res.writeHead(status, responseHeaders({
1316
- 'content-type': 'text/html; charset=utf-8',
1317
- 'content-length': Buffer.byteLength(content, 'utf8'),
1318
- }));
1319
- res.write(content);
1320
- res.end();
1321
- }
1322
- catch (e) {
1323
- serverCtx.serve500(req, res, e, `ssrPageRequest`);
1324
- }
1325
- }
1326
- async function ssrStaticDataRequest(devServerConfig, serverCtx, req, res) {
1327
- try {
1328
- const data = {};
1329
- let httpCache = false;
1330
- const { hydrateApp, srcIndexHtml, diagnostics } = await setupHydrateApp(devServerConfig, serverCtx);
1331
- if (!diagnostics.some((diagnostic) => diagnostic.level === 'error')) {
1332
- try {
1333
- const { ssrPath, hasQueryString } = getSsrStaticDataPath(req);
1334
- const url = new URL(ssrPath, req.url);
1335
- const opts = getSsrHydrateOptions(devServerConfig, serverCtx, url);
1336
- const ssrResults = await hydrateApp.renderToString(srcIndexHtml, opts);
1337
- diagnostics.push(...ssrResults.diagnostics);
1338
- ssrResults.staticData.forEach((s) => {
1339
- if (s.type === 'application/json') {
1340
- data[s.id] = JSON.parse(s.content);
1341
- }
1342
- else {
1343
- data[s.id] = s.content;
1344
- }
1345
- });
1346
- data.components = ssrResults.components.map((c) => c.tag).sort();
1347
- httpCache = hasQueryString;
1348
- }
1349
- catch (e) {
1350
- catchError(diagnostics, e);
1351
- }
1352
- }
1353
- if (diagnostics.length > 0) {
1354
- data.diagnostics = diagnostics;
1355
- }
1356
- const status = diagnostics.some((diagnostic) => diagnostic.level === 'error') ? 500 : 200;
1357
- const content = JSON.stringify(data);
1358
- serverCtx.logRequest(req, status);
1359
- res.writeHead(status, responseHeaders({
1360
- 'content-type': 'application/json; charset=utf-8',
1361
- 'content-length': Buffer.byteLength(content, 'utf8'),
1362
- }, httpCache && status === 200));
1363
- res.write(content);
1364
- res.end();
1365
- }
1366
- catch (e) {
1367
- serverCtx.serve500(req, res, e, `ssrStaticDataRequest`);
1368
- }
1369
- }
1370
- async function setupHydrateApp(devServerConfig, serverCtx) {
1371
- let srcIndexHtml = null;
1372
- let hydrateApp = null;
1373
- const buildResults = await serverCtx.getBuildResults();
1374
- const diagnostics = [];
1375
- if (serverCtx.prerenderConfig == null && isString(devServerConfig.prerenderConfig)) {
1376
- const compilerPath = path__default['default'].join(devServerConfig.devServerDir, '..', 'compiler', 'rindo.js');
1377
- const compiler = require(compilerPath);
1378
- const prerenderConfigResults = compiler.nodeRequire(devServerConfig.prerenderConfig);
1379
- diagnostics.push(...prerenderConfigResults.diagnostics);
1380
- if (prerenderConfigResults.module && prerenderConfigResults.module.config) {
1381
- serverCtx.prerenderConfig = prerenderConfigResults.module.config;
1382
- }
1383
- }
1384
- if (!isString(buildResults.hydrateAppFilePath)) {
1385
- diagnostics.push({ messageText: `Missing hydrateAppFilePath`, level: `error`, type: `ssr`, lines: [] });
1386
- }
1387
- else if (!isString(devServerConfig.srcIndexHtml)) {
1388
- diagnostics.push({ messageText: `Missing srcIndexHtml`, level: `error`, type: `ssr`, lines: [] });
1389
- }
1390
- else {
1391
- srcIndexHtml = await serverCtx.sys.readFile(devServerConfig.srcIndexHtml);
1392
- if (!isString(srcIndexHtml)) {
1393
- diagnostics.push({
1394
- level: `error`,
1395
- lines: [],
1396
- messageText: `Unable to load src index html: ${devServerConfig.srcIndexHtml}`,
1397
- type: `ssr`,
1398
- });
1399
- }
1400
- else {
1401
- // ensure we cleared out node's internal require() cache for this file
1402
- const hydrateAppFilePath = path__default['default'].resolve(buildResults.hydrateAppFilePath);
1403
- // brute force way of clearning node's module cache
1404
- // not using `delete require.cache[id]` since it'll cause memory leaks
1405
- require.cache = {};
1406
- const Module = require('module');
1407
- Module._cache[hydrateAppFilePath] = undefined;
1408
- hydrateApp = require(hydrateAppFilePath);
1409
- }
1410
- }
1411
- return {
1412
- hydrateApp,
1413
- srcIndexHtml,
1414
- diagnostics,
1415
- };
1416
- }
1417
- function getSsrHydrateOptions(devServerConfig, serverCtx, url) {
1418
- const opts = {
1419
- url: url.href,
1420
- addModulePreloads: false,
1421
- approximateLineWidth: 120,
1422
- inlineExternalStyleSheets: false,
1423
- minifyScriptElements: false,
1424
- minifyStyleElements: false,
1425
- removeAttributeQuotes: false,
1426
- removeBooleanAttributeQuotes: false,
1427
- removeEmptyAttributes: false,
1428
- removeHtmlComments: false,
1429
- prettyHtml: true,
1430
- };
1431
- const prerenderConfig = serverCtx === null || serverCtx === void 0 ? void 0 : serverCtx.prerenderConfig;
1432
- if (isFunction(prerenderConfig === null || prerenderConfig === void 0 ? void 0 : prerenderConfig.hydrateOptions)) {
1433
- const userOpts = prerenderConfig.hydrateOptions(url);
1434
- if (userOpts) {
1435
- Object.assign(opts, userOpts);
1436
- }
1437
- }
1438
- if (isFunction(serverCtx.sys.applyPrerenderGlobalPatch)) {
1439
- const orgBeforeHydrate = opts.beforeHydrate;
1440
- opts.beforeHydrate = (document) => {
1441
- // patch this new window with the fetch global from node-fetch
1442
- const devServerBaseUrl = new URL(devServerConfig.browserUrl);
1443
- const devServerHostUrl = devServerBaseUrl.origin;
1444
- serverCtx.sys.applyPrerenderGlobalPatch({
1445
- devServerHostUrl: devServerHostUrl,
1446
- window: document.defaultView,
1447
- });
1448
- if (typeof orgBeforeHydrate === 'function') {
1449
- return orgBeforeHydrate(document);
1450
- }
1451
- };
1452
- }
1453
- return opts;
1454
- }
1455
- 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) {
1456
1478
  return `<!doctype html>
1457
1479
  <html>
1458
1480
  <head>
@@ -1471,330 +1493,330 @@ function getSsrErrorContent(diagnostics) {
1471
1493
  </p>
1472
1494
  `)}
1473
1495
  </body>
1474
- </html>`;
1496
+ </html>`;
1475
1497
  }
1476
1498
 
1477
- function createRequestHandler(devServerConfig, serverCtx) {
1478
- let userRequestHandler = null;
1479
- if (typeof devServerConfig.requestListenerPath === 'string') {
1480
- userRequestHandler = require(devServerConfig.requestListenerPath);
1481
- }
1482
- return async function (incomingReq, res) {
1483
- async function defaultHandler() {
1484
- try {
1485
- const req = normalizeHttpRequest(devServerConfig, incomingReq);
1486
- if (!req.url) {
1487
- return serverCtx.serve302(req, res);
1488
- }
1489
- if (isDevClient(req.pathname) && devServerConfig.websocket) {
1490
- return serveDevClient(devServerConfig, serverCtx, req, res);
1491
- }
1492
- if (isDevModule(req.pathname)) {
1493
- return serveDevNodeModule(serverCtx, req, res);
1494
- }
1495
- if (!isValidUrlBasePath(devServerConfig.basePath, req.url)) {
1496
- return serverCtx.serve404(req, res, `invalid basePath`, `404 File Not Found, base path: ${devServerConfig.basePath}`);
1497
- }
1498
- if (devServerConfig.ssr) {
1499
- if (isExtensionLessPath(req.url.pathname)) {
1500
- return ssrPageRequest(devServerConfig, serverCtx, req, res);
1501
- }
1502
- if (isSsrStaticDataPath(req.url.pathname)) {
1503
- return ssrStaticDataRequest(devServerConfig, serverCtx, req, res);
1504
- }
1505
- }
1506
- req.stats = await serverCtx.sys.stat(req.filePath);
1507
- if (req.stats.isFile) {
1508
- return serveFile(devServerConfig, serverCtx, req, res);
1509
- }
1510
- if (req.stats.isDirectory) {
1511
- return serveDirectoryIndex(devServerConfig, serverCtx, req, res);
1512
- }
1513
- const xSource = ['notfound'];
1514
- const validHistoryApi = isValidHistoryApi(devServerConfig, req);
1515
- xSource.push(`validHistoryApi: ${validHistoryApi}`);
1516
- if (validHistoryApi) {
1517
- try {
1518
- const indexFilePath = path__default['default'].join(devServerConfig.root, devServerConfig.historyApiFallback.index);
1519
- xSource.push(`indexFilePath: ${indexFilePath}`);
1520
- req.stats = await serverCtx.sys.stat(indexFilePath);
1521
- if (req.stats.isFile) {
1522
- req.filePath = indexFilePath;
1523
- return serveFile(devServerConfig, serverCtx, req, res);
1524
- }
1525
- }
1526
- catch (e) {
1527
- xSource.push(`notfound error: ${e}`);
1528
- }
1529
- }
1530
- return serverCtx.serve404(req, res, xSource.join(', '));
1531
- }
1532
- catch (e) {
1533
- return serverCtx.serve500(incomingReq, res, e, `not found error`);
1534
- }
1535
- }
1536
- if (typeof userRequestHandler === 'function') {
1537
- await userRequestHandler(incomingReq, res, defaultHandler);
1538
- }
1539
- else {
1540
- await defaultHandler();
1541
- }
1542
- };
1543
- }
1544
- function isValidUrlBasePath(basePath, url) {
1545
- // normalize the paths to always end with a slash for the check
1546
- let pathname = url.pathname;
1547
- if (!pathname.endsWith('/')) {
1548
- pathname += '/';
1549
- }
1550
- if (!basePath.endsWith('/')) {
1551
- basePath += '/';
1552
- }
1553
- return pathname.startsWith(basePath);
1554
- }
1555
- function normalizeHttpRequest(devServerConfig, incomingReq) {
1556
- const req = {
1557
- method: (incomingReq.method || 'GET').toUpperCase(),
1558
- headers: incomingReq.headers,
1559
- acceptHeader: (incomingReq.headers && typeof incomingReq.headers.accept === 'string' && incomingReq.headers.accept) || '',
1560
- host: (incomingReq.headers && typeof incomingReq.headers.host === 'string' && incomingReq.headers.host) || null,
1561
- url: null,
1562
- searchParams: null,
1563
- };
1564
- const incomingUrl = (incomingReq.url || '').trim() || null;
1565
- if (incomingUrl) {
1566
- if (req.host) {
1567
- req.url = new URL(incomingReq.url, `http://${req.host}`);
1568
- }
1569
- else {
1570
- req.url = new URL(incomingReq.url, `http://rindojs-dev.web.app`);
1571
- }
1572
- req.searchParams = req.url.searchParams;
1573
- }
1574
- if (req.url) {
1575
- const parts = req.url.pathname.replace(/\\/g, '/').split('/');
1576
- req.pathname = parts.map((part) => decodeURIComponent(part)).join('/');
1577
- if (req.pathname.length > 0 && !isDevClient(req.pathname)) {
1578
- req.pathname = '/' + req.pathname.substring(devServerConfig.basePath.length);
1579
- }
1580
- req.filePath = normalizePath(path__default['default'].normalize(path__default['default'].join(devServerConfig.root, path__default['default'].relative('/', req.pathname))));
1581
- }
1582
- return req;
1583
- }
1584
- function isValidHistoryApi(devServerConfig, req) {
1585
- if (!devServerConfig.historyApiFallback) {
1586
- return false;
1587
- }
1588
- if (req.method !== 'GET') {
1589
- return false;
1590
- }
1591
- if (!req.acceptHeader.includes('text/html')) {
1592
- return false;
1593
- }
1594
- if (!devServerConfig.historyApiFallback.disableDotRule && req.pathname.includes('.')) {
1595
- return false;
1596
- }
1597
- 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;
1598
1620
  }
1599
1621
 
1600
- function createHttpServer(devServerConfig, serverCtx) {
1601
- // create our request handler
1602
- const reqHandler = createRequestHandler(devServerConfig, serverCtx);
1603
- const credentials = devServerConfig.https;
1604
- return credentials ? https__namespace.createServer(credentials, reqHandler) : http__namespace.createServer(reqHandler);
1605
- }
1606
- async function findClosestOpenPort(host, port) {
1607
- async function t(portToCheck) {
1608
- const isTaken = await isPortTaken(host, portToCheck);
1609
- if (!isTaken) {
1610
- return portToCheck;
1611
- }
1612
- return t(portToCheck + 1);
1613
- }
1614
- return t(port);
1615
- }
1616
- function isPortTaken(host, port) {
1617
- return new Promise((resolve, reject) => {
1618
- const tester = net__namespace
1619
- .createServer()
1620
- .once('error', () => {
1621
- resolve(true);
1622
- })
1623
- .once('listening', () => {
1624
- tester
1625
- .once('close', () => {
1626
- resolve(false);
1627
- })
1628
- .close();
1629
- })
1630
- .on('error', (err) => {
1631
- reject(err);
1632
- })
1633
- .listen(port, host);
1634
- });
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
+ });
1635
1657
  }
1636
1658
 
1637
- function createWebSocket(httpServer, onMessageFromClient) {
1638
- const wsConfig = {
1639
- server: httpServer,
1640
- };
1641
- const wsServer = new ws__namespace.Server(wsConfig);
1642
- function heartbeat() {
1643
- // we need to coerce the `ws` type to our custom `DevWS` type here, since
1644
- // this function is going to be passed in to `ws.on('pong'` which expects
1645
- // to be passed a functon where `this` is bound to `ws`.
1646
- this.isAlive = true;
1647
- }
1648
- wsServer.on('connection', (ws) => {
1649
- ws.on('message', (data) => {
1650
- // the server process has received a message from the browser
1651
- // pass the message received from the browser to the main cli process
1652
- try {
1653
- onMessageFromClient(JSON.parse(data.toString()));
1654
- }
1655
- catch (e) {
1656
- console.error(e);
1657
- }
1658
- });
1659
- ws.isAlive = true;
1660
- ws.on('pong', heartbeat);
1661
- // ignore invalid close frames sent by Safari 15
1662
- ws.on('error', console.error);
1663
- });
1664
- const pingInternval = setInterval(() => {
1665
- wsServer.clients.forEach((ws) => {
1666
- if (!ws.isAlive) {
1667
- return ws.close(1000);
1668
- }
1669
- ws.isAlive = false;
1670
- ws.ping(noop);
1671
- });
1672
- }, 10000);
1673
- return {
1674
- sendToBrowser: (msg) => {
1675
- if (msg && wsServer && wsServer.clients) {
1676
- const data = JSON.stringify(msg);
1677
- wsServer.clients.forEach((ws) => {
1678
- if (ws.readyState === ws.OPEN) {
1679
- ws.send(data);
1680
- }
1681
- });
1682
- }
1683
- },
1684
- close: () => {
1685
- return new Promise((resolve, reject) => {
1686
- clearInterval(pingInternval);
1687
- wsServer.clients.forEach((ws) => {
1688
- ws.close(1000);
1689
- });
1690
- wsServer.close((err) => {
1691
- if (err) {
1692
- reject(err);
1693
- }
1694
- else {
1695
- resolve();
1696
- }
1697
- });
1698
- });
1699
- },
1700
- };
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
+ };
1701
1723
  }
1702
1724
 
1703
- function initServerProcess(sendMsg) {
1704
- let server = null;
1705
- let webSocket = null;
1706
- let serverCtx = null;
1707
- const buildResultsResolves = [];
1708
- const compilerRequestResolves = [];
1709
- const startServer = async (msg) => {
1710
- const devServerConfig = msg.startServer;
1711
- devServerConfig.port = await findClosestOpenPort(devServerConfig.address, devServerConfig.port);
1712
- devServerConfig.browserUrl = getBrowserUrl(devServerConfig.protocol, devServerConfig.address, devServerConfig.port, devServerConfig.basePath, '/');
1713
- devServerConfig.root = normalizePath(devServerConfig.root);
1714
- const sys = index_js.createNodeSys({ process });
1715
- serverCtx = createServerContext(sys, sendMsg, devServerConfig, buildResultsResolves, compilerRequestResolves);
1716
- server = createHttpServer(devServerConfig, serverCtx);
1717
- webSocket = devServerConfig.websocket ? createWebSocket(server, sendMsg) : null;
1718
- server.listen(devServerConfig.port, devServerConfig.address);
1719
- serverCtx.isServerListening = true;
1720
- if (devServerConfig.openBrowser) {
1721
- const initialLoadUrl = getBrowserUrl(devServerConfig.protocol, devServerConfig.address, devServerConfig.port, devServerConfig.basePath, devServerConfig.initialLoadUrl || DEV_SERVER_INIT_URL);
1722
- openInBrowser({ url: initialLoadUrl });
1723
- }
1724
- sendMsg({ serverStarted: devServerConfig });
1725
- };
1726
- const closeServer = () => {
1727
- const promises = [];
1728
- buildResultsResolves.forEach((r) => r.reject('dev server closed'));
1729
- buildResultsResolves.length = 0;
1730
- compilerRequestResolves.forEach((r) => r.reject('dev server closed'));
1731
- compilerRequestResolves.length = 0;
1732
- if (serverCtx) {
1733
- if (serverCtx.sys) {
1734
- promises.push(serverCtx.sys.destroy());
1735
- }
1736
- }
1737
- if (webSocket) {
1738
- promises.push(webSocket.close());
1739
- webSocket = null;
1740
- }
1741
- if (server) {
1742
- promises.push(new Promise((resolve) => {
1743
- server.close((err) => {
1744
- if (err) {
1745
- console.error(`close error: ${err}`);
1746
- }
1747
- resolve();
1748
- });
1749
- }));
1750
- }
1751
- Promise.all(promises).finally(() => {
1752
- sendMsg({
1753
- serverClosed: true,
1754
- });
1755
- });
1756
- };
1757
- const receiveMessageFromMain = (msg) => {
1758
- // the server process received a message from main thread
1759
- try {
1760
- if (msg) {
1761
- if (msg.startServer) {
1762
- startServer(msg);
1763
- }
1764
- else if (msg.closeServer) {
1765
- closeServer();
1766
- }
1767
- else if (msg.compilerRequestResults) {
1768
- for (let i = compilerRequestResolves.length - 1; i >= 0; i--) {
1769
- const r = compilerRequestResolves[i];
1770
- if (r.path === msg.compilerRequestResults.path) {
1771
- r.resolve(msg.compilerRequestResults);
1772
- compilerRequestResolves.splice(i, 1);
1773
- }
1774
- }
1775
- }
1776
- else if (serverCtx) {
1777
- if (msg.buildResults && !msg.isActivelyBuilding) {
1778
- buildResultsResolves.forEach((r) => r.resolve(msg.buildResults));
1779
- buildResultsResolves.length = 0;
1780
- }
1781
- if (webSocket) {
1782
- webSocket.sendToBrowser(msg);
1783
- }
1784
- }
1785
- }
1786
- }
1787
- catch (e) {
1788
- let stack = null;
1789
- if (e instanceof Error) {
1790
- stack = e.stack;
1791
- }
1792
- sendMsg({
1793
- error: { message: e + '', stack },
1794
- });
1795
- }
1796
- };
1797
- 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;
1798
1820
  }
1799
1821
 
1800
1822
  exports.initServerProcess = initServerProcess;