entity_graph/
templates.rs

1//! Tera template strings embedded at compile time.
2//!
3//! Keeping templates here (rather than on the filesystem) means the binary is
4//! self-contained and users get no "template not found" surprises at runtime.
5
6/// TypeScript entity type interface template.
7///
8/// Context variables (set by `generate`):
9/// - `entity_name` : PascalCase entity name          (string)
10/// - `fields`      : array of FieldCtx               (see below)
11/// - `relations`   : array of RelationCtx
12pub const ENTITY_TYPES_TS: &str = r#"// AUTO-GENERATED by entity-graph-cli {{ cli_version }}
13// Source: {{ schema_path }}
14// Do not edit by hand — regenerate with `entity-graph generate`.
15
16{% for entity in entities %}
17// ── {{ entity.pascal_name }} ──────────────────────────────────────────────────
18
19export interface {{ entity.pascal_name }} {
20{% for field in entity.fields %}  {{ field.name }}{% if field.optional %}?{% endif %}: {{ field.ts_type }};
21{% endfor %}
22}
23
24export type Create{{ entity.pascal_name }}Input = Omit<{{ entity.pascal_name }}, '{{ entity.primary_key }}'{% if entity.has_auto_fields %} | {{ entity.auto_field_names }}{% endif %}>;
25export type Update{{ entity.pascal_name }}Input = Partial<Create{{ entity.pascal_name }}Input>;
26
27{% endfor %}
28"#;
29
30/// TypeScript transport registration stub template.
31///
32/// Emits a `registerTransports.ts` that calls `registerEntityTransport` for
33/// every entity in the IR, ready for the user to fill in supabase/REST details.
34pub const REGISTER_TRANSPORTS_TS: &str = r#"// AUTO-GENERATED by entity-graph-cli {{ cli_version }}
35// Source: {{ schema_path }}
36// Do not edit by hand — regenerate with `entity-graph generate`.
37
38/**
39 * Call this once at application boot (before any component mounts) to register
40 * all entity transports with the @prometheus-ags/entity-graph-core store.
41 *
42 * Replace the `makeRestTransport` calls with the transport appropriate for
43 * your backend (GraphQL, Supabase, etc.).
44 */
45
46import {
47  registerEntityTransport,
48  makeRestTransport,
49} from '@prometheus-ags/entity-graph-core';
50{% for entity in entities %}
51import type { {{ entity.pascal_name }} } from './entity-types';
52{% endfor %}
53
54export function registerTransports(baseUrl: string): void {
55{% for entity in entities %}
56  registerEntityTransport<{{ entity.pascal_name }}>('{{ entity.pascal_name }}', makeRestTransport({
57    endpoint: `${baseUrl}/{{ entity.table }}`,
58    primaryKey: '{{ entity.primary_key }}',
59  }));
60{% endfor %}
61}
62"#;
63
64/// Index barrel file that re-exports everything from the generated directory.
65pub const INDEX_TS: &str = r#"// AUTO-GENERATED by entity-graph-cli {{ cli_version }}
66// Re-exports for the generated entity-graph bindings.
67export * from './entity-types';
68export * from './register-transports';
69"#;
70
71#[cfg(test)]
72mod tests {
73    use super::*;
74
75    #[test]
76    fn entity_types_template_contains_required_markers() {
77        assert!(ENTITY_TYPES_TS.contains("{% for entity in entities %}"));
78        assert!(ENTITY_TYPES_TS.contains("{% for field in entity.fields %}"));
79        assert!(ENTITY_TYPES_TS.contains("AUTO-GENERATED"));
80    }
81
82    #[test]
83    fn register_transports_template_contains_required_markers() {
84        assert!(REGISTER_TRANSPORTS_TS.contains("registerEntityTransport"));
85        assert!(REGISTER_TRANSPORTS_TS.contains("{% for entity in entities %}"));
86    }
87
88    #[test]
89    fn index_template_re_exports_all() {
90        assert!(INDEX_TS.contains("export * from './entity-types'"));
91        assert!(INDEX_TS.contains("export * from './register-transports'"));
92    }
93}