arcane-os 0.27.1 → 0.28.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/CHANGELOG.md +18 -0
- package/README.md +7 -1
- package/browser-runtime/pwa-install.mjs +4 -4
- package/browser-runtime/pwa.mjs +1 -1
- package/docs/reference/inventory/package-api.json +4 -0
- package/docs/reference/protocols.md +15 -1
- package/docs/reference/sdk-api.md +9 -2
- package/package.json +3 -1
- package/src/import-map.mjs +8 -3
- package/src/scaffold.mjs +11 -6
- package/src/templates/workspace-template.mjs +8 -6
- package/src/workspace.mjs +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.28.0
|
|
4
|
+
|
|
5
|
+
- Expose existing runtime modules and entities directly through
|
|
6
|
+
`arcane-os/modules/<filename>` and `arcane-os/entities/<filename>`, including
|
|
7
|
+
extensions. Package exports and managed maps point to the actual files, so
|
|
8
|
+
relative imports, component resources and `import.meta.resolve` keep their
|
|
9
|
+
established directory and lifecycle. Existing lowercase exports remain.
|
|
10
|
+
- Root apps using direct npm routes generate package-namespaced maps without
|
|
11
|
+
the old `arcane/*` or `./arcane/*` keys. Update authored root-app bare imports
|
|
12
|
+
before regenerating the managed map. Installed `runtime/arcane/` directories
|
|
13
|
+
remain unchanged; physical, virtual and nested layouts retain compatibility.
|
|
14
|
+
- Use the package namespace for generated root app code and shared PWA imports,
|
|
15
|
+
preserving parallel startup and the existing storage and installation owners.
|
|
16
|
+
- New root apps declare the SDK as a runtime dependency. Init promotes their
|
|
17
|
+
SDK development declaration and preserves existing runtime or optional
|
|
18
|
+
classification in every layout, including aliases. Existing nested scaffold
|
|
19
|
+
defaults remain unchanged. No server, listener or application policy changes.
|
|
20
|
+
|
|
3
21
|
## 0.27.1
|
|
4
22
|
|
|
5
23
|
- Preserve the previous `apps/<id>/arcane-sw.js` and `arcane-offline.json`
|
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ version-locked SDK runtime, while an integrated Arcane checkout uses its live
|
|
|
19
19
|
`arcane/` runtime. Both profiles preserve the same app URLs, theme, packaging,
|
|
20
20
|
event, cancellation, and browser run contracts.
|
|
21
21
|
|
|
22
|
-
This checkout defines the `0.
|
|
22
|
+
This checkout defines the `0.28.0` SDK contract. Applications pin one exact npm
|
|
23
23
|
version and lockfile; registry state is deliberately not baked into application
|
|
24
24
|
artifacts.
|
|
25
25
|
|
|
@@ -33,6 +33,12 @@ Select `appsRoot: "."` for a standalone root app, or scaffold one with
|
|
|
33
33
|
`arcane new my-app --apps-root .`. After npm installation, `arcane import-map`
|
|
34
34
|
refreshes managed maps and the root app's static PWA/navigation files for ordinary
|
|
35
35
|
static hosting. Portable app packages still contain their selected runtime.
|
|
36
|
+
Root/direct maps use `arcane-os/modules/<filename>` and
|
|
37
|
+
`arcane-os/entities/<filename>` (including extensions) plus the focused lowercase
|
|
38
|
+
exports, rather than `arcane/*` aliases. These paths resolve to the actual npm
|
|
39
|
+
files, preserving relative component URLs. New root apps put the SDK in runtime
|
|
40
|
+
`dependencies`; init preserves existing runtime/optional declarations and promotes
|
|
41
|
+
a root app's SDK development declaration without changing its other packages.
|
|
36
42
|
Existing `apps/<id>`, virtual `/arcane` routes, and materialized workspaces remain
|
|
37
43
|
supported. Node services continue to
|
|
38
44
|
use the installed CLI or public imports such as `arcane-os/mail`.
|
|
@@ -89,7 +89,7 @@ export function getPwaInstall() {
|
|
|
89
89
|
|
|
90
90
|
async function loadInstallStorage() {
|
|
91
91
|
if (!globalThis.dbopfs) {
|
|
92
|
-
await import('arcane/DBOPFS');
|
|
92
|
+
await import('arcane-os/modules/DBOPFS.js');
|
|
93
93
|
}
|
|
94
94
|
const storage = globalThis.dbopfs;
|
|
95
95
|
if (!storage) {
|
|
@@ -273,8 +273,8 @@ export function mountPwaInstallPrompt({appName = ''} = {}) {
|
|
|
273
273
|
if (!globalThis.document) return null;
|
|
274
274
|
// Both modules may start independently; saved theme loading is not a barrier.
|
|
275
275
|
await Promise.all([
|
|
276
|
-
import('arcane/HTMLImport'),
|
|
277
|
-
import('arcane/ThemeBootstrap')
|
|
276
|
+
import('arcane-os/modules/HTMLImport.js'),
|
|
277
|
+
import('arcane-os/modules/ThemeBootstrap.js')
|
|
278
278
|
]);
|
|
279
279
|
if (owner.state.status === 'disposed') return null;
|
|
280
280
|
if (!document.body) {
|
|
@@ -295,7 +295,7 @@ export function mountPwaInstallPrompt({appName = ''} = {}) {
|
|
|
295
295
|
host.hidden = true;
|
|
296
296
|
host.dataset.appName = String(appName);
|
|
297
297
|
host.dataset.arcanePwaInstall = '';
|
|
298
|
-
host.setAttribute('href', new URL('../components/pwa-install.html', import.meta.resolve('arcane/HTMLImport')).href);
|
|
298
|
+
host.setAttribute('href', new URL('../components/pwa-install.html', import.meta.resolve('arcane-os/modules/HTMLImport.js')).href);
|
|
299
299
|
return new Promise(function waitForInstallComponent(resolve, reject) {
|
|
300
300
|
const observer = new MutationObserver(function observeRemovedInstallComponent() {
|
|
301
301
|
if (!host.isConnected) cancelMount();
|
package/browser-runtime/pwa.mjs
CHANGED
|
@@ -156,7 +156,7 @@ export function registerPwa({workerUrl = './arcane-sw.js', scope} = {}) {
|
|
|
156
156
|
|
|
157
157
|
async function loadCheckStorage() {
|
|
158
158
|
if (!globalThis.dbopfs) {
|
|
159
|
-
await import('arcane/DBOPFS');
|
|
159
|
+
await import('arcane-os/modules/DBOPFS.js');
|
|
160
160
|
}
|
|
161
161
|
const storage = globalThis.dbopfs;
|
|
162
162
|
if (!storage) {
|
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
"moduleSystem": "ESM"
|
|
8
8
|
},
|
|
9
9
|
"memberCount": 210,
|
|
10
|
+
"runtimeSubpathPatterns": {
|
|
11
|
+
"arcane-os/modules/*": "./runtime/arcane/modules/*",
|
|
12
|
+
"arcane-os/entities/*": "./runtime/arcane/entities/*"
|
|
13
|
+
},
|
|
10
14
|
"members": [
|
|
11
15
|
{
|
|
12
16
|
"id": "root:APP_BUNDLE_DESCRIPTOR_NAME",
|
|
@@ -146,7 +146,7 @@ all four source and destination paths. Package selection and SDK
|
|
|
146
146
|
version come from the installed dependency, not a generated runtime lock.
|
|
147
147
|
|
|
148
148
|
`arcane import-map`, `arcane dev`, packaging, and generated PWA inventories use
|
|
149
|
-
the same actual npm destinations. For example, `arcane/HTMLImport` resolves to
|
|
149
|
+
the same actual npm destinations. For example, `arcane-os/modules/HTMLImport.js` resolves to
|
|
150
150
|
`./node_modules/arcane-os/runtime/arcane/modules/HTMLImport.js`, and
|
|
151
151
|
`arcane-os/event-manager` resolves to
|
|
152
152
|
`./node_modules/arcane-os/browser-runtime/event-manager.mjs`. A normal static
|
|
@@ -180,6 +180,20 @@ query strings and fragments. It preserves authored files at those destinations.
|
|
|
180
180
|
For a direct-installed root PWA it generates the static PWA records at the root,
|
|
181
181
|
so normal static hosting needs no SDK request handler or runtime copy.
|
|
182
182
|
|
|
183
|
+
Direct-installed root maps expose `arcane-os/modules/<filename>` and
|
|
184
|
+
`arcane-os/entities/<filename>` (including extensions), plus the existing
|
|
185
|
+
focused lowercase package exports. They omit the old `arcane/*` and
|
|
186
|
+
`./arcane/*` keys. Real installed `runtime/arcane/` directories are unchanged.
|
|
187
|
+
Physical, nested and virtual layouts retain their established aliases and also
|
|
188
|
+
support the package-namespaced module/entity keys. Relative module and component
|
|
189
|
+
URLs still resolve from the actual selected file, not a reexport wrapper.
|
|
190
|
+
|
|
191
|
+
New root apps declare the SDK in `dependencies` because serving their npm
|
|
192
|
+
resources requires the installed package at runtime. Root `init` promotes an
|
|
193
|
+
existing SDK development declaration while preserving other dependencies.
|
|
194
|
+
Existing runtime or optional declarations retain their classification across
|
|
195
|
+
layouts; the default nested scaffold continues to use its development dependency.
|
|
196
|
+
|
|
183
197
|
## Installed SDK runtime materialization
|
|
184
198
|
|
|
185
199
|
`materializeInstalledSdkRuntime()` is the Node entrypoint for refreshing one
|
|
@@ -5,11 +5,16 @@ The npm package exposes a Node.js ESM control plane, the portable
|
|
|
5
5
|
`arcane-os/preference-store`, `arcane-os/speech-playback`,
|
|
6
6
|
`arcane-os/speech-text`, `arcane-os/ai/tool-text-stream`, and `arcane-os/browser-device` entrypoints, and the browser-only
|
|
7
7
|
`arcane-os/pwa`, `arcane-os/ai/browser-wasm` and `arcane-os/ai/browser-speech` entrypoints.
|
|
8
|
+
The `arcane-os/modules/<filename>` and `arcane-os/entities/<filename>` paths
|
|
9
|
+
resolve directly to the existing runtime files, with their actual extension.
|
|
10
|
+
They are public Node package exports and managed browser keys, without a wrapper.
|
|
11
|
+
For example, `import.meta.resolve('arcane-os/modules/WaitForComponent.js')`
|
|
12
|
+
retains the module directory needed to resolve `../components/modal.html`.
|
|
8
13
|
Lowercase runtime subpaths also expose existing module namespaces through both
|
|
9
14
|
Node package exports and managed browser imports, as listed below. Established
|
|
10
15
|
browser names such as `arcane/AIProviderRuntime`, `arcane/AIRuntimeState`, and
|
|
11
|
-
`arcane/ThemeBootstrap` remain
|
|
12
|
-
|
|
16
|
+
`arcane/ThemeBootstrap` remain compatibility names in physical/nested maps;
|
|
17
|
+
direct-installed root maps use the package namespace instead. Applications call `globalThis.Arcane` for capability-gated host
|
|
13
18
|
behavior.
|
|
14
19
|
|
|
15
20
|
This page is the canonical inventory for every JavaScript name reachable through `package.json#exports`. The same binding can appear at the root and a focused subpath; those entrypoints are listed together. The root workspace `discoverApps` and the low-level packager `discoverApps` are intentionally separate records because they are different functions.
|
|
@@ -36,6 +41,8 @@ runtime layouts.
|
|
|
36
41
|
| `arcane-os/packager` | Low-level browser app packager. |
|
|
37
42
|
| `arcane-os/release-bundle` | Deterministic external release bundles. |
|
|
38
43
|
| `arcane-os/event-manager` | Central synchronous events, complete time-travel history, playback, and optional DOM instrumentation. |
|
|
44
|
+
| `arcane-os/modules/<filename>` | Direct existing runtime module, including its `.js` or `.mjs` extension. |
|
|
45
|
+
| `arcane-os/entities/<filename>` | Direct existing runtime entity, including its extension. |
|
|
39
46
|
| `arcane-os/logging` | Shared console diagnostics controlled by the existing `user.developer` preference. |
|
|
40
47
|
| `arcane-os/preference-store` | Portable preference records and injected storage adapters. |
|
|
41
48
|
| `arcane-os/ai` | Existing `AI.js` provider-neutral inference and speech namespace. |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "arcane-os",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.0",
|
|
4
4
|
"description": "Arcane OS JavaScript SDK, project-local CLI, browser runtime, and repository-portable application packager.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.mjs",
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
"./toolchain": "./src/toolchain.mjs",
|
|
14
14
|
"./events": "./src/events.mjs",
|
|
15
15
|
"./event-manager": "./src/event-manager.mjs",
|
|
16
|
+
"./modules/*": "./runtime/arcane/modules/*",
|
|
17
|
+
"./entities/*": "./runtime/arcane/entities/*",
|
|
16
18
|
"./logging": "./browser-runtime/logging.mjs",
|
|
17
19
|
"./browser-device": "./browser-runtime/browser-device.mjs",
|
|
18
20
|
"./pwa": "./browser-runtime/pwa.mjs",
|
package/src/import-map.mjs
CHANGED
|
@@ -1390,6 +1390,9 @@ export async function buildImportMap({files,signal,version=SDK_VERSION,encodePat
|
|
|
1390
1390
|
for(const relative of [...inventory].sort(compareText)){
|
|
1391
1391
|
if(JAVASCRIPT_EXTENSION.test(relative)){
|
|
1392
1392
|
const target=runtimeTarget(relative);
|
|
1393
|
+
if(relative.startsWith('modules/')||relative.startsWith('entities/')){
|
|
1394
|
+
registerSpecifier(namedRegistry,`arcane-os/${relative}`,target);
|
|
1395
|
+
}
|
|
1393
1396
|
registerSpecifier(namedRegistry,target,target);
|
|
1394
1397
|
}
|
|
1395
1398
|
}
|
|
@@ -1453,7 +1456,7 @@ async function physicalRuntime(workspaceRoot,signal){
|
|
|
1453
1456
|
return {files};
|
|
1454
1457
|
}
|
|
1455
1458
|
|
|
1456
|
-
async function managedImportMapBuild(resolvedWorkspace,signal,pwaEnabled=false){
|
|
1459
|
+
async function managedImportMapBuild(resolvedWorkspace,resolvedApp,signal,pwaEnabled=false){
|
|
1457
1460
|
const installed=await readInstalledSdkLayout(resolvedWorkspace);
|
|
1458
1461
|
const [runtime,version]=await Promise.all([
|
|
1459
1462
|
installed?installedRuntimeFiles(resolvedWorkspace,installed,signal):physicalRuntime(resolvedWorkspace,signal),
|
|
@@ -1462,13 +1465,15 @@ async function managedImportMapBuild(resolvedWorkspace,signal,pwaEnabled=false){
|
|
|
1462
1465
|
const built=await buildImportMap({files:runtime.files,signal,version});
|
|
1463
1466
|
if(installed?.direct){
|
|
1464
1467
|
const imports={};
|
|
1468
|
+
const rootApplication=samePath(resolvedWorkspace,resolvedApp);
|
|
1465
1469
|
function installedBrowserUrl(value){
|
|
1466
1470
|
return value.startsWith('./')
|
|
1467
1471
|
?`./${installedRuntimeTarget(value.slice(2),installed,{browser:true})}`:value;
|
|
1468
1472
|
}
|
|
1469
1473
|
for(const [specifier,target] of Object.entries(built.imports)){
|
|
1474
|
+
if(rootApplication&&specifier.startsWith('arcane/'))continue;
|
|
1470
1475
|
const selected=installedBrowserUrl(target);
|
|
1471
|
-
imports[specifier]=selected;
|
|
1476
|
+
if(!rootApplication)imports[specifier]=selected;
|
|
1472
1477
|
// Relative module imports and bare names must resolve to the same instance.
|
|
1473
1478
|
imports[installedBrowserUrl(specifier)]=selected;
|
|
1474
1479
|
}
|
|
@@ -2846,7 +2851,7 @@ async function generateImportMapUnlocked({
|
|
|
2846
2851
|
}catch(error){
|
|
2847
2852
|
if(error?.code!=='ENOENT')throw error;
|
|
2848
2853
|
}
|
|
2849
|
-
const {built,json,version}=await managedImportMapBuild(resolvedWorkspace,signal,pwaEnabled);
|
|
2854
|
+
const {built,json,version}=await managedImportMapBuild(resolvedWorkspace,resolvedApp,signal,pwaEnabled);
|
|
2850
2855
|
const renderedDocuments=documentStates.map(item=>({
|
|
2851
2856
|
...item,
|
|
2852
2857
|
content:rewriteAssetReferences(renderManagedHtml(item.html,json,item.baseHref),{
|
package/src/scaffold.mjs
CHANGED
|
@@ -192,21 +192,26 @@ async function prepareExistingPackage(workspaceRoot,files,existingPackage,sdkDec
|
|
|
192
192
|
if(conflicts.length){
|
|
193
193
|
fail(`Existing package.json conflicts with Arcane setup; no values were overwritten. Resolve: ${conflicts.join('; ')}.`);
|
|
194
194
|
}
|
|
195
|
+
const dependencyGroup=sdkDeclaration.dependencyGroup==='optionalDependencies'
|
|
196
|
+
?'optionalDependencies'
|
|
197
|
+
:generated.dependencies||sdkDeclaration.dependencyGroup==='dependencies'
|
|
198
|
+
?'dependencies':'devDependencies';
|
|
195
199
|
const merged={
|
|
196
200
|
...existing,
|
|
197
201
|
private:true,
|
|
198
202
|
type:'module',
|
|
199
203
|
scripts:{...generated.scripts,...(existing.scripts||{})},
|
|
200
|
-
|
|
201
|
-
...(existing
|
|
204
|
+
[dependencyGroup]:{
|
|
205
|
+
...(existing[dependencyGroup]||{}),
|
|
202
206
|
[sdkDeclaration.dependencyName]:sdkDeclaration.specifier
|
|
203
207
|
},
|
|
204
208
|
engines:{...generated.engines,...(existing.engines||{})}
|
|
205
209
|
};
|
|
206
|
-
if(
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
+
if(dependencyGroup!=='devDependencies'
|
|
211
|
+
&&existing.devDependencies?.[sdkDeclaration.dependencyName]!==undefined){
|
|
212
|
+
merged.devDependencies={...existing.devDependencies};
|
|
213
|
+
delete merged.devDependencies[sdkDeclaration.dependencyName];
|
|
214
|
+
if(Object.keys(merged.devDependencies).length===0)delete merged.devDependencies;
|
|
210
215
|
}
|
|
211
216
|
if(JSON.stringify(existing)===JSON.stringify(merged)){
|
|
212
217
|
return {exists:true,updated:false};
|
|
@@ -159,7 +159,7 @@ appropriate.
|
|
|
159
159
|
|
|
160
160
|
- Use plain JavaScript, HTML, and CSS; do not introduce TypeScript or TSX.
|
|
161
161
|
- Keep reusable portable mechanisms in the Arcane SDK and app-specific behavior under \`${appPrefix||'./'}\`.
|
|
162
|
-
- Keep \`${runtimePrefix}/css/theme.css\` before app styles and import
|
|
162
|
+
- Keep \`${runtimePrefix}/css/theme.css\` before app styles and import \`${directRuntime?'arcane-os/modules/ThemeBootstrap.js':'arcane/ThemeBootstrap'}\` before app code runs.
|
|
163
163
|
- Use \`rgb(...)\` or \`rgba(...)\` for new CSS colors.
|
|
164
164
|
- Build one named app and one explicit target at a time. Native targets may be unavailable until their adapters are installed.
|
|
165
165
|
- Preserve complete application, model, document, message, log, diagnostic, process, and tool content. Do not truncate, clip, tail, elide, or silently discard it.
|
|
@@ -181,7 +181,7 @@ npm run dev
|
|
|
181
181
|
|
|
182
182
|
Open the loopback URL printed by the development server. ${directRuntime?'This root app reads SDK files directly from its installed npm package; an ordinary static host uses the same resource paths.':'This app uses the existing physical arcane/ runtime layout.'} The SDK server does not expose an Ollama HTTP endpoint.
|
|
183
183
|
|
|
184
|
-
Commit the generated \`package-lock.json\` after dependency installation. CI intentionally uses \`npm ci\` and therefore requires that lock. Before the SDK is published, install a locally packed \`${SDK_NAME}\` \`.tgz\` with \`npm install --save-dev --save-exact <path-to-tarball>\`; keep that tarball at the lock file's relative path for repeatable local \`npm ci\` runs.
|
|
184
|
+
Commit the generated \`package-lock.json\` after dependency installation. CI intentionally uses \`npm ci\` and therefore requires that lock. ${directRuntime?'The SDK is a runtime dependency: keep it installed when serving this app directly from node_modules. ':''}Before the SDK is published, install a locally packed \`${SDK_NAME}\` \`.tgz\` with \`npm install ${directRuntime?'--save-prod':'--save-dev'} --save-exact <path-to-tarball>\`; keep that tarball at the lock file's relative path for repeatable local \`npm ci\` runs.
|
|
185
185
|
|
|
186
186
|
## Optional browser release commands
|
|
187
187
|
|
|
@@ -199,7 +199,7 @@ import map in every directly navigable descriptor-admitted \`.html\`/\`.htm\`
|
|
|
199
199
|
document. HTML component fragments remain package files but do not receive a
|
|
200
200
|
document-level base or managed import map.
|
|
201
201
|
Development, package, and build refresh that shared inventory when the selected operation needs it.
|
|
202
|
-
Named
|
|
202
|
+
Named \`${directRuntime?'arcane-os/modules/* and arcane-os/entities/*':'arcane/*'}\` imports resolve through the managed map to the selected SDK files. Packaging copies the complete selected application, runtime, and specifier
|
|
203
203
|
map to \`dist/${appId}\` without running application tests. Run \`verify\` only when
|
|
204
204
|
the user explicitly selects verification or a release artifact that requires it;
|
|
205
205
|
\`bundle\` creates the distributable archive and \`run\` launches the selected
|
|
@@ -231,7 +231,7 @@ Every browser release also carries Arcane OS licensing material under \`${direct
|
|
|
231
231
|
'run:browser':'arcane run --target browser'
|
|
232
232
|
}:{})
|
|
233
233
|
},
|
|
234
|
-
devDependencies:{
|
|
234
|
+
[directRuntime?'dependencies':'devDependencies']:{
|
|
235
235
|
[sdkDependencyName]:sdkDependencySpecifier
|
|
236
236
|
},
|
|
237
237
|
engines:{node:'>=22.23.2'}
|
|
@@ -369,9 +369,11 @@ ${bootstrapMarkup}</head>
|
|
|
369
369
|
files.set(`${appPrefix}modules/arcane.importmap.json`,json({imports:{}}));
|
|
370
370
|
}
|
|
371
371
|
const themeSpecifier=namedImports
|
|
372
|
-
?'arcane/ThemeBootstrap
|
|
372
|
+
?directRuntime?'arcane-os/modules/ThemeBootstrap.js':'arcane/ThemeBootstrap'
|
|
373
|
+
:`${appsRoot==='.'?'../':'../../../'}${runtimePrefix.slice(2)}/modules/ThemeBootstrap.js`;
|
|
373
374
|
const appDataSpecifier=namedImports
|
|
374
|
-
?'arcane/
|
|
375
|
+
?directRuntime?'arcane-os/app-data-scope':'arcane/AppDataScope'
|
|
376
|
+
:`${appsRoot==='.'?'../':'../../../'}${runtimePrefix.slice(2)}/modules/AppDataScope.js`;
|
|
375
377
|
const strongTypeSpecifier=namedImports
|
|
376
378
|
?'strong-type':directRuntime?`../${sdkPackageSource}/runtime/strong-type/index.js`:'../../../arcane/dependencies/strong-type/index.js';
|
|
377
379
|
files.set(`${appPrefix}modules/App.js`,`import Is from '${strongTypeSpecifier}';
|
package/src/workspace.mjs
CHANGED
|
@@ -117,7 +117,7 @@ export function resolveSdkPackageDeclaration(rootPackage,{
|
|
|
117
117
|
}={}){
|
|
118
118
|
if(!isObject(rootPackage))fail('package.json must contain a JSON object.');
|
|
119
119
|
const candidates=[];
|
|
120
|
-
for(const groupName of ['devDependencies','dependencies']){
|
|
120
|
+
for(const groupName of ['devDependencies','dependencies','optionalDependencies']){
|
|
121
121
|
const group=rootPackage[groupName];
|
|
122
122
|
if(group===undefined)continue;
|
|
123
123
|
if(!isObject(group))fail(`package.json ${groupName} must be a JSON object.`);
|