@almadar/core 2.4.0 → 2.5.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/dist/builders.d.ts +2 -0
- package/dist/builders.js +2 -1
- package/dist/builders.js.map +1 -1
- package/package.json +1 -1
package/dist/builders.d.ts
CHANGED
|
@@ -30,6 +30,8 @@ interface MakeEntityOpts {
|
|
|
30
30
|
fields: EntityField[];
|
|
31
31
|
persistence?: EntityPersistence;
|
|
32
32
|
collection?: string;
|
|
33
|
+
/** Pre-authored seed data instances */
|
|
34
|
+
instances?: Record<string, unknown>[];
|
|
33
35
|
}
|
|
34
36
|
/**
|
|
35
37
|
* Build an Entity from options. Auto-adds id field, auto-derives collection.
|
package/dist/builders.js
CHANGED
|
@@ -13,7 +13,8 @@ function makeEntity(opts) {
|
|
|
13
13
|
name: opts.name,
|
|
14
14
|
persistence,
|
|
15
15
|
...persistence === "persistent" ? { collection: opts.collection ?? plural(opts.name).toLowerCase() } : {},
|
|
16
|
-
fields
|
|
16
|
+
fields,
|
|
17
|
+
...opts.instances && opts.instances.length > 0 ? { instances: opts.instances } : {}
|
|
17
18
|
};
|
|
18
19
|
}
|
|
19
20
|
function makePage(opts) {
|
package/dist/builders.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/builders.ts"],"names":[],"mappings":";AA6BO,SAAS,cAAc,MAAA,EAAsC;AAClE,EAAA,IAAI,OAAO,IAAA,CAAK,CAAA,CAAA,KAAK,EAAE,IAAA,KAAS,IAAI,GAAG,OAAO,MAAA;AAC9C,EAAA,OAAO,CAAC,EAAE,IAAA,EAAM,IAAA,EAAM,IAAA,EAAM,UAAU,QAAA,EAAU,IAAA,EAAK,EAAG,GAAG,MAAM,CAAA;AACnE;AAKO,SAAS,OAAO,IAAA,EAAsB;AAC3C,EAAA,OAAO,IAAA,GAAO,GAAA;AAChB;AAgBO,SAAS,WAAW,IAAA,EAA8B;AACvD,EAAA,MAAM,MAAA,GAAS,aAAA,CAAc,IAAA,CAAK,MAAM,CAAA;AACxC,EAAA,MAAM,WAAA,GAAc,KAAK,WAAA,IAAe,SAAA;AACxC,EAAA,OAAO;AAAA,IACL,MAAM,IAAA,CAAK,IAAA;AAAA,IACX,WAAA;AAAA,IACA,GAAI,WAAA,KAAgB,YAAA,GAChB,EAAE,YAAY,IAAA,CAAK,UAAA,IAAc,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA,CAAE,WAAA,EAAY,KAC/D,EAAC;AAAA,IACL;AAAA,GACF;AACF;AAgBO,SAAS,SAAS,IAAA,EAA0B;AACjD,EAAA,OAAO;AAAA,IACL,MAAM,IAAA,CAAK,IAAA;AAAA,IACX,MAAM,IAAA,CAAK,IAAA;AAAA,IACX,GAAI,IAAA,CAAK,SAAA,GAAY,EAAE,SAAA,EAAW,IAAA,KAAS,EAAC;AAAA,IAC5C,QAAQ,CAAC,EAAE,GAAA,EAAK,IAAA,CAAK,WAAW;AAAA,GAClC;AACF;AASO,SAAS,WAAA,CACd,IAAA,EACA,MAAA,EACA,MAAA,EACA,KAAA,EACmB;AACnB,EAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,MAAA,EAAQ,KAAA,EAAM;AACvC;AAWO,SAAS,aAAA,CACd,IAAA,EACA,MAAA,EACA,OAAA,EACA,KAAA,EACmB;AACnB,EAAA,MAAM,YAAY,OAAA,CAAQ,OAAA;AAAA,IAAQ,OAC/B,CAAA,CAAE,MAAA,CAAmB,IAAI,CAAA,CAAA,KAAK,eAAA,CAAgB,CAAC,CAAC;AAAA,GACnD;AACA,EAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,MAAA,EAAQ,WAAW,KAAA,EAAM;AAClD;AAOO,SAAS,IAAA,CACd,MAAA,EACA,MAAA,EACA,KAAA,EACA,QAAA,EACgB;AAChB,EAAA,MAAM,CAAA,GAAI,gBAAgB,MAAM,CAAA;AAChC,EAAA,MAAM,CAAA,GAAI,gBAAgB,MAAM,CAAA;AAEhC,EAAA,CAAA,CAAE,KAAA,GAAQ,CAAC,GAAI,CAAA,CAAE,SAAS,EAAC,EAAI,EAAE,GAAG,KAAA,EAAO,KAAA,EAAO,KAAA,CAAM,KAAA,IAAU,YAAsB,CAAA;AACxF,EAAA,CAAA,CAAE,UAAU,CAAC,GAAI,CAAA,CAAE,OAAA,IAAW,EAAC,EAAI;AAAA,IACjC,OAAO,KAAA,CAAM,KAAA;AAAA,IACb,QAAA;AAAA,IACA,KAAA,EAAO;AAAA,GACR,CAAA;AAED,EAAA,OAAO,CAAC,GAAG,CAAC,CAAA;AACd;AAKO,SAAS,aAAa,OAAA,EAAmC;AAC9D,EAAA,OAAO,eAAA,CAAiB,OAAA,CAAQ,MAAA,CAAmB,CAAC,CAAC,CAAA;AACvD;AAWO,SAAS,OAAA,CACd,CAAA,EACA,CAAA,EACA,KAAA,EACA,QAAA,EACwC;AACxC,EAAA,MAAM,MAAA,GAAS,gBAAgB,CAAC,CAAA;AAChC,EAAA,MAAM,MAAA,GAAS,gBAAgB,CAAC,CAAA;AAGhC,EAAA,MAAM,MAAA,GAAU,MAAA,CAAO,MAAA,CAAmB,CAAC,CAAA;AAC3C,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,MAAM,YAAA,GAAmC;AAAA,MACvC,GAAG,KAAA;AAAA,MACH,KAAA,EAAO,MAAM,KAAA,IAAS;AAAA,KACxB;AACA,IAAA,MAAA,CAAO,QAAQ,CAAC,GAAI,OAAO,KAAA,IAAS,IAAK,YAAY,CAAA;AAAA,EACvD;AAGA,EAAA,MAAM,MAAA,GAAU,MAAA,CAAO,MAAA,CAAmB,CAAC,CAAA;AAC3C,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,MAAM,QAAA,GAA+B;AAAA,MACnC,OAAO,KAAA,CAAM,KAAA;AAAA,MACb,UAAU,QAAA,IAAY,MAAA;AAAA,MACtB,KAAA,EAAO;AAAA,KACT;AACA,IAAA,MAAA,CAAO,UAAU,CAAC,GAAI,OAAO,OAAA,IAAW,IAAK,QAAQ,CAAA;AAAA,EACvD;AAEA,EAAA,OAAO,CAAC,QAAQ,MAAM,CAAA;AACxB;AAwBO,SAAS,OAAA,CACd,QAAA,EACA,KAAA,EACA,WAAA,EACA,OAAA,EACe;AACf,EAAA,MAAM,MAAA,GAAS,gBAAgB,QAAQ,CAAA;AAGvC,EAAA,KAAA,MAAW,QAAQ,WAAA,EAAa;AAC9B,IAAA,MAAM,OAAA,GAAU,MAAA,CAAO,IAAA,CAAK,CAAA,CAAA,KAAK;AAC/B,MAAA,MAAM,SAAS,CAAA,CAAE,MAAA;AACjB,MAAA,OAAO,OAAO,IAAA,CAAK,CAAA,CAAA,KAAK,CAAA,CAAE,IAAA,KAAS,KAAK,IAAI,CAAA;AAAA,IAC9C,CAAC,CAAA;AACD,IAAA,MAAM,QAAA,GAAW,MAAA,CAAO,IAAA,CAAK,CAAA,CAAA,KAAK;AAChC,MAAA,MAAM,SAAS,CAAA,CAAE,MAAA;AACjB,MAAA,OAAO,OAAO,IAAA,CAAK,CAAA,CAAA,KAAK,CAAA,CAAE,IAAA,KAAS,KAAK,EAAE,CAAA;AAAA,IAC5C,CAAC,CAAA;AAED,IAAA,IAAI,WAAW,QAAA,EAAU;AACvB,MAAA,MAAM,MAAA,GAAU,QAAQ,MAAA,CAAmB,IAAA,CAAK,OAAK,CAAA,CAAE,IAAA,KAAS,KAAK,IAAI,CAAA;AACzE,MAAA,MAAM,MAAA,GAAU,SAAS,MAAA,CAAmB,IAAA,CAAK,OAAK,CAAA,CAAE,IAAA,KAAS,KAAK,EAAE,CAAA;AAExE,MAAA,IAAI,MAAA,EAAQ;AACV,QAAA,MAAM,YAAA,GAAmC,EAAE,GAAG,IAAA,CAAK,OAAO,KAAA,EAAO,IAAA,CAAK,KAAA,CAAM,KAAA,IAAS,UAAA,EAAW;AAChG,QAAA,MAAA,CAAO,QAAQ,CAAC,GAAI,OAAO,KAAA,IAAS,IAAK,YAAY,CAAA;AAAA,MACvD;AACA,MAAA,IAAI,MAAA,EAAQ;AACV,QAAA,MAAM,cAAA,GAAqC;AAAA,UACzC,KAAA,EAAO,KAAK,KAAA,CAAM,KAAA;AAAA,UAClB,QAAA,EAAU,KAAK,QAAA,IAAY,MAAA;AAAA,UAC3B,KAAA,EAAO;AAAA,SACT;AACA,QAAA,MAAA,CAAO,UAAU,CAAC,GAAI,OAAO,OAAA,IAAW,IAAK,cAAc,CAAA;AAAA,MAC7D;AAAA,IACF;AAAA,EACF;AAGA,EAAA,KAAA,MAAW,WAAW,MAAA,EAAQ;AAC5B,IAAA,MAAM,aAAc,OAAA,CAAQ,MAAA,CAAmB,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,IAAI,CAAA;AAC9D,IAAA,MAAM,gBAAgB,KAAA,CAAM,MAAA;AAAA,MAAO,CAAA,CAAA,KACjC,EAAE,MAAA,CAAO,IAAA,CAAK,OAAK,UAAA,CAAW,QAAA,CAAS,CAAC,CAAC;AAAA,KAC3C;AACA,IAAA,OAAA,CAAQ,KAAA,GAAQ,aAAA,CAAc,GAAA,CAAI,CAAA,CAAA,MAAM;AAAA,MACtC,MAAM,CAAA,CAAE,IAAA;AAAA,MACR,MAAM,CAAA,CAAE,IAAA;AAAA,MACR,GAAI,CAAA,CAAE,SAAA,GAAY,EAAE,SAAA,EAAW,IAAA,KAAS,EAAC;AAAA,MACzC,MAAA,EAAQ,CAAA,CAAE,MAAA,CACP,MAAA,CAAO,OAAK,UAAA,CAAW,QAAA,CAAS,CAAC,CAAC,CAAA,CAClC,GAAA,CAAI,CAAA,GAAA,MAAQ,EAAE,KAAI,CAAE;AAAA,KACzB,CAAE,CAAA;AAAA,EACJ;AAEA,EAAA,OAAO;AAAA,IACL,MAAM,OAAA,IAAW,aAAA;AAAA,IACjB,OAAA,EAAS,OAAA;AAAA,IACT,QAAA,EAAU;AAAA,GACZ;AACF;AAUO,SAAS,IAAA,CACd,QAAA,EACA,MAAA,EACA,OAAA,EACe;AACf,EAAA,IAAI,MAAA,CAAO,MAAA,KAAW,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG;AACzC,IAAA,MAAM,IAAI,MAAM,CAAA,sBAAA,EAAyB,QAAA,CAAS,SAAS,CAAC,CAAA,YAAA,EAAe,QAAA,CAAS,MAAM,CAAA,SAAA,CAAW,CAAA;AAAA,EACvG;AAEA,EAAA,MAAM,MAAA,GAAS,gBAAgB,QAAQ,CAAA;AAGvC,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAA,CAAO,QAAQ,CAAA,EAAA,EAAK;AACtC,IAAA,MAAM,MAAA,GAAU,MAAA,CAAO,CAAC,CAAA,CAAE,OAAmB,CAAC,CAAA;AAC9C,IAAA,MAAM,SAAU,MAAA,CAAO,CAAA,GAAI,CAAC,CAAA,CAAE,OAAmB,CAAC,CAAA;AAElD,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,MAAM,YAAA,GAAmC,EAAE,GAAG,MAAA,CAAO,CAAC,CAAA,EAAG,KAAA,EAAO,MAAA,CAAO,CAAC,CAAA,CAAE,KAAA,IAAS,UAAA,EAAW;AAC9F,MAAA,MAAA,CAAO,QAAQ,CAAC,GAAI,OAAO,KAAA,IAAS,IAAK,YAAY,CAAA;AAAA,IACvD;AACA,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,MAAM,QAAA,GAA+B;AAAA,QACnC,KAAA,EAAO,MAAA,CAAO,CAAC,CAAA,CAAE,KAAA;AAAA,QACjB,QAAA,EAAU,MAAA;AAAA,QACV,KAAA,EAAO;AAAA,OACT;AACA,MAAA,MAAA,CAAO,UAAU,CAAC,GAAI,OAAO,OAAA,IAAW,IAAK,QAAQ,CAAA;AAAA,IACvD;AAAA,EACF;AAGA,EAAA,MAAM,KAAA,GAAgB,MAAA,CAAO,GAAA,CAAI,CAAC,GAAG,CAAA,KAAM;AACzC,IAAA,MAAM,UAAA,GAAa,OAAO,CAAA,CAAE,MAAA,KAAW,WAAW,CAAA,CAAE,MAAA,GAAS,EAAE,MAAA,CAAO,IAAA;AACtE,IAAA,MAAM,aAAc,CAAA,CAAE,MAAA,CAAmB,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,IAAI,CAAA;AACxD,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,GAAG,UAAU,CAAA,IAAA,CAAA;AAAA,MACnB,MAAM,CAAA,CAAA,EAAI,MAAA,CAAO,UAAU,CAAA,CAAE,aAAa,CAAA,CAAA;AAAA,MAC1C,GAAI,CAAA,KAAM,CAAA,GAAI,EAAE,SAAA,EAAW,IAAA,KAAS,EAAC;AAAA,MACrC,QAAQ,UAAA,CAAW,GAAA,CAAI,CAAA,GAAA,MAAQ,EAAE,KAAI,CAAE;AAAA,KACzC;AAAA,EACF,CAAC,CAAA;AAGD,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAA,CAAO,QAAQ,CAAA,EAAA,EAAK;AACtC,IAAA,MAAA,CAAO,CAAC,CAAA,CAAE,KAAA,GAAQ,CAAC,KAAA,CAAM,CAAC,CAAC,CAAA;AAAA,EAC7B;AAEA,EAAA,OAAO;AAAA,IACL,MAAM,OAAA,IAAW,aAAA;AAAA,IACjB,OAAA,EAAS,OAAA;AAAA,IACT,QAAA,EAAU;AAAA,GACZ;AACF","file":"builders.js","sourcesContent":["/**\n * Orbital Builders\n *\n * Pure functions for constructing and composing Orbitals.\n * No new types. Everything uses existing core types:\n * Entity, Trait, Page, OrbitalDefinition, OrbitalSchema.\n *\n * Three categories:\n * 1. Builders: construct Entity, Page from common params\n * 2. Utilities: ensureIdField, resolveDefaults\n * 3. Composition: connect, compose, pipe\n *\n * @packageDocumentation\n */\n\nimport type { Entity, EntityPersistence } from './types/entity.js';\nimport type { EntityField } from './types/field.js';\nimport type { Page } from './types/page.js';\nimport type { OrbitalDefinition } from './types/orbital.js';\nimport type { OrbitalSchema } from './types/schema.js';\nimport type { TraitEventContract, TraitEventListener, Trait } from './types/trait.js';\n\n// ============================================================================\n// Utilities\n// ============================================================================\n\n/**\n * Ensure the fields array has an `id` field. Prepends one if missing.\n */\nexport function ensureIdField(fields: EntityField[]): EntityField[] {\n if (fields.some(f => f.name === 'id')) return fields;\n return [{ name: 'id', type: 'string', required: true }, ...fields];\n}\n\n/**\n * Simple pluralization: append 's'.\n */\nexport function plural(name: string): string {\n return name + 's';\n}\n\n// ============================================================================\n// Entity Builder\n// ============================================================================\n\nexport interface MakeEntityOpts {\n name: string;\n fields: EntityField[];\n persistence?: EntityPersistence;\n collection?: string;\n}\n\n/**\n * Build an Entity from options. Auto-adds id field, auto-derives collection.\n */\nexport function makeEntity(opts: MakeEntityOpts): Entity {\n const fields = ensureIdField(opts.fields);\n const persistence = opts.persistence ?? 'runtime';\n return {\n name: opts.name,\n persistence,\n ...(persistence === 'persistent'\n ? { collection: opts.collection ?? plural(opts.name).toLowerCase() }\n : {}),\n fields,\n };\n}\n\n// ============================================================================\n// Page Builder\n// ============================================================================\n\nexport interface MakePageOpts {\n name: string;\n path: string;\n traitName: string;\n isInitial?: boolean;\n}\n\n/**\n * Build a Page that binds to a single trait.\n */\nexport function makePage(opts: MakePageOpts): Page {\n return {\n name: opts.name,\n path: opts.path,\n ...(opts.isInitial ? { isInitial: true } : {}),\n traits: [{ ref: opts.traitName }],\n };\n}\n\n// ============================================================================\n// Orbital Builder\n// ============================================================================\n\n/**\n * Build an OrbitalDefinition from its three components.\n */\nexport function makeOrbital(\n name: string,\n entity: Entity,\n traits: Trait[],\n pages: Page[],\n): OrbitalDefinition {\n return { name, entity, traits, pages } as OrbitalDefinition;\n}\n\n// ============================================================================\n// Intra-Orbital Composition\n// ============================================================================\n\n/**\n * Merge multiple OrbitalDefinitions into one.\n * Collects all traits from all sources into a single orbital with a shared entity.\n * Pure: clones all traits, no mutation.\n */\nexport function mergeOrbitals(\n name: string,\n entity: Entity,\n sources: OrbitalDefinition[],\n pages: Page[],\n): OrbitalDefinition {\n const allTraits = sources.flatMap(s =>\n (s.traits as Trait[]).map(t => structuredClone(t)),\n );\n return { name, entity, traits: allTraits, pages } as OrbitalDefinition;\n}\n\n/**\n * Wire an intra-orbital event between two traits.\n * Adds emits to the source trait, listens to the target trait.\n * Pure: returns cloned traits, no mutation.\n */\nexport function wire(\n source: Trait,\n target: Trait,\n event: TraitEventContract,\n triggers: string,\n): [Trait, Trait] {\n const s = structuredClone(source);\n const t = structuredClone(target);\n\n s.emits = [...(s.emits ?? []), { ...event, scope: event.scope ?? ('internal' as const) }];\n t.listens = [...(t.listens ?? []), {\n event: event.event,\n triggers,\n scope: 'internal' as const,\n }];\n\n return [s, t];\n}\n\n/**\n * Extract the first trait from an OrbitalDefinition.\n */\nexport function extractTrait(orbital: OrbitalDefinition): Trait {\n return structuredClone((orbital.traits as Trait[])[0]);\n}\n\n// ============================================================================\n// Composition: connect\n// ============================================================================\n\n/**\n * Wire a cross-orbital event between two orbitals.\n * Adds emits to a's first trait, listens to b's first trait.\n * Pure: returns new orbitals, no mutation.\n */\nexport function connect(\n a: OrbitalDefinition,\n b: OrbitalDefinition,\n event: TraitEventContract,\n triggers?: string,\n): [OrbitalDefinition, OrbitalDefinition] {\n const aClone = structuredClone(a);\n const bClone = structuredClone(b);\n\n // Add emit to first trait of a\n const aTrait = (aClone.traits as Trait[])[0];\n if (aTrait) {\n const emitContract: TraitEventContract = {\n ...event,\n scope: event.scope ?? 'external',\n };\n aTrait.emits = [...(aTrait.emits ?? []), emitContract];\n }\n\n // Add listen to first trait of b\n const bTrait = (bClone.traits as Trait[])[0];\n if (bTrait) {\n const listener: TraitEventListener = {\n event: event.event,\n triggers: triggers ?? 'INIT',\n scope: 'external',\n };\n bTrait.listens = [...(bTrait.listens ?? []), listener];\n }\n\n return [aClone, bClone];\n}\n\n// ============================================================================\n// Composition: compose\n// ============================================================================\n\nexport interface ComposeConnection {\n from: string;\n to: string;\n event: TraitEventContract;\n triggers?: string;\n}\n\nexport interface ComposePage {\n name: string;\n path: string;\n traits: string[];\n isInitial?: boolean;\n}\n\n/**\n * Compose multiple orbitals into a single OrbitalSchema (application).\n * Applies connections (cross-orbital event wiring) and page assignments.\n */\nexport function compose(\n orbitals: OrbitalDefinition[],\n pages: ComposePage[],\n connections: ComposeConnection[],\n appName?: string,\n): OrbitalSchema {\n const cloned = structuredClone(orbitals);\n\n // Apply connections\n for (const conn of connections) {\n const emitter = cloned.find(o => {\n const traits = o.traits as Trait[];\n return traits.some(t => t.name === conn.from);\n });\n const listener = cloned.find(o => {\n const traits = o.traits as Trait[];\n return traits.some(t => t.name === conn.to);\n });\n\n if (emitter && listener) {\n const eTrait = (emitter.traits as Trait[]).find(t => t.name === conn.from);\n const lTrait = (listener.traits as Trait[]).find(t => t.name === conn.to);\n\n if (eTrait) {\n const emitContract: TraitEventContract = { ...conn.event, scope: conn.event.scope ?? 'external' };\n eTrait.emits = [...(eTrait.emits ?? []), emitContract];\n }\n if (lTrait) {\n const listenContract: TraitEventListener = {\n event: conn.event.event,\n triggers: conn.triggers ?? 'INIT',\n scope: 'external',\n };\n lTrait.listens = [...(lTrait.listens ?? []), listenContract];\n }\n }\n }\n\n // Assign pages to orbitals\n for (const orbital of cloned) {\n const traitNames = (orbital.traits as Trait[]).map(t => t.name);\n const matchingPages = pages.filter(p =>\n p.traits.some(t => traitNames.includes(t)),\n );\n orbital.pages = matchingPages.map(p => ({\n name: p.name,\n path: p.path,\n ...(p.isInitial ? { isInitial: true } : {}),\n traits: p.traits\n .filter(t => traitNames.includes(t))\n .map(ref => ({ ref })),\n }));\n }\n\n return {\n name: appName ?? 'Application',\n version: '1.0.0',\n orbitals: cloned,\n };\n}\n\n// ============================================================================\n// Composition: pipe\n// ============================================================================\n\n/**\n * Chain orbitals in sequence with automatic event wiring.\n * Sugar over connect + compose: wires events[0] from orbital[0] to orbital[1], etc.\n */\nexport function pipe(\n orbitals: OrbitalDefinition[],\n events: TraitEventContract[],\n appName?: string,\n): OrbitalSchema {\n if (events.length !== orbitals.length - 1) {\n throw new Error(`pipe requires exactly ${orbitals.length - 1} events for ${orbitals.length} orbitals`);\n }\n\n const cloned = structuredClone(orbitals);\n\n // Wire adjacent pairs\n for (let i = 0; i < events.length; i++) {\n const aTrait = (cloned[i].traits as Trait[])[0];\n const bTrait = (cloned[i + 1].traits as Trait[])[0];\n\n if (aTrait) {\n const emitContract: TraitEventContract = { ...events[i], scope: events[i].scope ?? 'external' };\n aTrait.emits = [...(aTrait.emits ?? []), emitContract];\n }\n if (bTrait) {\n const listener: TraitEventListener = {\n event: events[i].event,\n triggers: 'INIT',\n scope: 'external',\n };\n bTrait.listens = [...(bTrait.listens ?? []), listener];\n }\n }\n\n // Auto-generate pages: one per orbital, first is initial\n const pages: Page[] = cloned.map((o, i) => {\n const entityName = typeof o.entity === 'string' ? o.entity : o.entity.name;\n const traitNames = (o.traits as Trait[]).map(t => t.name);\n return {\n name: `${entityName}Page`,\n path: `/${plural(entityName).toLowerCase()}`,\n ...(i === 0 ? { isInitial: true } : {}),\n traits: traitNames.map(ref => ({ ref })),\n };\n });\n\n // Assign pages back to orbitals\n for (let i = 0; i < cloned.length; i++) {\n cloned[i].pages = [pages[i]];\n }\n\n return {\n name: appName ?? 'Application',\n version: '1.0.0',\n orbitals: cloned,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/builders.ts"],"names":[],"mappings":"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","file":"builders.js","sourcesContent":["/**\n * Orbital Builders\n *\n * Pure functions for constructing and composing Orbitals.\n * No new types. Everything uses existing core types:\n * Entity, Trait, Page, OrbitalDefinition, OrbitalSchema.\n *\n * Three categories:\n * 1. Builders: construct Entity, Page from common params\n * 2. Utilities: ensureIdField, resolveDefaults\n * 3. Composition: connect, compose, pipe\n *\n * @packageDocumentation\n */\n\nimport type { Entity, EntityPersistence } from './types/entity.js';\nimport type { EntityField } from './types/field.js';\nimport type { Page } from './types/page.js';\nimport type { OrbitalDefinition } from './types/orbital.js';\nimport type { OrbitalSchema } from './types/schema.js';\nimport type { TraitEventContract, TraitEventListener, Trait } from './types/trait.js';\n\n// ============================================================================\n// Utilities\n// ============================================================================\n\n/**\n * Ensure the fields array has an `id` field. Prepends one if missing.\n */\nexport function ensureIdField(fields: EntityField[]): EntityField[] {\n if (fields.some(f => f.name === 'id')) return fields;\n return [{ name: 'id', type: 'string', required: true }, ...fields];\n}\n\n/**\n * Simple pluralization: append 's'.\n */\nexport function plural(name: string): string {\n return name + 's';\n}\n\n// ============================================================================\n// Entity Builder\n// ============================================================================\n\nexport interface MakeEntityOpts {\n name: string;\n fields: EntityField[];\n persistence?: EntityPersistence;\n collection?: string;\n /** Pre-authored seed data instances */\n instances?: Record<string, unknown>[];\n}\n\n/**\n * Build an Entity from options. Auto-adds id field, auto-derives collection.\n */\nexport function makeEntity(opts: MakeEntityOpts): Entity {\n const fields = ensureIdField(opts.fields);\n const persistence = opts.persistence ?? 'runtime';\n return {\n name: opts.name,\n persistence,\n ...(persistence === 'persistent'\n ? { collection: opts.collection ?? plural(opts.name).toLowerCase() }\n : {}),\n fields,\n ...(opts.instances && opts.instances.length > 0 ? { instances: opts.instances } : {}),\n };\n}\n\n// ============================================================================\n// Page Builder\n// ============================================================================\n\nexport interface MakePageOpts {\n name: string;\n path: string;\n traitName: string;\n isInitial?: boolean;\n}\n\n/**\n * Build a Page that binds to a single trait.\n */\nexport function makePage(opts: MakePageOpts): Page {\n return {\n name: opts.name,\n path: opts.path,\n ...(opts.isInitial ? { isInitial: true } : {}),\n traits: [{ ref: opts.traitName }],\n };\n}\n\n// ============================================================================\n// Orbital Builder\n// ============================================================================\n\n/**\n * Build an OrbitalDefinition from its three components.\n */\nexport function makeOrbital(\n name: string,\n entity: Entity,\n traits: Trait[],\n pages: Page[],\n): OrbitalDefinition {\n return { name, entity, traits, pages } as OrbitalDefinition;\n}\n\n// ============================================================================\n// Intra-Orbital Composition\n// ============================================================================\n\n/**\n * Merge multiple OrbitalDefinitions into one.\n * Collects all traits from all sources into a single orbital with a shared entity.\n * Pure: clones all traits, no mutation.\n */\nexport function mergeOrbitals(\n name: string,\n entity: Entity,\n sources: OrbitalDefinition[],\n pages: Page[],\n): OrbitalDefinition {\n const allTraits = sources.flatMap(s =>\n (s.traits as Trait[]).map(t => structuredClone(t)),\n );\n return { name, entity, traits: allTraits, pages } as OrbitalDefinition;\n}\n\n/**\n * Wire an intra-orbital event between two traits.\n * Adds emits to the source trait, listens to the target trait.\n * Pure: returns cloned traits, no mutation.\n */\nexport function wire(\n source: Trait,\n target: Trait,\n event: TraitEventContract,\n triggers: string,\n): [Trait, Trait] {\n const s = structuredClone(source);\n const t = structuredClone(target);\n\n s.emits = [...(s.emits ?? []), { ...event, scope: event.scope ?? ('internal' as const) }];\n t.listens = [...(t.listens ?? []), {\n event: event.event,\n triggers,\n scope: 'internal' as const,\n }];\n\n return [s, t];\n}\n\n/**\n * Extract the first trait from an OrbitalDefinition.\n */\nexport function extractTrait(orbital: OrbitalDefinition): Trait {\n return structuredClone((orbital.traits as Trait[])[0]);\n}\n\n// ============================================================================\n// Composition: connect\n// ============================================================================\n\n/**\n * Wire a cross-orbital event between two orbitals.\n * Adds emits to a's first trait, listens to b's first trait.\n * Pure: returns new orbitals, no mutation.\n */\nexport function connect(\n a: OrbitalDefinition,\n b: OrbitalDefinition,\n event: TraitEventContract,\n triggers?: string,\n): [OrbitalDefinition, OrbitalDefinition] {\n const aClone = structuredClone(a);\n const bClone = structuredClone(b);\n\n // Add emit to first trait of a\n const aTrait = (aClone.traits as Trait[])[0];\n if (aTrait) {\n const emitContract: TraitEventContract = {\n ...event,\n scope: event.scope ?? 'external',\n };\n aTrait.emits = [...(aTrait.emits ?? []), emitContract];\n }\n\n // Add listen to first trait of b\n const bTrait = (bClone.traits as Trait[])[0];\n if (bTrait) {\n const listener: TraitEventListener = {\n event: event.event,\n triggers: triggers ?? 'INIT',\n scope: 'external',\n };\n bTrait.listens = [...(bTrait.listens ?? []), listener];\n }\n\n return [aClone, bClone];\n}\n\n// ============================================================================\n// Composition: compose\n// ============================================================================\n\nexport interface ComposeConnection {\n from: string;\n to: string;\n event: TraitEventContract;\n triggers?: string;\n}\n\nexport interface ComposePage {\n name: string;\n path: string;\n traits: string[];\n isInitial?: boolean;\n}\n\n/**\n * Compose multiple orbitals into a single OrbitalSchema (application).\n * Applies connections (cross-orbital event wiring) and page assignments.\n */\nexport function compose(\n orbitals: OrbitalDefinition[],\n pages: ComposePage[],\n connections: ComposeConnection[],\n appName?: string,\n): OrbitalSchema {\n const cloned = structuredClone(orbitals);\n\n // Apply connections\n for (const conn of connections) {\n const emitter = cloned.find(o => {\n const traits = o.traits as Trait[];\n return traits.some(t => t.name === conn.from);\n });\n const listener = cloned.find(o => {\n const traits = o.traits as Trait[];\n return traits.some(t => t.name === conn.to);\n });\n\n if (emitter && listener) {\n const eTrait = (emitter.traits as Trait[]).find(t => t.name === conn.from);\n const lTrait = (listener.traits as Trait[]).find(t => t.name === conn.to);\n\n if (eTrait) {\n const emitContract: TraitEventContract = { ...conn.event, scope: conn.event.scope ?? 'external' };\n eTrait.emits = [...(eTrait.emits ?? []), emitContract];\n }\n if (lTrait) {\n const listenContract: TraitEventListener = {\n event: conn.event.event,\n triggers: conn.triggers ?? 'INIT',\n scope: 'external',\n };\n lTrait.listens = [...(lTrait.listens ?? []), listenContract];\n }\n }\n }\n\n // Assign pages to orbitals\n for (const orbital of cloned) {\n const traitNames = (orbital.traits as Trait[]).map(t => t.name);\n const matchingPages = pages.filter(p =>\n p.traits.some(t => traitNames.includes(t)),\n );\n orbital.pages = matchingPages.map(p => ({\n name: p.name,\n path: p.path,\n ...(p.isInitial ? { isInitial: true } : {}),\n traits: p.traits\n .filter(t => traitNames.includes(t))\n .map(ref => ({ ref })),\n }));\n }\n\n return {\n name: appName ?? 'Application',\n version: '1.0.0',\n orbitals: cloned,\n };\n}\n\n// ============================================================================\n// Composition: pipe\n// ============================================================================\n\n/**\n * Chain orbitals in sequence with automatic event wiring.\n * Sugar over connect + compose: wires events[0] from orbital[0] to orbital[1], etc.\n */\nexport function pipe(\n orbitals: OrbitalDefinition[],\n events: TraitEventContract[],\n appName?: string,\n): OrbitalSchema {\n if (events.length !== orbitals.length - 1) {\n throw new Error(`pipe requires exactly ${orbitals.length - 1} events for ${orbitals.length} orbitals`);\n }\n\n const cloned = structuredClone(orbitals);\n\n // Wire adjacent pairs\n for (let i = 0; i < events.length; i++) {\n const aTrait = (cloned[i].traits as Trait[])[0];\n const bTrait = (cloned[i + 1].traits as Trait[])[0];\n\n if (aTrait) {\n const emitContract: TraitEventContract = { ...events[i], scope: events[i].scope ?? 'external' };\n aTrait.emits = [...(aTrait.emits ?? []), emitContract];\n }\n if (bTrait) {\n const listener: TraitEventListener = {\n event: events[i].event,\n triggers: 'INIT',\n scope: 'external',\n };\n bTrait.listens = [...(bTrait.listens ?? []), listener];\n }\n }\n\n // Auto-generate pages: one per orbital, first is initial\n const pages: Page[] = cloned.map((o, i) => {\n const entityName = typeof o.entity === 'string' ? o.entity : o.entity.name;\n const traitNames = (o.traits as Trait[]).map(t => t.name);\n return {\n name: `${entityName}Page`,\n path: `/${plural(entityName).toLowerCase()}`,\n ...(i === 0 ? { isInitial: true } : {}),\n traits: traitNames.map(ref => ({ ref })),\n };\n });\n\n // Assign pages back to orbitals\n for (let i = 0; i < cloned.length; i++) {\n cloned[i].pages = [pages[i]];\n }\n\n return {\n name: appName ?? 'Application',\n version: '1.0.0',\n orbitals: cloned,\n };\n}\n"]}
|