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
package/types/types.ts ADDED
@@ -0,0 +1,292 @@
1
+ /**
2
+ * Shared Database Types & Validation
3
+ *
4
+ * InstantDB handles: type checking, required/optional, unique constraints
5
+ * We handle: business logic validation that InstantDB can't express
6
+ *
7
+ * Types vs Interfaces:
8
+ * - `type` aliases are direct re-exports from InstantDB (InstaQLEntity)
9
+ * - `interface` adds proper typing for enum/JSON fields that InstantDB types as number/any
10
+ * - Code should use the interfaces (Company, ParentOfEdge) not the raw types
11
+ */
12
+
13
+ import { z } from "zod";
14
+ import type { InstaQLEntity } from "@instantdb/core";
15
+ import type schema from "../instant.schema";
16
+
17
+ // ============================================================================
18
+ // ENUMS
19
+ // ============================================================================
20
+
21
+ export const CompanyType = {
22
+ PUBLIC: 1,
23
+ PRIVATE: 2,
24
+ ISSUER: 3,
25
+ UNKNOWN: 4,
26
+ TRUST: 5,
27
+ } as const;
28
+
29
+ export type CompanyTypeValue = (typeof CompanyType)[keyof typeof CompanyType];
30
+
31
+ export const ParentOfSource = {
32
+ MA_EVENT: 1,
33
+ SPINOFF: 2,
34
+ IPO: 3,
35
+ MANUAL: 4,
36
+ SEC_FILING: 5,
37
+ } as const;
38
+
39
+ export type ParentOfSourceValue =
40
+ (typeof ParentOfSource)[keyof typeof ParentOfSource];
41
+
42
+ // ============================================================================
43
+ // RAW TYPES (from InstantDB - don't use directly, use interfaces below)
44
+ // ============================================================================
45
+
46
+ type CompanyRaw = InstaQLEntity<typeof schema, "company">;
47
+ type ParentOfEdgeRaw = InstaQLEntity<typeof schema, "parent_of">;
48
+
49
+ // These are fine to use directly (no enum/JSON fields needing better typing)
50
+ export type Filing = InstaQLEntity<typeof schema, "filing">;
51
+ export type FilingAttachments = Record<string, string>;
52
+ export type SubsidiaryEnrichment = InstaQLEntity<
53
+ typeof schema,
54
+ "subsidiary_enrichment"
55
+ >;
56
+ export type Audit = InstaQLEntity<typeof schema, "audit">;
57
+ // export type CompanyInfo = InstaQLEntity<typeof schema, "company_info">;
58
+ // export type BusinessSegment = InstaQLEntity<typeof schema, "business_segment">;
59
+ // export type Brand = InstaQLEntity<typeof schema, "brand">;
60
+ // export type OwnsEdge = InstaQLEntity<typeof schema, "owns">;
61
+
62
+ // ============================================================================
63
+ // INTERFACES (use these - proper typing for enum/JSON fields)
64
+ // ============================================================================
65
+
66
+ /** JSON structure for company.identity field */
67
+ export interface CompanyIdentity {
68
+ primaryCIK?: string;
69
+ ciks?: string;
70
+ tickers?: string;
71
+ exchanges?: string;
72
+ sp500?: boolean;
73
+ lei?: string;
74
+ duns?: string;
75
+ entityType?: string;
76
+ sic?: string;
77
+ sicDescription?: string;
78
+ ein?: string;
79
+ category?: string;
80
+ ownerOrg?: string;
81
+ }
82
+
83
+ /** Company with properly typed `type` (enum) and `identity` (JSON) */
84
+ export interface Company extends Omit<CompanyRaw, "type" | "identity"> {
85
+ type: CompanyTypeValue;
86
+ identity?: CompanyIdentity;
87
+ }
88
+
89
+ /** ParentOfEdge with properly typed `source` (enum) */
90
+ export interface ParentOfEdge extends Omit<ParentOfEdgeRaw, "source"> {
91
+ source: ParentOfSourceValue;
92
+ }
93
+
94
+ /** JSON structure for audit.fields_changed array items */
95
+ export interface FieldChange {
96
+ field: string;
97
+ old_value: unknown;
98
+ new_value: unknown;
99
+ }
100
+
101
+ /** Audit with properly typed `fields_changed` (JSON array) */
102
+ export interface AuditWithChanges extends Omit<Audit, "fields_changed"> {
103
+ fields_changed: FieldChange[];
104
+ }
105
+
106
+ // ============================================================================
107
+ // FIELD VALIDATORS (business logic InstantDB can't express)
108
+ // ============================================================================
109
+
110
+ export const NonEmptyString = z.string().min(1);
111
+ export const IntNumber = z.number().int();
112
+
113
+ /** CIK: 1-10 digit numeric string, normalized to 10 digits with leading zeros */
114
+ export const CIKString = z
115
+ .string()
116
+ .regex(/^\d{1,10}$/, "CIK must be 1-10 digits")
117
+ .transform((val) => val.trim().padStart(10, "0"));
118
+
119
+ /**
120
+ * Accession Number: SEC filing identifier
121
+ * Format: XXXXXXXXXX-XX-XXXXXX (with dashes) or XXXXXXXXXXXXXXXXXX (without)
122
+ * Normalized by removing dashes
123
+ */
124
+ export const AccessionNumberString = z
125
+ .string()
126
+ .min(1, "Accession number is required")
127
+ .transform((val) => val.replace(/-/g, ""));
128
+
129
+ /** Jurisdiction: rejects numbers/percentages (common parsing errors) */
130
+ export const JurisdictionString = z.string().refine(
131
+ (val) => {
132
+ const trimmed = val.trim();
133
+ if (/^\d+(\.\d+)?$/.test(trimmed)) return false;
134
+ if (/^\d+(\.\d+)?%$/.test(trimmed)) return false;
135
+ return true;
136
+ },
137
+ { message: "Jurisdiction cannot be a number or percentage" },
138
+ );
139
+
140
+ // ============================================================================
141
+ // COMPANY VALIDATION (type-specific rules)
142
+ // ============================================================================
143
+
144
+ const CompanyIdentitySchema = z.object({
145
+ primaryCIK: CIKString.optional(),
146
+ ciks: z.string().optional(),
147
+ tickers: z.string().optional(),
148
+ exchanges: z.string().optional(),
149
+ sp500: z.boolean().optional(),
150
+ lei: z.string().length(20).optional(),
151
+ duns: z.string().length(9).optional(),
152
+ entityType: z.string().optional(),
153
+ sic: z.string().optional(),
154
+ sicDescription: z.string().optional(),
155
+ ein: z.string().optional(),
156
+ category: z.string().optional(),
157
+ ownerOrg: z.string().optional(),
158
+ });
159
+
160
+ /** PUBLIC company: requires name, identity required */
161
+ export const PublicCompanySchema = z.object({
162
+ type: z.literal(CompanyType.PUBLIC),
163
+ name: NonEmptyString,
164
+ identity: CompanyIdentitySchema,
165
+ jurisdiction_raw: z.string().optional(),
166
+ });
167
+
168
+ /** PRIVATE company: requires name + jurisdiction, identity optional */
169
+ export const PrivateCompanySchema = z.object({
170
+ type: z.literal(CompanyType.PRIVATE),
171
+ name: NonEmptyString,
172
+ jurisdiction_raw: JurisdictionString,
173
+ identity: CompanyIdentitySchema.optional(),
174
+ });
175
+
176
+ /** ISSUER company: requires name, identity required */
177
+ export const IssuerCompanySchema = z.object({
178
+ type: z.literal(CompanyType.ISSUER),
179
+ name: NonEmptyString,
180
+ identity: CompanyIdentitySchema,
181
+ jurisdiction_raw: z.string().optional(),
182
+ });
183
+
184
+ /** UNKNOWN company: requires name, jurisdiction optional, identity optional */
185
+ export const UnknownCompanySchema = z.object({
186
+ type: z.literal(CompanyType.UNKNOWN),
187
+ name: NonEmptyString,
188
+ jurisdiction_raw: JurisdictionString.optional(),
189
+ identity: CompanyIdentitySchema.optional(),
190
+ });
191
+
192
+ /** TRUST company: requires name, identity optional */
193
+ export const TrustCompanySchema = z.object({
194
+ type: z.literal(CompanyType.TRUST),
195
+ name: NonEmptyString,
196
+ jurisdiction_raw: z.string().optional(),
197
+ identity: CompanyIdentitySchema.optional(),
198
+ });
199
+
200
+ /** Company validation by type */
201
+ export const CompanySchema = z.discriminatedUnion("type", [
202
+ PublicCompanySchema,
203
+ PrivateCompanySchema,
204
+ IssuerCompanySchema,
205
+ UnknownCompanySchema,
206
+ TrustCompanySchema,
207
+ ]);
208
+
209
+ // ============================================================================
210
+ // ID GENERATION PARAMS (for composite key generation)
211
+ // ============================================================================
212
+
213
+ export const ParentOfParamsSchema = z.object({
214
+ parentId: NonEmptyString,
215
+ subsidiaryId: NonEmptyString,
216
+ establishedDate: NonEmptyString.optional(),
217
+ });
218
+
219
+ export const SubsidiaryEnrichmentParamsSchema = z.object({
220
+ companyId: NonEmptyString,
221
+ filingId: NonEmptyString,
222
+ });
223
+
224
+ export const BusinessSegmentParamsSchema = z.object({
225
+ companyId: NonEmptyString,
226
+ segmentName: NonEmptyString,
227
+ fiscalYear: IntNumber,
228
+ fiscalQuarter: IntNumber.nullable(),
229
+ });
230
+
231
+ export const BrandParamsSchema = z.object({
232
+ companyId: NonEmptyString,
233
+ name: NonEmptyString,
234
+ });
235
+
236
+ export const OwnsParamsSchema = z.object({
237
+ companyId: NonEmptyString,
238
+ brandId: NonEmptyString,
239
+ });
240
+
241
+ // ============================================================================
242
+ // TYPE GUARDS
243
+ // ============================================================================
244
+
245
+ export function isPublicCompany(company: Company): boolean {
246
+ return (
247
+ company.type === CompanyType.PUBLIC || company.type === CompanyType.ISSUER
248
+ );
249
+ }
250
+
251
+ export function isPrivateCompany(company: Company): boolean {
252
+ return company.type === CompanyType.PRIVATE;
253
+ }
254
+
255
+ export function isFromSecFiling(edge: ParentOfEdge): boolean {
256
+ return edge.source === ParentOfSource.SEC_FILING;
257
+ }
258
+
259
+ // ============================================================================
260
+ // VALIDATION HELPERS
261
+ // ============================================================================
262
+
263
+ export function validate<T>(
264
+ schema: z.ZodSchema<T>,
265
+ data: unknown,
266
+ schemaName?: string,
267
+ ): T {
268
+ try {
269
+ return schema.parse(data);
270
+ } catch (error) {
271
+ if (error instanceof z.ZodError) {
272
+ const errors = error.issues
273
+ .map((e) => `${e.path.join(".")}: ${e.message}`)
274
+ .join(", ");
275
+ throw new Error(
276
+ `Validation failed${schemaName ? ` for ${schemaName}` : ""}: ${errors}`,
277
+ );
278
+ }
279
+ throw error;
280
+ }
281
+ }
282
+
283
+ export function safeValidate<T>(
284
+ schema: z.ZodSchema<T>,
285
+ data: unknown,
286
+ ): { success: true; data: T } | { success: false; error: z.ZodError } {
287
+ const result = schema.safeParse(data);
288
+ if (result.success) {
289
+ return { success: true, data: result.data };
290
+ }
291
+ return { success: false, error: result.error };
292
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Validation Re-exports (backward compatibility)
3
+ *
4
+ * For new code, import directly from "./types"
5
+ */
6
+
7
+ export {
8
+ // Field validators
9
+ NonEmptyString,
10
+ IntNumber,
11
+ CIKString,
12
+ JurisdictionString,
13
+
14
+ // Company validation (type-specific rules)
15
+ CompanySchema,
16
+ PublicCompanySchema,
17
+ PrivateCompanySchema,
18
+ IssuerCompanySchema,
19
+ UnknownCompanySchema,
20
+
21
+ // ID generation params
22
+ AccessionNumberString,
23
+ ParentOfParamsSchema,
24
+ SubsidiaryEnrichmentParamsSchema,
25
+ BusinessSegmentParamsSchema,
26
+ BrandParamsSchema,
27
+ OwnsParamsSchema,
28
+
29
+ // Helpers
30
+ validate,
31
+ safeValidate,
32
+ } from "./types";