dopespec 0.0.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.
Files changed (179) hide show
  1. package/README.md +195 -0
  2. package/bin/dopespec.mjs +26 -0
  3. package/dist/__tests__/codegen.test.d.ts +2 -0
  4. package/dist/__tests__/codegen.test.d.ts.map +1 -0
  5. package/dist/__tests__/codegen.test.js +713 -0
  6. package/dist/__tests__/codegen.test.js.map +1 -0
  7. package/dist/__tests__/e2e-proof.test.d.ts +2 -0
  8. package/dist/__tests__/e2e-proof.test.d.ts.map +1 -0
  9. package/dist/__tests__/e2e-proof.test.js +153 -0
  10. package/dist/__tests__/e2e-proof.test.js.map +1 -0
  11. package/dist/__tests__/schema.test.d.ts +2 -0
  12. package/dist/__tests__/schema.test.d.ts.map +1 -0
  13. package/dist/__tests__/schema.test.js +822 -0
  14. package/dist/__tests__/schema.test.js.map +1 -0
  15. package/dist/__tests__/type-errors.d.ts +2 -0
  16. package/dist/__tests__/type-errors.d.ts.map +1 -0
  17. package/dist/__tests__/type-errors.js +128 -0
  18. package/dist/__tests__/type-errors.js.map +1 -0
  19. package/dist/cli/generate.d.ts +2 -0
  20. package/dist/cli/generate.d.ts.map +1 -0
  21. package/dist/cli/generate.js +250 -0
  22. package/dist/cli/generate.js.map +1 -0
  23. package/dist/codegen/commands.d.ts +4 -0
  24. package/dist/codegen/commands.d.ts.map +1 -0
  25. package/dist/codegen/commands.js +25 -0
  26. package/dist/codegen/commands.js.map +1 -0
  27. package/dist/codegen/decisions-evaluate.d.ts +3 -0
  28. package/dist/codegen/decisions-evaluate.d.ts.map +1 -0
  29. package/dist/codegen/decisions-evaluate.js +50 -0
  30. package/dist/codegen/decisions-evaluate.js.map +1 -0
  31. package/dist/codegen/decisions-table.d.ts +3 -0
  32. package/dist/codegen/decisions-table.d.ts.map +1 -0
  33. package/dist/codegen/decisions-table.js +27 -0
  34. package/dist/codegen/decisions-table.js.map +1 -0
  35. package/dist/codegen/decisions-tests.d.ts +3 -0
  36. package/dist/codegen/decisions-tests.d.ts.map +1 -0
  37. package/dist/codegen/decisions-tests.js +43 -0
  38. package/dist/codegen/decisions-tests.js.map +1 -0
  39. package/dist/codegen/e2e-stubs.d.ts +4 -0
  40. package/dist/codegen/e2e-stubs.d.ts.map +1 -0
  41. package/dist/codegen/e2e-stubs.js +21 -0
  42. package/dist/codegen/e2e-stubs.js.map +1 -0
  43. package/dist/codegen/events.d.ts +8 -0
  44. package/dist/codegen/events.d.ts.map +1 -0
  45. package/dist/codegen/events.js +36 -0
  46. package/dist/codegen/events.js.map +1 -0
  47. package/dist/codegen/index.d.ts +18 -0
  48. package/dist/codegen/index.d.ts.map +1 -0
  49. package/dist/codegen/index.js +18 -0
  50. package/dist/codegen/index.js.map +1 -0
  51. package/dist/codegen/invariants.d.ts +4 -0
  52. package/dist/codegen/invariants.d.ts.map +1 -0
  53. package/dist/codegen/invariants.js +53 -0
  54. package/dist/codegen/invariants.js.map +1 -0
  55. package/dist/codegen/mermaid.d.ts +4 -0
  56. package/dist/codegen/mermaid.d.ts.map +1 -0
  57. package/dist/codegen/mermaid.js +21 -0
  58. package/dist/codegen/mermaid.js.map +1 -0
  59. package/dist/codegen/orchestrators.d.ts +7 -0
  60. package/dist/codegen/orchestrators.d.ts.map +1 -0
  61. package/dist/codegen/orchestrators.js +32 -0
  62. package/dist/codegen/orchestrators.js.map +1 -0
  63. package/dist/codegen/policy-index.d.ts +7 -0
  64. package/dist/codegen/policy-index.d.ts.map +1 -0
  65. package/dist/codegen/policy-index.js +40 -0
  66. package/dist/codegen/policy-index.js.map +1 -0
  67. package/dist/codegen/policy-mermaid.d.ts +7 -0
  68. package/dist/codegen/policy-mermaid.d.ts.map +1 -0
  69. package/dist/codegen/policy-mermaid.js +30 -0
  70. package/dist/codegen/policy-mermaid.js.map +1 -0
  71. package/dist/codegen/policy-tests.d.ts +8 -0
  72. package/dist/codegen/policy-tests.d.ts.map +1 -0
  73. package/dist/codegen/policy-tests.js +167 -0
  74. package/dist/codegen/policy-tests.js.map +1 -0
  75. package/dist/codegen/policy-validator.d.ts +8 -0
  76. package/dist/codegen/policy-validator.d.ts.map +1 -0
  77. package/dist/codegen/policy-validator.js +69 -0
  78. package/dist/codegen/policy-validator.js.map +1 -0
  79. package/dist/codegen/tests.d.ts +4 -0
  80. package/dist/codegen/tests.d.ts.map +1 -0
  81. package/dist/codegen/tests.js +125 -0
  82. package/dist/codegen/tests.js.map +1 -0
  83. package/dist/codegen/transitions.d.ts +4 -0
  84. package/dist/codegen/transitions.d.ts.map +1 -0
  85. package/dist/codegen/transitions.js +41 -0
  86. package/dist/codegen/transitions.js.map +1 -0
  87. package/dist/codegen/types.d.ts +4 -0
  88. package/dist/codegen/types.d.ts.map +1 -0
  89. package/dist/codegen/types.js +48 -0
  90. package/dist/codegen/types.js.map +1 -0
  91. package/dist/codegen/utils.d.ts +85 -0
  92. package/dist/codegen/utils.d.ts.map +1 -0
  93. package/dist/codegen/utils.js +357 -0
  94. package/dist/codegen/utils.js.map +1 -0
  95. package/dist/codegen/zod.d.ts +4 -0
  96. package/dist/codegen/zod.d.ts.map +1 -0
  97. package/dist/codegen/zod.js +32 -0
  98. package/dist/codegen/zod.js.map +1 -0
  99. package/dist/examples/generated/customer.types.d.ts +7 -0
  100. package/dist/examples/generated/customer.types.d.ts.map +1 -0
  101. package/dist/examples/generated/customer.types.js +2 -0
  102. package/dist/examples/generated/customer.types.js.map +1 -0
  103. package/dist/examples/generated/order.types.d.ts +9 -0
  104. package/dist/examples/generated/order.types.d.ts.map +1 -0
  105. package/dist/examples/generated/order.types.js +2 -0
  106. package/dist/examples/generated/order.types.js.map +1 -0
  107. package/dist/examples/generated/pet.types.d.ts +11 -0
  108. package/dist/examples/generated/pet.types.d.ts.map +1 -0
  109. package/dist/examples/generated/pet.types.js +2 -0
  110. package/dist/examples/generated/pet.types.js.map +1 -0
  111. package/dist/examples/pet-store.d.ts +137 -0
  112. package/dist/examples/pet-store.d.ts.map +1 -0
  113. package/dist/examples/pet-store.js +139 -0
  114. package/dist/examples/pet-store.js.map +1 -0
  115. package/dist/examples/src/customer.e2e.d.ts +2 -0
  116. package/dist/examples/src/customer.e2e.d.ts.map +1 -0
  117. package/dist/examples/src/customer.e2e.js +17 -0
  118. package/dist/examples/src/customer.e2e.js.map +1 -0
  119. package/dist/examples/src/customer.orchestrators.d.ts +5 -0
  120. package/dist/examples/src/customer.orchestrators.d.ts.map +1 -0
  121. package/dist/examples/src/customer.orchestrators.js +5 -0
  122. package/dist/examples/src/customer.orchestrators.js.map +1 -0
  123. package/dist/examples/src/order.e2e.d.ts +2 -0
  124. package/dist/examples/src/order.e2e.d.ts.map +1 -0
  125. package/dist/examples/src/order.e2e.js +22 -0
  126. package/dist/examples/src/order.e2e.js.map +1 -0
  127. package/dist/examples/src/order.orchestrators.d.ts +9 -0
  128. package/dist/examples/src/order.orchestrators.d.ts.map +1 -0
  129. package/dist/examples/src/order.orchestrators.js +10 -0
  130. package/dist/examples/src/order.orchestrators.js.map +1 -0
  131. package/dist/examples/src/pet.e2e.d.ts +2 -0
  132. package/dist/examples/src/pet.e2e.d.ts.map +1 -0
  133. package/dist/examples/src/pet.e2e.js +17 -0
  134. package/dist/examples/src/pet.e2e.js.map +1 -0
  135. package/dist/examples/src/pet.orchestrators.d.ts +8 -0
  136. package/dist/examples/src/pet.orchestrators.d.ts.map +1 -0
  137. package/dist/examples/src/pet.orchestrators.js +9 -0
  138. package/dist/examples/src/pet.orchestrators.js.map +1 -0
  139. package/dist/schema/actions.d.ts +37 -0
  140. package/dist/schema/actions.d.ts.map +1 -0
  141. package/dist/schema/actions.js +35 -0
  142. package/dist/schema/actions.js.map +1 -0
  143. package/dist/schema/constraints.d.ts +20 -0
  144. package/dist/schema/constraints.d.ts.map +1 -0
  145. package/dist/schema/constraints.js +15 -0
  146. package/dist/schema/constraints.js.map +1 -0
  147. package/dist/schema/decisions.d.ts +29 -0
  148. package/dist/schema/decisions.d.ts.map +1 -0
  149. package/dist/schema/decisions.js +56 -0
  150. package/dist/schema/decisions.js.map +1 -0
  151. package/dist/schema/index.d.ts +17 -0
  152. package/dist/schema/index.d.ts.map +1 -0
  153. package/dist/schema/index.js +8 -0
  154. package/dist/schema/index.js.map +1 -0
  155. package/dist/schema/model.d.ts +65 -0
  156. package/dist/schema/model.d.ts.map +1 -0
  157. package/dist/schema/model.js +30 -0
  158. package/dist/schema/model.js.map +1 -0
  159. package/dist/schema/policy.d.ts +25 -0
  160. package/dist/schema/policy.d.ts.map +1 -0
  161. package/dist/schema/policy.js +53 -0
  162. package/dist/schema/policy.js.map +1 -0
  163. package/dist/schema/props.d.ts +57 -0
  164. package/dist/schema/props.d.ts.map +1 -0
  165. package/dist/schema/props.js +53 -0
  166. package/dist/schema/props.js.map +1 -0
  167. package/dist/schema/relations.d.ts +9 -0
  168. package/dist/schema/relations.d.ts.map +1 -0
  169. package/dist/schema/relations.js +9 -0
  170. package/dist/schema/relations.js.map +1 -0
  171. package/dist/schema/transitions.d.ts +34 -0
  172. package/dist/schema/transitions.d.ts.map +1 -0
  173. package/dist/schema/transitions.js +25 -0
  174. package/dist/schema/transitions.js.map +1 -0
  175. package/dist/schema/types.d.ts +18 -0
  176. package/dist/schema/types.d.ts.map +1 -0
  177. package/dist/schema/types.js +11 -0
  178. package/dist/schema/types.js.map +1 -0
  179. package/package.json +55 -0
@@ -0,0 +1,65 @@
1
+ import type { ActionDef } from "./actions.js";
2
+ import type { ConstraintBuilder, ConstraintData } from "./constraints.js";
3
+ import type { InferContext, LifecycleProp, PropDef } from "./props.js";
4
+ import type { RelationDef } from "./relations.js";
5
+ import type { TransitionBuilder, TransitionData } from "./transitions.js";
6
+ import type { ModelRef } from "./types.js";
7
+ export type ConstraintHelpers<Ctx, ActionKeys extends string> = {
8
+ rule: () => ConstraintBuilder<Ctx, ActionKeys>;
9
+ };
10
+ export type ModelDef<Name extends string = string, P extends Record<string, PropDef> = Record<string, PropDef>, A extends Record<string, ActionDef> = Record<string, ActionDef>, R extends Record<string, RelationDef> = Record<string, RelationDef>, T extends Record<string, TransitionDefBase> = Record<string, TransitionDefBase>, C extends Record<string, ConstraintDefBase> = Record<string, ConstraintDefBase>> = IfProvided<"actions", A> & IfProvided<"constraints", StripConstraintMethods<C>> & IfProvided<"props", P> & IfProvided<"relations", R> & IfProvided<"transitions", StripTransitionMethods<T>> & ModelRef & {
11
+ readonly name: Name;
12
+ };
13
+ /**
14
+ * Extracts the state union from lifecycle() props only (not oneOf).
15
+ * Returns `never` if zero or multiple lifecycle() props exist — only one allowed per model.
16
+ */
17
+ export type StatesOf<P extends Record<string, PropDef>> = IsUnion<LifecycleKeys<P>> extends true ? never : string & {
18
+ [K in keyof P]: P[K] extends LifecycleProp<infer T> ? T[number] : never;
19
+ }[keyof P];
20
+ export type TransitionHelpers<Ctx, States extends string> = {
21
+ from: <F extends States>(state: F) => {
22
+ to: <T extends States>(toState: T) => TransitionBuilder<F, T, Ctx, States>;
23
+ };
24
+ };
25
+ type ConstraintDefBase = {
26
+ readonly kind: "constraint";
27
+ };
28
+ /**
29
+ * Makes field K required when V has concrete keys (user-provided),
30
+ * optional when V has a string index signature (unparameterized default).
31
+ * Depends on ModelDef defaults being Record<string, …> and model() defaults
32
+ * being Record<string, never> — both have `string` as keyof.
33
+ */
34
+ type IfProvided<K extends string, V> = string extends keyof V ? {
35
+ readonly [k in K]?: V;
36
+ } : {
37
+ readonly [k in K]: V;
38
+ };
39
+ type IsUnion<T> = [T] extends [UnionToIntersection<T>] ? false : true;
40
+ type LifecycleKeys<P extends Record<string, PropDef>> = {
41
+ [K in keyof P]: P[K] extends LifecycleProp<readonly string[]> ? K : never;
42
+ }[keyof P];
43
+ type StripConstraintMethods<C extends Record<string, ConstraintDefBase>> = {
44
+ readonly [K in keyof C]: ToConstraintData<C[K]>;
45
+ };
46
+ type StripTransitionMethods<T extends Record<string, TransitionDefBase>> = {
47
+ readonly [K in keyof T]: ToTransitionData<T[K]>;
48
+ };
49
+ type ToConstraintData<T> = T extends ConstraintBuilder<infer Ctx, infer A> ? ConstraintData<Ctx, A> : T extends ConstraintData<infer Ctx, infer A> ? ConstraintData<Ctx, A> : T;
50
+ type ToTransitionData<T> = T extends TransitionBuilder<infer F, infer To, infer Ctx, infer S> ? TransitionData<F, To, Ctx, S> : T extends TransitionData<infer F, infer To, infer Ctx, infer S> ? TransitionData<F, To, Ctx, S> : T;
51
+ type TransitionDefBase = {
52
+ readonly from: string;
53
+ readonly kind: "transition";
54
+ readonly to: string;
55
+ };
56
+ type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
57
+ export declare function model<const Name extends string, const P extends Record<string, PropDef> = Record<string, never>, const A extends Record<string, ActionDef> = Record<string, never>, const R extends Record<string, RelationDef> = Record<string, never>, T extends Record<string, TransitionDefBase> = Record<string, never>, C extends Record<string, ConstraintDefBase> = Record<string, never>>(name: Name, config: {
58
+ readonly actions?: A;
59
+ readonly constraints?: (helpers: ConstraintHelpers<InferContext<P>, Extract<keyof A, string>>) => C;
60
+ readonly props?: P;
61
+ readonly relations?: R;
62
+ readonly transitions?: (helpers: TransitionHelpers<InferContext<P>, StatesOf<P>>) => T;
63
+ }): ModelDef<Name, P, A, R, T, C>;
64
+ export {};
65
+ //# sourceMappingURL=model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/schema/model.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { createTypedRule } from "./constraints.js";
2
+ import { createTypedFrom } from "./transitions.js";
3
+ // Implementation — callers see the public overload's return type, not this one.
4
+ // The phantom ModelRef brand exists only at the type level.
5
+ // eslint-disable-next-line padding-line-between-statements -- overload implementation must be adjacent
6
+ export function model(name, config) {
7
+ const trimmed = name.trim();
8
+ if (!trimmed)
9
+ throw new Error("model() requires a non-empty name");
10
+ const cfg = config;
11
+ const transitions = cfg.transitions
12
+ ? cfg.transitions({ from: createTypedFrom() })
13
+ : undefined;
14
+ const constraints = cfg.constraints
15
+ ? cfg.constraints({ rule: createTypedRule() })
16
+ : undefined;
17
+ const result = { kind: "model", name: trimmed };
18
+ if (cfg.props !== undefined)
19
+ result["props"] = cfg.props;
20
+ if (cfg.actions !== undefined)
21
+ result["actions"] = cfg.actions;
22
+ if (cfg.relations !== undefined)
23
+ result["relations"] = cfg.relations;
24
+ if (transitions !== undefined)
25
+ result["transitions"] = transitions;
26
+ if (constraints !== undefined)
27
+ result["constraints"] = constraints;
28
+ return result;
29
+ }
30
+ //# sourceMappingURL=model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/schema/model.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAqInD,gFAAgF;AAChF,4DAA4D;AAC5D,uGAAuG;AACvG,MAAM,UAAU,KAAK,CAAC,IAAY,EAAE,MAA+B;IACjE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAE5B,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IAEnE,MAAM,GAAG,GAAG,MAUX,CAAC;IAEF,MAAM,WAAW,GAAG,GAAG,CAAC,WAAW;QACjC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,EAAE,CAAC;QAC9C,CAAC,CAAC,SAAS,CAAC;IAEd,MAAM,WAAW,GAAG,GAAG,CAAC,WAAW;QACjC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,EAAE,CAAC;QAC9C,CAAC,CAAC,SAAS,CAAC;IAEd,MAAM,MAAM,GAA4B,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IAEzE,IAAI,GAAG,CAAC,KAAK,KAAK,SAAS;QAAE,MAAM,CAAC,OAAO,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC;IACzD,IAAI,GAAG,CAAC,OAAO,KAAK,SAAS;QAAE,MAAM,CAAC,SAAS,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC;IAC/D,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS;QAAE,MAAM,CAAC,WAAW,CAAC,GAAG,GAAG,CAAC,SAAS,CAAC;IACrE,IAAI,WAAW,KAAK,SAAS;QAAE,MAAM,CAAC,aAAa,CAAC,GAAG,WAAW,CAAC;IACnE,IAAI,WAAW,KAAK,SAAS;QAAE,MAAM,CAAC,aAAa,CAAC,GAAG,WAAW,CAAC;IAEnE,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,25 @@
1
+ import type { RelationDef } from "./relations.js";
2
+ import type { ModelRef } from "./types.js";
3
+ export type PolicyDef<Name extends string = string> = {
4
+ readonly kind: "policy";
5
+ readonly name: Name;
6
+ readonly on: {
7
+ readonly action: string;
8
+ readonly model: ModelRef;
9
+ };
10
+ readonly requires: Record<string, RelationDef>;
11
+ readonly rules: readonly PolicyRule[];
12
+ };
13
+ export type PolicyRule = {
14
+ readonly effect: "prevent" | "warn";
15
+ readonly when: (ctx: any) => boolean;
16
+ };
17
+ export declare function policy<const Name extends string>(name: Name, config: {
18
+ readonly on: {
19
+ readonly action: string;
20
+ readonly model: ModelRef;
21
+ };
22
+ readonly requires: Record<string, RelationDef>;
23
+ readonly rules: readonly PolicyRule[];
24
+ }): PolicyDef<Name>;
25
+ //# sourceMappingURL=policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../src/schema/policy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,MAAM,MAAM,SAAS,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM,IAAI;IACpD,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAA;KAAE,CAAC;IACnE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC/C,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAAC;IAEpC,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC;CACtC,CAAC;AAKF,wBAAgB,MAAM,CAAC,KAAK,CAAC,IAAI,SAAS,MAAM,EAC9C,IAAI,EAAE,IAAI,EACV,MAAM,EAAE;IACN,QAAQ,CAAC,EAAE,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAA;KAAE,CAAC;IACnE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC/C,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;CACvC,GACA,SAAS,CAAC,IAAI,CAAC,CAAC"}
@@ -0,0 +1,53 @@
1
+ const VALID_EFFECTS = new Set(["prevent", "warn"]);
2
+ // Implementation — callers see the public overload's return type, not this one.
3
+ // eslint-disable-next-line padding-line-between-statements -- overload implementation must be adjacent
4
+ export function policy(name, config) {
5
+ const trimmed = name.trim();
6
+ if (!trimmed)
7
+ throw new Error("policy() requires a non-empty name");
8
+ const cfg = config;
9
+ const action = validateOn(cfg.on);
10
+ validateRequires(cfg.requires);
11
+ validateRules(cfg.rules);
12
+ return {
13
+ kind: "policy",
14
+ name: trimmed,
15
+ on: { action, model: cfg.on.model },
16
+ requires: cfg.requires,
17
+ rules: cfg.rules,
18
+ };
19
+ }
20
+ function validateOn(on) {
21
+ if (!on || typeof on !== "object" || !on.model || on.model.kind !== "model")
22
+ throw new Error("policy() on.model must be a model() or ref() reference");
23
+ const action = typeof on.action === "string" ? on.action.trim() : "";
24
+ if (!action)
25
+ throw new Error("policy() on.action must be a non-empty string");
26
+ // Validate action exists on target model (skip for ref() — model not yet defined)
27
+ const modelActions = on.model["actions"];
28
+ if (modelActions && !Object.keys(modelActions).includes(action))
29
+ throw new Error(`policy() on.action "${action}" is not a defined action on model "${on.model.name}"`);
30
+ return action;
31
+ }
32
+ function validateRequires(requires) {
33
+ const keys = Object.keys(requires ?? {});
34
+ if (keys.length === 0)
35
+ throw new Error("policy() requires at least one entry in requires");
36
+ for (const [key, rel] of Object.entries(requires ?? {})) {
37
+ if (!rel ||
38
+ typeof rel !== "object" ||
39
+ (rel.kind !== "belongsTo" && rel.kind !== "hasMany"))
40
+ throw new Error(`policy() requires["${key}"] must be a belongsTo() or hasMany() relation`);
41
+ }
42
+ }
43
+ function validateRules(rules) {
44
+ if (!rules || rules.length === 0)
45
+ throw new Error("policy() requires at least one rule");
46
+ for (const [i, rule] of rules.entries()) {
47
+ if (typeof rule.when !== "function")
48
+ throw new Error(`policy() rules[${String(i)}].when must be a function`);
49
+ if (!VALID_EFFECTS.has(rule.effect))
50
+ throw new Error(`policy() rules[${String(i)}].effect must be "prevent" or "warn"`);
51
+ }
52
+ }
53
+ //# sourceMappingURL=policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.js","sourceRoot":"","sources":["../../src/schema/policy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ export type BooleanProp = PropDef<"boolean", null>;
2
+ export type DateProp = PropDef<"date", null>;
3
+ export type InferContext<Props extends Record<string, PropDef>> = InferContextRaw<Props> extends infer T ? {
4
+ [K in keyof T]: T[K];
5
+ } & {} : never;
6
+ export type InferPropType<P> = P extends StringProp ? string : P extends NumberProp ? number : P extends BooleanProp ? boolean : P extends DateProp ? Date : P extends OneOfProp<infer T> ? T[number] : P extends LifecycleProp<infer T> ? T[number] : never;
7
+ /**
8
+ * Lifecycle prop — defines the state machine states for a model.
9
+ * Only lifecycle() values are valid in from().to() transitions.
10
+ * Use oneOf() for regular enums that don't participate in transitions.
11
+ */
12
+ export type LifecycleProp<T extends readonly string[]> = PropDef<"lifecycle", T>;
13
+ export type NumberProp = PropDef<"number", null>;
14
+ export type OneOfProp<T extends readonly string[]> = PropDef<"oneOf", T>;
15
+ export type PropDef<K extends PropKind = PropKind, V = unknown> = {
16
+ readonly kind: K;
17
+ readonly values: V;
18
+ };
19
+ export type PropKind = "boolean" | "date" | "lifecycle" | "number" | "oneOf" | "string";
20
+ export type StringProp = PropDef<"string", null>;
21
+ type InferContextRaw<Props extends Record<string, PropDef>> = {
22
+ [K in keyof Props as Props[K] extends OptionalPropDef ? K : never]?: InferPropType<Props[K]>;
23
+ } & {
24
+ [K in keyof Props as Props[K] extends OptionalPropDef ? never : K]: InferPropType<Props[K]>;
25
+ };
26
+ /** Runtime brand for optional props — set by optional(), checked by isOptional(). */
27
+ declare const OPTIONAL_BRAND: unique symbol;
28
+ export { OPTIONAL_BRAND };
29
+ /** Symbol used to store the original tuple on a StatesObject. */
30
+ declare const STATES_VALUES: unique symbol;
31
+ /** Phantom brand — type-level only, prevents structural spoofing. Same pattern as ModelRef. */
32
+ declare const STATES_BRAND: unique symbol;
33
+ /** Object returned by lifecycle.states() — named keys mapping to themselves, plus a hidden tuple. */
34
+ export type StatesObject<T extends readonly string[]> = {
35
+ readonly [K in T[number]]: K;
36
+ } & {
37
+ readonly [STATES_BRAND]: true;
38
+ readonly [STATES_VALUES]: T;
39
+ };
40
+ export declare const string: () => StringProp;
41
+ export declare const number: () => NumberProp;
42
+ export declare const boolean: () => BooleanProp;
43
+ export declare const date: () => DateProp;
44
+ export type OptionalPropDef<P extends PropDef = PropDef> = P & {
45
+ readonly [OPTIONAL_BRAND]: true;
46
+ };
47
+ /** Wraps a prop as optional. Lifecycle props cannot be optional — a model always has a current state. */
48
+ export declare const optional: <P extends PropDef>(prop: P & (P extends LifecycleProp<readonly string[]> ? never : P)) => OptionalPropDef<P>;
49
+ /** Check if a prop was wrapped with optional() at runtime. */
50
+ export declare const isOptional: (prop: PropDef) => prop is OptionalPropDef;
51
+ export declare const oneOf: <const T extends readonly string[]>(values: T) => OneOfProp<T>;
52
+ declare function _lifecycle<const T extends readonly string[]>(values: StatesObject<T>): LifecycleProp<T>;
53
+ declare function _lifecycle<const T extends readonly string[]>(values: T): LifecycleProp<T>;
54
+ export declare const lifecycle: typeof _lifecycle & {
55
+ states: <const T extends readonly string[]>(...names: T) => StatesObject<T>;
56
+ };
57
+ //# sourceMappingURL=props.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"props.d.ts","sourceRoot":"","sources":["../../src/schema/props.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAEnD,MAAM,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AAG7C,MAAM,MAAM,YAAY,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC5D,eAAe,CAAC,KAAK,CAAC,SAAS,MAAM,CAAC,GAClC;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAE,GAAG,EAAE,GAC7B,KAAK,CAAC;AAEZ,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI,CAAC,SAAS,UAAU,GAC/C,MAAM,GACN,CAAC,SAAS,UAAU,GAClB,MAAM,GACN,CAAC,SAAS,WAAW,GACnB,OAAO,GACP,CAAC,SAAS,QAAQ,GAChB,IAAI,GACJ,CAAC,SAAS,SAAS,CAAC,MAAM,CAAC,CAAC,GAC1B,CAAC,CAAC,MAAM,CAAC,GACT,CAAC,SAAS,aAAa,CAAC,MAAM,CAAC,CAAC,GAC9B,CAAC,CAAC,MAAM,CAAC,GACT,KAAK,CAAC;AACpB;;;;GAIG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,SAAS,MAAM,EAAE,IAAI,OAAO,CAC9D,WAAW,EACX,CAAC,CACF,CAAC;AACF,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AACjD,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,SAAS,MAAM,EAAE,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;AAEzE,MAAM,MAAM,OAAO,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ,EAAE,CAAC,GAAG,OAAO,IAAI;IAChE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACjB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAChB,SAAS,GACT,MAAM,GACN,WAAW,GACX,QAAQ,GACR,OAAO,GACP,QAAQ,CAAC;AAEb,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AAEjD,KAAK,eAAe,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;KAC3D,CAAC,IAAI,MAAM,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC,SAAS,eAAe,GACjD,CAAC,GACD,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;CACrC,GAAG;KACD,CAAC,IAAI,MAAM,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC,SAAS,eAAe,GACjD,KAAK,GACL,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;CAChC,CAAC;AAEF,qFAAqF;AACrF,QAAA,MAAM,cAAc,EAAE,OAAO,MAAoC,CAAC;AAElE,OAAO,EAAE,cAAc,EAAE,CAAC;AAE1B,iEAAiE;AACjE,QAAA,MAAM,aAAa,EAAE,OAAO,MAAkC,CAAC;AAE/D,+FAA+F;AAC/F,OAAO,CAAC,MAAM,YAAY,EAAE,OAAO,MAAM,CAAC;AAE1C,qGAAqG;AACrG,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,SAAS,MAAM,EAAE,IAAI;IACtD,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;CAC7B,GAAG;IAAE,QAAQ,CAAC,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,CAAA;CAAE,CAAC;AAEnE,eAAO,MAAM,MAAM,QAAO,UAAgD,CAAC;AAC3E,eAAO,MAAM,MAAM,QAAO,UAAgD,CAAC;AAC3E,eAAO,MAAM,OAAO,QAAO,WAAkD,CAAC;AAC9E,eAAO,MAAM,IAAI,QAAO,QAA4C,CAAC;AAErE,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,IAAI,CAAC,GAAG;IAC7D,QAAQ,CAAC,CAAC,cAAc,CAAC,EAAE,IAAI,CAAC;CACjC,CAAC;AAEF,yGAAyG;AACzG,eAAO,MAAM,QAAQ,GAAI,CAAC,SAAS,OAAO,EACxC,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,aAAa,CAAC,SAAS,MAAM,EAAE,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,KACjE,eAAe,CAAC,CAAC,CAanB,CAAC;AAEF,8DAA8D;AAC9D,eAAO,MAAM,UAAU,GAAI,MAAM,OAAO,KAAG,IAAI,IAAI,eACkB,CAAC;AAEtE,eAAO,MAAM,KAAK,GAAI,KAAK,CAAC,CAAC,SAAS,SAAS,MAAM,EAAE,EACrD,QAAQ,CAAC,KACR,SAAS,CAAC,CAAC,CAGZ,CAAC;AAEH,iBAAS,UAAU,CAAC,KAAK,CAAC,CAAC,SAAS,SAAS,MAAM,EAAE,EACnD,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GACtB,aAAa,CAAC,CAAC,CAAC,CAAC;AACpB,iBAAS,UAAU,CAAC,KAAK,CAAC,CAAC,SAAS,SAAS,MAAM,EAAE,EACnD,MAAM,EAAE,CAAC,GACR,aAAa,CAAC,CAAC,CAAC,CAAC;AAWpB,eAAO,MAAM,SAAS;mBACL,CAAC,SAAS,SAAS,MAAM,EAAE,YAAY,CAAC,KAAG,YAAY,CAAC,CAAC,CAAC;CAsBzE,CAAC"}
@@ -0,0 +1,53 @@
1
+ /** Runtime brand for optional props — set by optional(), checked by isOptional(). */
2
+ const OPTIONAL_BRAND = Symbol("dopespec.optional");
3
+ export { OPTIONAL_BRAND };
4
+ /** Symbol used to store the original tuple on a StatesObject. */
5
+ const STATES_VALUES = Symbol("dopespec.states");
6
+ export const string = () => ({ kind: "string", values: null });
7
+ export const number = () => ({ kind: "number", values: null });
8
+ export const boolean = () => ({ kind: "boolean", values: null });
9
+ export const date = () => ({ kind: "date", values: null });
10
+ /** Wraps a prop as optional. Lifecycle props cannot be optional — a model always has a current state. */
11
+ export const optional = (prop) => {
12
+ if (prop.kind === "lifecycle") {
13
+ throw new Error("lifecycle props cannot be optional");
14
+ }
15
+ const result = { ...prop };
16
+ Object.defineProperty(result, OPTIONAL_BRAND, {
17
+ enumerable: false,
18
+ value: true,
19
+ });
20
+ return result;
21
+ };
22
+ /** Check if a prop was wrapped with optional() at runtime. */
23
+ export const isOptional = (prop) => OPTIONAL_BRAND in prop && prop[OPTIONAL_BRAND];
24
+ export const oneOf = (values) => ({
25
+ kind: "oneOf",
26
+ values,
27
+ });
28
+ function _lifecycle(values) {
29
+ const tuple = Array.isArray(values)
30
+ ? values
31
+ : values[STATES_VALUES];
32
+ return { kind: "lifecycle", values: tuple };
33
+ }
34
+ export const lifecycle = Object.assign(_lifecycle, {
35
+ states: (...names) => {
36
+ const seen = new Set();
37
+ for (const name of names) {
38
+ if (seen.has(name)) {
39
+ throw new Error(`lifecycle.states() received duplicate name '${name}'`);
40
+ }
41
+ seen.add(name);
42
+ }
43
+ const obj = {};
44
+ for (const name of names)
45
+ obj[name] = name;
46
+ Object.defineProperty(obj, STATES_VALUES, {
47
+ enumerable: false,
48
+ value: names,
49
+ });
50
+ return Object.freeze(obj);
51
+ },
52
+ });
53
+ //# sourceMappingURL=props.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"props.js","sourceRoot":"","sources":["../../src/schema/props.ts"],"names":[],"mappings":"AA4DA,qFAAqF;AACrF,MAAM,cAAc,GAAkB,MAAM,CAAC,mBAAmB,CAAC,CAAC;AAElE,OAAO,EAAE,cAAc,EAAE,CAAC;AAE1B,iEAAiE;AACjE,MAAM,aAAa,GAAkB,MAAM,CAAC,iBAAiB,CAAC,CAAC;AAU/D,MAAM,CAAC,MAAM,MAAM,GAAG,GAAe,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;AAC3E,MAAM,CAAC,MAAM,MAAM,GAAG,GAAe,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;AAC3E,MAAM,CAAC,MAAM,OAAO,GAAG,GAAgB,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;AAC9E,MAAM,CAAC,MAAM,IAAI,GAAG,GAAa,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;AAMrE,yGAAyG;AACzG,MAAM,CAAC,MAAM,QAAQ,GAAG,CACtB,IAAkE,EAC9C,EAAE;IACtB,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IAED,MAAM,MAAM,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC;IAE3B,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,cAAc,EAAE;QAC5C,UAAU,EAAE,KAAK;QACjB,KAAK,EAAE,IAAI;KACZ,CAAC,CAAC;IAEH,OAAO,MAAuC,CAAC;AACjD,CAAC,CAAC;AAEF,8DAA8D;AAC9D,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,IAAa,EAA2B,EAAE,CACnE,cAAc,IAAI,IAAI,IAAK,IAAwB,CAAC,cAAc,CAAC,CAAC;AAEtE,MAAM,CAAC,MAAM,KAAK,GAAG,CACnB,MAAS,EACK,EAAE,CAAC,CAAC;IAClB,IAAI,EAAE,OAAO;IACb,MAAM;CACP,CAAC,CAAC;AAQH,SAAS,UAAU,CACjB,MAA2D;IAE3D,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QACjC,CAAC,CAAC,MAAM;QACR,CAAC,CAAE,MAA0C,CAAC,aAAa,CAAC,CAAC;IAE/D,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AAC9C,CAAC;AAED,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE;IACjD,MAAM,EAAE,CAAoC,GAAG,KAAQ,EAAmB,EAAE;QAC1E,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAE/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnB,MAAM,IAAI,KAAK,CAAC,+CAA+C,IAAI,GAAG,CAAC,CAAC;YAC1E,CAAC;YAED,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACjB,CAAC;QAED,MAAM,GAAG,GAAG,EAA4B,CAAC;QAEzC,KAAK,MAAM,IAAI,IAAI,KAAK;YAAE,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QAE3C,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,aAAa,EAAE;YACxC,UAAU,EAAE,KAAK;YACjB,KAAK,EAAE,KAAK;SACb,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC,MAAM,CAAC,GAAG,CAAoB,CAAC;IAC/C,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { ModelRef } from "./types.js";
2
+ export type RelationDef<K extends RelationKind = RelationKind> = {
3
+ readonly kind: K;
4
+ readonly target: ModelRef;
5
+ };
6
+ export type RelationKind = "belongsTo" | "hasMany";
7
+ export declare const hasMany: (target: ModelRef) => RelationDef<"hasMany">;
8
+ export declare const belongsTo: (target: ModelRef) => RelationDef<"belongsTo">;
9
+ //# sourceMappingURL=relations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relations.d.ts","sourceRoot":"","sources":["../../src/schema/relations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,YAAY,GAAG,YAAY,IAAI;IAC/D,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACjB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,SAAS,CAAC;AAEnD,eAAO,MAAM,OAAO,GAAI,QAAQ,QAAQ,KAAG,WAAW,CAAC,SAAS,CAG9D,CAAC;AAEH,eAAO,MAAM,SAAS,GAAI,QAAQ,QAAQ,KAAG,WAAW,CAAC,WAAW,CAGlE,CAAC"}
@@ -0,0 +1,9 @@
1
+ export const hasMany = (target) => ({
2
+ kind: "hasMany",
3
+ target,
4
+ });
5
+ export const belongsTo = (target) => ({
6
+ kind: "belongsTo",
7
+ target,
8
+ });
9
+ //# sourceMappingURL=relations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relations.js","sourceRoot":"","sources":["../../src/schema/relations.ts"],"names":[],"mappings":"AASA,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,MAAgB,EAA0B,EAAE,CAAC,CAAC;IACpE,IAAI,EAAE,SAAS;IACf,MAAM;CACP,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,MAAgB,EAA4B,EAAE,CAAC,CAAC;IACxE,IAAI,EAAE,WAAW;IACjB,MAAM;CACP,CAAC,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * A test scenario for a transition. `given` is a partial set of model props —
3
+ * only the fields relevant to this scenario need be specified. `expected` is
4
+ * the state the model should be in after the transition.
5
+ */
6
+ export type Scenario<Ctx = Record<string, unknown>, States extends string = string> = {
7
+ readonly expected: States;
8
+ readonly given: Partial<Ctx>;
9
+ };
10
+ /** Builder — returned during model definition for chaining .when()/.scenario(). */
11
+ export type TransitionBuilder<From extends string = string, To extends string = string, Ctx = Record<string, unknown>, States extends string = string> = {
12
+ scenario(given: Partial<Ctx>, expected: States): TransitionBuilder<From, To, Ctx, States>;
13
+ /**
14
+ * Replaces previous guard (last-wins semantics).
15
+ * Guards on optional props must handle undefined values — no automatic null checks are added.
16
+ */
17
+ when(fn: (ctx: Ctx) => boolean): TransitionBuilder<From, To, Ctx, States>;
18
+ } & TransitionData<From, To, Ctx, States>;
19
+ /** Plain data — stored in ModelDef, consumed by codegen. No builder methods. */
20
+ export type TransitionData<From extends string = string, To extends string = string, Ctx = Record<string, unknown>, States extends string = string> = {
21
+ readonly from: From;
22
+ readonly guard: ((ctx: Ctx) => boolean) | null;
23
+ readonly kind: "transition";
24
+ readonly scenarios: readonly Scenario<Ctx, States>[];
25
+ readonly to: To;
26
+ };
27
+ export declare const from: <F extends string>(state: F) => {
28
+ to<T extends string>(toState: T): TransitionBuilder<F, T>;
29
+ };
30
+ /** @internal Used by model() to create typed from() factories. Phantom generics — type-level only, erased at runtime. */
31
+ export declare const createTypedFrom: <Ctx, States extends string>() => <F extends States>(state: F) => {
32
+ to<T extends States>(toState: T): TransitionBuilder<F, T, Ctx, States>;
33
+ };
34
+ //# sourceMappingURL=transitions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transitions.d.ts","sourceRoot":"","sources":["../../src/schema/transitions.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,QAAQ,CAClB,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,MAAM,SAAS,MAAM,GAAG,MAAM,IAC5B;IACF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;CAC9B,CAAC;AAEF,mFAAmF;AACnF,MAAM,MAAM,iBAAiB,CAC3B,IAAI,SAAS,MAAM,GAAG,MAAM,EAC5B,EAAE,SAAS,MAAM,GAAG,MAAM,EAC1B,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,MAAM,SAAS,MAAM,GAAG,MAAM,IAC5B;IACF,QAAQ,CACN,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,EACnB,QAAQ,EAAE,MAAM,GACf,iBAAiB,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;IAC5C;;;OAGG;IACH,IAAI,CAAC,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,GAAG,iBAAiB,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;CAC3E,GAAG,cAAc,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;AAE1C,gFAAgF;AAChF,MAAM,MAAM,cAAc,CACxB,IAAI,SAAS,MAAM,GAAG,MAAM,EAC5B,EAAE,SAAS,MAAM,GAAG,MAAM,EAC1B,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,MAAM,SAAS,MAAM,GAAG,MAAM,IAC5B;IACF,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,IAAI,CAAC;IAC/C,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,SAAS,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,CAAC;IACrD,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC;CACjB,CAAC;AAoCF,eAAO,MAAM,IAAI,GAAI,CAAC,SAAS,MAAM,EAAE,OAAO,CAAC;OAC1C,CAAC,SAAS,MAAM,WAAW,CAAC,GAAG,iBAAiB,CAAC,CAAC,EAAE,CAAC,CAAC;CAGzD,CAAC;AAEH,yHAAyH;AACzH,eAAO,MAAM,eAAe,GACzB,GAAG,EAAE,MAAM,SAAS,MAAM,QAC1B,CAAC,SAAS,MAAM,EAAE,OAAO,CAAC;OACtB,CAAC,SAAS,MAAM,WAAW,CAAC,GAAG,iBAAiB,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;CAQtE,CAAC"}
@@ -0,0 +1,25 @@
1
+ const createTransitionBuilder = (fromState, toState, guard, scenarios) => ({
2
+ from: fromState,
3
+ guard,
4
+ kind: "transition",
5
+ scenario(given, expected) {
6
+ return createTransitionBuilder(fromState, toState, guard, [...scenarios, { expected, given }]);
7
+ },
8
+ scenarios,
9
+ to: toState,
10
+ when(fn) {
11
+ return createTransitionBuilder(fromState, toState, fn, scenarios);
12
+ },
13
+ });
14
+ export const from = (state) => ({
15
+ to(toState) {
16
+ return createTransitionBuilder(state, toState, null, []);
17
+ },
18
+ });
19
+ /** @internal Used by model() to create typed from() factories. Phantom generics — type-level only, erased at runtime. */
20
+ export const createTypedFrom = () => (state) => ({
21
+ to(toState) {
22
+ return createTransitionBuilder(state, toState, null, []);
23
+ },
24
+ });
25
+ //# sourceMappingURL=transitions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transitions.js","sourceRoot":"","sources":["../../src/schema/transitions.ts"],"names":[],"mappings":"AA6CA,MAAM,uBAAuB,GAAG,CAM9B,SAAY,EACZ,OAAU,EACV,KAAqC,EACrC,SAA2C,EACL,EAAE,CAAC,CAAC;IAC1C,IAAI,EAAE,SAAS;IACf,KAAK;IACL,IAAI,EAAE,YAAY;IAClB,QAAQ,CAAC,KAAK,EAAE,QAAQ;QACtB,OAAO,uBAAuB,CAC5B,SAAS,EACT,OAAO,EACP,KAAK,EACL,CAAC,GAAG,SAAS,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CACpC,CAAC;IACJ,CAAC;IACD,SAAS;IACT,EAAE,EAAE,OAAO;IACX,IAAI,CAAC,EAAE;QACL,OAAO,uBAAuB,CAC5B,SAAS,EACT,OAAO,EACP,EAAE,EACF,SAAS,CACV,CAAC;IACJ,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,IAAI,GAAG,CAAmB,KAAQ,EAAE,EAAE,CAAC,CAAC;IACnD,EAAE,CAAmB,OAAU;QAC7B,OAAO,uBAAuB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;IAC3D,CAAC;CACF,CAAC,CAAC;AAEH,yHAAyH;AACzH,MAAM,CAAC,MAAM,eAAe,GAC1B,GAA+B,EAAE,CACjC,CAAmB,KAAQ,EAAE,EAAE,CAAC,CAAC;IAC/B,EAAE,CAAmB,OAAU;QAC7B,OAAO,uBAAuB,CAC5B,KAAK,EACL,OAAO,EACP,IAAI,EACJ,EAAE,CACH,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,18 @@
1
+ declare const MODEL_BRAND: unique symbol;
2
+ /**
3
+ * Branded model reference — only model() outputs and ref() calls produce this type.
4
+ * The symbol brand does not exist at runtime; it prevents arbitrary objects
5
+ * from satisfying the type structurally.
6
+ */
7
+ export type ModelRef = {
8
+ readonly kind: "model";
9
+ readonly [MODEL_BRAND]: true;
10
+ readonly name: string;
11
+ };
12
+ /**
13
+ * Create a forward reference to a model that hasn't been defined yet.
14
+ * Use this when two models reference each other (circular relations).
15
+ */
16
+ export declare const ref: (name: string) => ModelRef;
17
+ export {};
18
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/schema/types.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,WAAW,EAAE,OAAO,MAAM,CAAC;AAEzC;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAAG;IACrB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,CAAC,WAAW,CAAC,EAAE,IAAI,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,GAAG,GAAI,MAAM,MAAM,KAAG,QAMlC,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Create a forward reference to a model that hasn't been defined yet.
3
+ * Use this when two models reference each other (circular relations).
4
+ */
5
+ export const ref = (name) => {
6
+ const trimmed = name.trim();
7
+ if (!trimmed)
8
+ throw new Error("ref() requires a non-empty model name");
9
+ return { kind: "model", name: trimmed };
10
+ };
11
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/schema/types.ts"],"names":[],"mappings":"AAaA;;;GAGG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,IAAY,EAAY,EAAE;IAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAE5B,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAEvE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAc,CAAC;AACtD,CAAC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "dopespec",
3
+ "version": "0.0.1",
4
+ "description": "Schema-first domain modeling. Describe your business logic in TypeScript, generate types, state machines, validators, tests, Zod schemas, and Mermaid diagrams.",
5
+ "type": "module",
6
+ "main": "dist/schema/index.js",
7
+ "exports": {
8
+ ".": "./dist/schema/index.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "bin",
13
+ "README.md"
14
+ ],
15
+ "bin": {
16
+ "dopespec": "./bin/dopespec.mjs"
17
+ },
18
+ "scripts": {
19
+ "build": "tsc",
20
+ "generate": "tsx src/cli/generate.ts",
21
+ "test": "vitest run",
22
+ "typecheck": "tsc --noEmit",
23
+ "lint": "eslint src/",
24
+ "lint:fix": "eslint src/ --fix",
25
+ "format": "prettier --write .",
26
+ "format:check": "prettier --check ."
27
+ },
28
+ "keywords": [
29
+ "domain-modeling",
30
+ "codegen",
31
+ "typescript",
32
+ "ddd",
33
+ "state-machine",
34
+ "decision-table",
35
+ "schema"
36
+ ],
37
+ "author": "Yuri Mikhin",
38
+ "license": "ISC",
39
+ "packageManager": "pnpm@10.30.3",
40
+ "dependencies": {
41
+ "tsx": "^4.19.0"
42
+ },
43
+ "devDependencies": {
44
+ "@eslint/js": "^10.0.1",
45
+ "@types/node": "^25.5.0",
46
+ "eslint": "^10.1.0",
47
+ "eslint-plugin-perfectionist": "^5.7.0",
48
+ "eslint-plugin-sonarjs": "^4.0.2",
49
+ "prettier": "^3.8.1",
50
+ "typescript": "^6.0.2",
51
+ "typescript-eslint": "^8.57.2",
52
+ "vitest": "^4.1.1",
53
+ "zod": "^4.3.6"
54
+ }
55
+ }