arcane-os 0.2.0 → 0.2.2
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/CHANGELOG.md +35 -0
- package/README.md +8 -8
- package/browser-runtime/ARCANE_SDK_BROWSER_RELEASE.json +5 -5
- package/browser-runtime/ai/browser-speech-providers.mjs +331 -25
- package/docs/architecture.md +2 -2
- package/docs/reference/README.md +79 -13
- package/docs/reference/ai/browser-speech.md +336 -0
- package/docs/reference/ai/browser-wasm.md +207 -82
- package/docs/reference/availability-and-normalization.md +30 -4
- package/docs/reference/behavioral-testing.md +4 -1
- package/docs/reference/cli.md +29 -10
- package/docs/reference/core/arcane-ai-contracts.md +43 -9
- package/docs/reference/inventory/package-api.json +110 -14
- package/docs/reference/inventory/runtime-components.json +19 -6
- package/docs/reference/inventory/runtime-modules.json +113 -9
- package/docs/reference/protocols.md +260 -38
- package/docs/reference/runtime-components.md +108 -15
- package/docs/reference/runtime-modules.md +422 -8
- package/docs/reference/sdk-api.md +626 -85
- package/package.json +1 -1
- package/runtime/ARCANE_RUNTIME_RELEASE.json +19 -19
- package/runtime/arcane/components/chat.html +288 -52
- package/runtime/arcane/components/speech.html +339 -15
- package/runtime/arcane/modules/AI.js +1245 -136
- package/runtime/arcane/modules/AIProviderRuntime.js +299 -30
- package/runtime/arcane/modules/AIRuntimeState.js +23 -4
- package/runtime/arcane/modules/ConfiguredAIChatSession.js +93 -8
- package/runtime/arcane/modules/DBOPFSDocumentLibrary.js +448 -24
- package/runtime/arcane/modules/LocalAIReadinessController.js +1 -1
- package/schemas/arcane-lock.schema.json +6 -4
- package/src/dev-server.mjs +29 -13
- package/src/doctor.mjs +1 -3
- package/src/import-map.mjs +134 -83
- package/src/packager/core.mjs +311 -39
- package/src/scaffold.mjs +45 -17
- package/src/templates/workspace-template.mjs +23 -4
- package/src/toolchain.mjs +10 -2
- package/src/workspace.mjs +177 -24
package/src/dev-server.mjs
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
} from './workspace-runtime.mjs';
|
|
16
16
|
import {verifyRuntime} from './runtime.mjs';
|
|
17
17
|
import {verifySdkBrowserRuntime} from './sdk-browser-runtime.mjs';
|
|
18
|
-
import {resolveWorkspace} from './workspace.mjs';
|
|
18
|
+
import {resolveWorkspace,validateWorkspace} from './workspace.mjs';
|
|
19
19
|
import {createEventQueue} from './event-queue.mjs';
|
|
20
20
|
import {SDK_NAME,SDK_VERSION} from './constants.mjs';
|
|
21
21
|
|
|
@@ -570,24 +570,29 @@ async function sourceRoutes(workspaceRoot,appId,{
|
|
|
570
570
|
};
|
|
571
571
|
}
|
|
572
572
|
const runtimeRoot=path.join(resolved.workspaceRoot,'arcane');
|
|
573
|
+
const validation=await validateWorkspace({
|
|
574
|
+
workspaceRoot:resolved.workspaceRoot,
|
|
575
|
+
appId:resolved.appId,
|
|
576
|
+
allowMissingManagedImportMap:true,
|
|
577
|
+
signal
|
|
578
|
+
});
|
|
579
|
+
const sdkInstallation=validation.sdkInstallation;
|
|
580
|
+
if(!sdkInstallation
|
|
581
|
+
||typeof sdkInstallation.runtimeRoot!=='string'
|
|
582
|
+
||typeof sdkInstallation.browserRuntimeRoot!=='string'){
|
|
583
|
+
fail(
|
|
584
|
+
'Validated external workspace is missing its bound SDK installation authority.',
|
|
585
|
+
'ARCANE_WORKSPACE_INVALID'
|
|
586
|
+
);
|
|
587
|
+
}
|
|
573
588
|
let verified=workspaceRuntimeReceipt;
|
|
574
589
|
if(!verified){
|
|
575
|
-
const sdkRuntimeRoot=
|
|
576
|
-
resolved.workspaceRoot,
|
|
577
|
-
'node_modules',
|
|
578
|
-
'arcane-os',
|
|
579
|
-
'runtime'
|
|
580
|
-
);
|
|
590
|
+
const sdkRuntimeRoot=sdkInstallation.runtimeRoot;
|
|
581
591
|
const sdkRuntimeReceipt=await verifyRuntime({
|
|
582
592
|
runtimeRoot:sdkRuntimeRoot,
|
|
583
593
|
signal
|
|
584
594
|
});
|
|
585
|
-
const sdkBrowserRuntimeRoot=
|
|
586
|
-
resolved.workspaceRoot,
|
|
587
|
-
'node_modules',
|
|
588
|
-
'arcane-os',
|
|
589
|
-
'browser-runtime'
|
|
590
|
-
);
|
|
595
|
+
const sdkBrowserRuntimeRoot=sdkInstallation.browserRuntimeRoot;
|
|
591
596
|
const sdkBrowserRuntimeReceipt=await verifySdkBrowserRuntime({
|
|
592
597
|
browserRuntimeRoot:sdkBrowserRuntimeRoot,
|
|
593
598
|
signal
|
|
@@ -605,6 +610,17 @@ async function sourceRoutes(workspaceRoot,appId,{
|
|
|
605
610
|
workspaceRoot:resolved.workspaceRoot,
|
|
606
611
|
signal
|
|
607
612
|
});
|
|
613
|
+
if(typeof verified.sourceRuntimeLocation!=='string'
|
|
614
|
+
||typeof verified.sourceBrowserRuntimeLocation!=='string'
|
|
615
|
+
||canonicalLocationKey(verified.sourceRuntimeLocation)
|
|
616
|
+
!==canonicalLocationKey(sdkInstallation.runtimeRoot)
|
|
617
|
+
||canonicalLocationKey(verified.sourceBrowserRuntimeLocation)
|
|
618
|
+
!==canonicalLocationKey(sdkInstallation.browserRuntimeRoot)){
|
|
619
|
+
fail(
|
|
620
|
+
'Workspace runtime receipt sources do not match the bound SDK installation authority.',
|
|
621
|
+
'ARCANE_INTEGRITY_FAILED'
|
|
622
|
+
);
|
|
623
|
+
}
|
|
608
624
|
const arcaneIdentities=identityMap(verified.identities);
|
|
609
625
|
return {
|
|
610
626
|
workspaceRoot:resolved.workspaceRoot,
|
package/src/doctor.mjs
CHANGED
|
@@ -290,9 +290,7 @@ export async function runDoctor({
|
|
|
290
290
|
));
|
|
291
291
|
}else if(result.workspaceMode==='external'){
|
|
292
292
|
try{
|
|
293
|
-
const
|
|
294
|
-
const runtimeRoot=path.join(installedRoot,'runtime');
|
|
295
|
-
const browserRuntimeRoot=path.join(installedRoot,'browser-runtime');
|
|
293
|
+
const {runtimeRoot,browserRuntimeRoot}=result.sdkInstallation;
|
|
296
294
|
const runtimeReceipt=await verifyRuntime({runtimeRoot,signal,onEvent});
|
|
297
295
|
const sdkBrowserRuntimeReceipt=await verifySdkBrowserRuntime({
|
|
298
296
|
browserRuntimeRoot,
|
package/src/import-map.mjs
CHANGED
|
@@ -86,6 +86,35 @@ function safeRelativePath(value,label='path'){
|
|
|
86
86
|
return value;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
+
function normalizedDocumentPaths(entry,documents){
|
|
90
|
+
if(documents===undefined)return Object.freeze([entry]);
|
|
91
|
+
if(!Array.isArray(documents)||documents.length===0){
|
|
92
|
+
fail('Import-map documents must be a non-empty array of application-relative paths.');
|
|
93
|
+
}
|
|
94
|
+
const normalized=[];
|
|
95
|
+
const identities=new Map();
|
|
96
|
+
for(const [index,value] of documents.entries()){
|
|
97
|
+
const relative=safeRelativePath(value,`documents[${String(index)}]`);
|
|
98
|
+
const key=collisionKey(relative);
|
|
99
|
+
const prior=identities.get(key);
|
|
100
|
+
if(prior!==undefined){
|
|
101
|
+
fail(
|
|
102
|
+
`Import-map documents contain a duplicate or portable path collision: `
|
|
103
|
+
+`${prior} and ${relative}.`
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
identities.set(key,relative);
|
|
107
|
+
normalized.push(relative);
|
|
108
|
+
}
|
|
109
|
+
if(!normalized.includes(entry)){
|
|
110
|
+
fail(`Import-map documents must include the configured application entry: ${entry}.`);
|
|
111
|
+
}
|
|
112
|
+
return Object.freeze([
|
|
113
|
+
entry,
|
|
114
|
+
...normalized.filter(relative=>relative!==entry).sort(compareUtf8)
|
|
115
|
+
]);
|
|
116
|
+
}
|
|
117
|
+
|
|
89
118
|
function decodedEscape(source,index){
|
|
90
119
|
const character=source[index];
|
|
91
120
|
if(/[1-9]/u.test(character)||(character==='0'&&/[0-9]/u.test(source[index+1]??''))){
|
|
@@ -1760,14 +1789,20 @@ export function inspectImportMapHtml(html){
|
|
|
1760
1789
|
});
|
|
1761
1790
|
}
|
|
1762
1791
|
|
|
1763
|
-
function
|
|
1792
|
+
function documentBaseHref(relative){
|
|
1793
|
+
const directory=path.posix.dirname(relative);
|
|
1794
|
+
const depth=directory==='.'?0:directory.split('/').length;
|
|
1795
|
+
return '../'.repeat(depth+2);
|
|
1796
|
+
}
|
|
1797
|
+
|
|
1798
|
+
function renderManagedHtml(html,json,baseHref='../../'){
|
|
1764
1799
|
const structure=scanHtmlStructure(html);
|
|
1765
1800
|
const activeBases=structure.bases.map(base=>({
|
|
1766
1801
|
...base,
|
|
1767
1802
|
href:structuralAttribute(parseTagAttributes(base.open),'href','base')
|
|
1768
1803
|
}));
|
|
1769
|
-
if(activeBases.length!==1||activeBases[0].href!==
|
|
1770
|
-
fail(
|
|
1804
|
+
if(activeBases.length!==1||activeBases[0].href!==baseHref){
|
|
1805
|
+
fail(`Application HTML must contain exactly one active <base href="${baseHref}"> element.`);
|
|
1771
1806
|
}
|
|
1772
1807
|
const complete=[];
|
|
1773
1808
|
for(const script of structure.scripts){
|
|
@@ -1796,8 +1831,8 @@ function renderManagedHtml(html,json){
|
|
|
1796
1831
|
...base,
|
|
1797
1832
|
href:structuralAttribute(parseTagAttributes(base.open),'href','base')
|
|
1798
1833
|
}));
|
|
1799
|
-
if(cleanedBases.length!==1||cleanedBases[0].href!==
|
|
1800
|
-
fail(
|
|
1834
|
+
if(cleanedBases.length!==1||cleanedBases[0].href!==baseHref){
|
|
1835
|
+
fail(`Application HTML must retain exactly one active <base href="${baseHref}"> element.`);
|
|
1801
1836
|
}
|
|
1802
1837
|
const firstBlocking=firstBlockingLoadPosition(withoutManaged);
|
|
1803
1838
|
if(firstBlocking>=0&&cleanedBases[0].start>firstBlocking){
|
|
@@ -2155,73 +2190,53 @@ async function installStagedFile(state,staged,label){
|
|
|
2155
2190
|
};
|
|
2156
2191
|
}
|
|
2157
2192
|
|
|
2158
|
-
async function
|
|
2159
|
-
|
|
2160
|
-
entryState,
|
|
2161
|
-
artifactBytes,
|
|
2162
|
-
entryBytes,
|
|
2193
|
+
async function commitGeneratedFiles({
|
|
2194
|
+
files,
|
|
2163
2195
|
signal,
|
|
2164
2196
|
onEvent
|
|
2165
2197
|
}){
|
|
2166
|
-
const
|
|
2167
|
-
|
|
2168
|
-
artifactBytes,
|
|
2169
|
-
artifactState.directoryState
|
|
2170
|
-
);
|
|
2171
|
-
let entryStage;
|
|
2172
|
-
let artifactInstall;
|
|
2173
|
-
let entryInstall;
|
|
2198
|
+
const staged=[];
|
|
2199
|
+
const installed=[];
|
|
2174
2200
|
let failure;
|
|
2175
2201
|
try{
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2202
|
+
for(const file of files){
|
|
2203
|
+
throwIfAborted(signal);
|
|
2204
|
+
staged.push(await stageSibling(
|
|
2205
|
+
file.state.filePath,
|
|
2206
|
+
file.bytes,
|
|
2207
|
+
file.state.directoryState
|
|
2208
|
+
));
|
|
2209
|
+
}
|
|
2181
2210
|
await emit(onEvent,{type:'import-map.commit.staged'});
|
|
2182
2211
|
throwIfAborted(signal);
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
);
|
|
2188
|
-
entryInstall=await installStagedFile(entryState,entryStage,'Import-map application entry');
|
|
2189
|
-
await artifactInstall.verify();
|
|
2190
|
-
await entryInstall.verify();
|
|
2212
|
+
for(const [index,file] of files.entries()){
|
|
2213
|
+
installed.push(await installStagedFile(file.state,staged[index],file.label));
|
|
2214
|
+
throwIfAborted(signal);
|
|
2215
|
+
}
|
|
2216
|
+
for(const transaction of installed)await transaction.verify();
|
|
2191
2217
|
await emit(onEvent,{
|
|
2192
2218
|
type:'import-map.commit.progress',
|
|
2193
|
-
paths:Object.freeze(
|
|
2219
|
+
paths:Object.freeze(files.map(file=>file.state.filePath))
|
|
2194
2220
|
});
|
|
2195
2221
|
throwIfAborted(signal);
|
|
2196
|
-
await
|
|
2197
|
-
await entryInstall.verify();
|
|
2222
|
+
for(const transaction of installed)await transaction.verify();
|
|
2198
2223
|
}catch(error){
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
await artifactInstall.rollback().catch(rollback=>{error.rollbackError??=rollback;});
|
|
2224
|
+
for(const transaction of [...installed].reverse()){
|
|
2225
|
+
await transaction.rollback().catch(rollback=>{error.rollbackError??=rollback;});
|
|
2202
2226
|
}
|
|
2203
2227
|
failure=error;
|
|
2204
2228
|
}
|
|
2205
2229
|
const cleanupErrors=[];
|
|
2206
|
-
|
|
2230
|
+
for(const [index,stage] of staged.entries()){
|
|
2231
|
+
if(index<installed.length)continue;
|
|
2207
2232
|
try{
|
|
2208
2233
|
const removed=await removeOwnedPath(
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
);
|
|
2213
|
-
if(!removed)fail(`Import-map artifact stage could not be safely cleaned: ${artifactStage.path}.`);
|
|
2214
|
-
}catch(error){cleanupErrors.push(error);}
|
|
2215
|
-
}
|
|
2216
|
-
if(entryStage&&!entryInstall){
|
|
2217
|
-
try{
|
|
2218
|
-
const removed=await removeOwnedPath(
|
|
2219
|
-
entryStage.path,
|
|
2220
|
-
entryStage.identity,
|
|
2221
|
-
entryStage.directoryState
|
|
2234
|
+
stage.path,
|
|
2235
|
+
stage.identity,
|
|
2236
|
+
stage.directoryState
|
|
2222
2237
|
);
|
|
2223
2238
|
if(!removed){
|
|
2224
|
-
fail(
|
|
2239
|
+
fail(`${files[index].label} stage could not be safely cleaned: ${stage.path}.`);
|
|
2225
2240
|
}
|
|
2226
2241
|
}catch(error){cleanupErrors.push(error);}
|
|
2227
2242
|
}
|
|
@@ -2238,12 +2253,11 @@ async function commitGeneratedPair({
|
|
|
2238
2253
|
}
|
|
2239
2254
|
|
|
2240
2255
|
const cleanupWarnings=[];
|
|
2241
|
-
for(const
|
|
2242
|
-
try{await
|
|
2256
|
+
for(const transaction of [...installed].reverse()){
|
|
2257
|
+
try{await transaction.commit();}
|
|
2243
2258
|
catch(error){cleanupWarnings.push(error);}
|
|
2244
2259
|
}
|
|
2245
|
-
await
|
|
2246
|
-
await entryInstall.verify();
|
|
2260
|
+
for(const transaction of installed)await transaction.verify();
|
|
2247
2261
|
if(cleanupWarnings.length>0){
|
|
2248
2262
|
return Object.freeze(cleanupWarnings.map(error=>String(error?.message??error)));
|
|
2249
2263
|
}
|
|
@@ -2264,6 +2278,7 @@ async function generateImportMapUnlocked({
|
|
|
2264
2278
|
appId,
|
|
2265
2279
|
appRoot,
|
|
2266
2280
|
entry='index.html',
|
|
2281
|
+
documents,
|
|
2267
2282
|
workspaceRuntimeReceipt,
|
|
2268
2283
|
signal,
|
|
2269
2284
|
onEvent
|
|
@@ -2275,21 +2290,45 @@ async function generateImportMapUnlocked({
|
|
|
2275
2290
|
const resolvedWorkspace=path.resolve(workspaceRoot);
|
|
2276
2291
|
const resolvedApp=resolvedAppRoot(resolvedWorkspace,appId,appRoot);
|
|
2277
2292
|
const safeEntry=safeRelativePath(entry,'application entry');
|
|
2278
|
-
const
|
|
2279
|
-
|
|
2293
|
+
const safeDocuments=normalizedDocumentPaths(safeEntry,documents);
|
|
2294
|
+
const documentPaths=Object.freeze(safeDocuments.map(relative=>{
|
|
2295
|
+
const documentPath=path.resolve(resolvedApp,...relative.split('/'));
|
|
2296
|
+
if(!pathInside(resolvedApp,documentPath)){
|
|
2297
|
+
fail(`Import-map application document escapes its app root: ${relative}.`);
|
|
2298
|
+
}
|
|
2299
|
+
return documentPath;
|
|
2300
|
+
}));
|
|
2301
|
+
const entryPath=documentPaths[0];
|
|
2280
2302
|
const artifactPath=path.join(resolvedApp,...IMPORT_MAP_RELATIVE_PATH.split('/'));
|
|
2281
|
-
await emit(onEvent,{
|
|
2303
|
+
await emit(onEvent,{
|
|
2304
|
+
type:'import-map.started',
|
|
2305
|
+
appId,
|
|
2306
|
+
artifactPath,
|
|
2307
|
+
entryPath,
|
|
2308
|
+
documentPaths,
|
|
2309
|
+
documentCount:documentPaths.length
|
|
2310
|
+
});
|
|
2282
2311
|
|
|
2283
|
-
const
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2312
|
+
const documentStates=[];
|
|
2313
|
+
for(const [index,documentPath] of documentPaths.entries()){
|
|
2314
|
+
throwIfAborted(signal);
|
|
2315
|
+
const label=index===0
|
|
2316
|
+
?'Import-map application entry'
|
|
2317
|
+
:`Import-map application document ${safeDocuments[index]}`;
|
|
2318
|
+
const directoryState=await captureDirectoryState(
|
|
2319
|
+
resolvedWorkspace,
|
|
2320
|
+
path.dirname(documentPath)
|
|
2321
|
+
);
|
|
2322
|
+
const state=await readRealFileState(documentPath,label);
|
|
2323
|
+
throwIfAborted(signal);
|
|
2324
|
+
state.directoryState=directoryState;
|
|
2325
|
+
const html=state.bytes.toString('utf8');
|
|
2326
|
+
// Reject malformed application structure before traversing the substantially larger
|
|
2327
|
+
// runtime graph. The real generated map is rendered and revalidated before commit.
|
|
2328
|
+
const baseHref=documentBaseHref(safeDocuments[index]);
|
|
2329
|
+
renderManagedHtml(html,'{"imports":{}}\n',baseHref);
|
|
2330
|
+
documentStates.push({state,html,label,baseHref});
|
|
2331
|
+
}
|
|
2293
2332
|
let runtime;
|
|
2294
2333
|
if(workspaceRuntimeReceipt){
|
|
2295
2334
|
await authenticateWorkspaceRuntimeReceipt(workspaceRuntimeReceipt,{
|
|
@@ -2319,7 +2358,10 @@ async function generateImportMapUnlocked({
|
|
|
2319
2358
|
const built=await buildImportMap({files:runtime.files,readFile:runtime.readFile,signal});
|
|
2320
2359
|
const document={imports:built.imports};
|
|
2321
2360
|
const json=`${JSON.stringify(document,null,2).replaceAll('<','\\u003c')}\n`;
|
|
2322
|
-
const
|
|
2361
|
+
const renderedDocuments=documentStates.map(item=>Object.freeze({
|
|
2362
|
+
...item,
|
|
2363
|
+
bytes:Buffer.from(renderManagedHtml(item.html,json,item.baseHref),'utf8')
|
|
2364
|
+
}));
|
|
2323
2365
|
|
|
2324
2366
|
throwIfAborted(signal);
|
|
2325
2367
|
const artifactDirectoryState=await captureDirectoryState(
|
|
@@ -2333,11 +2375,16 @@ async function generateImportMapUnlocked({
|
|
|
2333
2375
|
{optional:true}
|
|
2334
2376
|
);
|
|
2335
2377
|
artifactState.directoryState=artifactDirectoryState;
|
|
2336
|
-
const
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2378
|
+
const artifactBytes=Buffer.from(json,'utf8');
|
|
2379
|
+
const cleanupWarnings=await commitGeneratedFiles({
|
|
2380
|
+
files:[
|
|
2381
|
+
{state:artifactState,bytes:artifactBytes,label:'Import-map artifact'},
|
|
2382
|
+
...renderedDocuments.map(item=>({
|
|
2383
|
+
state:item.state,
|
|
2384
|
+
bytes:item.bytes,
|
|
2385
|
+
label:item.label
|
|
2386
|
+
}))
|
|
2387
|
+
],
|
|
2341
2388
|
signal,
|
|
2342
2389
|
onEvent
|
|
2343
2390
|
});
|
|
@@ -2345,21 +2392,23 @@ async function generateImportMapUnlocked({
|
|
|
2345
2392
|
Object.freeze({
|
|
2346
2393
|
role:'artifact',
|
|
2347
2394
|
path:path.relative(resolvedWorkspace,artifactPath).split(path.sep).join('/'),
|
|
2348
|
-
bytes:
|
|
2349
|
-
sha256:sha256(
|
|
2395
|
+
bytes:artifactBytes.length,
|
|
2396
|
+
sha256:sha256(artifactBytes)
|
|
2350
2397
|
}),
|
|
2351
|
-
Object.freeze({
|
|
2352
|
-
role:'entry',
|
|
2353
|
-
path:path.relative(resolvedWorkspace,
|
|
2354
|
-
bytes:
|
|
2355
|
-
sha256:sha256(
|
|
2356
|
-
})
|
|
2398
|
+
...renderedDocuments.map((item,index)=>Object.freeze({
|
|
2399
|
+
role:index===0?'entry':'document',
|
|
2400
|
+
path:path.relative(resolvedWorkspace,item.state.filePath).split(path.sep).join('/'),
|
|
2401
|
+
bytes:item.bytes.length,
|
|
2402
|
+
sha256:sha256(item.bytes)
|
|
2403
|
+
}))
|
|
2357
2404
|
]);
|
|
2358
2405
|
const receipt=Object.freeze({
|
|
2359
2406
|
appId,
|
|
2360
2407
|
artifactPath,
|
|
2361
2408
|
artifactRelativePath:path.relative(resolvedWorkspace,artifactPath).split(path.sep).join('/'),
|
|
2362
2409
|
entryPath,
|
|
2410
|
+
documentPaths,
|
|
2411
|
+
documentCount:documentPaths.length,
|
|
2363
2412
|
imports:built.imports,
|
|
2364
2413
|
entryCount:built.entryCount,
|
|
2365
2414
|
excludedModules:built.excludedModules,
|
|
@@ -2373,6 +2422,8 @@ async function generateImportMapUnlocked({
|
|
|
2373
2422
|
appId,
|
|
2374
2423
|
artifactPath,
|
|
2375
2424
|
entryPath,
|
|
2425
|
+
documentPaths,
|
|
2426
|
+
documentCount:receipt.documentCount,
|
|
2376
2427
|
entryCount:receipt.entryCount,
|
|
2377
2428
|
cleanupWarnings:receipt.cleanupWarnings,
|
|
2378
2429
|
committed:true
|