@almadar/core 3.0.0 → 4.0.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.
@@ -1,4 +1,4 @@
1
- import { O as OrbitalDefinition, c as OrbitalSchema } from './schema-COvHzxfu.js';
1
+ import { O as OrbitalDefinition, c as OrbitalSchema } from './schema-CDA_dJjH.js';
2
2
 
3
3
  /**
4
4
  * Event Wiring
@@ -1,4 +1,4 @@
1
- import { bG as SExpr, e as Entity, P as Page, c as OrbitalSchema, d as Trait } from '../schema-COvHzxfu.js';
1
+ import { bG as SExpr, e as Entity, P as Page, c as OrbitalSchema, d as Trait } from '../schema-CDA_dJjH.js';
2
2
  import 'zod';
3
3
  import '@almadar/patterns';
4
4
 
@@ -3681,10 +3681,40 @@ z.object({
3681
3681
  ref: z.string().min(1),
3682
3682
  linkedEntity: z.string().optional(),
3683
3683
  name: z.string().optional(),
3684
- events: z.record(z.string(), z.string()).optional(),
3684
+ events: z.record(
3685
+ z.string().min(1, "events key (atom event name) must be non-empty"),
3686
+ z.string().min(1, "events value (caller event name) must be non-empty")
3687
+ ).optional(),
3685
3688
  config: z.record(z.record(z.unknown())).optional(),
3686
- appliesTo: z.array(z.string()).optional()
3687
- });
3689
+ appliesTo: z.array(z.string()).optional(),
3690
+ // Phase F.7: zod accepts an array (the inliner validates element
3691
+ // shape). The full ListenDefinition shape isn't recursively encoded
3692
+ // here because TraitReference is the call-site form — listen entries
3693
+ // pasted in are already-resolved structured definitions, not nested
3694
+ // overrides.
3695
+ listens: z.array(z.unknown()).optional(),
3696
+ emitsScope: z.enum(["internal", "external"]).optional(),
3697
+ // Phase F.8: per-transition effects override. The keys are event
3698
+ // names (the transition triggers AFTER renames). Values are arrays
3699
+ // of SExpression-shaped data; the inliner validates the SExpression
3700
+ // shape during application, so the schema accepts loose `unknown[]`.
3701
+ effects: z.record(
3702
+ z.string().min(1, "effects override key (event name) must be non-empty"),
3703
+ z.array(z.unknown())
3704
+ ).optional()
3705
+ }).refine(
3706
+ (ref2) => {
3707
+ if (!ref2.events) return true;
3708
+ for (const [from, to] of Object.entries(ref2.events)) {
3709
+ if (from.length === 0 || to.length === 0) return false;
3710
+ }
3711
+ return true;
3712
+ },
3713
+ {
3714
+ message: 'TraitReference "events" entries must have non-empty atom and caller event names',
3715
+ path: ["events"]
3716
+ }
3717
+ );
3688
3718
  var TraitSchema = z.object({
3689
3719
  name: z.string().min(1),
3690
3720
  description: z.string().optional(),
@@ -3707,7 +3737,13 @@ var TraitRefSchema = z.union([
3707
3737
  config: z.record(z.unknown()).optional(),
3708
3738
  linkedEntity: z.string().optional(),
3709
3739
  name: z.string().optional(),
3710
- events: z.record(z.string(), z.string()).optional()
3740
+ // Phase F.4: same non-empty refine as TraitReferenceSchema.events.
3741
+ // Both schemas accept the same call-site argument shape, so the
3742
+ // validators should agree.
3743
+ events: z.record(
3744
+ z.string().min(1, "events key (atom event name) must be non-empty"),
3745
+ z.string().min(1, "events value (caller event name) must be non-empty")
3746
+ ).optional()
3711
3747
  }),
3712
3748
  TraitSchema
3713
3749
  // Allow inline trait definitions
@@ -3950,8 +3986,17 @@ var ServiceRefStringSchema = z.string().regex(
3950
3986
  /^[A-Z][a-zA-Z0-9]*\.services\.[a-zA-Z][a-zA-Z0-9]*$/,
3951
3987
  'Service reference must be in format "Alias.services.ServiceName" (e.g., "Weather.services.openweather")'
3952
3988
  );
3989
+ var ServiceRefObjectSchema = z.object({
3990
+ ref: ServiceRefStringSchema,
3991
+ description: z.string().optional(),
3992
+ baseUrl: z.string().url("baseUrl override must be a valid URL").optional(),
3993
+ headers: z.record(z.string()).optional(),
3994
+ url: z.string().url("url override must be a valid URL").optional(),
3995
+ serverPath: z.string().optional()
3996
+ });
3953
3997
  var ServiceRefSchema = z.union([
3954
3998
  ServiceDefinitionSchema,
3999
+ ServiceRefObjectSchema,
3955
4000
  ServiceRefStringSchema
3956
4001
  ]);
3957
4002
 
@@ -3982,7 +4027,21 @@ var EntityCallSchema = z.object({
3982
4027
  fields: z.array(EntityFieldSchema).optional(),
3983
4028
  persistence: EntityPersistenceSchema.optional(),
3984
4029
  collection: z.string().optional()
3985
- });
4030
+ }).refine(
4031
+ (call) => {
4032
+ if (!call.fields) return true;
4033
+ const seen = /* @__PURE__ */ new Set();
4034
+ for (const field of call.fields) {
4035
+ if (seen.has(field.name)) return false;
4036
+ seen.add(field.name);
4037
+ }
4038
+ return true;
4039
+ },
4040
+ {
4041
+ message: 'EntityCall "fields" override list must not contain duplicate field names',
4042
+ path: ["fields"]
4043
+ }
4044
+ );
3986
4045
  var EntityRefSchema = z.union([
3987
4046
  EntitySchema,
3988
4047
  EntityRefStringSchema,