financial-graph-shared 1.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.
Files changed (43) hide show
  1. package/README.md +75 -0
  2. package/dist/db/index.d.ts +11 -0
  3. package/dist/db/index.d.ts.map +1 -0
  4. package/dist/db/index.js +11 -0
  5. package/dist/db/queries/cik-lookup.d.ts +49 -0
  6. package/dist/db/queries/cik-lookup.d.ts.map +1 -0
  7. package/dist/db/queries/cik-lookup.js +78 -0
  8. package/dist/db/queries/company-lookup.d.ts +43 -0
  9. package/dist/db/queries/company-lookup.d.ts.map +1 -0
  10. package/dist/db/queries/company-lookup.js +65 -0
  11. package/dist/db/queries/index.d.ts +8 -0
  12. package/dist/db/queries/index.d.ts.map +1 -0
  13. package/dist/db/queries/index.js +7 -0
  14. package/dist/index.d.ts +14 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +18 -0
  17. package/dist/instant.schema.d.ts +170 -0
  18. package/dist/instant.schema.d.ts.map +1 -0
  19. package/dist/instant.schema.js +222 -0
  20. package/dist/types/ids.d.ts +135 -0
  21. package/dist/types/ids.d.ts.map +1 -0
  22. package/dist/types/ids.js +188 -0
  23. package/dist/types/instant.schema.future.d.ts +39 -0
  24. package/dist/types/instant.schema.future.d.ts.map +1 -0
  25. package/dist/types/instant.schema.future.js +52 -0
  26. package/dist/types/types.d.ts +321 -0
  27. package/dist/types/types.d.ts.map +1 -0
  28. package/dist/types/types.js +180 -0
  29. package/dist/types/validation.d.ts +7 -0
  30. package/dist/types/validation.d.ts.map +1 -0
  31. package/dist/types/validation.js +14 -0
  32. package/dist/utils/index.d.ts +5 -0
  33. package/dist/utils/index.d.ts.map +1 -0
  34. package/dist/utils/index.js +4 -0
  35. package/dist/utils/logger-interface.d.ts +57 -0
  36. package/dist/utils/logger-interface.d.ts.map +1 -0
  37. package/dist/utils/logger-interface.js +38 -0
  38. package/package.json +54 -0
  39. package/types/ids.ts +249 -0
  40. package/types/instant.schema.future.js +55 -0
  41. package/types/instant.schema.future.ts +59 -0
  42. package/types/types.ts +292 -0
  43. package/types/validation.ts +32 -0
@@ -0,0 +1,222 @@
1
+ // Shared InstantDB schema
2
+ // Used by both backend and frontend
3
+ // Docs: https://www.instantdb.com/docs/modeling-data
4
+ import { i } from "@instantdb/core";
5
+ const _schema = i.schema({
6
+ entities: {
7
+ // InstantDB system entities
8
+ $files: i.entity({
9
+ path: i.string().unique().indexed(),
10
+ url: i.string(),
11
+ }),
12
+ $users: i.entity({
13
+ email: i.string().unique().indexed().optional(),
14
+ imageURL: i.string().optional(),
15
+ type: i.string().optional(),
16
+ }),
17
+ // === CURRENTLY USED ENTITIES ===
18
+ company: i.entity({
19
+ name: i.string().indexed(),
20
+ type: i.number().indexed(), // 1=public, 2=private, 3=issuer, 4=unknown, 5=trust
21
+ jurisdiction_raw: i.string().optional(),
22
+ jurisdiction_iso: i.string().optional(),
23
+ aliases: i.json().optional(),
24
+ identity: i.json().optional(),
25
+ updated_at: i.string(),
26
+ }),
27
+ filing: i.entity({
28
+ accession_number: i.string().unique(),
29
+ accession_number_nodashes: i.string().unique().indexed(),
30
+ file_url: i.string(),
31
+ form_type: i.string().indexed(),
32
+ source_quarter: i.number().indexed(), // When filed: 1-4
33
+ source_year: i.number().indexed(), // When filed: e.g., 2025
34
+ filing_date: i.string().indexed(), // Date when filed with SEC
35
+ period_of_report: i.string().optional(), // Period end date from the filing (renamed from period_end_date)
36
+ attachments: i.json().optional(),
37
+ file_name: i.string().optional(),
38
+ updated_at: i.string(),
39
+ }),
40
+ parent_of: i.entity({
41
+ source: i.number().indexed(), // 1=ma_event, 2=spinoff, 3=ipo, 4=manual, 5=sec_filing
42
+ ownership_percent: i.number().optional(),
43
+ established_date: i.string().optional(),
44
+ ended_date: i.string().optional(),
45
+ updated_at: i.string(),
46
+ }),
47
+ subsidiary_enrichment: i.entity({
48
+ footnoteRefs: i.json(),
49
+ footnotesHtml: i.string().optional(),
50
+ llmEnriched: i.boolean().indexed(),
51
+ llmEnrichedAt: i.string().optional(),
52
+ updated_at: i.string(),
53
+ }),
54
+ company_info: i.entity({
55
+ fiscal_year_end: i.string().optional(),
56
+ addresses: i.json().optional(),
57
+ phone: i.string().optional(),
58
+ former_names: i.json().optional(),
59
+ updated_at: i.string(),
60
+ }),
61
+ brand: i.entity({
62
+ category: i.string().indexed().optional(),
63
+ created_at: i.string(),
64
+ launch_date: i.string().optional(),
65
+ name: i.string().indexed(),
66
+ status: i.string().indexed(),
67
+ updated_at: i.string(),
68
+ }),
69
+ owns: i.entity({
70
+ acquired_date: i.string().optional(),
71
+ created_at: i.string(),
72
+ divested_date: i.string().indexed().optional(),
73
+ updated_at: i.string(),
74
+ }),
75
+ // Audit trail (optional - can be disabled via ENABLE_AUDIT_TRAIL=false)
76
+ audit: i.entity({
77
+ changed_at: i.string().indexed(),
78
+ changed_by: i.string().indexed(),
79
+ entity_id: i.string().indexed(),
80
+ entity_type: i.string().indexed(),
81
+ expires_at: i.string().indexed(),
82
+ fields_changed: i.json(),
83
+ operation: i.string().indexed(),
84
+ source_id: i.string().indexed().optional(),
85
+ }),
86
+ },
87
+ links: {
88
+ // Company -> Filing (many-to-many: multiple companies can file the same document)
89
+ filing: {
90
+ forward: {
91
+ on: "company",
92
+ has: "many",
93
+ label: "filings",
94
+ },
95
+ reverse: {
96
+ on: "filing",
97
+ has: "many",
98
+ label: "companies",
99
+ },
100
+ },
101
+ // Parent company link (parent_of.parentCompany -> company)
102
+ parentCompany: {
103
+ forward: {
104
+ on: "parent_of",
105
+ has: "one",
106
+ label: "parentCompany",
107
+ },
108
+ reverse: {
109
+ on: "company",
110
+ has: "many",
111
+ label: "subsidiaries",
112
+ },
113
+ },
114
+ // Subsidiary company link (parent_of.subsidiaryCompany -> company)
115
+ subsidiaryCompany: {
116
+ forward: {
117
+ on: "parent_of",
118
+ has: "one",
119
+ label: "subsidiaryCompany",
120
+ },
121
+ reverse: {
122
+ on: "company",
123
+ has: "many", //Temporal tracking: a company could have different parents over time
124
+ label: "parents",
125
+ },
126
+ },
127
+ // Source filing link (parent_of.sourceFiling -> filing, when source=5/sec_filing)
128
+ sourceFiling: {
129
+ forward: {
130
+ on: "parent_of",
131
+ has: "one",
132
+ label: "sourceFiling",
133
+ },
134
+ reverse: {
135
+ on: "filing",
136
+ has: "many",
137
+ label: "parentOfEdges",
138
+ },
139
+ },
140
+ // Company -> Subsidiary Enrichment
141
+ subsidiaryEnrichment: {
142
+ forward: {
143
+ on: "company",
144
+ has: "many",
145
+ label: "subsidiaryEnrichments",
146
+ },
147
+ reverse: {
148
+ on: "subsidiary_enrichment",
149
+ has: "one",
150
+ label: "company",
151
+ },
152
+ },
153
+ // Filing -> Subsidiary Enrichment
154
+ filingEnrichment: {
155
+ forward: {
156
+ on: "filing",
157
+ has: "many",
158
+ label: "subsidiaryEnrichments",
159
+ },
160
+ reverse: {
161
+ on: "subsidiary_enrichment",
162
+ has: "one",
163
+ label: "filing",
164
+ },
165
+ },
166
+ // Company -> Company Info
167
+ companyInfo: {
168
+ forward: {
169
+ on: "company",
170
+ has: "one",
171
+ label: "companyInfo",
172
+ },
173
+ reverse: {
174
+ on: "company_info",
175
+ has: "one",
176
+ label: "company",
177
+ },
178
+ },
179
+ // // Company -> Brand (direct ownership link)
180
+ // brandOwner: {
181
+ // forward: {
182
+ // on: "company",
183
+ // has: "many",
184
+ // label: "brands",
185
+ // },
186
+ // reverse: {
187
+ // on: "brand",
188
+ // has: "one",
189
+ // label: "owningCompany",
190
+ // },
191
+ // },
192
+ // // Company -> Brand (via owns edge for historical tracking)
193
+ // ownsLink: {
194
+ // forward: {
195
+ // on: "owns",
196
+ // has: "one",
197
+ // label: "company",
198
+ // },
199
+ // reverse: {
200
+ // on: "company",
201
+ // has: "many",
202
+ // label: "ownedBrands",
203
+ // },
204
+ // },
205
+ // // Brand -> Owns
206
+ // brandOwnership: {
207
+ // forward: {
208
+ // on: "owns",
209
+ // has: "one",
210
+ // label: "brand",
211
+ // },
212
+ // reverse: {
213
+ // on: "brand",
214
+ // has: "many",
215
+ // label: "ownership",
216
+ // },
217
+ // },
218
+ },
219
+ rooms: {},
220
+ });
221
+ const schema = _schema;
222
+ export default schema;
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Deterministic ID Generation for InstantDB
3
+ *
4
+ * Benefits:
5
+ * - Deterministic: Same input always produces the same UUID
6
+ * - Idempotent: Upserts with identical data update the same record
7
+ * - No redundancy: No need for separate composite_key column
8
+ * - Compatible: UUID v5 format works with InstantDB's ID requirements
9
+ */
10
+ import { type CompanyIdentity } from './types';
11
+ /**
12
+ * Namespace UUIDs for each entity type.
13
+ * These are used with UUID v5 to generate deterministic IDs.
14
+ * Each namespace ensures IDs are unique within their entity type.
15
+ */
16
+ export declare const NAMESPACES: {
17
+ /** Namespace for company entity IDs */
18
+ readonly COMPANY: "6ba7b810-9dad-11d1-80b4-00c04fd430c8";
19
+ /** Namespace for filing entity IDs */
20
+ readonly FILING: "6ba7b811-9dad-11d1-80b4-00c04fd430c8";
21
+ /** Namespace for parent_of relationship IDs */
22
+ readonly PARENT_OF: "6ba7b812-9dad-11d1-80b4-00c04fd430c8";
23
+ /** Namespace for subsidiary_enrichment entity IDs */
24
+ readonly SUBSIDIARY_ENRICHMENT: "6ba7b813-9dad-11d1-80b4-00c04fd430c8";
25
+ /** Namespace for business_segment entity IDs */
26
+ readonly BUSINESS_SEGMENT: "6ba7b814-9dad-11d1-80b4-00c04fd430c8";
27
+ /** Namespace for brand entity IDs */
28
+ readonly BRAND: "6ba7b815-9dad-11d1-80b4-00c04fd430c8";
29
+ /** Namespace for owns relationship IDs */
30
+ readonly OWNS: "6ba7b816-9dad-11d1-80b4-00c04fd430c8";
31
+ /** Namespace for company_info entity IDs */
32
+ readonly COMPANY_INFO: "6ba7b817-9dad-11d1-80b4-00c04fd430c8";
33
+ };
34
+ export type NamespaceKey = keyof typeof NAMESPACES;
35
+ /**
36
+ * Company data required for ID generation
37
+ */
38
+ export interface CompanyIdInput {
39
+ type: number;
40
+ name?: string;
41
+ jurisdiction_raw?: string;
42
+ identity?: CompanyIdentity;
43
+ }
44
+ /**
45
+ * Generate a deterministic UUID v5 ID for a company.
46
+ * @param company - Company data with type and required fields
47
+ * @returns UUID v5 string
48
+ */
49
+ export declare function generateCompanyId(company: CompanyIdInput): string;
50
+ /**
51
+ * Generate a deterministic UUID v5 ID for a filing.
52
+ *
53
+ * @param accessionNumber - SEC accession number (e.g., "0001193125-24-123456" or "0001193125241234567")
54
+ * @returns UUID v5 string
55
+ * @throws ZodError if accession number is invalid
56
+ *
57
+ * @example
58
+ * generateFilingId("0001193125-24-123456") // Returns UUID v5
59
+ * generateFilingId("0001193125241234567") // Returns same UUID v5 (normalized)
60
+ */
61
+ export declare function generateFilingId(accessionNumber: string): string;
62
+ /**
63
+ * Generate a deterministic UUID v5 ID for a parent_of relationship.
64
+ *
65
+ * @param parentId - UUID of the parent company
66
+ * @param subsidiaryId - UUID of the subsidiary company
67
+ * @returns UUID v5 string
68
+ * @throws ZodError if parentId or subsidiaryId is empty
69
+ *
70
+ * @example
71
+ * generateParentOfId("parent-uuid", "subsidiary-uuid")
72
+ */
73
+ export declare function generateParentOfId(parentId: string, subsidiaryId: string): string;
74
+ /**
75
+ * Generate a deterministic UUID v5 ID for a subsidiary_enrichment.
76
+ *
77
+ * @param companyId - UUID of the company
78
+ * @param filingId - UUID of the filing
79
+ * @returns UUID v5 string
80
+ * @throws ZodError if companyId or filingId is empty
81
+ *
82
+ * @example
83
+ * generateSubsidiaryEnrichmentId("company-uuid", "filing-uuid")
84
+ */
85
+ export declare function generateSubsidiaryEnrichmentId(companyId: string, filingId: string): string;
86
+ /**
87
+ * Generate a deterministic UUID v5 ID for an owns relationship.
88
+ *
89
+ * @param companyId - UUID of the owning company
90
+ * @param brandId - UUID of the brand
91
+ * @returns UUID v5 string
92
+ * @throws ZodError if companyId or brandId is empty
93
+ *
94
+ * @example
95
+ * generateOwnsId("company-uuid", "brand-uuid")
96
+ */
97
+ export declare function generateOwnsId(companyId: string, brandId: string): string;
98
+ /**
99
+ * Generate a deterministic UUID v5 ID for a business_segment.
100
+ *
101
+ * @param companyId - UUID of the company
102
+ * @param segmentName - Name of the business segment
103
+ * @param fiscalYear - Fiscal year (integer)
104
+ * @param fiscalQuarter - Fiscal quarter (1-4) or null for annual
105
+ * @returns UUID v5 string
106
+ * @throws ZodError if required fields are invalid
107
+ *
108
+ * @example
109
+ * generateBusinessSegmentId("company-uuid", "Cloud Services", 2024, 1)
110
+ * generateBusinessSegmentId("company-uuid", "Cloud Services", 2024, null) // Annual
111
+ */
112
+ export declare function generateBusinessSegmentId(companyId: string, segmentName: string, fiscalYear: number, fiscalQuarter: number | null): string;
113
+ /**
114
+ * Generate a deterministic UUID v5 ID for a brand.
115
+ *
116
+ * @param companyId - UUID of the owning company
117
+ * @param name - Name of the brand
118
+ * @returns UUID v5 string
119
+ * @throws ZodError if companyId or name is empty
120
+ *
121
+ * @example
122
+ * generateBrandId("company-uuid", "iPhone")
123
+ */
124
+ export declare function generateBrandId(companyId: string, name: string): string;
125
+ /**
126
+ * Generate a deterministic UUID v5 ID for company_info.
127
+ *
128
+ * @param companyId - UUID of the company
129
+ * @returns UUID v5 string
130
+ *
131
+ * @example
132
+ * generateCompanyInfoId("company-uuid")
133
+ */
134
+ export declare function generateCompanyInfoId(companyId: string): string;
135
+ //# sourceMappingURL=ids.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ids.d.ts","sourceRoot":"","sources":["../../types/ids.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAEL,KAAK,eAAe,EAWrB,MAAM,SAAS,CAAC;AAEjB;;;;GAIG;AACH,eAAO,MAAM,UAAU;IACrB,uCAAuC;;IAEvC,sCAAsC;;IAEtC,+CAA+C;;IAE/C,qDAAqD;;IAErD,gDAAgD;;IAEhD,qCAAqC;;IAErC,0CAA0C;;IAE1C,4CAA4C;;CAEpC,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,MAAM,OAAO,UAAU,CAAC;AAMnD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CA6BjE;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAGhE;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GACnB,MAAM,CAIR;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,8BAA8B,CAC5C,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,MAAM,CAIR;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,MAAM,CAIR;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,GAAG,IAAI,GAC3B,MAAM,CAMR;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,GACX,MAAM,CAKR;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAK/D"}
@@ -0,0 +1,188 @@
1
+ /**
2
+ * Deterministic ID Generation for InstantDB
3
+ *
4
+ * Benefits:
5
+ * - Deterministic: Same input always produces the same UUID
6
+ * - Idempotent: Upserts with identical data update the same record
7
+ * - No redundancy: No need for separate composite_key column
8
+ * - Compatible: UUID v5 format works with InstantDB's ID requirements
9
+ */
10
+ import { v5 as uuidv5 } from 'uuid';
11
+ import { CompanyType, PublicCompanySchema, IssuerCompanySchema, PrivateCompanySchema, UnknownCompanySchema, AccessionNumberString, ParentOfParamsSchema, SubsidiaryEnrichmentParamsSchema, BusinessSegmentParamsSchema, BrandParamsSchema, OwnsParamsSchema, } from './types';
12
+ /**
13
+ * Namespace UUIDs for each entity type.
14
+ * These are used with UUID v5 to generate deterministic IDs.
15
+ * Each namespace ensures IDs are unique within their entity type.
16
+ */
17
+ export const NAMESPACES = {
18
+ /** Namespace for company entity IDs */
19
+ COMPANY: '6ba7b810-9dad-11d1-80b4-00c04fd430c8',
20
+ /** Namespace for filing entity IDs */
21
+ FILING: '6ba7b811-9dad-11d1-80b4-00c04fd430c8',
22
+ /** Namespace for parent_of relationship IDs */
23
+ PARENT_OF: '6ba7b812-9dad-11d1-80b4-00c04fd430c8',
24
+ /** Namespace for subsidiary_enrichment entity IDs */
25
+ SUBSIDIARY_ENRICHMENT: '6ba7b813-9dad-11d1-80b4-00c04fd430c8',
26
+ /** Namespace for business_segment entity IDs */
27
+ BUSINESS_SEGMENT: '6ba7b814-9dad-11d1-80b4-00c04fd430c8',
28
+ /** Namespace for brand entity IDs */
29
+ BRAND: '6ba7b815-9dad-11d1-80b4-00c04fd430c8',
30
+ /** Namespace for owns relationship IDs */
31
+ OWNS: '6ba7b816-9dad-11d1-80b4-00c04fd430c8',
32
+ /** Namespace for company_info entity IDs */
33
+ COMPANY_INFO: '6ba7b817-9dad-11d1-80b4-00c04fd430c8',
34
+ };
35
+ /**
36
+ * Generate a deterministic UUID v5 ID for a company.
37
+ * @param company - Company data with type and required fields
38
+ * @returns UUID v5 string
39
+ */
40
+ export function generateCompanyId(company) {
41
+ switch (company.type) {
42
+ case CompanyType.PUBLIC: {
43
+ const validated = PublicCompanySchema.parse(company);
44
+ return uuidv5(`${company.type}:${validated.identity.primaryCIK}`, NAMESPACES.COMPANY);
45
+ }
46
+ case CompanyType.ISSUER: {
47
+ const validated = IssuerCompanySchema.parse(company);
48
+ return uuidv5(`${company.type}:${validated.identity.primaryCIK}`, NAMESPACES.COMPANY);
49
+ }
50
+ case CompanyType.PRIVATE: {
51
+ const validated = PrivateCompanySchema.parse(company);
52
+ const normalizedName = validated.name.trim().toLowerCase();
53
+ const normalizedJurisdiction = validated.jurisdiction_raw.trim().toLowerCase();
54
+ return uuidv5(`${company.type}:${normalizedName}:${normalizedJurisdiction}`, NAMESPACES.COMPANY);
55
+ }
56
+ default: {
57
+ const validated = UnknownCompanySchema.parse(company);
58
+ const normalizedName = validated.name.trim().toLowerCase();
59
+ const normalizedJurisdiction = validated.jurisdiction_raw?.trim().toLowerCase() || '';
60
+ const compositeString = normalizedJurisdiction
61
+ ? `${company.type}:${normalizedName}:${normalizedJurisdiction}`
62
+ : `${company.type}:${normalizedName}`;
63
+ return uuidv5(compositeString, NAMESPACES.COMPANY);
64
+ }
65
+ }
66
+ }
67
+ // ============================================================================
68
+ // FILING ID GENERATION
69
+ // ============================================================================
70
+ /**
71
+ * Generate a deterministic UUID v5 ID for a filing.
72
+ *
73
+ * @param accessionNumber - SEC accession number (e.g., "0001193125-24-123456" or "0001193125241234567")
74
+ * @returns UUID v5 string
75
+ * @throws ZodError if accession number is invalid
76
+ *
77
+ * @example
78
+ * generateFilingId("0001193125-24-123456") // Returns UUID v5
79
+ * generateFilingId("0001193125241234567") // Returns same UUID v5 (normalized)
80
+ */
81
+ export function generateFilingId(accessionNumber) {
82
+ const normalized = AccessionNumberString.parse(accessionNumber);
83
+ return uuidv5(normalized, NAMESPACES.FILING);
84
+ }
85
+ // ============================================================================
86
+ // RELATIONSHIP ENTITY ID GENERATION
87
+ // ============================================================================
88
+ /**
89
+ * Generate a deterministic UUID v5 ID for a parent_of relationship.
90
+ *
91
+ * @param parentId - UUID of the parent company
92
+ * @param subsidiaryId - UUID of the subsidiary company
93
+ * @returns UUID v5 string
94
+ * @throws ZodError if parentId or subsidiaryId is empty
95
+ *
96
+ * @example
97
+ * generateParentOfId("parent-uuid", "subsidiary-uuid")
98
+ */
99
+ export function generateParentOfId(parentId, subsidiaryId) {
100
+ ParentOfParamsSchema.parse({ parentId, subsidiaryId });
101
+ const compositeString = `${parentId}:${subsidiaryId}`;
102
+ return uuidv5(compositeString, NAMESPACES.PARENT_OF);
103
+ }
104
+ /**
105
+ * Generate a deterministic UUID v5 ID for a subsidiary_enrichment.
106
+ *
107
+ * @param companyId - UUID of the company
108
+ * @param filingId - UUID of the filing
109
+ * @returns UUID v5 string
110
+ * @throws ZodError if companyId or filingId is empty
111
+ *
112
+ * @example
113
+ * generateSubsidiaryEnrichmentId("company-uuid", "filing-uuid")
114
+ */
115
+ export function generateSubsidiaryEnrichmentId(companyId, filingId) {
116
+ SubsidiaryEnrichmentParamsSchema.parse({ companyId, filingId });
117
+ const compositeString = `${companyId}:${filingId}`;
118
+ return uuidv5(compositeString, NAMESPACES.SUBSIDIARY_ENRICHMENT);
119
+ }
120
+ /**
121
+ * Generate a deterministic UUID v5 ID for an owns relationship.
122
+ *
123
+ * @param companyId - UUID of the owning company
124
+ * @param brandId - UUID of the brand
125
+ * @returns UUID v5 string
126
+ * @throws ZodError if companyId or brandId is empty
127
+ *
128
+ * @example
129
+ * generateOwnsId("company-uuid", "brand-uuid")
130
+ */
131
+ export function generateOwnsId(companyId, brandId) {
132
+ OwnsParamsSchema.parse({ companyId, brandId });
133
+ const compositeString = `${companyId}:${brandId}`;
134
+ return uuidv5(compositeString, NAMESPACES.OWNS);
135
+ }
136
+ /**
137
+ * Generate a deterministic UUID v5 ID for a business_segment.
138
+ *
139
+ * @param companyId - UUID of the company
140
+ * @param segmentName - Name of the business segment
141
+ * @param fiscalYear - Fiscal year (integer)
142
+ * @param fiscalQuarter - Fiscal quarter (1-4) or null for annual
143
+ * @returns UUID v5 string
144
+ * @throws ZodError if required fields are invalid
145
+ *
146
+ * @example
147
+ * generateBusinessSegmentId("company-uuid", "Cloud Services", 2024, 1)
148
+ * generateBusinessSegmentId("company-uuid", "Cloud Services", 2024, null) // Annual
149
+ */
150
+ export function generateBusinessSegmentId(companyId, segmentName, fiscalYear, fiscalQuarter) {
151
+ BusinessSegmentParamsSchema.parse({ companyId, segmentName, fiscalYear, fiscalQuarter });
152
+ const normalizedName = segmentName.trim().toLowerCase();
153
+ const quarter = fiscalQuarter !== null ? fiscalQuarter.toString() : 'null';
154
+ const compositeString = `${companyId}:${normalizedName}:${fiscalYear}:${quarter}`;
155
+ return uuidv5(compositeString, NAMESPACES.BUSINESS_SEGMENT);
156
+ }
157
+ /**
158
+ * Generate a deterministic UUID v5 ID for a brand.
159
+ *
160
+ * @param companyId - UUID of the owning company
161
+ * @param name - Name of the brand
162
+ * @returns UUID v5 string
163
+ * @throws ZodError if companyId or name is empty
164
+ *
165
+ * @example
166
+ * generateBrandId("company-uuid", "iPhone")
167
+ */
168
+ export function generateBrandId(companyId, name) {
169
+ BrandParamsSchema.parse({ companyId, name });
170
+ const normalizedName = name.trim().toLowerCase();
171
+ const compositeString = `${companyId}:${normalizedName}`;
172
+ return uuidv5(compositeString, NAMESPACES.BRAND);
173
+ }
174
+ /**
175
+ * Generate a deterministic UUID v5 ID for company_info.
176
+ *
177
+ * @param companyId - UUID of the company
178
+ * @returns UUID v5 string
179
+ *
180
+ * @example
181
+ * generateCompanyInfoId("company-uuid")
182
+ */
183
+ export function generateCompanyInfoId(companyId) {
184
+ if (!companyId || companyId.trim().length === 0) {
185
+ throw new Error("companyId is required for company_info ID generation");
186
+ }
187
+ return uuidv5(companyId, NAMESPACES.COMPANY_INFO);
188
+ }
@@ -0,0 +1,39 @@
1
+ export declare const futureEntities: {
2
+ ma_events: import("@instantdb/core").EntityDef<{
3
+ acquirer_id: import("@instantdb/core").DataAttrDef<string, true, true>;
4
+ announced_date: import("@instantdb/core").DataAttrDef<string, false, false>;
5
+ created_at: import("@instantdb/core").DataAttrDef<any, true, false>;
6
+ deal_value: import("@instantdb/core").DataAttrDef<number, false, false>;
7
+ deal_value_currency: import("@instantdb/core").DataAttrDef<any, true, false>;
8
+ effective_date: import("@instantdb/core").DataAttrDef<string, true, true>;
9
+ event_type: import("@instantdb/core").DataAttrDef<string, true, true>;
10
+ status: import("@instantdb/core").DataAttrDef<string, true, true>;
11
+ target_id: import("@instantdb/core").DataAttrDef<string, true, true>;
12
+ updated_at: import("@instantdb/core").DataAttrDef<any, true, false>;
13
+ }, {}, void>;
14
+ acquired: import("@instantdb/core").EntityDef<{
15
+ created_at: import("@instantdb/core").DataAttrDef<any, true, false>;
16
+ from_company_id: import("@instantdb/core").DataAttrDef<string, true, true>;
17
+ ma_event_id: import("@instantdb/core").DataAttrDef<string, true, true>;
18
+ to_company_id: import("@instantdb/core").DataAttrDef<string, true, true>;
19
+ }, {}, void>;
20
+ was_acquired_by: import("@instantdb/core").EntityDef<{
21
+ created_at: import("@instantdb/core").DataAttrDef<any, true, false>;
22
+ from_company_id: import("@instantdb/core").DataAttrDef<string, true, true>;
23
+ ma_event_id: import("@instantdb/core").DataAttrDef<string, true, true>;
24
+ to_company_id: import("@instantdb/core").DataAttrDef<string, true, true>;
25
+ }, {}, void>;
26
+ company_snapshots: import("@instantdb/core").EntityDef<{
27
+ aliases: import("@instantdb/core").DataAttrDef<any, true, false>;
28
+ change_reason: import("@instantdb/core").DataAttrDef<string, true, true>;
29
+ company_id: import("@instantdb/core").DataAttrDef<string, true, true>;
30
+ created_at: import("@instantdb/core").DataAttrDef<any, true, false>;
31
+ identity: import("@instantdb/core").DataAttrDef<any, true, false>;
32
+ ma_event_id: import("@instantdb/core").DataAttrDef<string, false, true>;
33
+ name: import("@instantdb/core").DataAttrDef<any, true, false>;
34
+ type: import("@instantdb/core").DataAttrDef<any, true, false>;
35
+ valid_from: import("@instantdb/core").DataAttrDef<string, true, true>;
36
+ valid_to: import("@instantdb/core").DataAttrDef<string, false, true>;
37
+ }, {}, void>;
38
+ };
39
+ //# sourceMappingURL=instant.schema.future.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instant.schema.future.d.ts","sourceRoot":"","sources":["../../types/instant.schema.future.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2C1B,CAAC"}
@@ -0,0 +1,52 @@
1
+ // Future schema additions - M&A tracking entities
2
+ // These are not yet implemented but defined for future use
3
+ // To use: merge these entities into instant.schema.ts when ready
4
+ import { i } from "@instantdb/core";
5
+ // === M&A Event Tracking ===
6
+ // Track mergers, acquisitions, spinoffs, and divestitures
7
+ export const futureEntities = {
8
+ ma_events: i.entity({
9
+ acquirer_id: i.string().indexed(),
10
+ announced_date: i.string().optional(),
11
+ created_at: i.string(),
12
+ deal_value: i.number().optional(),
13
+ deal_value_currency: i.string(),
14
+ effective_date: i.string().indexed(),
15
+ event_type: i.string().indexed(), // "acquisition" | "merger" | "spinoff" | "divestiture"
16
+ status: i.string().indexed(), // "pending" | "completed" | "terminated"
17
+ target_id: i.string().indexed(),
18
+ updated_at: i.string(),
19
+ }),
20
+ // Edge: Acquirer acquired Target
21
+ acquired: i.entity({
22
+ created_at: i.string(),
23
+ from_company_id: i.string().indexed(), // Acquirer
24
+ ma_event_id: i.string().indexed(),
25
+ to_company_id: i.string().indexed(), // Target
26
+ }),
27
+ // Edge: Target was acquired by Acquirer (reverse)
28
+ was_acquired_by: i.entity({
29
+ created_at: i.string(),
30
+ from_company_id: i.string().indexed(), // Target
31
+ ma_event_id: i.string().indexed(),
32
+ to_company_id: i.string().indexed(), // Acquirer
33
+ }),
34
+ // Temporal snapshots of company state
35
+ company_snapshots: i.entity({
36
+ aliases: i.any(),
37
+ change_reason: i.string().indexed(), // "ma_event" | "spinoff" | "ipo" | "delisting" | "name_change"
38
+ company_id: i.string().indexed(),
39
+ created_at: i.string(),
40
+ identity: i.any(),
41
+ ma_event_id: i.string().indexed().optional(),
42
+ name: i.string(),
43
+ type: i.string(),
44
+ valid_from: i.string().indexed(),
45
+ valid_to: i.string().indexed().optional(),
46
+ }),
47
+ };
48
+ // Usage example:
49
+ // 1. Copy entities above into instant.schema.ts entities section
50
+ // 2. Implement M&A ingestion pipeline
51
+ // 3. Create repo functions for M&A operations
52
+ // 4. Update frontend to display M&A events