arcane-os 0.1.0-dev.5 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/toolchain.mjs CHANGED
@@ -11,7 +11,17 @@ import {
11
11
  } from './workspace.mjs';
12
12
  import {loadArcaneIntegratedProvider} from './integrated-provider-loader.mjs';
13
13
  import {startDevServer} from './dev-server.mjs';
14
- import {authenticateRuntimeReceipt,loadRuntimeRelease,verifyRuntime} from './runtime.mjs';
14
+ import {authenticateRuntimeReceipt,verifyRuntime} from './runtime.mjs';
15
+ import {
16
+ authenticateSdkBrowserRuntimeReceipt,
17
+ verifySdkBrowserRuntime
18
+ } from './sdk-browser-runtime.mjs';
19
+ import {
20
+ authenticateWorkspaceRuntimeReceipt,
21
+ verifyWorkspaceRuntime
22
+ } from './workspace-runtime.mjs';
23
+ import {generateImportMap} from './import-map.mjs';
24
+ import {withWorkspaceOperationLock} from './workspace-operation-lock.mjs';
15
25
  import {
16
26
  authenticateSharedPayloadSnapshot,
17
27
  packageApp,
@@ -147,12 +157,32 @@ function withEventDeliveryFailure(result,error){
147
157
  return {...result,eventDelivery};
148
158
  }
149
159
 
150
- function isNativeCommitEvent(_label,event){
151
- return event?.type==='native.build.committed'
152
- ||(event?.phase==='publish'&&event?.status==='completed');
160
+ function isOuterCommitEvent(label,event){
161
+ if(label==='build')return event?.type==='native.build.committed';
162
+ return label==='bundle'&&event?.type==='bundle.committed'
163
+ &&event?.phase==='publish'&&event?.status==='completed';
164
+ }
165
+
166
+ function isAppReleaseReceipt(value){
167
+ return value?.kind==='arcane-app-release-verification'
168
+ &&typeof value?.contentSha256==='string';
169
+ }
170
+
171
+ function hasAuthenticatedOuterResult(label,result){
172
+ if(label==='import-map')return result?.committed===true;
173
+ if(label==='package')return isAppReleaseReceipt(result?.receipt);
174
+ if(label==='bundle')return result?.artifactReceipt?.kind
175
+ ==='arcane-app-release-bundle-artifact';
176
+ if(label!=='build')return false;
177
+ return nativeArtifactReceipt(result)!=null||isAppReleaseReceipt(result?.release?.receipt);
153
178
  }
154
179
 
155
- async function ownedWork(label,work,{signal,onEvent,heartbeatMs=5000}={}){
180
+ async function ownedWork(label,work,{
181
+ signal,
182
+ onEvent,
183
+ heartbeatMs=5000,
184
+ workspaceRoot
185
+ }={}){
156
186
  throwIfAborted(signal);
157
187
  const controller=new AbortController();
158
188
  const forwardAbort=()=>controller.abort(signal?.reason);
@@ -168,7 +198,7 @@ async function ownedWork(label,work,{signal,onEvent,heartbeatMs=5000}={}){
168
198
  }
169
199
  });
170
200
  const forwardEvent=async event=>{
171
- if(isNativeCommitEvent(label,event))committed=true;
201
+ if(isOuterCommitEvent(label,event))committed=true;
172
202
  try{
173
203
  await events.send(event);
174
204
  }catch(error){
@@ -202,11 +232,21 @@ async function ownedWork(label,work,{signal,onEvent,heartbeatMs=5000}={}){
202
232
  );
203
233
  },Math.max(1000,heartbeatMs));
204
234
  heartbeat.unref?.();
205
- const result=await work({
235
+ const execute=workspaceOperationLease=>work({
206
236
  signal:controller.signal,
207
- onEvent:forwardEvent
237
+ onEvent:forwardEvent,
238
+ workspaceOperationLease
208
239
  });
209
- if(nativeArtifactReceipt(result))committed=true;
240
+ const mutating=new Set(['import-map','package','bundle','build','run']).has(label);
241
+ const result=mutating&&workspaceRoot
242
+ ?await withWorkspaceOperationLock({
243
+ workspaceRoot,
244
+ operation:label,
245
+ signal:controller.signal,
246
+ onEvent:forwardEvent
247
+ },execute)
248
+ :await execute();
249
+ if(hasAuthenticatedOuterResult(label,result))committed=true;
210
250
  stopProducers();
211
251
  if(!committed||label==='run')throwIfAborted(controller.signal);
212
252
  try{
@@ -335,6 +375,7 @@ async function preparedWorkspace(options){
335
375
  const workspace=await validateWorkspace({
336
376
  workspaceRoot:options.workspaceRoot,
337
377
  appId:options.appId,
378
+ allowMissingManagedImportMap:Boolean(options.allowMissingManagedImportMap),
338
379
  signal:options.signal,
339
380
  onEvent:options.onEvent
340
381
  });
@@ -342,6 +383,9 @@ async function preparedWorkspace(options){
342
383
  const runtimeRoot=external
343
384
  ?path.join(workspace.workspaceRoot,'node_modules','arcane-os','runtime')
344
385
  :workspace.workspaceRoot;
386
+ const browserRuntimeRoot=external
387
+ ?path.join(workspace.workspaceRoot,'node_modules','arcane-os','browser-runtime')
388
+ :null;
345
389
  const runtimeReceipt=external&&!options.deferRuntimeVerification
346
390
  ?await verifyRuntime({
347
391
  runtimeRoot,
@@ -349,9 +393,34 @@ async function preparedWorkspace(options){
349
393
  onEvent:options.onEvent
350
394
  })
351
395
  :null;
396
+ const sdkBrowserRuntimeReceipt=external&&!options.deferRuntimeVerification
397
+ ?await verifySdkBrowserRuntime({
398
+ browserRuntimeRoot,
399
+ signal:options.signal,
400
+ onEvent:options.onEvent
401
+ })
402
+ :null;
403
+ const workspaceRuntimeReceipt=external&&!options.deferRuntimeVerification
404
+ ?await verifyWorkspaceRuntime({
405
+ workspaceRoot:workspace.workspaceRoot,
406
+ runtimeRoot,
407
+ runtimeReceipt,
408
+ browserRuntimeRoot,
409
+ sdkBrowserRuntimeReceipt,
410
+ signal:options.signal,
411
+ onEvent:options.onEvent
412
+ })
413
+ :null;
414
+ const runtimeVerificationState=external&&!options.deferRuntimeVerification
415
+ ?Object.freeze({runtimeReceipt,sdkBrowserRuntimeReceipt,workspaceRuntimeReceipt})
416
+ :null;
352
417
  return {
353
418
  runtimeReceipt,
419
+ sdkBrowserRuntimeReceipt,
420
+ workspaceRuntimeReceipt,
421
+ runtimeVerificationState,
354
422
  runtimeRoot,
423
+ browserRuntimeRoot,
355
424
  workspaceMode:workspace.workspaceMode,
356
425
  descriptor:workspace.app.descriptor,
357
426
  descriptorSource:workspace.app.descriptorSource,
@@ -362,6 +431,12 @@ async function preparedWorkspace(options){
362
431
  };
363
432
  }
364
433
 
434
+ function forwardedRuntimeVerificationState(options,prepared){
435
+ return Object.hasOwn(options,'runtimeVerificationState')
436
+ ?options.runtimeVerificationState
437
+ :prepared.runtimeVerificationState??undefined;
438
+ }
439
+
365
440
  function compareRuntimeInventory(left,right){
366
441
  return left.path.localeCompare(right.path,'en');
367
442
  }
@@ -373,49 +448,121 @@ async function externalRuntimeSnapshotReceipt(prepared,sharedPayloadSnapshot,sha
373
448
  sharedPayloadIds,
374
449
  signal
375
450
  });
376
- const release=await loadRuntimeRelease({runtimeRoot:prepared.runtimeRoot});
377
- const runtimePrefix='node_modules/arcane-os/runtime/';
378
- const files=sharedPayloadSnapshot.files
379
- .filter(file=>file.source.startsWith(runtimePrefix))
451
+ const runtimeReceipt=await verifyRuntime({
452
+ runtimeRoot:prepared.runtimeRoot,
453
+ signal,
454
+ onEvent
455
+ });
456
+ const sdkBrowserRuntimeReceipt=await verifySdkBrowserRuntime({
457
+ browserRuntimeRoot:prepared.browserRuntimeRoot,
458
+ signal,
459
+ onEvent
460
+ });
461
+ const workspaceRuntimeReceipt=await verifyWorkspaceRuntime({
462
+ workspaceRoot:prepared.workspaceRoot,
463
+ runtimeRoot:prepared.runtimeRoot,
464
+ runtimeReceipt,
465
+ browserRuntimeRoot:prepared.browserRuntimeRoot,
466
+ sdkBrowserRuntimeReceipt,
467
+ signal,
468
+ onEvent
469
+ });
470
+ const retained=sharedPayloadSnapshot.files
471
+ .filter(file=>file.source.startsWith('arcane/'))
380
472
  .map(file=>Object.freeze({
381
- path:file.source.slice(runtimePrefix.length),
473
+ path:file.source.slice('arcane/'.length),
382
474
  bytes:file.bytes,
383
475
  sha256:file.sha256
384
476
  }))
385
477
  .sort(compareRuntimeInventory);
386
- const expected=[...release.files].sort(compareRuntimeInventory);
387
- if(JSON.stringify(files)!==JSON.stringify(expected)){
478
+ const upstreamFiles=runtimeReceipt.files.map(file=>Object.freeze({
479
+ path:file.path.startsWith('arcane/')
480
+ ?file.path.slice('arcane/'.length)
481
+ :`dependencies/strong-type/${file.path.slice('strong-type/'.length)}`,
482
+ sourcePath:file.path,
483
+ bytes:file.bytes,
484
+ sha256:file.sha256
485
+ })).sort(compareRuntimeInventory);
486
+ const sdkFiles=sdkBrowserRuntimeReceipt.files.map(file=>Object.freeze({
487
+ path:`sdk/${file.path}`,
488
+ sourcePath:file.path,
489
+ bytes:file.bytes,
490
+ sha256:file.sha256
491
+ })).sort(compareRuntimeInventory);
492
+ const expected=[...upstreamFiles,...sdkFiles]
493
+ .map(file=>Object.freeze({path:file.path,bytes:file.bytes,sha256:file.sha256}))
494
+ .sort(compareRuntimeInventory);
495
+ if(JSON.stringify(retained)!==JSON.stringify(expected)){
388
496
  throw new ArcaneError(
389
497
  ERROR_CODES.integrityFailed,
390
- 'The retained shared payload does not match the installed Arcane runtime manifest.'
498
+ 'The retained shared payload does not match the composed Arcane and SDK browser runtime receipts.'
391
499
  );
392
500
  }
393
501
  const receipt=Object.freeze({
394
502
  schemaVersion:1,
395
503
  kind:'arcane-sdk-runtime-shared-payload',
396
504
  canonicalLocation:prepared.runtimeRoot,
397
- source:Object.freeze({...release.source}),
398
- files:Object.freeze(files),
399
- fileCount:release.fileCount,
400
- totalBytes:release.totalBytes,
401
- contentSha256:release.contentSha256,
505
+ source:Object.freeze({...runtimeReceipt.source}),
506
+ sources:Object.freeze({
507
+ arcane:Object.freeze({
508
+ manifestSha256:runtimeReceipt.manifestSha256,
509
+ contentSha256:runtimeReceipt.contentSha256,
510
+ source:runtimeReceipt.source
511
+ }),
512
+ sdkBrowser:Object.freeze({
513
+ manifestSha256:sdkBrowserRuntimeReceipt.manifestSha256,
514
+ contentSha256:sdkBrowserRuntimeReceipt.contentSha256,
515
+ source:sdkBrowserRuntimeReceipt.source
516
+ })
517
+ }),
518
+ files:Object.freeze(runtimeReceipt.files.map(file=>Object.freeze({...file}))),
519
+ fileCount:runtimeReceipt.fileCount,
520
+ totalBytes:runtimeReceipt.totalBytes,
521
+ contentSha256:runtimeReceipt.contentSha256,
522
+ browserFiles:Object.freeze(sdkBrowserRuntimeReceipt.files.map(
523
+ file=>Object.freeze({...file})
524
+ )),
525
+ browserFileCount:sdkBrowserRuntimeReceipt.fileCount,
526
+ browserTotalBytes:sdkBrowserRuntimeReceipt.totalBytes,
527
+ browserContentSha256:sdkBrowserRuntimeReceipt.contentSha256,
528
+ sharedFiles:Object.freeze(retained),
529
+ sharedFileCount:retained.length,
530
+ sharedTotalBytes:retained.reduce((total,file)=>total+file.bytes,0),
402
531
  sharedPayloadContentSha256:sharedPayloadSnapshot.contentSha256
403
532
  });
404
533
  await emit(onEvent,{
405
534
  type:'runtime.snapshot.verified',
406
535
  contentSha256:receipt.contentSha256,
407
536
  fileCount:receipt.fileCount,
408
- totalBytes:receipt.totalBytes
537
+ totalBytes:receipt.totalBytes,
538
+ browserContentSha256:receipt.browserContentSha256,
539
+ browserFileCount:receipt.browserFileCount,
540
+ browserTotalBytes:receipt.browserTotalBytes
541
+ });
542
+ return Object.freeze({
543
+ receipt,
544
+ runtimeVerificationState:Object.freeze({
545
+ runtimeReceipt,
546
+ sdkBrowserRuntimeReceipt,
547
+ workspaceRuntimeReceipt
548
+ })
409
549
  });
410
- return receipt;
411
550
  }
412
551
 
413
552
  async function validatePreparedRuntime(prepared,{signal}={}){
414
553
  if(prepared.workspaceMode==='external'){
415
- return authenticateRuntimeReceipt(prepared.runtimeReceipt,{
554
+ await authenticateRuntimeReceipt(prepared.runtimeReceipt,{
416
555
  runtimeRoot:prepared.runtimeRoot,
417
556
  signal
418
557
  });
558
+ await authenticateSdkBrowserRuntimeReceipt(prepared.sdkBrowserRuntimeReceipt,{
559
+ browserRuntimeRoot:prepared.browserRuntimeRoot,
560
+ signal
561
+ });
562
+ return authenticateWorkspaceRuntimeReceipt(prepared.workspaceRuntimeReceipt,{
563
+ workspaceRoot:prepared.workspaceRoot,
564
+ signal
565
+ });
419
566
  }
420
567
  const validation=await validateWorkspace({
421
568
  workspaceRoot:prepared.workspaceRoot,
@@ -428,6 +575,47 @@ async function validatePreparedRuntime(prepared,{signal}={}){
428
575
  return validation;
429
576
  }
430
577
 
578
+ async function refreshPreparedImportMap(prepared,{signal,onEvent,workspaceOperationLease}={}){
579
+ if(prepared.workspaceMode==='integrated'
580
+ &&prepared.validation.config.browserRuntimeLayout==='integrated-legacy'){
581
+ const receipt=Object.freeze({
582
+ appId:prepared.appId,
583
+ skipped:true,
584
+ compatibility:'integrated-legacy',
585
+ reason:'The canonical integrated Arcane OS root retains its physical two-route browser runtime.'
586
+ });
587
+ await emit(onEvent,{type:'import-map.compatibility.skipped',...receipt});
588
+ return receipt;
589
+ }
590
+ return generateImportMap({
591
+ workspaceRoot:prepared.workspaceRoot,
592
+ appId:prepared.appId,
593
+ appRoot:prepared.appRoot,
594
+ entry:prepared.validation.app.manifest.entry,
595
+ workspaceRuntimeReceipt:prepared.workspaceRuntimeReceipt,
596
+ workspaceOperationLease,
597
+ signal,
598
+ onEvent
599
+ });
600
+ }
601
+
602
+ async function importMapApplication(options={}){
603
+ assertApplicationScope(options,'Import-map generation');
604
+ const prepared=await preparedWorkspace({...options,allowMissingManagedImportMap:true});
605
+ const importMap=await ownedWork(
606
+ 'import-map',
607
+ context=>refreshPreparedImportMap(prepared,context),
608
+ {...options,workspaceRoot:prepared.workspaceRoot}
609
+ );
610
+ await validatePreparedRuntime(prepared,{signal:options.signal});
611
+ return {
612
+ workspaceRoot:prepared.workspaceRoot,
613
+ workspaceMode:prepared.workspaceMode,
614
+ appId:prepared.appId,
615
+ importMap
616
+ };
617
+ }
618
+
431
619
  export async function createApplication(options={}){
432
620
  return createWorkspace(options);
433
621
  }
@@ -587,12 +775,21 @@ export async function checkApplication(options={}){
587
775
 
588
776
  export async function developApplication(options={}){
589
777
  assertApplicationScope(options,'Development serving');
590
- const prepared=await preparedWorkspace(options);
778
+ const prepared=await preparedWorkspace({...options,allowMissingManagedImportMap:true});
779
+ await withWorkspaceOperationLock({
780
+ workspaceRoot:prepared.workspaceRoot,
781
+ operation:'dev-refresh',
782
+ signal:options.signal,
783
+ onEvent:options.onEvent
784
+ },workspaceOperationLease=>refreshPreparedImportMap(prepared,{
785
+ ...options,
786
+ workspaceOperationLease
787
+ }));
591
788
  const server=await startDevServer({
592
789
  workspaceRoot:prepared.workspaceRoot,
593
790
  appId:prepared.appId,
594
791
  mode:'source',
595
- runtimeReceipt:prepared.runtimeReceipt,
792
+ workspaceRuntimeReceipt:prepared.workspaceRuntimeReceipt,
596
793
  workspaceMode:prepared.workspaceMode,
597
794
  host:options.host,
598
795
  port:options.port,
@@ -604,18 +801,23 @@ export async function developApplication(options={}){
604
801
 
605
802
  export async function packageApplication(options={}){
606
803
  assertApplicationScope(options,'Packaging');
607
- const prepared=await preparedWorkspace(options);
804
+ const prepared=await preparedWorkspace({
805
+ ...options,
806
+ allowMissingManagedImportMap:!options.dryRun
807
+ });
608
808
  const release=await ownedWork(
609
809
  'package',
610
- ({signal,onEvent})=>packageApp({
611
- workspaceRoot:prepared.workspaceRoot,
612
- appId:prepared.appId,
613
- dryRun:Boolean(options.dryRun),
614
- signal,
615
- onEvent,
616
- validateSourceState:({signal}={})=>validatePreparedRuntime(prepared,{signal})
617
- }),
618
- options
810
+ ({signal,onEvent,workspaceOperationLease})=>packageApp({
811
+ workspaceRoot:prepared.workspaceRoot,
812
+ appId:prepared.appId,
813
+ dryRun:Boolean(options.dryRun),
814
+ signal,
815
+ onEvent,
816
+ workspaceOperationLease,
817
+ runtimeVerificationState:forwardedRuntimeVerificationState(options,prepared),
818
+ validateSourceState:({signal}={})=>validatePreparedRuntime(prepared,{signal})
819
+ }),
820
+ {...options,workspaceRoot:prepared.workspaceRoot}
619
821
  );
620
822
  return {
621
823
  workspaceRoot:prepared.workspaceRoot,
@@ -634,10 +836,11 @@ export async function verifyApplication(options={}){
634
836
  ({signal,onEvent})=>verifyApp({
635
837
  workspaceRoot:prepared.workspaceRoot,
636
838
  appId:prepared.appId,
839
+ runtimeVerificationState:forwardedRuntimeVerificationState(options,prepared),
637
840
  signal,
638
841
  onEvent
639
842
  }),
640
- options
843
+ {...options,workspaceRoot:prepared.workspaceRoot}
641
844
  );
642
845
  await validatePreparedRuntime(prepared,{signal:options.signal});
643
846
  return {
@@ -661,6 +864,7 @@ export async function bundleApplication(options={}){
661
864
  const verified=await verifyApp({
662
865
  workspaceRoot:prepared.workspaceRoot,
663
866
  appId:prepared.appId,
867
+ runtimeVerificationState:forwardedRuntimeVerificationState(options,prepared),
664
868
  signal,
665
869
  onEvent
666
870
  });
@@ -679,7 +883,7 @@ export async function bundleApplication(options={}){
679
883
  onEvent
680
884
  });
681
885
  },
682
- options
886
+ {...options,workspaceRoot:prepared.workspaceRoot}
683
887
  );
684
888
  return {
685
889
  workspaceRoot:prepared.workspaceRoot,
@@ -1005,7 +1209,12 @@ function pathsOverlap(left,right){
1005
1209
  return sameOrDescendant(left,right)||sameOrDescendant(right,left);
1006
1210
  }
1007
1211
 
1008
- async function packageNativeRelease(prepared,app,{sharedPayloadSnapshot,signal,onEvent}={}){
1212
+ async function packageNativeRelease(prepared,app,{
1213
+ sharedPayloadSnapshot,
1214
+ workspaceOperationLease,
1215
+ signal,
1216
+ onEvent
1217
+ }={}){
1009
1218
  const sourceState={
1010
1219
  ...prepared,
1011
1220
  appId:app.appId,
@@ -1017,6 +1226,8 @@ async function packageNativeRelease(prepared,app,{sharedPayloadSnapshot,signal,o
1017
1226
  workspaceRoot:prepared.workspaceRoot,
1018
1227
  appId:app.appId,
1019
1228
  sharedPayloadSnapshot,
1229
+ runtimeVerificationState:prepared.runtimeVerificationState??undefined,
1230
+ workspaceOperationLease,
1020
1231
  signal,
1021
1232
  onEvent,
1022
1233
  validateSourceState:({signal:validationSignal}={})=>validateDiscoveredApplication({
@@ -1040,7 +1251,11 @@ async function packageNativeRelease(prepared,app,{sharedPayloadSnapshot,signal,o
1040
1251
  });
1041
1252
  }
1042
1253
 
1043
- async function executePairedNativeBuild(options,adapter,{signal,onEvent}={}){
1254
+ async function executePairedNativeBuild(options,adapter,{
1255
+ signal,
1256
+ onEvent,
1257
+ workspaceOperationLease
1258
+ }={}){
1044
1259
  const target=options.target??options.targetRequest?.target;
1045
1260
  const initialPrepared=await preparedWorkspace({
1046
1261
  ...options,
@@ -1085,7 +1300,7 @@ async function executePairedNativeBuild(options,adapter,{signal,onEvent}={}){
1085
1300
  signal,
1086
1301
  onEvent
1087
1302
  });
1088
- const runtimeReceipt=initialPrepared.workspaceMode==='external'
1303
+ const externalRuntimeState=initialPrepared.workspaceMode==='external'
1089
1304
  ?await externalRuntimeSnapshotReceipt(
1090
1305
  initialPrepared,
1091
1306
  sharedPayloadSnapshot,
@@ -1093,7 +1308,13 @@ async function executePairedNativeBuild(options,adapter,{signal,onEvent}={}){
1093
1308
  {signal,onEvent}
1094
1309
  )
1095
1310
  :null;
1096
- const prepared={...initialPrepared,runtimeReceipt};
1311
+ const prepared={
1312
+ ...initialPrepared,
1313
+ runtimeReceipt:externalRuntimeState?.receipt??null,
1314
+ runtimeVerificationState:externalRuntimeState?.runtimeVerificationState??null,
1315
+ workspaceRuntimeReceipt:
1316
+ externalRuntimeState?.runtimeVerificationState.workspaceRuntimeReceipt??null
1317
+ };
1097
1318
  const selectedRelease=await packageNativeRelease(prepared,{
1098
1319
  appId:prepared.appId,
1099
1320
  appRoot:prepared.appRoot,
@@ -1102,13 +1323,13 @@ async function executePairedNativeBuild(options,adapter,{signal,onEvent}={}){
1102
1323
  descriptorSource:prepared.validation.app.descriptorSource,
1103
1324
  descriptorPath:prepared.validation.app.descriptorPath,
1104
1325
  validation:prepared.validation
1105
- },{sharedPayloadSnapshot,signal,onEvent});
1326
+ },{sharedPayloadSnapshot,workspaceOperationLease,signal,onEvent});
1106
1327
  const dependencyReleases=[];
1107
1328
  for(const dependency of dependencyApps){
1108
1329
  dependencyReleases.push(await packageNativeRelease(
1109
1330
  prepared,
1110
1331
  dependency,
1111
- {sharedPayloadSnapshot,signal,onEvent}
1332
+ {sharedPayloadSnapshot,workspaceOperationLease,signal,onEvent}
1112
1333
  ));
1113
1334
  }
1114
1335
  const toolchainReceipt=await adapter.prepare({
@@ -1189,17 +1410,22 @@ export async function buildApplication(options={}){
1189
1410
  options
1190
1411
  );
1191
1412
  }
1192
- const prepared=await preparedWorkspace(options);
1413
+ const prepared=await preparedWorkspace({
1414
+ ...options,
1415
+ allowMissingManagedImportMap:!options.dryRun
1416
+ });
1193
1417
  const result=await ownedWork(
1194
1418
  'build',
1195
- ({signal,onEvent})=>buildTarget({
1196
- ...options,
1197
- ...prepared,
1198
- signal,
1199
- onEvent,
1200
- validateSourceState:({signal}={})=>validatePreparedRuntime(prepared,{signal})
1201
- }),
1202
- options
1419
+ ({signal,onEvent,workspaceOperationLease})=>buildTarget({
1420
+ ...options,
1421
+ ...prepared,
1422
+ runtimeVerificationState:forwardedRuntimeVerificationState(options,prepared),
1423
+ signal,
1424
+ onEvent,
1425
+ workspaceOperationLease,
1426
+ validateSourceState:({signal}={})=>validatePreparedRuntime(prepared,{signal})
1427
+ }),
1428
+ {...options,workspaceRoot:prepared.workspaceRoot}
1203
1429
  );
1204
1430
  return {
1205
1431
  ...result,
@@ -1250,7 +1476,12 @@ export async function runApplication(options={}){
1250
1476
  );
1251
1477
  }
1252
1478
  const prepared=await preparedWorkspace(selectedOptions);
1253
- return runTarget({...selectedOptions,...prepared,target});
1479
+ return runTarget({
1480
+ ...selectedOptions,
1481
+ ...prepared,
1482
+ runtimeVerificationState:forwardedRuntimeVerificationState(selectedOptions,prepared),
1483
+ target
1484
+ });
1254
1485
  }
1255
1486
 
1256
1487
  export async function describeTargets(options={}){
@@ -1285,6 +1516,7 @@ export async function executeOperation(command,options={}){
1285
1516
  new:createApplication,
1286
1517
  init:initializeApplication,
1287
1518
  doctor:doctorApplication,
1519
+ 'import-map':importMapApplication,
1288
1520
  dev:developApplication,
1289
1521
  test:testApplication,
1290
1522
  check:checkApplication,
@@ -1315,6 +1547,7 @@ export function createToolchain(defaults={}){
1315
1547
  create:options=>createApplication({...defaults,...options}),
1316
1548
  init:options=>initializeApplication({...defaults,...options}),
1317
1549
  doctor:options=>doctorApplication({...defaults,...options}),
1550
+ importMap:options=>importMapApplication({...defaults,...options}),
1318
1551
  dev:options=>developApplication({...defaults,...options}),
1319
1552
  test:options=>testApplication({...defaults,...options}),
1320
1553
  check:options=>checkApplication({...defaults,...options}),