oox 0.3.0-beta12 → 0.3.0-beta14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/loader.mjs CHANGED
@@ -1,459 +1,379 @@
1
-
2
- import path from 'node:path'
3
-
4
- import os from 'node:os'
5
-
6
- import fs from 'node:fs'
7
-
8
- import { get as httpGet } from 'node:http'
9
-
10
- import { get as httpsGet } from 'node:https'
11
-
12
- import oox from '../index.mjs'
13
-
14
-
15
- /**
16
- * NodeJS versions < 16 dose not support loader chain
17
- */
18
- const NodeJSBigVersion = +process.versions.node.split('.').shift()
19
- const useCompatLoader = NodeJSBigVersion < 16
20
- const compatLoaders = []
21
- if ( useCompatLoader ) {
22
- const args = process.execArgv
23
- let index = -1, size = args.length
24
- let isLoaderTag = false
25
- while ( ++index < size ) {
26
-
27
- const symbol = args [ index ]
28
-
29
- if ( isLoaderTag ) {
30
-
31
- isLoaderTag = false
32
-
33
- if ( 'oox/loader' === symbol ) break
34
-
35
- compatLoaders.push ( await import ( symbol ) )
36
- }
37
-
38
- if ( [ '--loader', '--experimental-loader' ].includes ( symbol ) ) {
39
-
40
- isLoaderTag = true
41
- }
42
- }
43
-
44
- compatLoaders.reverse ( )
45
- }
46
-
47
-
48
-
49
- function generateRPCProxyScript ( name, attributes = [ ] ) {
50
-
51
- let attrExports = ''
52
-
53
- for ( const attr of attributes ) {
54
-
55
- attrExports += `\nexport const ${attr} = proxyer.${attr}\n`
56
- }
57
-
58
- const script = `
59
- import oox from 'oox'
60
- function RPC_${name} ( ) { }
61
- function dotCall ( name, action ) {
62
-
63
- return new Proxy ( RPC_${name}, {
64
-
65
- get ( target, key ) {
66
-
67
- return dotCall ( name, action ? action + '.' + key : key )
68
- },
69
-
70
- has ( target, key ) { return true },
71
-
72
- apply ( target, thisArg, args ) {
73
-
74
- return oox.rpc ( name, action, args )
75
- }
76
- } )
77
- }
78
- const proxyer = dotCall ( '${name}', '' )
79
- export default proxyer
80
- ${attrExports}
81
- `
82
-
83
- return script
84
- }
85
-
86
-
87
-
88
- function generateRPCProxyURL ( name, attributes ) {
89
-
90
- let searchText = ''
91
-
92
- if ( attributes.length ) {
93
-
94
- const search = new URLSearchParams ( )
95
-
96
- for ( const attr of attributes ) {
97
-
98
- search.append ( 'attr', attr )
99
- }
100
-
101
- searchText = '?' + search.toString ( )
102
- }
103
-
104
- return `oox://rpc/${name}.mjs${searchText}`
105
- }
106
-
107
-
108
-
109
- function isWebURL ( url ) {
110
-
111
- return url && ( url.startsWith ( 'https://' ) || url.startsWith ( 'http://' ) )
112
- }
113
-
114
-
115
-
116
- function isFileURL ( url ) {
117
-
118
- return url && url.startsWith ( 'file://' )
119
- }
120
-
121
-
122
-
123
- function isOOXURL ( url ) {
124
-
125
- return url && url.startsWith ( 'oox://' )
126
- }
127
-
128
-
129
-
130
- function pathCorrect ( path ) {
131
-
132
- return os.platform ( ) === 'win32' && path.startsWith ( '/' ) ? path.replace ( '/', '' ) : path
133
- }
134
-
135
-
136
-
137
- /**
138
- * make ESModule support dynamic <export *> attributes import
139
- * @param {string} importerSpecifier the import url
140
- * @param {string} specifier parentURL
141
- * @returns {string[]}
142
- */
143
- function getImportAttributes ( importerSpecifier, specifier ) {
144
-
145
- const attributes = [ ]
146
-
147
- const contents = fs.readFileSync ( importerSpecifier, 'utf-8' )
148
-
149
- // import * as xxx from "xxx"
150
- const mergeImport = contents.match ( new RegExp ( `import.+\\*\\s*as\\s+(\\w+)\\s+from\\s*["']${specifier}["']` ) )
151
-
152
- if ( mergeImport ) {
153
-
154
- const mergeName = mergeImport [ 1 ]
155
-
156
- const attributesIterator = contents.matchAll ( new RegExp ( `${mergeName}\\s*\\.\\s*(\\w+)`, 'g' ) )
157
-
158
- for ( const caseItem of attributesIterator ) {
159
-
160
- attributes.push ( caseItem [ 1 ] )
161
- }
162
- }
163
-
164
- // import { a, b, c } from 'xxx'
165
- const attributeImport = contents.match ( new RegExp ( `import.+{(.+)}\\s*from\\s*["']${specifier}["']` ) )
166
-
167
- if ( attributeImport ) {
168
-
169
- const definedAttributes = attributeImport [ 1 ].split ( ',' ).map ( v => v.trim ( ) ).filter ( v => !v.startsWith ( 'default' ) )
170
-
171
- attributes.push ( ...definedAttributes )
172
- }
173
-
174
- return Array.from ( new Set ( attributes ) )
175
- }
176
-
177
-
178
-
179
- /**
180
- * transform local call => RPC
181
- * @param {string} originalSpecifier
182
- * @param {string} specifier
183
- * @param {string} parentURL
184
- * @returns
185
- */
186
- function ooxRPCImportTransform ( originalSpecifier, specifier, parentURL ) {
187
-
188
- const { entryFile } = oox.config
189
-
190
- const url = new URL ( specifier )
191
-
192
- const groupURL = entryFile.group ? new URL ( '/' + entryFile.group, 'file://' ) : null
193
-
194
- // OOX RPC Proxy URL generation
195
- if ( !specifier.endsWith ( entryFile.path ) && groupURL && url.href.startsWith ( groupURL.href ) ) {
196
-
197
- const subSpecifier = url.href.slice ( groupURL.href.length )
198
-
199
- const matchResult = subSpecifier.match ( /^\/?([\w-]+)(\/index)?(\.((\w?js)|(ts\w?)))?$/ )
200
-
201
- if ( matchResult ) {
202
-
203
- const importerSpecifier = parentURL.replace ( os.platform ( ) === 'win32' ? /file:\/+/ : 'file://', '' )
204
-
205
- const attributes = getImportAttributes ( importerSpecifier, originalSpecifier )
206
-
207
- return { shortCircuit: true, url: generateRPCProxyURL ( matchResult [ 1 ], attributes ) }
208
- }
209
- }
210
-
211
- return null
212
- }
213
-
214
-
215
-
216
- /**
217
- * Directory import supported
218
- * Ignored '.ts|.js' suffix import supported
219
- * @param {string} specifier
220
- * @returns {string}
221
- */
222
- function directoryImportTransform ( specifier ) {
223
-
224
- let filename = new URL ( specifier ).pathname
225
-
226
- if ( os.platform ( ) === 'win32' && filename.startsWith ( '/' ) ) {
227
-
228
- filename = filename.replace ( '/', '' )
229
- }
230
-
231
- const stat0 = fs.statSync ( filename, {
232
- throwIfNoEntry: false
233
- } )
234
-
235
- if ( !stat0 || stat0.isDirectory ( ) ) {
236
-
237
- const justNeedEntry = stat0 && stat0.isDirectory ( )
238
-
239
- const dirname = justNeedEntry ? filename : path.dirname ( filename )
240
-
241
- const stat1 = justNeedEntry ? stat0 : fs.statSync ( dirname, {
242
- throwIfNoEntry: false
243
- } )
244
-
245
- // find entry file
246
- if ( stat1 && stat1.isDirectory ( ) ) {
247
-
248
- const paths = filename.split ( '/' )
249
-
250
- const filenameWithoutExtension = justNeedEntry ? 'index' : paths.pop ( )
251
-
252
- const matchEntryRegExp = new RegExp ( `^${filenameWithoutExtension}\\.((\\w?js)|(ts\\w?))$` )
253
-
254
- const entries = fs.readdirSync ( dirname )
255
-
256
- for ( const entry of entries ) {
257
-
258
- if ( !matchEntryRegExp.test ( entry ) ) continue
259
-
260
- paths.push ( entry )
261
-
262
- specifier = 'file://' + paths.join ( '/' )
263
-
264
- break
265
- }
266
- }
267
- }
268
-
269
- return specifier
270
- }
271
-
272
-
273
-
274
- /**
275
- * @param {string} specifier
276
- * @param {{
277
- * conditions: string[],
278
- * parentURL: string | undefined,
279
- * }} context
280
- * @param {Function} defaultResolve
281
- * @returns {Promise<{ url: string }>}
282
- */
283
- export async function resolve ( specifier, context, defaultResolve ) {
284
-
285
- const originalSpecifier = specifier
286
-
287
- const { parentURL } = context
288
-
289
- // HTTP & HTTPS
290
- if ( isWebURL ( specifier ) ) {
291
-
292
- return { shortCircuit: true, url: specifier }
293
- } else if ( isWebURL ( parentURL ) && ( specifier.startsWith ( '.' ) || specifier.startsWith ( '/' ) ) ) {
294
-
295
- return { shortCircuit: true, url: new URL ( specifier, parentURL ).href }
296
- }
297
-
298
- // OOX special alias for web package
299
- if ( specifier === 'oox' && !isFileURL ( parentURL ) ) {
300
-
301
- return {
302
- shortCircuit: true,
303
- url: await import.meta.resolve ( specifier )
304
- }
305
- }
306
-
307
- if ( !isFileURL ( specifier ) ) {
308
-
309
- try {
310
-
311
- specifier = ( await defaultResolve ( specifier, context, defaultResolve ) ).url
312
- } catch ( error ) {
313
-
314
- if ( !isFileURL ( parentURL ) ) throw error
315
-
316
- const _specifier = directoryImportTransform ( new URL ( specifier, parentURL ).href )
317
-
318
- if ( _specifier === specifier ) throw error
319
-
320
- specifier = _specifier
321
- }
322
- }
323
-
324
- const ooxRPCTransform = ooxRPCImportTransform ( originalSpecifier, specifier, parentURL )
325
-
326
- if ( ooxRPCTransform ) return ooxRPCTransform
327
-
328
- if ( useCompatLoader ) {
329
-
330
- const iterator = compatLoaders.values ( )
331
-
332
- const { value } = iterator.next ( )
333
-
334
- if ( value ) {
335
-
336
- return value.resolve ( specifier, context, ( specifier, context, nextResolve ) => {
337
-
338
- const { value } = iterator.next ( )
339
-
340
- if ( value ) return value.resolve ( specifier, context, nextResolve )
341
-
342
- return defaultResolve ( specifier, context, defaultResolve )
343
- } )
344
- }
345
- }
346
-
347
- return defaultResolve ( specifier, context, defaultResolve )
348
- }
349
-
350
-
351
-
352
- /**
353
- * @param {string} url
354
- * @param {{
355
- * format: string,
356
- * }} context If resolve settled with a `format`, that value is included here.
357
- * @param {Function} defaultLoad
358
- * @returns {Promise<{
359
- * format: string,
360
- * source: string | ArrayBuffer | SharedArrayBuffer | Uint8Array,
361
- * }>}
362
- */
363
- export async function load ( url, context, defaultLoad ) {
364
-
365
- if ( isWebURL ( url ) || isOOXURL ( url ) ) {
366
-
367
- return getSource ( url, context, defaultLoad )
368
- }
369
-
370
- if ( useCompatLoader ) {
371
-
372
- const iterator = compatLoaders.values ( )
373
-
374
- const { value } = iterator.next ( )
375
-
376
- if ( value ) {
377
-
378
- return value.load ( url, context, ( url, context, nextLoad ) => {
379
-
380
- const { value } = iterator.next ( )
381
-
382
- if ( value ) return value.load ( url, context, nextLoad )
383
-
384
- return defaultLoad ( url, context, defaultLoad )
385
- } )
386
- }
387
- }
388
-
389
- return defaultLoad ( url, context, defaultLoad )
390
- }
391
-
392
-
393
-
394
- export function getFormat ( url, context, defaultGetFormat ) {
395
-
396
- if ( isWebURL ( url ) || isOOXURL ( url ) ) {
397
-
398
- return {
399
- format: 'module'
400
- }
401
- }
402
-
403
- if ( useCompatLoader ) {
404
-
405
- const iterator = compatLoaders.values ( )
406
-
407
- const { value } = iterator.next ( )
408
-
409
- if ( value ) {
410
-
411
- return value.getFormat ( url, context, ( url, context, nextGetFormat ) => {
412
-
413
- const { value } = iterator.next ( )
414
-
415
- if ( value ) return value.getFormat ( url, context, nextGetFormat )
416
-
417
- return defaultGetFormat ( url, context, defaultGetFormat )
418
- } )
419
- }
420
- }
421
-
422
- return defaultGetFormat ( url, context, defaultGetFormat )
423
- }
424
-
425
-
426
-
427
- export function getSource ( url, context, defaultGetSource ) {
428
-
429
- if ( isWebURL ( url ) ) {
430
-
431
- const getMethod = url.startsWith ( 'https://' ) ? httpsGet : httpGet
432
-
433
- return new Promise ( ( resolve, reject ) => getMethod ( url, res => {
434
- let source = ''
435
- res
436
- .on ( 'data', chunk => source += chunk )
437
- .on ( 'end', () => resolve ( { shortCircuit: true, format: 'module', source } ) )
438
- } ).on ( 'error', reject ) )
439
- } else if ( isOOXURL ( url ) ) {
440
-
441
- const mURL = new URL ( url )
442
-
443
- if ( mURL.host === 'rpc' ) {
444
-
445
- const regexp = /\/([\w-]+)\.mjs$/
446
-
447
- const matchResult = mURL.pathname.match ( regexp )
448
-
449
- // read all import attributes
450
- const attributes = mURL.searchParams.getAll ( 'attr' )
451
-
452
- const source = generateRPCProxyScript ( matchResult [ 1 ], attributes )
453
-
454
- return { shortCircuit: true, format: 'module', source }
455
- }
456
- }
457
-
458
- return defaultGetSource ( url, context, defaultGetSource )
459
- }
1
+
2
+ import path from 'node:path'
3
+
4
+ import os from 'node:os'
5
+
6
+ import fs from 'node:fs'
7
+
8
+ import { get as httpGet } from 'node:http'
9
+
10
+ import { get as httpsGet } from 'node:https'
11
+
12
+ const ooxConfig = { }
13
+
14
+ function generateRPCProxyScript ( name, attributes = [ ] ) {
15
+
16
+ let attrExports = ''
17
+
18
+ for ( const attr of attributes ) {
19
+
20
+ attrExports += `\nexport const ${attr} = proxyer.${attr}\n`
21
+ }
22
+
23
+ const script = `
24
+ import oox from 'oox'
25
+ function RPC_${name} ( ) { }
26
+ function dotCall ( name, action ) {
27
+
28
+ return new Proxy ( RPC_${name}, {
29
+
30
+ get ( target, key ) {
31
+
32
+ return dotCall ( name, action ? action + '.' + key : key )
33
+ },
34
+
35
+ has ( target, key ) { return true },
36
+
37
+ apply ( target, thisArg, args ) {
38
+
39
+ return oox.rpc ( name, action, args )
40
+ }
41
+ } )
42
+ }
43
+ const proxyer = dotCall ( '${name}', '' )
44
+ export default proxyer
45
+ ${attrExports}
46
+ `
47
+
48
+ return script
49
+ }
50
+
51
+
52
+
53
+ function generateRPCProxyURL ( name, attributes ) {
54
+
55
+ let searchText = ''
56
+
57
+ if ( attributes.length ) {
58
+
59
+ const search = new URLSearchParams ( )
60
+
61
+ for ( const attr of attributes ) {
62
+
63
+ search.append ( 'attr', attr )
64
+ }
65
+
66
+ searchText = '?' + search.toString ( )
67
+ }
68
+
69
+ return `oox://rpc/${name}.mjs${searchText}`
70
+ }
71
+
72
+
73
+
74
+ function isWebURL ( url ) {
75
+
76
+ return url && ( url.startsWith ( 'https://' ) || url.startsWith ( 'http://' ) )
77
+ }
78
+
79
+
80
+
81
+ function isFileURL ( url ) {
82
+
83
+ return url && url.startsWith ( 'file://' )
84
+ }
85
+
86
+
87
+
88
+ function isOOXURL ( url ) {
89
+
90
+ return url && url.startsWith ( 'oox://' )
91
+ }
92
+
93
+
94
+
95
+ function pathCorrect ( path ) {
96
+
97
+ return os.platform ( ) === 'win32' && path.startsWith ( '/' ) ? path.replace ( '/', '' ) : path
98
+ }
99
+
100
+
101
+
102
+ /**
103
+ * make ESModule support dynamic <export *> attributes import
104
+ * @param {string} importerSpecifier the import url
105
+ * @param {string} specifier parentURL
106
+ * @returns {string[]}
107
+ */
108
+ function getImportAttributes ( importerSpecifier, specifier ) {
109
+
110
+ const attributes = [ ]
111
+
112
+ const contents = fs.readFileSync ( importerSpecifier, 'utf-8' )
113
+
114
+ // import * as xxx from "xxx"
115
+ const mergeImport = contents.match ( new RegExp ( `import.+\\*\\s*as\\s+(\\w+)\\s+from\\s*["']${specifier}["']` ) )
116
+
117
+ if ( mergeImport ) {
118
+
119
+ const mergeName = mergeImport [ 1 ]
120
+
121
+ const attributesIterator = contents.matchAll ( new RegExp ( `${mergeName}\\s*\\.\\s*(\\w+)`, 'g' ) )
122
+
123
+ for ( const caseItem of attributesIterator ) {
124
+
125
+ attributes.push ( caseItem [ 1 ] )
126
+ }
127
+ }
128
+
129
+ // import { a, b, c } from 'xxx'
130
+ const attributeImport = contents.match ( new RegExp ( `import.+{(.+)}\\s*from\\s*["']${specifier}["']` ) )
131
+
132
+ if ( attributeImport ) {
133
+
134
+ const definedAttributes = attributeImport [ 1 ].split ( ',' ).map ( v => v.trim ( ) ).filter ( v => !v.startsWith ( 'default' ) )
135
+
136
+ attributes.push ( ...definedAttributes )
137
+ }
138
+
139
+ return Array.from ( new Set ( attributes ) )
140
+ }
141
+
142
+
143
+
144
+ /**
145
+ * transform local call => RPC
146
+ * @param {string} originalSpecifier
147
+ * @param {string} specifier
148
+ * @param {string} parentURL
149
+ * @returns
150
+ */
151
+ function ooxRPCImportTransform ( originalSpecifier, specifier, parentURL ) {
152
+
153
+ const { entryInfo, ignore } = ooxConfig
154
+
155
+ const url = new URL ( specifier )
156
+
157
+ const groupURL = entryInfo.group ? new URL ( 'file://' + path.resolve ( '/', entryInfo.group ) ) : null
158
+
159
+ // OOX RPC Proxy URL generation
160
+ if ( !specifier.endsWith ( entryInfo.path ) && groupURL && url.href.startsWith ( groupURL.href ) ) {
161
+
162
+ const name = url.href.slice ( groupURL.href.length ).split ( '/' ).filter ( v => v ) [ 0 ].split ( '.' ) [ 0 ]
163
+
164
+ if ( ignore.includes ( name ) ) return null
165
+
166
+ const subSpecifier = url.href.slice ( groupURL.href.length )
167
+
168
+ const matchResult = subSpecifier.match ( /^\/?([\w-]+)(\/index)?(\.((\w?js)|(ts\w?)))?$/ )
169
+
170
+ if ( matchResult ) {
171
+
172
+ const importerSpecifier = parentURL.replace ( os.platform ( ) === 'win32' ? /file:\/+/ : 'file://', '' )
173
+
174
+ const attributes = getImportAttributes ( importerSpecifier, originalSpecifier )
175
+
176
+ return { shortCircuit: true, url: generateRPCProxyURL ( matchResult [ 1 ], attributes ) }
177
+ }
178
+ }
179
+
180
+ return null
181
+ }
182
+
183
+
184
+
185
+ /**
186
+ * Directory import supported
187
+ * Ignored '.ts|.js' suffix import supported
188
+ * @param {string} specifier
189
+ * @returns {string}
190
+ */
191
+ function directoryImportTransform ( specifier ) {
192
+
193
+ let filename = new URL ( specifier ).pathname
194
+
195
+ if ( os.platform ( ) === 'win32' && filename.startsWith ( '/' ) ) {
196
+
197
+ filename = filename.replace ( '/', '' )
198
+ }
199
+
200
+ const stat0 = fs.statSync ( filename, {
201
+ throwIfNoEntry: false
202
+ } )
203
+
204
+ if ( !stat0 || stat0.isDirectory ( ) ) {
205
+
206
+ const justNeedEntry = stat0 && stat0.isDirectory ( )
207
+
208
+ const dirname = justNeedEntry ? filename : path.dirname ( filename )
209
+
210
+ const stat1 = justNeedEntry ? stat0 : fs.statSync ( dirname, {
211
+ throwIfNoEntry: false
212
+ } )
213
+
214
+ // find entry file
215
+ if ( stat1 && stat1.isDirectory ( ) ) {
216
+
217
+ const paths = filename.split ( '/' )
218
+
219
+ const filenameWithoutExtension = justNeedEntry ? 'index' : paths.pop ( )
220
+
221
+ const matchEntryRegExp = new RegExp ( `^${filenameWithoutExtension}\\.((\\w?js)|(ts\\w?))$` )
222
+
223
+ const entries = fs.readdirSync ( dirname )
224
+
225
+ for ( const entry of entries ) {
226
+
227
+ if ( !matchEntryRegExp.test ( entry ) ) continue
228
+
229
+ paths.push ( entry )
230
+
231
+ specifier = 'file://' + paths.join ( '/' )
232
+
233
+ break
234
+ }
235
+ }
236
+ }
237
+
238
+ return specifier
239
+ }
240
+
241
+
242
+
243
+ /**
244
+ * NodeJS version 18 or higher
245
+ * @param {*} param0
246
+ */
247
+ export async function initialize ( { ooxConfig: config } ) {
248
+
249
+ if ( !config ) {
250
+
251
+ throw new Error ( 'Loader initialize failed' )
252
+ }
253
+
254
+ Object.assign ( ooxConfig, config )
255
+ }
256
+
257
+
258
+
259
+ /**
260
+ * @param {string} specifier
261
+ * @param {{
262
+ * conditions: string[],
263
+ * parentURL: string | undefined,
264
+ * }} context
265
+ * @param {Function} defaultResolve
266
+ * @returns {Promise<{ url: string }>}
267
+ */
268
+ export async function resolve ( specifier, context, defaultResolve ) {
269
+
270
+ const originalSpecifier = specifier
271
+
272
+ const { parentURL } = context
273
+
274
+ // HTTP & HTTPS
275
+ if ( isWebURL ( specifier ) ) {
276
+
277
+ return { shortCircuit: true, url: specifier }
278
+ } else if ( isWebURL ( parentURL ) && ( specifier.startsWith ( '.' ) || specifier.startsWith ( '/' ) ) ) {
279
+
280
+ return { shortCircuit: true, url: new URL ( specifier, parentURL ).href }
281
+ }
282
+
283
+ // OOX special alias for web package
284
+ if ( specifier === 'oox' && !isFileURL ( parentURL ) ) {
285
+
286
+ const url = ( await defaultResolve ( specifier, {
287
+ conditions: [ 'node', 'import', 'module-sync', 'node-addons' ],
288
+ parentURL: import.meta.url
289
+ }, defaultResolve ) ).url
290
+
291
+ return {
292
+ shortCircuit: true,
293
+ url
294
+ // url: await import.meta.resolve ( specifier )
295
+ }
296
+ }
297
+
298
+ if ( !isFileURL ( specifier ) ) {
299
+
300
+ try {
301
+
302
+ specifier = ( await defaultResolve ( specifier, context, defaultResolve ) ).url
303
+ } catch ( error ) {
304
+
305
+ if ( !isFileURL ( parentURL ) ) throw error
306
+
307
+ const _specifier = directoryImportTransform ( new URL ( specifier, parentURL ).href )
308
+
309
+ if ( _specifier === specifier ) throw error
310
+
311
+ specifier = _specifier
312
+ }
313
+ }
314
+
315
+ const ooxRPCTransform = ooxRPCImportTransform ( originalSpecifier, specifier, parentURL )
316
+
317
+ if ( ooxRPCTransform ) return ooxRPCTransform
318
+
319
+ return defaultResolve ( specifier, context, defaultResolve )
320
+ }
321
+
322
+
323
+
324
+ /**
325
+ * @param {string} url
326
+ * @param {{
327
+ * format: string,
328
+ * }} context If resolve settled with a `format`, that value is included here.
329
+ * @param {Function} defaultLoad
330
+ * @returns {Promise<{
331
+ * format: string,
332
+ * source: string | ArrayBuffer | SharedArrayBuffer | Uint8Array,
333
+ * }>}
334
+ */
335
+ export async function load ( url, context, defaultLoad ) {
336
+
337
+ if ( isWebURL ( url ) || isOOXURL ( url ) ) {
338
+
339
+ return getSource ( url, context, defaultLoad )
340
+ }
341
+
342
+ return defaultLoad ( url, context, defaultLoad )
343
+ }
344
+
345
+
346
+
347
+ export function getSource ( url, context, defaultGetSource ) {
348
+
349
+ if ( isWebURL ( url ) ) {
350
+
351
+ const getMethod = url.startsWith ( 'https://' ) ? httpsGet : httpGet
352
+
353
+ return new Promise ( ( resolve, reject ) => getMethod ( url, res => {
354
+ let source = ''
355
+ res
356
+ .on ( 'data', chunk => source += chunk )
357
+ .on ( 'end', () => resolve ( { shortCircuit: true, format: 'module', source } ) )
358
+ } ).on ( 'error', reject ) )
359
+ } else if ( isOOXURL ( url ) ) {
360
+
361
+ const mURL = new URL ( url )
362
+
363
+ if ( mURL.host === 'rpc' ) {
364
+
365
+ const regexp = /\/([\w-]+)\.mjs$/
366
+
367
+ const matchResult = mURL.pathname.match ( regexp )
368
+
369
+ // read all import attributes
370
+ const attributes = mURL.searchParams.getAll ( 'attr' )
371
+
372
+ const source = generateRPCProxyScript ( matchResult [ 1 ], attributes )
373
+
374
+ return { shortCircuit: true, format: 'module', source }
375
+ }
376
+ }
377
+
378
+ return defaultGetSource ( url, context, defaultGetSource )
379
+ }