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.
- package/README.md +75 -0
- package/dist/db/index.d.ts +11 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +11 -0
- package/dist/db/queries/cik-lookup.d.ts +49 -0
- package/dist/db/queries/cik-lookup.d.ts.map +1 -0
- package/dist/db/queries/cik-lookup.js +78 -0
- package/dist/db/queries/company-lookup.d.ts +43 -0
- package/dist/db/queries/company-lookup.d.ts.map +1 -0
- package/dist/db/queries/company-lookup.js +65 -0
- package/dist/db/queries/index.d.ts +8 -0
- package/dist/db/queries/index.d.ts.map +1 -0
- package/dist/db/queries/index.js +7 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/instant.schema.d.ts +170 -0
- package/dist/instant.schema.d.ts.map +1 -0
- package/dist/instant.schema.js +222 -0
- package/dist/types/ids.d.ts +135 -0
- package/dist/types/ids.d.ts.map +1 -0
- package/dist/types/ids.js +188 -0
- package/dist/types/instant.schema.future.d.ts +39 -0
- package/dist/types/instant.schema.future.d.ts.map +1 -0
- package/dist/types/instant.schema.future.js +52 -0
- package/dist/types/types.d.ts +321 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/types.js +180 -0
- package/dist/types/validation.d.ts +7 -0
- package/dist/types/validation.d.ts.map +1 -0
- package/dist/types/validation.js +14 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +4 -0
- package/dist/utils/logger-interface.d.ts +57 -0
- package/dist/utils/logger-interface.d.ts.map +1 -0
- package/dist/utils/logger-interface.js +38 -0
- package/package.json +54 -0
- package/types/ids.ts +249 -0
- package/types/instant.schema.future.js +55 -0
- package/types/instant.schema.future.ts +59 -0
- package/types/types.ts +292 -0
- package/types/validation.ts +32 -0
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "financial-graph-shared",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Shared types, schema, and utilities for financial-graph",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./types": "./dist/types/types.js",
|
|
14
|
+
"./schema": "./dist/types/schema.js",
|
|
15
|
+
"./validation": "./dist/types/validation.js",
|
|
16
|
+
"./composite-keys": "./dist/types/composite-keys.js",
|
|
17
|
+
"./ids": "./dist/types/ids.js",
|
|
18
|
+
"./db": {
|
|
19
|
+
"types": "./dist/db/index.d.ts",
|
|
20
|
+
"default": "./dist/db/index.js"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "tsc",
|
|
25
|
+
"watch": "tsc --watch",
|
|
26
|
+
"clean": "rm -rf dist",
|
|
27
|
+
"test": "bun run build && bun test tests/",
|
|
28
|
+
"test:watch": "bun test --watch tests/",
|
|
29
|
+
"test:only": "bun test tests/",
|
|
30
|
+
"schema:push": "bunx instant-cli@latest push schema"
|
|
31
|
+
},
|
|
32
|
+
"keywords": ["types", "schema", "instantdb"],
|
|
33
|
+
"author": "",
|
|
34
|
+
"license": "ISC",
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=24.0.0"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@instantdb/core": "^0.22.96",
|
|
40
|
+
"fast-check": "^4.5.3",
|
|
41
|
+
"uuid": "^13.0.0",
|
|
42
|
+
"zod": "^4.3.5"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/bun": "^1.3.5",
|
|
46
|
+
"@types/node": "^25.0.3",
|
|
47
|
+
"@types/uuid": "^11.0.0",
|
|
48
|
+
"typescript": "^5.9.3"
|
|
49
|
+
},
|
|
50
|
+
"files": [
|
|
51
|
+
"dist",
|
|
52
|
+
"types"
|
|
53
|
+
]
|
|
54
|
+
}
|
package/types/ids.ts
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
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
|
+
|
|
11
|
+
import { v5 as uuidv5 } from 'uuid';
|
|
12
|
+
import {
|
|
13
|
+
CompanyType,
|
|
14
|
+
type CompanyIdentity,
|
|
15
|
+
PublicCompanySchema,
|
|
16
|
+
IssuerCompanySchema,
|
|
17
|
+
PrivateCompanySchema,
|
|
18
|
+
UnknownCompanySchema,
|
|
19
|
+
AccessionNumberString,
|
|
20
|
+
ParentOfParamsSchema,
|
|
21
|
+
SubsidiaryEnrichmentParamsSchema,
|
|
22
|
+
BusinessSegmentParamsSchema,
|
|
23
|
+
BrandParamsSchema,
|
|
24
|
+
OwnsParamsSchema,
|
|
25
|
+
} from './types';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Namespace UUIDs for each entity type.
|
|
29
|
+
* These are used with UUID v5 to generate deterministic IDs.
|
|
30
|
+
* Each namespace ensures IDs are unique within their entity type.
|
|
31
|
+
*/
|
|
32
|
+
export const NAMESPACES = {
|
|
33
|
+
/** Namespace for company entity IDs */
|
|
34
|
+
COMPANY: '6ba7b810-9dad-11d1-80b4-00c04fd430c8',
|
|
35
|
+
/** Namespace for filing entity IDs */
|
|
36
|
+
FILING: '6ba7b811-9dad-11d1-80b4-00c04fd430c8',
|
|
37
|
+
/** Namespace for parent_of relationship IDs */
|
|
38
|
+
PARENT_OF: '6ba7b812-9dad-11d1-80b4-00c04fd430c8',
|
|
39
|
+
/** Namespace for subsidiary_enrichment entity IDs */
|
|
40
|
+
SUBSIDIARY_ENRICHMENT: '6ba7b813-9dad-11d1-80b4-00c04fd430c8',
|
|
41
|
+
/** Namespace for business_segment entity IDs */
|
|
42
|
+
BUSINESS_SEGMENT: '6ba7b814-9dad-11d1-80b4-00c04fd430c8',
|
|
43
|
+
/** Namespace for brand entity IDs */
|
|
44
|
+
BRAND: '6ba7b815-9dad-11d1-80b4-00c04fd430c8',
|
|
45
|
+
/** Namespace for owns relationship IDs */
|
|
46
|
+
OWNS: '6ba7b816-9dad-11d1-80b4-00c04fd430c8',
|
|
47
|
+
/** Namespace for company_info entity IDs */
|
|
48
|
+
COMPANY_INFO: '6ba7b817-9dad-11d1-80b4-00c04fd430c8',
|
|
49
|
+
} as const;
|
|
50
|
+
|
|
51
|
+
export type NamespaceKey = keyof typeof NAMESPACES;
|
|
52
|
+
|
|
53
|
+
// ============================================================================
|
|
54
|
+
// COMPANY ID GENERATION
|
|
55
|
+
// ============================================================================
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Company data required for ID generation
|
|
59
|
+
*/
|
|
60
|
+
export interface CompanyIdInput {
|
|
61
|
+
type: number;
|
|
62
|
+
name?: string;
|
|
63
|
+
jurisdiction_raw?: string;
|
|
64
|
+
identity?: CompanyIdentity;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Generate a deterministic UUID v5 ID for a company.
|
|
69
|
+
* @param company - Company data with type and required fields
|
|
70
|
+
* @returns UUID v5 string
|
|
71
|
+
*/
|
|
72
|
+
export function generateCompanyId(company: CompanyIdInput): string {
|
|
73
|
+
switch (company.type) {
|
|
74
|
+
case CompanyType.PUBLIC: {
|
|
75
|
+
const validated = PublicCompanySchema.parse(company);
|
|
76
|
+
return uuidv5(`${company.type}:${validated.identity.primaryCIK}`, NAMESPACES.COMPANY);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
case CompanyType.ISSUER: {
|
|
80
|
+
const validated = IssuerCompanySchema.parse(company);
|
|
81
|
+
return uuidv5(`${company.type}:${validated.identity.primaryCIK}`, NAMESPACES.COMPANY);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
case CompanyType.PRIVATE: {
|
|
85
|
+
const validated = PrivateCompanySchema.parse(company);
|
|
86
|
+
const normalizedName = validated.name.trim().toLowerCase();
|
|
87
|
+
const normalizedJurisdiction = validated.jurisdiction_raw.trim().toLowerCase();
|
|
88
|
+
return uuidv5(`${company.type}:${normalizedName}:${normalizedJurisdiction}`, NAMESPACES.COMPANY);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
default: {
|
|
92
|
+
const validated = UnknownCompanySchema.parse(company);
|
|
93
|
+
const normalizedName = validated.name.trim().toLowerCase();
|
|
94
|
+
const normalizedJurisdiction = validated.jurisdiction_raw?.trim().toLowerCase() || '';
|
|
95
|
+
const compositeString = normalizedJurisdiction
|
|
96
|
+
? `${company.type}:${normalizedName}:${normalizedJurisdiction}`
|
|
97
|
+
: `${company.type}:${normalizedName}`;
|
|
98
|
+
return uuidv5(compositeString, NAMESPACES.COMPANY);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// ============================================================================
|
|
104
|
+
// FILING ID GENERATION
|
|
105
|
+
// ============================================================================
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Generate a deterministic UUID v5 ID for a filing.
|
|
109
|
+
*
|
|
110
|
+
* @param accessionNumber - SEC accession number (e.g., "0001193125-24-123456" or "0001193125241234567")
|
|
111
|
+
* @returns UUID v5 string
|
|
112
|
+
* @throws ZodError if accession number is invalid
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* generateFilingId("0001193125-24-123456") // Returns UUID v5
|
|
116
|
+
* generateFilingId("0001193125241234567") // Returns same UUID v5 (normalized)
|
|
117
|
+
*/
|
|
118
|
+
export function generateFilingId(accessionNumber: string): string {
|
|
119
|
+
const normalized = AccessionNumberString.parse(accessionNumber);
|
|
120
|
+
return uuidv5(normalized, NAMESPACES.FILING);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// ============================================================================
|
|
124
|
+
// RELATIONSHIP ENTITY ID GENERATION
|
|
125
|
+
// ============================================================================
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Generate a deterministic UUID v5 ID for a parent_of relationship.
|
|
129
|
+
*
|
|
130
|
+
* @param parentId - UUID of the parent company
|
|
131
|
+
* @param subsidiaryId - UUID of the subsidiary company
|
|
132
|
+
* @returns UUID v5 string
|
|
133
|
+
* @throws ZodError if parentId or subsidiaryId is empty
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* generateParentOfId("parent-uuid", "subsidiary-uuid")
|
|
137
|
+
*/
|
|
138
|
+
export function generateParentOfId(
|
|
139
|
+
parentId: string,
|
|
140
|
+
subsidiaryId: string
|
|
141
|
+
): string {
|
|
142
|
+
ParentOfParamsSchema.parse({ parentId, subsidiaryId });
|
|
143
|
+
const compositeString = `${parentId}:${subsidiaryId}`;
|
|
144
|
+
return uuidv5(compositeString, NAMESPACES.PARENT_OF);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Generate a deterministic UUID v5 ID for a subsidiary_enrichment.
|
|
149
|
+
*
|
|
150
|
+
* @param companyId - UUID of the company
|
|
151
|
+
* @param filingId - UUID of the filing
|
|
152
|
+
* @returns UUID v5 string
|
|
153
|
+
* @throws ZodError if companyId or filingId is empty
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* generateSubsidiaryEnrichmentId("company-uuid", "filing-uuid")
|
|
157
|
+
*/
|
|
158
|
+
export function generateSubsidiaryEnrichmentId(
|
|
159
|
+
companyId: string,
|
|
160
|
+
filingId: string
|
|
161
|
+
): string {
|
|
162
|
+
SubsidiaryEnrichmentParamsSchema.parse({ companyId, filingId });
|
|
163
|
+
const compositeString = `${companyId}:${filingId}`;
|
|
164
|
+
return uuidv5(compositeString, NAMESPACES.SUBSIDIARY_ENRICHMENT);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Generate a deterministic UUID v5 ID for an owns relationship.
|
|
169
|
+
*
|
|
170
|
+
* @param companyId - UUID of the owning company
|
|
171
|
+
* @param brandId - UUID of the brand
|
|
172
|
+
* @returns UUID v5 string
|
|
173
|
+
* @throws ZodError if companyId or brandId is empty
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* generateOwnsId("company-uuid", "brand-uuid")
|
|
177
|
+
*/
|
|
178
|
+
export function generateOwnsId(
|
|
179
|
+
companyId: string,
|
|
180
|
+
brandId: string
|
|
181
|
+
): string {
|
|
182
|
+
OwnsParamsSchema.parse({ companyId, brandId });
|
|
183
|
+
const compositeString = `${companyId}:${brandId}`;
|
|
184
|
+
return uuidv5(compositeString, NAMESPACES.OWNS);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Generate a deterministic UUID v5 ID for a business_segment.
|
|
189
|
+
*
|
|
190
|
+
* @param companyId - UUID of the company
|
|
191
|
+
* @param segmentName - Name of the business segment
|
|
192
|
+
* @param fiscalYear - Fiscal year (integer)
|
|
193
|
+
* @param fiscalQuarter - Fiscal quarter (1-4) or null for annual
|
|
194
|
+
* @returns UUID v5 string
|
|
195
|
+
* @throws ZodError if required fields are invalid
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* generateBusinessSegmentId("company-uuid", "Cloud Services", 2024, 1)
|
|
199
|
+
* generateBusinessSegmentId("company-uuid", "Cloud Services", 2024, null) // Annual
|
|
200
|
+
*/
|
|
201
|
+
export function generateBusinessSegmentId(
|
|
202
|
+
companyId: string,
|
|
203
|
+
segmentName: string,
|
|
204
|
+
fiscalYear: number,
|
|
205
|
+
fiscalQuarter: number | null
|
|
206
|
+
): string {
|
|
207
|
+
BusinessSegmentParamsSchema.parse({ companyId, segmentName, fiscalYear, fiscalQuarter });
|
|
208
|
+
const normalizedName = segmentName.trim().toLowerCase();
|
|
209
|
+
const quarter = fiscalQuarter !== null ? fiscalQuarter.toString() : 'null';
|
|
210
|
+
const compositeString = `${companyId}:${normalizedName}:${fiscalYear}:${quarter}`;
|
|
211
|
+
return uuidv5(compositeString, NAMESPACES.BUSINESS_SEGMENT);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Generate a deterministic UUID v5 ID for a brand.
|
|
216
|
+
*
|
|
217
|
+
* @param companyId - UUID of the owning company
|
|
218
|
+
* @param name - Name of the brand
|
|
219
|
+
* @returns UUID v5 string
|
|
220
|
+
* @throws ZodError if companyId or name is empty
|
|
221
|
+
*
|
|
222
|
+
* @example
|
|
223
|
+
* generateBrandId("company-uuid", "iPhone")
|
|
224
|
+
*/
|
|
225
|
+
export function generateBrandId(
|
|
226
|
+
companyId: string,
|
|
227
|
+
name: string
|
|
228
|
+
): string {
|
|
229
|
+
BrandParamsSchema.parse({ companyId, name });
|
|
230
|
+
const normalizedName = name.trim().toLowerCase();
|
|
231
|
+
const compositeString = `${companyId}:${normalizedName}`;
|
|
232
|
+
return uuidv5(compositeString, NAMESPACES.BRAND);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Generate a deterministic UUID v5 ID for company_info.
|
|
237
|
+
*
|
|
238
|
+
* @param companyId - UUID of the company
|
|
239
|
+
* @returns UUID v5 string
|
|
240
|
+
*
|
|
241
|
+
* @example
|
|
242
|
+
* generateCompanyInfoId("company-uuid")
|
|
243
|
+
*/
|
|
244
|
+
export function generateCompanyInfoId(companyId: string): string {
|
|
245
|
+
if (!companyId || companyId.trim().length === 0) {
|
|
246
|
+
throw new Error("companyId is required for company_info ID generation");
|
|
247
|
+
}
|
|
248
|
+
return uuidv5(companyId, NAMESPACES.COMPANY_INFO);
|
|
249
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Future schema additions - M&A tracking entities
|
|
3
|
+
// These are not yet implemented but defined for future use
|
|
4
|
+
// To use: merge these entities into instant.schema.ts when ready
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.futureEntities = void 0;
|
|
7
|
+
const core_1 = require("@instantdb/core");
|
|
8
|
+
// === M&A Event Tracking ===
|
|
9
|
+
// Track mergers, acquisitions, spinoffs, and divestitures
|
|
10
|
+
exports.futureEntities = {
|
|
11
|
+
ma_events: core_1.i.entity({
|
|
12
|
+
acquirer_id: core_1.i.string().indexed(),
|
|
13
|
+
announced_date: core_1.i.string().optional(),
|
|
14
|
+
created_at: core_1.i.string(),
|
|
15
|
+
deal_value: core_1.i.number().optional(),
|
|
16
|
+
deal_value_currency: core_1.i.string(),
|
|
17
|
+
effective_date: core_1.i.string().indexed(),
|
|
18
|
+
event_type: core_1.i.string().indexed(), // "acquisition" | "merger" | "spinoff" | "divestiture"
|
|
19
|
+
status: core_1.i.string().indexed(), // "pending" | "completed" | "terminated"
|
|
20
|
+
target_id: core_1.i.string().indexed(),
|
|
21
|
+
updated_at: core_1.i.string(),
|
|
22
|
+
}),
|
|
23
|
+
// Edge: Acquirer acquired Target
|
|
24
|
+
acquired: core_1.i.entity({
|
|
25
|
+
created_at: core_1.i.string(),
|
|
26
|
+
from_company_id: core_1.i.string().indexed(), // Acquirer
|
|
27
|
+
ma_event_id: core_1.i.string().indexed(),
|
|
28
|
+
to_company_id: core_1.i.string().indexed(), // Target
|
|
29
|
+
}),
|
|
30
|
+
// Edge: Target was acquired by Acquirer (reverse)
|
|
31
|
+
was_acquired_by: core_1.i.entity({
|
|
32
|
+
created_at: core_1.i.string(),
|
|
33
|
+
from_company_id: core_1.i.string().indexed(), // Target
|
|
34
|
+
ma_event_id: core_1.i.string().indexed(),
|
|
35
|
+
to_company_id: core_1.i.string().indexed(), // Acquirer
|
|
36
|
+
}),
|
|
37
|
+
// Temporal snapshots of company state
|
|
38
|
+
company_snapshots: core_1.i.entity({
|
|
39
|
+
aliases: core_1.i.any(),
|
|
40
|
+
change_reason: core_1.i.string().indexed(), // "ma_event" | "spinoff" | "ipo" | "delisting" | "name_change"
|
|
41
|
+
company_id: core_1.i.string().indexed(),
|
|
42
|
+
created_at: core_1.i.string(),
|
|
43
|
+
identity: core_1.i.any(),
|
|
44
|
+
ma_event_id: core_1.i.string().indexed().optional(),
|
|
45
|
+
name: core_1.i.string(),
|
|
46
|
+
type: core_1.i.string(),
|
|
47
|
+
valid_from: core_1.i.string().indexed(),
|
|
48
|
+
valid_to: core_1.i.string().indexed().optional(),
|
|
49
|
+
}),
|
|
50
|
+
};
|
|
51
|
+
// Usage example:
|
|
52
|
+
// 1. Copy entities above into instant.schema.ts entities section
|
|
53
|
+
// 2. Implement M&A ingestion pipeline
|
|
54
|
+
// 3. Create repo functions for M&A operations
|
|
55
|
+
// 4. Update frontend to display M&A events
|
|
@@ -0,0 +1,59 @@
|
|
|
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
|
+
|
|
5
|
+
import { i } from "@instantdb/core";
|
|
6
|
+
|
|
7
|
+
// === M&A Event Tracking ===
|
|
8
|
+
// Track mergers, acquisitions, spinoffs, and divestitures
|
|
9
|
+
|
|
10
|
+
export const futureEntities = {
|
|
11
|
+
ma_events: i.entity({
|
|
12
|
+
acquirer_id: i.string().indexed(),
|
|
13
|
+
announced_date: i.string().optional(),
|
|
14
|
+
created_at: i.string(),
|
|
15
|
+
deal_value: i.number().optional(),
|
|
16
|
+
deal_value_currency: i.string(),
|
|
17
|
+
effective_date: i.string().indexed(),
|
|
18
|
+
event_type: i.string().indexed(), // "acquisition" | "merger" | "spinoff" | "divestiture"
|
|
19
|
+
status: i.string().indexed(), // "pending" | "completed" | "terminated"
|
|
20
|
+
target_id: i.string().indexed(),
|
|
21
|
+
updated_at: i.string(),
|
|
22
|
+
}),
|
|
23
|
+
|
|
24
|
+
// Edge: Acquirer acquired Target
|
|
25
|
+
acquired: i.entity({
|
|
26
|
+
created_at: i.string(),
|
|
27
|
+
from_company_id: i.string().indexed(), // Acquirer
|
|
28
|
+
ma_event_id: i.string().indexed(),
|
|
29
|
+
to_company_id: i.string().indexed(), // Target
|
|
30
|
+
}),
|
|
31
|
+
|
|
32
|
+
// Edge: Target was acquired by Acquirer (reverse)
|
|
33
|
+
was_acquired_by: i.entity({
|
|
34
|
+
created_at: i.string(),
|
|
35
|
+
from_company_id: i.string().indexed(), // Target
|
|
36
|
+
ma_event_id: i.string().indexed(),
|
|
37
|
+
to_company_id: i.string().indexed(), // Acquirer
|
|
38
|
+
}),
|
|
39
|
+
|
|
40
|
+
// Temporal snapshots of company state
|
|
41
|
+
company_snapshots: i.entity({
|
|
42
|
+
aliases: i.any(),
|
|
43
|
+
change_reason: i.string().indexed(), // "ma_event" | "spinoff" | "ipo" | "delisting" | "name_change"
|
|
44
|
+
company_id: i.string().indexed(),
|
|
45
|
+
created_at: i.string(),
|
|
46
|
+
identity: i.any(),
|
|
47
|
+
ma_event_id: i.string().indexed().optional(),
|
|
48
|
+
name: i.string(),
|
|
49
|
+
type: i.string(),
|
|
50
|
+
valid_from: i.string().indexed(),
|
|
51
|
+
valid_to: i.string().indexed().optional(),
|
|
52
|
+
}),
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// Usage example:
|
|
56
|
+
// 1. Copy entities above into instant.schema.ts entities section
|
|
57
|
+
// 2. Implement M&A ingestion pipeline
|
|
58
|
+
// 3. Create repo functions for M&A operations
|
|
59
|
+
// 4. Update frontend to display M&A events
|