@pattern-stack/codegen 0.6.7 → 0.7.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 +12 -0
- package/dist/src/cli/index.js +516 -73
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/index.d.ts +208 -1
- package/dist/src/index.js +147 -0
- package/dist/src/index.js.map +1 -1
- package/package.json +1 -1
- package/src/patterns/library/base-junction-fields.ts +32 -0
- package/src/patterns/library/index.ts +7 -0
- package/src/patterns/library/junction.pattern.ts +41 -0
- package/templates/entity/new/backend/application/queries/get-by-id.ejs.t +3 -3
- package/templates/entity/new/backend/application/queries/grouped-index.ejs.t +5 -5
- package/templates/entity/new/backend/application/queries/index.ejs.t +3 -0
- package/templates/entity/new/backend/application/queries/list.ejs.t +3 -3
- package/templates/entity/new/backend/application/queries/relationships.queries.ejs.t +147 -0
- package/templates/entity/new/backend/database/repository.ejs.t +36 -176
- package/templates/entity/new/backend/domain/entity.ejs.t +0 -44
- package/templates/entity/new/backend/domain/grouped-index.ejs.t +4 -60
- package/templates/entity/new/backend/domain/index.ejs.t +2 -2
- package/templates/entity/new/backend/domain/repository-interface.ejs.t +16 -17
- package/templates/entity/new/backend/modules/core/module.ejs.t +10 -0
- package/templates/entity/new/backend/presentation/controller.ejs.t +2 -34
- package/templates/entity/new/clean-lite-ps/entity.ejs.t +21 -2
- package/templates/entity/new/clean-lite-ps/module.ejs.t +27 -2
- package/templates/entity/new/clean-lite-ps/prompt-extension.js +108 -9
- package/templates/entity/new/clean-lite-ps/repository.ejs.t +33 -1
- package/templates/entity/new/clean-lite-ps/service.ejs.t +79 -0
- package/templates/entity/new/prompt.js +1 -0
- package/templates/junction/new/_inject-parent-module-clp-left.ejs.t +8 -0
- package/templates/junction/new/_inject-parent-module-clp-right.ejs.t +8 -0
- package/templates/junction/new/_inject-parent-module-import-clp-left.ejs.t +9 -0
- package/templates/junction/new/_inject-parent-module-import-clp-right.ejs.t +9 -0
- package/templates/junction/new/_inject-parent-service-clp-left.ejs.t +51 -0
- package/templates/junction/new/_inject-parent-service-clp-right.ejs.t +48 -0
- package/templates/junction/new/_inject-parent-service-import-clp-left.ejs.t +11 -0
- package/templates/junction/new/_inject-parent-service-import-clp-right.ejs.t +11 -0
- package/templates/junction/new/entity.ejs.t +111 -0
- package/templates/junction/new/index.ejs.t +15 -0
- package/templates/junction/new/module.ejs.t +37 -0
- package/templates/junction/new/prompt.js +492 -0
- package/templates/junction/new/repository.ejs.t +67 -0
- package/templates/junction/new/service.ejs.t +174 -0
package/dist/src/index.d.ts
CHANGED
|
@@ -3453,6 +3453,149 @@ declare const RelationshipDefinitionSchema: z.ZodEffects<z.ZodEffects<z.ZodObjec
|
|
|
3453
3453
|
}>;
|
|
3454
3454
|
type RelationshipDefinition = z.infer<typeof RelationshipDefinitionSchema>;
|
|
3455
3455
|
|
|
3456
|
+
/**
|
|
3457
|
+
* Top-level junction YAML shape.
|
|
3458
|
+
*
|
|
3459
|
+
* pattern: Junction
|
|
3460
|
+
* between: [opportunity, contact]
|
|
3461
|
+
* temporal: true # optional, default true
|
|
3462
|
+
* sourced: true # optional, default true
|
|
3463
|
+
* fields:
|
|
3464
|
+
* role:
|
|
3465
|
+
* type: enum
|
|
3466
|
+
* values: [champion, decision_maker, influencer]
|
|
3467
|
+
* queries:
|
|
3468
|
+
* - by: [opportunity_id]
|
|
3469
|
+
*
|
|
3470
|
+
* Fields use the same shape as entity fields — validated downstream by the
|
|
3471
|
+
* template / codegen layer using the existing `FieldDefinitionSchema`.
|
|
3472
|
+
* This schema accepts the shape loosely (`z.any()`) and applies only the
|
|
3473
|
+
* reserved-column collision check; matches the relationship-schema
|
|
3474
|
+
* precedent (`relationship-definition.schema.ts` line ~250).
|
|
3475
|
+
*/
|
|
3476
|
+
declare const JunctionDefinitionSchema: z.ZodEffects<z.ZodEffects<z.ZodObject<{
|
|
3477
|
+
/** Discriminator literal — `pattern: Junction`. */
|
|
3478
|
+
pattern: z.ZodLiteral<"Junction">;
|
|
3479
|
+
/**
|
|
3480
|
+
* Exactly two endpoint entity names. Both intra- and cross-domain
|
|
3481
|
+
* pairings are accepted; entity existence is validated by the
|
|
3482
|
+
* analyzer in a later leaf.
|
|
3483
|
+
*/
|
|
3484
|
+
between: z.ZodTuple<[z.ZodString, z.ZodString], null>;
|
|
3485
|
+
/**
|
|
3486
|
+
* Emit BaseJunctionFields temporal columns (`started_at`, `ended_at`,
|
|
3487
|
+
* `matched_at`). Default true. Matches Relationship's `temporal` toggle.
|
|
3488
|
+
*/
|
|
3489
|
+
temporal: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
3490
|
+
/**
|
|
3491
|
+
* Emit BaseJunctionFields sourcing columns (`sourced_from`,
|
|
3492
|
+
* `confidence`). Default true. Matches Relationship's `sourced` toggle.
|
|
3493
|
+
*/
|
|
3494
|
+
sourced: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
3495
|
+
/**
|
|
3496
|
+
* Junction-specific fields beyond `BaseJunctionFields`. Includes the
|
|
3497
|
+
* per-pairing role enum (declared inline; never shared across
|
|
3498
|
+
* pairings). Shape is validated downstream by the codegen layer
|
|
3499
|
+
* using the existing entity FieldDefinitionSchema.
|
|
3500
|
+
*/
|
|
3501
|
+
fields: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
3502
|
+
/**
|
|
3503
|
+
* Declarative queries — same syntax as entity queries. Shape is
|
|
3504
|
+
* validated downstream by the codegen layer.
|
|
3505
|
+
*/
|
|
3506
|
+
queries: z.ZodOptional<z.ZodArray<z.ZodAny, "many">>;
|
|
3507
|
+
/**
|
|
3508
|
+
* Per-side opt-out for parent-service fan-out (CGP-60). When a side
|
|
3509
|
+
* is `false`, the `_inject-parent-service-*` templates emit nothing
|
|
3510
|
+
* on that side (and the corresponding module wiring is skipped).
|
|
3511
|
+
* The junction service body is always emitted regardless. Defaults
|
|
3512
|
+
* to `{ left: true, right: true }`.
|
|
3513
|
+
*/
|
|
3514
|
+
expose_on_parent: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
3515
|
+
left: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
3516
|
+
right: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
3517
|
+
}, "strip", z.ZodTypeAny, {
|
|
3518
|
+
left: boolean;
|
|
3519
|
+
right: boolean;
|
|
3520
|
+
}, {
|
|
3521
|
+
left?: boolean | undefined;
|
|
3522
|
+
right?: boolean | undefined;
|
|
3523
|
+
}>>>;
|
|
3524
|
+
}, "strict", z.ZodTypeAny, {
|
|
3525
|
+
pattern: "Junction";
|
|
3526
|
+
temporal: boolean;
|
|
3527
|
+
sourced: boolean;
|
|
3528
|
+
between: [string, string];
|
|
3529
|
+
expose_on_parent: {
|
|
3530
|
+
left: boolean;
|
|
3531
|
+
right: boolean;
|
|
3532
|
+
};
|
|
3533
|
+
fields?: Record<string, any> | undefined;
|
|
3534
|
+
queries?: any[] | undefined;
|
|
3535
|
+
}, {
|
|
3536
|
+
pattern: "Junction";
|
|
3537
|
+
between: [string, string];
|
|
3538
|
+
fields?: Record<string, any> | undefined;
|
|
3539
|
+
queries?: any[] | undefined;
|
|
3540
|
+
temporal?: boolean | undefined;
|
|
3541
|
+
sourced?: boolean | undefined;
|
|
3542
|
+
expose_on_parent?: {
|
|
3543
|
+
left?: boolean | undefined;
|
|
3544
|
+
right?: boolean | undefined;
|
|
3545
|
+
} | undefined;
|
|
3546
|
+
}>, {
|
|
3547
|
+
pattern: "Junction";
|
|
3548
|
+
temporal: boolean;
|
|
3549
|
+
sourced: boolean;
|
|
3550
|
+
between: [string, string];
|
|
3551
|
+
expose_on_parent: {
|
|
3552
|
+
left: boolean;
|
|
3553
|
+
right: boolean;
|
|
3554
|
+
};
|
|
3555
|
+
fields?: Record<string, any> | undefined;
|
|
3556
|
+
queries?: any[] | undefined;
|
|
3557
|
+
}, {
|
|
3558
|
+
pattern: "Junction";
|
|
3559
|
+
between: [string, string];
|
|
3560
|
+
fields?: Record<string, any> | undefined;
|
|
3561
|
+
queries?: any[] | undefined;
|
|
3562
|
+
temporal?: boolean | undefined;
|
|
3563
|
+
sourced?: boolean | undefined;
|
|
3564
|
+
expose_on_parent?: {
|
|
3565
|
+
left?: boolean | undefined;
|
|
3566
|
+
right?: boolean | undefined;
|
|
3567
|
+
} | undefined;
|
|
3568
|
+
}>, {
|
|
3569
|
+
pattern: "Junction";
|
|
3570
|
+
temporal: boolean;
|
|
3571
|
+
sourced: boolean;
|
|
3572
|
+
between: [string, string];
|
|
3573
|
+
expose_on_parent: {
|
|
3574
|
+
left: boolean;
|
|
3575
|
+
right: boolean;
|
|
3576
|
+
};
|
|
3577
|
+
fields?: Record<string, any> | undefined;
|
|
3578
|
+
queries?: any[] | undefined;
|
|
3579
|
+
}, {
|
|
3580
|
+
pattern: "Junction";
|
|
3581
|
+
between: [string, string];
|
|
3582
|
+
fields?: Record<string, any> | undefined;
|
|
3583
|
+
queries?: any[] | undefined;
|
|
3584
|
+
temporal?: boolean | undefined;
|
|
3585
|
+
sourced?: boolean | undefined;
|
|
3586
|
+
expose_on_parent?: {
|
|
3587
|
+
left?: boolean | undefined;
|
|
3588
|
+
right?: boolean | undefined;
|
|
3589
|
+
} | undefined;
|
|
3590
|
+
}>;
|
|
3591
|
+
type JunctionDefinition = z.infer<typeof JunctionDefinitionSchema>;
|
|
3592
|
+
declare function validateJunctionDefinition(data: unknown): JunctionDefinition;
|
|
3593
|
+
declare function safeValidateJunctionDefinition(data: unknown): {
|
|
3594
|
+
success: boolean;
|
|
3595
|
+
data?: JunctionDefinition;
|
|
3596
|
+
error?: z.ZodError;
|
|
3597
|
+
};
|
|
3598
|
+
|
|
3456
3599
|
interface LoadResult {
|
|
3457
3600
|
success: true;
|
|
3458
3601
|
definition: EntityDefinition;
|
|
@@ -3485,6 +3628,27 @@ type LoadRelationshipResult = RelationshipLoadResult | RelationshipLoadError;
|
|
|
3485
3628
|
* Load and validate a relationship definition from a YAML file
|
|
3486
3629
|
*/
|
|
3487
3630
|
declare function loadRelationshipFromYaml(filePath: string): LoadRelationshipResult;
|
|
3631
|
+
interface JunctionLoadResult {
|
|
3632
|
+
success: true;
|
|
3633
|
+
definition: JunctionDefinition;
|
|
3634
|
+
filePath: string;
|
|
3635
|
+
}
|
|
3636
|
+
interface JunctionLoadError {
|
|
3637
|
+
success: false;
|
|
3638
|
+
error: string;
|
|
3639
|
+
details?: string[];
|
|
3640
|
+
filePath: string;
|
|
3641
|
+
}
|
|
3642
|
+
type LoadJunctionResult = JunctionLoadResult | JunctionLoadError;
|
|
3643
|
+
/**
|
|
3644
|
+
* Load and validate a junction definition from a YAML file.
|
|
3645
|
+
*
|
|
3646
|
+
* Mirrors {@link loadRelationshipFromYaml}: existence check → readFileSync →
|
|
3647
|
+
* parseYaml → `JunctionDefinitionSchema.safeParse`. Returns a discriminated
|
|
3648
|
+
* result; callers are expected to aggregate into `AnalysisIssue`s rather
|
|
3649
|
+
* than throw.
|
|
3650
|
+
*/
|
|
3651
|
+
declare function loadJunctionFromYaml(filePath: string): LoadJunctionResult;
|
|
3488
3652
|
|
|
3489
3653
|
/**
|
|
3490
3654
|
* Entity Loader
|
|
@@ -3860,6 +4024,28 @@ declare const ActivityPattern: PatternDefinition<unknown>;
|
|
|
3860
4024
|
*/
|
|
3861
4025
|
declare const BasePattern: PatternDefinition<unknown>;
|
|
3862
4026
|
|
|
4027
|
+
/**
|
|
4028
|
+
* JunctionPattern — top-level discriminator for explicit many-to-many
|
|
4029
|
+
* junction YAML files.
|
|
4030
|
+
*
|
|
4031
|
+
* Unlike `Activity` / `Synced` / `Metadata` (which attach to an entity via
|
|
4032
|
+
* `pattern:` / `patterns:`), `Junction` IS the top-level YAML shape — a
|
|
4033
|
+
* junction file's discriminator is `pattern: Junction`, not `entity:`.
|
|
4034
|
+
* It therefore does not declare `repositoryClass` / `serviceClass`: the
|
|
4035
|
+
* downstream Hygen-template leaf emits a dedicated junction repo/service
|
|
4036
|
+
* per pairing.
|
|
4037
|
+
*
|
|
4038
|
+
* `columns` is set to `BaseJunctionFields` for two reasons:
|
|
4039
|
+
* 1. Registry-side declaration of the shared shape — discoverable through
|
|
4040
|
+
* `getPattern('Junction').columns` by the downstream template leaf.
|
|
4041
|
+
* 2. Satisfies the registry's `assertHasContribution()` check, which
|
|
4042
|
+
* insists every pattern contribute at least one of columns / repo /
|
|
4043
|
+
* service class. (See spec §"Open Questions Q3"; recommendation (a).)
|
|
4044
|
+
*
|
|
4045
|
+
* See `.ai-docs/stacks/codegen-app-patterns/specs/58.md`.
|
|
4046
|
+
*/
|
|
4047
|
+
declare const JunctionPattern: PatternDefinition<{}>;
|
|
4048
|
+
|
|
3863
4049
|
/**
|
|
3864
4050
|
* KnowledgePattern — replaces `family: knowledge`.
|
|
3865
4051
|
*
|
|
@@ -3900,6 +4086,27 @@ declare const MetadataPattern: PatternDefinition<unknown>;
|
|
|
3900
4086
|
*/
|
|
3901
4087
|
declare const SyncedPattern: PatternDefinition<unknown>;
|
|
3902
4088
|
|
|
4089
|
+
/**
|
|
4090
|
+
* BaseJunctionFields — shared column shape every junction table carries.
|
|
4091
|
+
*
|
|
4092
|
+
* Per-pairing role columns and pairing-specific fields are declared in the
|
|
4093
|
+
* consumer YAML's `fields:` block and are NOT part of this shape.
|
|
4094
|
+
*
|
|
4095
|
+
* Exposed as a TS const so two consumers can import it:
|
|
4096
|
+
* - `junction.pattern.ts` — registers it as the pattern's
|
|
4097
|
+
* column contribution so the
|
|
4098
|
+
* registry's `assertHasContribution()`
|
|
4099
|
+
* check passes structurally.
|
|
4100
|
+
* - `junction-definition.schema.ts` — uses the name set for the
|
|
4101
|
+
* reserved-column collision check
|
|
4102
|
+
* on the consumer's `fields:` block.
|
|
4103
|
+
*
|
|
4104
|
+
* See ADR-031 and `.ai-docs/stacks/codegen-app-patterns/specs/58.md`.
|
|
4105
|
+
*/
|
|
4106
|
+
|
|
4107
|
+
declare const BaseJunctionFields: readonly PatternColumnContribution[];
|
|
4108
|
+
declare const BASE_JUNCTION_FIELD_NAMES: ReadonlySet<string>;
|
|
4109
|
+
|
|
3903
4110
|
/**
|
|
3904
4111
|
* Pattern Registry — library + app pattern storage and discovery.
|
|
3905
4112
|
*
|
|
@@ -4137,4 +4344,4 @@ declare function validateEntities(entitiesDir: string): {
|
|
|
4137
4344
|
errors: string[];
|
|
4138
4345
|
};
|
|
4139
4346
|
|
|
4140
|
-
export { ActivityPattern, type AnalysisIssue, type AnalysisResult, type AnalyzeDomainOptions, type AnyPatternDefinition, BasePattern, type CodegenManifest, type DomainGraph, type DomainStatistics, type EntityNode, KnowledgePattern, type LoadAppPatternsResult, type ManifestEntity, type ManifestField, type ManifestRelationship, type ManifestSuggestion, MetadataPattern, type OrchestrationPatternDefinition, type OrchestrationProjectContext, type OrchestrationRegistrySpec, type OutputFormat, type ParsedEntity, type ParsedEvent, type ParsedField, type ParsedProviderSync, type ParsedQuery, type ParsedRelationship, type ParsedRelationshipDefinition, type ParsedSync, type ParsedTypeDirection, type PathHop, type PatternColumnContribution, type PatternDefinition, type PatternKind, type PatternProjectContext, type RelationshipEdge, type Severity, SyncedPattern, type TransitivePath, type TransitiveSuggestion, analyzeDomain, buildDomainGraph, checkConsistency, computeStatistics, defineOrchestrationPattern, definePattern, findCircularDependencies, findOrphanEntities, formatConsole, formatJson, formatMarkdown, formatMermaidGraph, getAllOrchestrationPatterns, getAllPatternNames, getAppPatternNames, getLibraryPatternNames, getOrchestrationPattern, getOrchestrationPatternNames, getPattern, getRelatedEntities, isDomainPattern, isOrchestrationPattern, isPatternDefinition, loadAppPatterns, loadEntities, loadEntityFromYaml, loadRelationshipFromYaml, loadRelationships, registerLibraryPattern, validateEntities, validateOrchestrationProject, validatePatternComposition, validatePatternProject };
|
|
4347
|
+
export { ActivityPattern, type AnalysisIssue, type AnalysisResult, type AnalyzeDomainOptions, type AnyPatternDefinition, BASE_JUNCTION_FIELD_NAMES, BaseJunctionFields, BasePattern, type CodegenManifest, type DomainGraph, type DomainStatistics, type EntityNode, type JunctionDefinition, JunctionDefinitionSchema, JunctionPattern, KnowledgePattern, type LoadAppPatternsResult, type ManifestEntity, type ManifestField, type ManifestRelationship, type ManifestSuggestion, MetadataPattern, type OrchestrationPatternDefinition, type OrchestrationProjectContext, type OrchestrationRegistrySpec, type OutputFormat, type ParsedEntity, type ParsedEvent, type ParsedField, type ParsedProviderSync, type ParsedQuery, type ParsedRelationship, type ParsedRelationshipDefinition, type ParsedSync, type ParsedTypeDirection, type PathHop, type PatternColumnContribution, type PatternDefinition, type PatternKind, type PatternProjectContext, type RelationshipEdge, type Severity, SyncedPattern, type TransitivePath, type TransitiveSuggestion, analyzeDomain, buildDomainGraph, checkConsistency, computeStatistics, defineOrchestrationPattern, definePattern, findCircularDependencies, findOrphanEntities, formatConsole, formatJson, formatMarkdown, formatMermaidGraph, getAllOrchestrationPatterns, getAllPatternNames, getAppPatternNames, getLibraryPatternNames, getOrchestrationPattern, getOrchestrationPatternNames, getPattern, getRelatedEntities, isDomainPattern, isOrchestrationPattern, isPatternDefinition, loadAppPatterns, loadEntities, loadEntityFromYaml, loadJunctionFromYaml, loadRelationshipFromYaml, loadRelationships, registerLibraryPattern, safeValidateJunctionDefinition, validateEntities, validateJunctionDefinition, validateOrchestrationProject, validatePatternComposition, validatePatternProject };
|
package/dist/src/index.js
CHANGED
|
@@ -1754,6 +1754,90 @@ function deriveUniqueConstraint(config) {
|
|
|
1754
1754
|
return columns;
|
|
1755
1755
|
}
|
|
1756
1756
|
|
|
1757
|
+
// src/schema/junction-definition.schema.ts
|
|
1758
|
+
import { z as z6 } from "zod";
|
|
1759
|
+
|
|
1760
|
+
// src/patterns/library/base-junction-fields.ts
|
|
1761
|
+
var BaseJunctionFields = [
|
|
1762
|
+
{ name: "is_primary", type: "boolean" },
|
|
1763
|
+
{ name: "started_at", type: "timestamp" },
|
|
1764
|
+
{ name: "ended_at", type: "timestamp" },
|
|
1765
|
+
{ name: "sourced_from", type: "text" },
|
|
1766
|
+
{ name: "confidence", type: "numeric(5,4)" },
|
|
1767
|
+
{ name: "matched_at", type: "timestamp" }
|
|
1768
|
+
];
|
|
1769
|
+
var BASE_JUNCTION_FIELD_NAMES = new Set(
|
|
1770
|
+
BaseJunctionFields.map((c) => c.name)
|
|
1771
|
+
);
|
|
1772
|
+
|
|
1773
|
+
// src/schema/junction-definition.schema.ts
|
|
1774
|
+
var EntityNameSchema = z6.string().regex(/^[a-z][a-z0-9_]*$/, "Entity reference must be snake_case");
|
|
1775
|
+
var JunctionDefinitionSchema = z6.object({
|
|
1776
|
+
/** Discriminator literal — `pattern: Junction`. */
|
|
1777
|
+
pattern: z6.literal("Junction"),
|
|
1778
|
+
/**
|
|
1779
|
+
* Exactly two endpoint entity names. Both intra- and cross-domain
|
|
1780
|
+
* pairings are accepted; entity existence is validated by the
|
|
1781
|
+
* analyzer in a later leaf.
|
|
1782
|
+
*/
|
|
1783
|
+
between: z6.tuple([EntityNameSchema, EntityNameSchema]),
|
|
1784
|
+
/**
|
|
1785
|
+
* Emit BaseJunctionFields temporal columns (`started_at`, `ended_at`,
|
|
1786
|
+
* `matched_at`). Default true. Matches Relationship's `temporal` toggle.
|
|
1787
|
+
*/
|
|
1788
|
+
temporal: z6.boolean().optional().default(true),
|
|
1789
|
+
/**
|
|
1790
|
+
* Emit BaseJunctionFields sourcing columns (`sourced_from`,
|
|
1791
|
+
* `confidence`). Default true. Matches Relationship's `sourced` toggle.
|
|
1792
|
+
*/
|
|
1793
|
+
sourced: z6.boolean().optional().default(true),
|
|
1794
|
+
/**
|
|
1795
|
+
* Junction-specific fields beyond `BaseJunctionFields`. Includes the
|
|
1796
|
+
* per-pairing role enum (declared inline; never shared across
|
|
1797
|
+
* pairings). Shape is validated downstream by the codegen layer
|
|
1798
|
+
* using the existing entity FieldDefinitionSchema.
|
|
1799
|
+
*/
|
|
1800
|
+
fields: z6.record(z6.string(), z6.any()).optional(),
|
|
1801
|
+
/**
|
|
1802
|
+
* Declarative queries — same syntax as entity queries. Shape is
|
|
1803
|
+
* validated downstream by the codegen layer.
|
|
1804
|
+
*/
|
|
1805
|
+
queries: z6.array(z6.any()).optional(),
|
|
1806
|
+
/**
|
|
1807
|
+
* Per-side opt-out for parent-service fan-out (CGP-60). When a side
|
|
1808
|
+
* is `false`, the `_inject-parent-service-*` templates emit nothing
|
|
1809
|
+
* on that side (and the corresponding module wiring is skipped).
|
|
1810
|
+
* The junction service body is always emitted regardless. Defaults
|
|
1811
|
+
* to `{ left: true, right: true }`.
|
|
1812
|
+
*/
|
|
1813
|
+
expose_on_parent: z6.object({
|
|
1814
|
+
left: z6.boolean().optional().default(true),
|
|
1815
|
+
right: z6.boolean().optional().default(true)
|
|
1816
|
+
}).optional().default({ left: true, right: true })
|
|
1817
|
+
}).strict().refine((d) => d.between[0] !== d.between[1], {
|
|
1818
|
+
message: "`between` endpoints must be distinct",
|
|
1819
|
+
path: ["between"]
|
|
1820
|
+
}).refine(
|
|
1821
|
+
(d) => {
|
|
1822
|
+
const fieldNames = Object.keys(d.fields ?? {});
|
|
1823
|
+
return !fieldNames.some((n) => BASE_JUNCTION_FIELD_NAMES.has(n));
|
|
1824
|
+
},
|
|
1825
|
+
{
|
|
1826
|
+
message: "`fields:` block redeclares a reserved BaseJunctionFields column (is_primary, started_at, ended_at, sourced_from, confidence, matched_at)",
|
|
1827
|
+
path: ["fields"]
|
|
1828
|
+
}
|
|
1829
|
+
);
|
|
1830
|
+
function validateJunctionDefinition(data) {
|
|
1831
|
+
return JunctionDefinitionSchema.parse(data);
|
|
1832
|
+
}
|
|
1833
|
+
function safeValidateJunctionDefinition(data) {
|
|
1834
|
+
const result = JunctionDefinitionSchema.safeParse(data);
|
|
1835
|
+
if (result.success) {
|
|
1836
|
+
return { success: true, data: result.data };
|
|
1837
|
+
}
|
|
1838
|
+
return { success: false, error: result.error };
|
|
1839
|
+
}
|
|
1840
|
+
|
|
1757
1841
|
// src/utils/yaml-loader.ts
|
|
1758
1842
|
function loadEntityFromYaml(filePath) {
|
|
1759
1843
|
if (!existsSync(filePath)) {
|
|
@@ -1852,6 +1936,51 @@ function loadRelationshipFromYaml(filePath) {
|
|
|
1852
1936
|
filePath
|
|
1853
1937
|
};
|
|
1854
1938
|
}
|
|
1939
|
+
function loadJunctionFromYaml(filePath) {
|
|
1940
|
+
if (!existsSync(filePath)) {
|
|
1941
|
+
return {
|
|
1942
|
+
success: false,
|
|
1943
|
+
error: `File not found: ${filePath}`,
|
|
1944
|
+
filePath
|
|
1945
|
+
};
|
|
1946
|
+
}
|
|
1947
|
+
let content;
|
|
1948
|
+
try {
|
|
1949
|
+
content = readFileSync(filePath, "utf-8");
|
|
1950
|
+
} catch (err) {
|
|
1951
|
+
return {
|
|
1952
|
+
success: false,
|
|
1953
|
+
error: `Failed to read file: ${filePath}`,
|
|
1954
|
+
details: [err instanceof Error ? err.message : String(err)],
|
|
1955
|
+
filePath
|
|
1956
|
+
};
|
|
1957
|
+
}
|
|
1958
|
+
let parsed;
|
|
1959
|
+
try {
|
|
1960
|
+
parsed = parseYaml(content);
|
|
1961
|
+
} catch (err) {
|
|
1962
|
+
return {
|
|
1963
|
+
success: false,
|
|
1964
|
+
error: `Invalid YAML syntax in ${filePath}`,
|
|
1965
|
+
details: [err instanceof Error ? err.message : String(err)],
|
|
1966
|
+
filePath
|
|
1967
|
+
};
|
|
1968
|
+
}
|
|
1969
|
+
const result = JunctionDefinitionSchema.safeParse(parsed);
|
|
1970
|
+
if (!result.success) {
|
|
1971
|
+
return {
|
|
1972
|
+
success: false,
|
|
1973
|
+
error: `Validation failed for ${filePath}`,
|
|
1974
|
+
details: formatZodErrors(result.error),
|
|
1975
|
+
filePath
|
|
1976
|
+
};
|
|
1977
|
+
}
|
|
1978
|
+
return {
|
|
1979
|
+
success: true,
|
|
1980
|
+
definition: result.data,
|
|
1981
|
+
filePath
|
|
1982
|
+
};
|
|
1983
|
+
}
|
|
1855
1984
|
|
|
1856
1985
|
// src/parser/load-entities.ts
|
|
1857
1986
|
function transformToEntity(result) {
|
|
@@ -3754,6 +3883,16 @@ var BasePattern = definePattern({
|
|
|
3754
3883
|
description: "Identity pattern \u2014 base CRUD, no extra columns or methods"
|
|
3755
3884
|
});
|
|
3756
3885
|
|
|
3886
|
+
// src/patterns/library/junction.pattern.ts
|
|
3887
|
+
import { z as z7 } from "zod";
|
|
3888
|
+
var JunctionPatternConfigSchema = z7.object({}).strict();
|
|
3889
|
+
var JunctionPattern = definePattern({
|
|
3890
|
+
name: "Junction",
|
|
3891
|
+
description: "Explicit many-to-many junction with role + temporal + sourcing metadata",
|
|
3892
|
+
columns: [...BaseJunctionFields],
|
|
3893
|
+
configSchema: JunctionPatternConfigSchema
|
|
3894
|
+
});
|
|
3895
|
+
|
|
3757
3896
|
// src/patterns/library/knowledge.pattern.ts
|
|
3758
3897
|
var KnowledgePattern = definePattern({
|
|
3759
3898
|
name: "Knowledge",
|
|
@@ -3818,6 +3957,7 @@ registerLibraryPattern(SyncedPattern);
|
|
|
3818
3957
|
registerLibraryPattern(ActivityPattern);
|
|
3819
3958
|
registerLibraryPattern(KnowledgePattern);
|
|
3820
3959
|
registerLibraryPattern(MetadataPattern);
|
|
3960
|
+
registerLibraryPattern(JunctionPattern);
|
|
3821
3961
|
|
|
3822
3962
|
// src/index.ts
|
|
3823
3963
|
async function analyzeDomain(entitiesDir, relationshipsOrOptions) {
|
|
@@ -3872,7 +4012,11 @@ function validateEntities(entitiesDir) {
|
|
|
3872
4012
|
}
|
|
3873
4013
|
export {
|
|
3874
4014
|
ActivityPattern,
|
|
4015
|
+
BASE_JUNCTION_FIELD_NAMES,
|
|
4016
|
+
BaseJunctionFields,
|
|
3875
4017
|
BasePattern,
|
|
4018
|
+
JunctionDefinitionSchema,
|
|
4019
|
+
JunctionPattern,
|
|
3876
4020
|
KnowledgePattern,
|
|
3877
4021
|
MetadataPattern,
|
|
3878
4022
|
SyncedPattern,
|
|
@@ -3902,10 +4046,13 @@ export {
|
|
|
3902
4046
|
loadAppPatterns,
|
|
3903
4047
|
loadEntities,
|
|
3904
4048
|
loadEntityFromYaml,
|
|
4049
|
+
loadJunctionFromYaml,
|
|
3905
4050
|
loadRelationshipFromYaml,
|
|
3906
4051
|
loadRelationships,
|
|
3907
4052
|
registerLibraryPattern,
|
|
4053
|
+
safeValidateJunctionDefinition,
|
|
3908
4054
|
validateEntities,
|
|
4055
|
+
validateJunctionDefinition,
|
|
3909
4056
|
validateOrchestrationProject,
|
|
3910
4057
|
validatePatternComposition,
|
|
3911
4058
|
validatePatternProject
|