@almadar/core 10.119.0 → 10.119.1

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.
@@ -323,6 +323,10 @@ declare function dedupeComposedSurface(orbitals: OrbitalDefinition[]): {
323
323
  * A literal compared against a field the winner does not declare is a
324
324
  * shape mismatch: compose fails with a deterministic error rather than
325
325
  * silently shipping dead policy branches.
326
+ * A loser is a demoted identity, or an identity an orbital `expects` by name that no orbital
327
+ * provides as identity (composed from another organism): its role vocabulary joins the winner's,
328
+ * and its expectation is rewritten when the app holds it as a plain record.
329
+ *
326
330
  * - FIX-L — a composed `expects identity <Loser>` would fail the link-check
327
331
  * (`ORB_S_EXPECTATION_PROVIDER_MISMATCH`) on every recompose; it is
328
332
  * rewritten to `expects entity <Loser>` — the compiled path's own
@@ -347,6 +351,15 @@ declare function asEntityObject(entity: OrbitalDefinition['entity']): {
347
351
  } | null;
348
352
  /** The entity an orbital DECLARES (object form only — a bare string ref owns nothing here). */
349
353
  declare function orbitalEntityName(def: OrbitalDefinition): string | null;
354
+ /**
355
+ * `organismOrderOf` for a registry: an orbital's position among its organism's declared orbitals,
356
+ * by the catalog orbital it was built from (`catalogOrbitalOf`, rename-stable). Each organism is
357
+ * loaded once.
358
+ */
359
+ declare function organismOrderResolver(catalogOrbitalOf: (orbitalName: string) => {
360
+ organism: string;
361
+ orbital: string;
362
+ } | undefined, loadOrganism: (organism: string) => OrbitalSchema | null): (orbitalName: string) => number | undefined;
350
363
  /**
351
364
  * `importedOrbitalOf` for a registry: an import's `reference.ref` (`Alias.orbitals.Name`)
352
365
  * resolved through the orbital's `uses` to the behavior it imports, then to that behavior's
@@ -416,6 +429,12 @@ interface ComposeSurfaceOptions {
416
429
  * own file follows.
417
430
  */
418
431
  organismOf?: (orbitalName: string) => string | undefined;
432
+ /**
433
+ * An orbital's position in its organism's declared orbitals. The first declared orbital boots
434
+ * the organism standalone, so composed behind another organism it is the landing page the nav
435
+ * must link; without it, the first composed orbital of the organism stands in.
436
+ */
437
+ organismOrderOf?: (orbitalName: string) => number | undefined;
419
438
  /** The atom's declaration of a referenced trait (see `RenameEntityOptions.atomTraitOf`); namespacing reads it. */
420
439
  atomTraitOf?: (orbital: OrbitalDefinition, traitRef: string) => Trait | undefined;
421
440
  /** An orbital import's source orbital (`orbitalImportResolver`); its pages count as owned when nav is narrowed. */
@@ -995,4 +1014,4 @@ declare function compose(orbitals: (OrbitalDefinition | OrbitalSchema)[], pages:
995
1014
  */
996
1015
  declare function pipe(orbitals: (OrbitalDefinition | OrbitalSchema)[], events: TraitEventContract[], appName?: string): OrbitalSchema;
997
1016
 
998
- export { type ComposeAppFromFilesOptions, type ComposeAppFromFilesResult, type ComposeBehaviorsInput, type ComposeBehaviorsResult, type ComposeConnection, type ComposePage, type ComposeSurfaceOptions, type ComposedSurface, type ConfigNavItemsNarrowResult, type EntityRenameBlocker, type EventWiringEntry, type FieldBindingContext, type IdentityDedupeResult, type IdentityDemotion, type IdentityExpectsRewrite, type IdentityRelationRetarget, type IdentityRoleUnion, type LandingNavResult, type LayoutStrategy, type MakeAtomOrbitalOpts, type MakeAtomOrbitalTraitOverrides, type MakeEntityOpts, type MakeLayoutTraitOpts, type MakeOrbitalWithUsesOpts, type MakePageOpts, type MakePageRefOpts, type MakePageRefOptsTyped, type MakeTraitRefOpts, type MakeTraitRefOptsTyped, type NavItemsNarrowResult, type OrganismRename, type RenameEntityOptions, type SurfaceRename, type UnrenamableCollision, applyEventWiring, applyTraitConfigOverrides, asEntityObject, atomTraitResolver, collectFieldComparisonLiterals, collectOwnedSurface, collectOwnerComparedFields, collectOwnerStampedFields, compose, composeAppFromFiles, composeBehaviors, composeOrbitalSurface, connect, dedupeComposedIdentity, dedupeComposedSurface, detectLayoutStrategy, ensureIdField, entityRenameBlockers, extractTrait, findDanglingRefs, makeAtomOrbital, makeEntity, makeLayoutTrait, makeOrbital, makeOrbitalWithUses, makePage, makePageRef, makeRenderUI, makeSchema, makeSlot, makeTraitRef, mergeLedgers, mergeOrbitals, orbitalEntityName, orbitalImportResolver, orbitalRouteSlug, pipe, plural, renameEntity, renameEntityInSchema, renameOrbital, wire };
1017
+ export { type ComposeAppFromFilesOptions, type ComposeAppFromFilesResult, type ComposeBehaviorsInput, type ComposeBehaviorsResult, type ComposeConnection, type ComposePage, type ComposeSurfaceOptions, type ComposedSurface, type ConfigNavItemsNarrowResult, type EntityRenameBlocker, type EventWiringEntry, type FieldBindingContext, type IdentityDedupeResult, type IdentityDemotion, type IdentityExpectsRewrite, type IdentityRelationRetarget, type IdentityRoleUnion, type LandingNavResult, type LayoutStrategy, type MakeAtomOrbitalOpts, type MakeAtomOrbitalTraitOverrides, type MakeEntityOpts, type MakeLayoutTraitOpts, type MakeOrbitalWithUsesOpts, type MakePageOpts, type MakePageRefOpts, type MakePageRefOptsTyped, type MakeTraitRefOpts, type MakeTraitRefOptsTyped, type NavItemsNarrowResult, type OrganismRename, type RenameEntityOptions, type SurfaceRename, type UnrenamableCollision, applyEventWiring, applyTraitConfigOverrides, asEntityObject, atomTraitResolver, collectFieldComparisonLiterals, collectOwnedSurface, collectOwnerComparedFields, collectOwnerStampedFields, compose, composeAppFromFiles, composeBehaviors, composeOrbitalSurface, connect, dedupeComposedIdentity, dedupeComposedSurface, detectLayoutStrategy, ensureIdField, entityRenameBlockers, extractTrait, findDanglingRefs, makeAtomOrbital, makeEntity, makeLayoutTrait, makeOrbital, makeOrbitalWithUses, makePage, makePageRef, makeRenderUI, makeSchema, makeSlot, makeTraitRef, mergeLedgers, mergeOrbitals, orbitalEntityName, orbitalImportResolver, orbitalRouteSlug, organismOrderResolver, pipe, plural, renameEntity, renameEntityInSchema, renameOrbital, wire };
package/dist/builders.js CHANGED
@@ -2947,12 +2947,32 @@ function dedupeComposedIdentity(orbitals) {
2947
2947
  demotions.push({ orbitalName: def.name, entityName: entity.name });
2948
2948
  demotedEntities.push(demoted);
2949
2949
  }
2950
- if (winnerIndex === -1 || demotions.length === 0) {
2950
+ if (winnerIndex === -1) {
2951
2951
  return { demotions, roleUnions: [], expectsRewrites: [], relationsRetargeted: [] };
2952
2952
  }
2953
- const roleUnions = unionDemotedRoleVocabularies(orbitals, winnerIndex, demotedEntities);
2954
- const expectsRewrites = rewriteDemotedIdentityExpects(orbitals, demotions);
2955
- const relationsRetargeted = retargetDemotedOwnerRelations(orbitals, winnerIndex, demotions);
2953
+ const winnerName = orbitalEntityName(orbitals[winnerIndex]);
2954
+ const demotedNames = new Set(demotions.map((d) => d.entityName));
2955
+ const strayExpects = [];
2956
+ for (const def of orbitals) {
2957
+ for (const e of def.expects ?? []) {
2958
+ if (e.kind !== "identity" || e.name === void 0 || e.name === winnerName || demotedNames.has(e.name)) continue;
2959
+ strayExpects.push({ name: e.name, shape: e.shape ?? [] });
2960
+ }
2961
+ }
2962
+ if (demotions.length === 0 && strayExpects.length === 0) {
2963
+ return { demotions, roleUnions: [], expectsRewrites: [], relationsRetargeted: [] };
2964
+ }
2965
+ const providedNames = new Set(orbitals.flatMap((def) => inlineEntitiesOf(def).map((e) => e.name)));
2966
+ const roleUnions = unionDemotedRoleVocabularies(orbitals, winnerIndex, [
2967
+ ...demotedEntities.map((d) => ({ name: d.name, fields: d.fields })),
2968
+ ...strayExpects.map((e) => ({ name: e.name, fields: e.shape }))
2969
+ ]);
2970
+ const loserNames = /* @__PURE__ */ new Set([
2971
+ ...demotedNames,
2972
+ ...strayExpects.map((e) => e.name).filter((name) => providedNames.has(name))
2973
+ ]);
2974
+ const expectsRewrites = rewriteDemotedIdentityExpects(orbitals, loserNames);
2975
+ const relationsRetargeted = retargetDemotedOwnerRelations(orbitals, winnerIndex, loserNames);
2956
2976
  return { demotions, roleUnions, expectsRewrites, relationsRetargeted };
2957
2977
  }
2958
2978
  function fieldVocabulary(field) {
@@ -3054,8 +3074,7 @@ function collectPersistedFields(node, entityName, out) {
3054
3074
  for (const value of Object.values(node)) collectPersistedFields(value, entityName, out);
3055
3075
  }
3056
3076
  }
3057
- function rewriteDemotedIdentityExpects(orbitals, demotions) {
3058
- const demotedNames = new Set(demotions.map((d) => d.entityName));
3077
+ function rewriteDemotedIdentityExpects(orbitals, demotedNames) {
3059
3078
  const entityByName = /* @__PURE__ */ new Map();
3060
3079
  for (const def of orbitals) for (const entity of inlineEntitiesOf(def)) entityByName.set(entity.name, entity);
3061
3080
  const rewrites = [];
@@ -3073,12 +3092,13 @@ function rewriteDemotedIdentityExpects(orbitals, demotions) {
3073
3092
  collectPersistedFields(def.traits ?? [], e.name, persisted);
3074
3093
  const declared = new Set(e.shape.map((f) => f.name));
3075
3094
  const entity = entityByName.get(e.name);
3095
+ const asDeclared = (field) => entity?.fields.find((f) => f.name === field.name) ?? field;
3076
3096
  const added = [...persisted].sort().flatMap((field) => {
3077
3097
  if (declared.has(field)) return [];
3078
3098
  const own = entity?.fields.find((f) => f.name === field);
3079
3099
  return own !== void 0 ? [own] : [];
3080
3100
  });
3081
- return { kind: "entity", name: e.name, shape: [...e.shape, ...added] };
3101
+ return { kind: "entity", name: e.name, shape: [...e.shape.map(asDeclared), ...added] };
3082
3102
  });
3083
3103
  if (mutated) orbitals[i] = { ...def, expects: next };
3084
3104
  }
@@ -3108,11 +3128,10 @@ function retargetOwnerRelationFields(entity, fieldNames, demotedNames, winner) {
3108
3128
  });
3109
3129
  return applied.length === 0 ? null : { entity: { ...entity, fields }, applied };
3110
3130
  }
3111
- function retargetDemotedOwnerRelations(orbitals, winnerIndex, demotions) {
3131
+ function retargetDemotedOwnerRelations(orbitals, winnerIndex, demotedNames) {
3112
3132
  const winnerDef = orbitals[winnerIndex];
3113
3133
  const winnerEntity = winnerDef.entity;
3114
3134
  if (winnerEntity === void 0 || isEntityReferenceAny(winnerEntity)) return [];
3115
- const demotedNames = new Set(demotions.map((d) => d.entityName));
3116
3135
  const candidates = /* @__PURE__ */ new Map();
3117
3136
  const addAll = (entityName, fields) => {
3118
3137
  if (fields.size === 0) return;
@@ -3222,6 +3241,18 @@ function collectOwnedPages(orbitals, importedOrbitalOf) {
3222
3241
  }
3223
3242
  return owned;
3224
3243
  }
3244
+ function organismOrderResolver(catalogOrbitalOf, loadOrganism) {
3245
+ const declared = /* @__PURE__ */ new Map();
3246
+ return (orbitalName) => {
3247
+ const source = catalogOrbitalOf(orbitalName);
3248
+ if (source === void 0) return void 0;
3249
+ if (!declared.has(source.organism)) {
3250
+ declared.set(source.organism, loadOrganism(source.organism)?.orbitals.map((o) => o.name) ?? null);
3251
+ }
3252
+ const index = declared.get(source.organism)?.indexOf(source.orbital) ?? -1;
3253
+ return index >= 0 ? index : void 0;
3254
+ };
3255
+ }
3225
3256
  function orbitalImportResolver(loadBehaviorOrb) {
3226
3257
  const loaded = /* @__PURE__ */ new Map();
3227
3258
  return (orbital) => {
@@ -3276,7 +3307,7 @@ function firstInlinePage(orbital) {
3276
3307
  }
3277
3308
  return void 0;
3278
3309
  }
3279
- function linkLandingPages(orbitals, config, organismOf, navDeclaringOrbitals) {
3310
+ function linkLandingPages(orbitals, config, organismOf, navDeclaringOrbitals, organismOrderOf) {
3280
3311
  const navKnobs = Object.entries(config).filter(([, field2]) => field2.type === "[NavItem]" && Array.isArray(field2.default));
3281
3312
  if (navKnobs.length !== 1) return { config, added: [] };
3282
3313
  const [knob, field] = navKnobs[0];
@@ -3301,7 +3332,15 @@ function linkLandingPages(orbitals, config, organismOf, navDeclaringOrbitals) {
3301
3332
  const organism = organismOf(name);
3302
3333
  if (organism !== void 0) navOrganisms.add(organism);
3303
3334
  }
3304
- const seenOrganisms = /* @__PURE__ */ new Set();
3335
+ const landingOf = /* @__PURE__ */ new Map();
3336
+ orbitals.forEach((orbital, i) => {
3337
+ const organism = organismOf(orbital.name);
3338
+ if (organism === void 0 || firstInlinePage(orbital) === void 0) return;
3339
+ const rank = organismOrderOf?.(orbital.name) ?? orbitals.length + i;
3340
+ const current = landingOf.get(organism);
3341
+ if (current === void 0 || rank < current.rank) landingOf.set(organism, { name: orbital.name, rank });
3342
+ });
3343
+ let bootOrganism;
3305
3344
  let booted = false;
3306
3345
  orbitals.forEach((orbital, i) => {
3307
3346
  const page = firstInlinePage(orbital);
@@ -3309,11 +3348,11 @@ function linkLandingPages(orbitals, config, organismOf, navDeclaringOrbitals) {
3309
3348
  const organism = organismOf(orbital.name);
3310
3349
  if (!booted) {
3311
3350
  booted = true;
3312
- if (organism !== void 0) seenOrganisms.add(organism);
3351
+ bootOrganism = organism;
3313
3352
  return;
3314
3353
  }
3315
- if (organism === void 0 || navOrganisms.has(organism) && seenOrganisms.has(organism)) return;
3316
- seenOrganisms.add(organism);
3354
+ if (organism === void 0) return;
3355
+ if (navOrganisms.has(organism) && (organism === bootOrganism || landingOf.get(organism)?.name !== orbital.name)) return;
3317
3356
  if (linked.has(page.path) || page.path.split("/").some((segment) => segment.startsWith(":"))) return;
3318
3357
  let at = 0;
3319
3358
  next.forEach((entry, p) => {
@@ -3571,7 +3610,7 @@ function composeOrbitalSurface(files, options = {}) {
3571
3610
  if (!Object.values(f.config).some((entry) => entry.type === "[NavItem]")) continue;
3572
3611
  for (const o of f.orbitals) navDeclaringOrbitals.add(o.name);
3573
3612
  }
3574
- const linked = linkLandingPages(orbitals, config, options.organismOf, navDeclaringOrbitals);
3613
+ const linked = linkLandingPages(orbitals, config, options.organismOf, navDeclaringOrbitals, options.organismOrderOf);
3575
3614
  config = linked.config;
3576
3615
  landingNavAdded = linked.added;
3577
3616
  }
@@ -3592,7 +3631,8 @@ function composeAppFromFiles(files, options) {
3592
3631
  const { orbitals, config, ledger, ...outcomes } = composeOrbitalSurface(files, {
3593
3632
  ...options.organismOf !== void 0 ? { organismOf: options.organismOf } : {},
3594
3633
  ...options.atomTraitOf !== void 0 ? { atomTraitOf: options.atomTraitOf } : {},
3595
- ...options.importedOrbitalOf !== void 0 ? { importedOrbitalOf: options.importedOrbitalOf } : {}
3634
+ ...options.importedOrbitalOf !== void 0 ? { importedOrbitalOf: options.importedOrbitalOf } : {},
3635
+ ...options.organismOrderOf !== void 0 ? { organismOrderOf: options.organismOrderOf } : {}
3596
3636
  });
3597
3637
  const result = composeBehaviors({
3598
3638
  appName: options.appName,
@@ -3942,6 +3982,6 @@ function pipe(orbitals, events, appName) {
3942
3982
  };
3943
3983
  }
3944
3984
 
3945
- export { applyEventWiring, applyTraitConfigOverrides, asEntityObject, atomTraitResolver, collectFieldComparisonLiterals, collectOwnedSurface, collectOwnerComparedFields, collectOwnerStampedFields, compose, composeAppFromFiles, composeBehaviors, composeOrbitalSurface, connect, dedupeComposedIdentity, dedupeComposedSurface, detectLayoutStrategy, ensureIdField, entityRenameBlockers, extractTrait, findDanglingRefs, makeAtomOrbital, makeEntity, makeLayoutTrait, makeOrbital, makeOrbitalWithUses, makePage, makePageRef, makeRenderUI, makeSchema, makeSlot, makeTraitRef, mergeLedgers, mergeOrbitals, orbitalEntityName, orbitalImportResolver, orbitalRouteSlug, pipe, plural, renameEntity, renameEntityInSchema, renameOrbital, wire };
3985
+ export { applyEventWiring, applyTraitConfigOverrides, asEntityObject, atomTraitResolver, collectFieldComparisonLiterals, collectOwnedSurface, collectOwnerComparedFields, collectOwnerStampedFields, compose, composeAppFromFiles, composeBehaviors, composeOrbitalSurface, connect, dedupeComposedIdentity, dedupeComposedSurface, detectLayoutStrategy, ensureIdField, entityRenameBlockers, extractTrait, findDanglingRefs, makeAtomOrbital, makeEntity, makeLayoutTrait, makeOrbital, makeOrbitalWithUses, makePage, makePageRef, makeRenderUI, makeSchema, makeSlot, makeTraitRef, mergeLedgers, mergeOrbitals, orbitalEntityName, orbitalImportResolver, orbitalRouteSlug, organismOrderResolver, pipe, plural, renameEntity, renameEntityInSchema, renameOrbital, wire };
3946
3986
  //# sourceMappingURL=builders.js.map
3947
3987
  //# sourceMappingURL=builders.js.map