@chatarmin/os 1.5.8 → 1.7.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 (58) hide show
  1. package/README.md +36 -122
  2. package/dist/companies/client.d.ts +8 -0
  3. package/dist/companies/client.d.ts.map +1 -0
  4. package/dist/companies/client.js +8 -0
  5. package/dist/companies/index.d.ts +3 -0
  6. package/dist/companies/index.d.ts.map +1 -0
  7. package/dist/companies/index.js +1 -0
  8. package/dist/companies/types.d.ts +66 -0
  9. package/dist/companies/types.d.ts.map +1 -0
  10. package/dist/index.d.ts +348 -245
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +194 -133
  13. package/dist/webhooks/constants.d.ts +5 -0
  14. package/dist/webhooks/constants.d.ts.map +1 -0
  15. package/dist/webhooks/constants.js +4 -0
  16. package/dist/webhooks/construct-event.d.ts +3 -0
  17. package/dist/webhooks/construct-event.d.ts.map +1 -0
  18. package/dist/webhooks/construct-event.js +64 -0
  19. package/dist/webhooks/errors.d.ts +4 -0
  20. package/dist/webhooks/errors.d.ts.map +1 -0
  21. package/dist/webhooks/errors.js +6 -0
  22. package/dist/webhooks/generate-test-headers.d.ts +3 -0
  23. package/dist/webhooks/generate-test-headers.d.ts.map +1 -0
  24. package/dist/webhooks/generate-test-headers.js +11 -0
  25. package/dist/webhooks/index.d.ts +16 -0
  26. package/dist/webhooks/index.d.ts.map +1 -0
  27. package/dist/webhooks/index.js +14 -0
  28. package/dist/webhooks/read-header.d.ts +3 -0
  29. package/dist/webhooks/read-header.d.ts.map +1 -0
  30. package/dist/webhooks/read-header.js +16 -0
  31. package/dist/webhooks/signing.d.ts +4 -0
  32. package/dist/webhooks/signing.d.ts.map +1 -0
  33. package/dist/webhooks/signing.js +16 -0
  34. package/dist/webhooks/types.d.ts +30 -0
  35. package/dist/webhooks/types.d.ts.map +1 -0
  36. package/package.json +10 -5
  37. package/CHANGELOG.md +0 -21
  38. package/dist/billing-get-dashboard-context.d.ts +0 -16
  39. package/dist/billing-get-dashboard-context.d.ts.map +0 -1
  40. package/dist/billing-get-dashboard-context.js +0 -7
  41. package/dist/chatarmin-os-billing-namespace.d.ts +0 -122
  42. package/dist/chatarmin-os-billing-namespace.d.ts.map +0 -1
  43. package/dist/chatarmin-os-billing-namespace.js +0 -24
  44. package/dist/features-list-for-product.d.ts +0 -26
  45. package/dist/features-list-for-product.d.ts.map +0 -1
  46. package/dist/features-list-for-product.js +0 -17
  47. package/dist/types/billing-dashboard-context.d.ts +0 -33
  48. package/dist/types/billing-dashboard-context.d.ts.map +0 -1
  49. package/dist/types/chatarmin-os-billing-inputs.d.ts +0 -90
  50. package/dist/types/chatarmin-os-billing-inputs.d.ts.map +0 -1
  51. package/dist/types/feature-access-list-item.d.ts +0 -7
  52. package/dist/types/feature-access-list-item.d.ts.map +0 -1
  53. package/dist/types/feature-access-list-item.js +0 -1
  54. package/dist/types/product-feature-catalog.d.ts +0 -24
  55. package/dist/types/product-feature-catalog.d.ts.map +0 -1
  56. package/dist/types/product-feature-catalog.js +0 -1
  57. /package/dist/{types/billing-dashboard-context.js → companies/types.js} +0 -0
  58. /package/dist/{types/chatarmin-os-billing-inputs.js → webhooks/types.js} +0 -0
package/README.md CHANGED
@@ -30,8 +30,8 @@
30
30
  - [Subscriptions & Tiers](#subscriptions--tiers)
31
31
  - [Links](#links)
32
32
  - [Onboarding](#onboarding)
33
+ - [Product Webhooks](#product-webhooks)
33
34
  - [Common Patterns](#common-patterns)
34
- - [Changelog](#changelog)
35
35
  - [TypeScript Support](#typescript-support)
36
36
  - [Configuration](#configuration)
37
37
  - [Error Handling](#error-handling)
@@ -75,7 +75,7 @@ const result = await os.onboard({
75
75
  })
76
76
 
77
77
  console.log(result.companyId) // Use this for all future API calls
78
- console.log(result.linkStatus) // 'created' | 'linked' | 'already_linked'
78
+ console.log(result.linkStatus) // 'created' | 'already_linked'
79
79
  ```
80
80
 
81
81
  ---
@@ -86,12 +86,12 @@ console.log(result.linkStatus) // 'created' | 'linked' | 'already_linked'
86
86
 
87
87
  Manage customer companies and their links to your product.
88
88
 
89
- #### `companies.getByProductLink(input)`
89
+ #### `companies.get(input)`
90
90
 
91
- Look up a company by your external organization ID.
91
+ Look up a company by your external organization ID or ChatarminOS company ID.
92
92
 
93
93
  ```typescript
94
- const company = await os.companies.getByProductLink({
94
+ const company = await os.companies.get({
95
95
  externalOrgId: "org_abc123",
96
96
  })
97
97
 
@@ -132,48 +132,6 @@ await os.companies.update({
132
132
  })
133
133
  ```
134
134
 
135
- #### `companies.smartLink(input)`
136
-
137
- Intelligently find and link a company using hints.
138
-
139
- ```typescript
140
- const result = await os.companies.smartLink({
141
- externalOrgId: "org_abc123",
142
- label: "My Product", // Display label for the product link (required)
143
- hints: {
144
- companyName: "Acme Inc",
145
- domain: "acme.com",
146
- emails: ["john@acme.com", "jane@acme.com"],
147
- },
148
- minConfidence: 0.7, // Default: 0.8
149
- })
150
-
151
- switch (result.status) {
152
- case "already_linked":
153
- console.log("Already linked to your product")
154
- break
155
- case "linked":
156
- console.log(
157
- `Auto-linked to ${result.customerName} (${result.confidence}% confidence)`
158
- )
159
- break
160
- case "suggestions":
161
- console.log("Multiple matches found:", result.suggestions)
162
- break
163
- case "no_match":
164
- console.log("No matching company found")
165
- break
166
- }
167
- ```
168
-
169
- **Matching priority:**
170
-
171
- 1. Domain match → 95% confidence
172
- 2. Name match → up to 80% confidence
173
- 3. Email domain match → 70% confidence
174
-
175
- ---
176
-
177
135
  ### Contacts
178
136
 
179
137
  Manage people associated with companies.
@@ -276,17 +234,6 @@ for (const f of features) {
276
234
  }
277
235
  ```
278
236
 
279
- #### `features.listForProduct(input?)`
280
-
281
- List **feature definitions** attached to your product (the API key’s product). No company id—use for catalog UI, empty states, or multi-feature shells. Inactive features are omitted unless you pass `{ includeInactive: true }`.
282
-
283
- ```typescript
284
- const defs = await os.features.listForProduct()
285
- for (const f of defs) {
286
- console.log(`${f.code}: ${f.name}${f.hasQuantity ? " (metered)" : ""}`)
287
- }
288
- ```
289
-
290
237
  #### `features.setAccess(input)`
291
238
 
292
239
  Update feature access with **partial config merge**.
@@ -347,34 +294,6 @@ if (access.canUse) {
347
294
 
348
295
  Track usage, claim subscriptions, and manage billing.
349
296
 
350
- #### `billing.getDashboardContext(input)`
351
-
352
- **Recommended** for billing/usage dashboards when you only have your tenant’s `externalOrgId`. One round-trip returns `companyId`, `productLinkId`, and an ordered list of features with usage, limits, optional Stripe `billing`, and `billingDegraded` when usage exists without a linked subscription item.
353
-
354
- Ordering uses `config_values.dashboard_order` or `dashboardOrder` when set; otherwise feature `displayOrder`.
355
-
356
- ```typescript
357
- const ctx = await os.billing.getDashboardContext({
358
- externalOrgId: "org_abc123",
359
- })
360
-
361
- console.log(ctx.companyId, ctx.productLinkId)
362
- for (const f of ctx.features) {
363
- console.log(
364
- f.featureCode,
365
- f.currentUsage,
366
- f.remaining,
367
- f.canUse,
368
- f.billingDegraded ? "(no Stripe period)" : "",
369
- f.billing?.currentPeriodEnd
370
- )
371
- }
372
- ```
373
-
374
- If the tenant is not linked, the call fails with `NOT_FOUND` (same message style as other `externalOrgId` flows).
375
-
376
- See [Changelog](#changelog) for migrating from `getByProductLink` + `listAccess` and hardcoded feature codes.
377
-
378
297
  #### `billing.trackUsage(input)`
379
298
 
380
299
  Track usage for a metered feature.
@@ -600,7 +519,7 @@ const result = await os.onboard({
600
519
  console.log({
601
520
  companyId: result.companyId,
602
521
  companyName: result.companyName,
603
- linkStatus: result.linkStatus, // 'created' | 'linked' | 'already_linked'
522
+ linkStatus: result.linkStatus, // 'created' | 'already_linked'
604
523
  tierApplied: result.billingStatus?.tierApplied,
605
524
  })
606
525
  ```
@@ -672,9 +591,6 @@ switch (result.linkStatus) {
672
591
  case "already_linked":
673
592
  console.log("Welcome back!")
674
593
  break
675
- case "linked":
676
- console.log("Found existing company, linked!")
677
- break
678
594
  case "created":
679
595
  console.log("New company created!")
680
596
  break
@@ -683,6 +599,36 @@ switch (result.linkStatus) {
683
599
 
684
600
  ---
685
601
 
602
+ ## Product Webhooks
603
+
604
+ When ChatarminOS pushes company and product-link changes to your app, verify the request with the SDK before handling the payload.
605
+
606
+ ```typescript
607
+ import { webhooks } from "@chatarmin/os/webhooks"
608
+
609
+ export async function POST(request: Request) {
610
+ const rawBody = await request.text()
611
+
612
+ const event = webhooks.constructEvent(
613
+ rawBody,
614
+ request.headers,
615
+ process.env.OS_WEBHOOK_SIGNING_SECRET!,
616
+ )
617
+
618
+ switch (`${event.type}.${event.action}`) {
619
+ case "company.updated":
620
+ // event.data, event.webhookId, event.idempotency_key
621
+ break
622
+ }
623
+
624
+ return Response.json({ received: true })
625
+ }
626
+ ```
627
+
628
+ Use `ChatarminOS.webhooks.constructEvent` if you already import the main client. Dedupe on `event.webhookId` or `event.idempotency_key`.
629
+
630
+ ---
631
+
686
632
  ## Common Patterns
687
633
 
688
634
  ### Feature Gating
@@ -784,15 +730,9 @@ import { ChatarminOS } from "@chatarmin/os"
784
730
  import type {
785
731
  ChatarminOSConfig,
786
732
  CreateCompanyInput,
787
- SmartLinkInput,
788
- SmartLinkResult,
789
733
  ContactInput,
790
734
  FeatureCheckInput,
791
735
  FeatureSetAccessInput,
792
- BillingDashboardContext,
793
- GetBillingDashboardContextInput,
794
- ListProductFeatureCatalogInput,
795
- ProductFeatureCatalogItem,
796
736
  TrackUsageInput,
797
737
  OnboardInput,
798
738
  OnboardResult,
@@ -871,32 +811,6 @@ try {
871
811
 
872
812
  ---
873
813
 
874
- ## Changelog
875
-
876
- Release notes live in **[CHANGELOG.md](./CHANGELOG.md)**.
877
-
878
- ### Dashboard context migration (PRD #194)
879
-
880
- **Before:** Resolve the company, then list access and filter client-side:
881
-
882
- ```typescript
883
- const company = await os.companies.getByProductLink({ externalOrgId })
884
- if (!company) {
885
- /* onboarding */
886
- }
887
- const rows = await os.features.listAccess({
888
- companyId: company.id,
889
- includeBillingDetails: true,
890
- })
891
- // Often: pick one featureCode in code, merge catalog labels manually
892
- ```
893
-
894
- **After:** Single product-key call keyed by tenant id; use `features.listForProduct()` for definition labels and `os.billing.getDashboardContext({ externalOrgId })` for per-tenant state. Server applies link disambiguation, row shape, optional `billing`, `billingDegraded`, and dashboard ordering from OS `config_values`.
895
-
896
- `features.listAccess` / `getAccessByExternalOrgId` remain supported; opt in when you need the new contract.
897
-
898
- ---
899
-
900
814
  ## Related Documentation
901
815
 
902
816
  - **[QUICKSTART.md](./QUICKSTART.md)** — Quick publishing & installation guide
@@ -0,0 +1,8 @@
1
+ import type { AppRouter } from '@chatarmin/api';
2
+ import type { createTRPCClient } from '@trpc/client';
3
+ import type { CompaniesClient } from './types';
4
+ type SdkClient = ReturnType<typeof createTRPCClient<AppRouter>>;
5
+ type SdkCall = <T>(operation: string, action: () => Promise<T>) => Promise<T>;
6
+ export declare function createCompaniesClient(client: SdkClient, call: SdkCall): CompaniesClient;
7
+ export {};
8
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/companies/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AACpD,OAAO,KAAK,EACV,eAAe,EAOhB,MAAM,SAAS,CAAA;AAEhB,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAA;AAC/D,KAAK,OAAO,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAA;AAE7E,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE,OAAO,GACZ,eAAe,CAiBjB"}
@@ -0,0 +1,8 @@
1
+ export function createCompaniesClient(client, call) {
2
+ return {
3
+ get: (input) => call('companies.get', () => client.companies.get.query(input)),
4
+ list: (input) => call('companies.list', () => client.companies.listForProduct.query(input ?? {})),
5
+ create: (input) => call('companies.create', () => client.companies.createWithLink.mutate(input)),
6
+ update: (input) => call('companies.update', () => client.companies.updateCompany.mutate(input)),
7
+ };
8
+ }
@@ -0,0 +1,3 @@
1
+ export { createCompaniesClient } from './client';
2
+ export type { CompaniesClient, CompanyAssignee, CompanyAssignees, CreateCompanyInput, CreateCompanyResult, GetCompanyInput, LinkedCompany, ListCompaniesInput, ListCompaniesResult, ListLinkedCompaniesInput, ListLinkedCompaniesResult, ProductCompany, UpdateCompanyResult, } from './types';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/companies/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAA;AAChD,YAAY,EACV,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,eAAe,EACf,aAAa,EACb,kBAAkB,EAClB,mBAAmB,EACnB,wBAAwB,EACxB,yBAAyB,EACzB,cAAc,EACd,mBAAmB,GACpB,MAAM,SAAS,CAAA"}
@@ -0,0 +1 @@
1
+ export { createCompaniesClient } from './client';
@@ -0,0 +1,66 @@
1
+ export interface CreateCompanyInput {
2
+ name: string;
3
+ domain?: string;
4
+ externalOrgId: string;
5
+ externalUserId?: string;
6
+ label?: string;
7
+ contactEmail?: string;
8
+ contactName?: string;
9
+ createdAt?: string;
10
+ }
11
+ export interface CompanyAssignee {
12
+ memberId: string;
13
+ displayName: string | null;
14
+ email: string | null;
15
+ }
16
+ export interface CompanyAssignees {
17
+ csm: CompanyAssignee | null;
18
+ sales: CompanyAssignee | null;
19
+ }
20
+ export interface ProductCompany {
21
+ id: string;
22
+ name: string;
23
+ shortId: string | null;
24
+ domain: string | null;
25
+ externalOrgId: string;
26
+ label: string | null;
27
+ externalUserId: string | null;
28
+ assignees: CompanyAssignees;
29
+ }
30
+ /** @deprecated Use ProductCompany */
31
+ export type LinkedCompany = ProductCompany;
32
+ export interface GetCompanyInput {
33
+ externalOrgId?: string;
34
+ companyId?: string;
35
+ }
36
+ export interface ListCompaniesInput {
37
+ limit?: number;
38
+ cursor?: string;
39
+ }
40
+ export interface ListCompaniesResult {
41
+ companies: ProductCompany[];
42
+ nextCursor?: string;
43
+ }
44
+ /** @deprecated Use ListCompaniesInput */
45
+ export type ListLinkedCompaniesInput = ListCompaniesInput;
46
+ /** @deprecated Use ListCompaniesResult */
47
+ export type ListLinkedCompaniesResult = ListCompaniesResult;
48
+ export interface CreateCompanyResult {
49
+ id: string;
50
+ shortId: string | null;
51
+ name: string;
52
+ externalOrgId: string;
53
+ }
54
+ export interface UpdateCompanyResult {
55
+ updated: boolean;
56
+ }
57
+ export interface CompaniesClient {
58
+ get: (input: GetCompanyInput) => Promise<ProductCompany | null>;
59
+ list: (input?: ListCompaniesInput) => Promise<ListCompaniesResult>;
60
+ create: (input: CreateCompanyInput) => Promise<CreateCompanyResult>;
61
+ update: (input: {
62
+ companyId: string;
63
+ createdAt?: string;
64
+ }) => Promise<UpdateCompanyResult>;
65
+ }
66
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/companies/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,aAAa,EAAE,MAAM,CAAA;IACrB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,eAAe,GAAG,IAAI,CAAA;IAC3B,KAAK,EAAE,eAAe,GAAG,IAAI,CAAA;CAC9B;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,aAAa,EAAE,MAAM,CAAA;IACrB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,SAAS,EAAE,gBAAgB,CAAA;CAC5B;AAED,qCAAqC;AACrC,MAAM,MAAM,aAAa,GAAG,cAAc,CAAA;AAE1C,MAAM,WAAW,eAAe;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,cAAc,EAAE,CAAA;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,yCAAyC;AACzC,MAAM,MAAM,wBAAwB,GAAG,kBAAkB,CAAA;AAEzD,0CAA0C;AAC1C,MAAM,MAAM,yBAAyB,GAAG,mBAAmB,CAAA;AAE3D,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,aAAa,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAA;IAC/D,IAAI,EAAE,CAAC,KAAK,CAAC,EAAE,kBAAkB,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAA;IAClE,MAAM,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAA;IACnE,MAAM,EAAE,CAAC,KAAK,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAA;CAC3F"}