browser-module-runtime 0.0.2 → 0.0.4

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/index.d.ts CHANGED
@@ -39,6 +39,8 @@ export interface RuntimePlugin {
39
39
  cacheKey?: string;
40
40
  /** Framework-owned exact package roots merged into the runtime package policy. */
41
41
  packageEntries?: NonNullable<PackageOptions['entries']>;
42
+ /** Optional coordinated package URL family; precedence/conflict validated at factory creation. */
43
+ packageFamilyRules?: Record<string,{url:string;version:string;provider:string;subpathUrl?:(subpath:string)=>string}>;
42
44
  compilers?: CompilerAdapter[];
43
45
  renderers?: RendererAdapter[];
44
46
  preprocess?: TransformHook[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "browser-module-runtime",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
package/src/index.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import {createRuntime as createModuleEngine} from './engine/runtime.js';
2
2
  import {createBuildPipeline} from './build/pipeline.js';
3
3
  import {createStyleManager} from './resources/styles.js';
4
- import {mergePluginPackageEntries} from './plugins/package-entries.js';
4
+ import {mergePluginPackageEntries,mergePluginPackageFamilyRules} from './plugins/package-entries.js';
5
+ import {parsePackageSpecifier,PackageVersionResolutionError} from './engine/package-resolution/index.js';
5
6
 
6
7
  /** Framework-neutral, synchronous factory. Async plugin setup is available on `.ready`. */
7
8
  export function createRuntime(options={}) {
@@ -10,22 +11,35 @@ export function createRuntime(options={}) {
10
11
  const metadata=new Map();
11
12
  const pipeline=createBuildPipeline({plugins,defaultType:options.defaultType||'javascript',onArtifact:(id,artifact)=>artifactById.set(id,artifact)});
12
13
  const effectivePackages=mergePluginPackageEntries(options.packages,plugins);
13
- const core=createModuleEngine({...options,packages:effectivePackages,compiler:pipeline});
14
+ const familyRules=mergePluginPackageFamilyRules(effectivePackages,plugins,options._solidFamilyRules,options.modules);
15
+ const protectedRoots=new Set(plugins.flatMap(plugin=>Object.keys(plugin.packageFamilyRules??{})));
16
+ function rejectProtected(id){
17
+ const name=parsePackageSpecifier(String(id))?.packageName;
18
+ if(name && protectedRoots.has(name))throw new PackageVersionResolutionError('PACKAGE_VERSION_CONFLICT',
19
+ `${JSON.stringify(id)} belongs to a framework-managed package family; use host mode to override its modules.`,{packageName:name});
20
+ }
21
+ for(const id of Object.keys(options.urls??{}))rejectProtected(id);
22
+ const core=createModuleEngine({...options,packages:effectivePackages,_solidFamilyRules:familyRules,compiler:pipeline});
14
23
  const styles=createStyleManager();
15
24
  const mounts=new Set();
16
25
  let disposed=false;
17
26
  const runtime={
18
27
  ...core,
19
28
  ready:null,
29
+ defineModule(id,namespace){rejectProtected(id);return core.defineModule(id,namespace);},
30
+ defineUrl(id,url){rejectProtected(id);return core.defineUrl(id,url);},
20
31
  define(id,source,config={}) {
32
+ rejectProtected(id);
21
33
  const type=pipeline.detectType(id,config.type||config.format);
22
34
  metadata.set(id,{type});
23
35
  return core.define(id,source,{...config,format:type});
24
36
  },
25
37
  defineMany(definitions) {
38
+ definitions.forEach(({id})=>rejectProtected(id));
26
39
  return definitions.map(({id,source,...opts})=>runtime.define(id,source,opts));
27
40
  },
28
41
  update(id,source,config={}) {
42
+ rejectProtected(id);
29
43
  const type=pipeline.detectType(id,config.type||config.format||metadata.get(id)?.type);
30
44
  metadata.set(id,{type});
31
45
  return core.update(id,source,{...config,format:type});
@@ -28,3 +28,33 @@ export function mergePluginPackageEntries(packages,plugins=[]) {
28
28
  }
29
29
  return {...source,versions,entries};
30
30
  }
31
+
32
+
33
+ /** Runtime-local provider rules for package families with strict identity
34
+ * requirements (e.g. Solid 2). Plugins own their family membership; the
35
+ * generic module engine only sees a regular root -> URL/subpath resolver map.
36
+ */
37
+ export function mergePluginPackageFamilyRules(packages, plugins=[], explicitRules={}, modules={}) {
38
+ const rules={...(explicitRules??{})};
39
+ const pinned=createPackagePolicy(packages);
40
+ for(const plugin of plugins){
41
+ for(const [name,rule] of Object.entries(plugin.packageFamilyRules??{})){
42
+ const previous=rules[name];
43
+ if(previous && (previous.url!==rule.url || previous.version!==rule.version))
44
+ throw new PackageVersionResolutionError('PACKAGE_VERSION_CONFLICT',
45
+ `Plugin ${JSON.stringify(plugin.name)} requires ${JSON.stringify(name)} from ${rule.url}, but another provider requires ${previous.url}.`,
46
+ {packageName:name,plugin:plugin.name,expected:rule.url,actual:previous.url});
47
+ const selected=pinned.inspect(name);
48
+ if(selected && selected.url!==rule.url)
49
+ throw new PackageVersionResolutionError('PACKAGE_VERSION_CONFLICT',
50
+ `Plugin ${JSON.stringify(plugin.name)} owns ${JSON.stringify(name)} at ${rule.url}, but the runtime pins ${selected.url}. Remove the duplicate family pin.`,
51
+ {packageName:name,plugin:plugin.name,expected:rule.url,actual:selected.url});
52
+ if(Object.hasOwn(modules,name))
53
+ throw new PackageVersionResolutionError('PACKAGE_VERSION_CONFLICT',
54
+ `Plugin ${JSON.stringify(plugin.name)} owns ${JSON.stringify(name)}; a caller-owned module namespace cannot guarantee the same framework identity. Use host mode.`,
55
+ {packageName:name,plugin:plugin.name});
56
+ rules[name]=rule;
57
+ }
58
+ }
59
+ return rules;
60
+ }