@major-tech/resource-client 0.1.3 → 0.1.5

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 CHANGED
@@ -1,90 +1,162 @@
1
1
  # @major-tech/resource-client
2
2
 
3
- TypeScript client for Major resources (PostgreSQL, Custom APIs, HubSpot, S3). Type-safe, zero dependencies, universal (Node/browser/edge), ESM & CJS.
3
+ TS client: PostgreSQL/CustomAPI/HubSpot/S3. Type-safe, 0-dep, universal (Node/browser/edge), ESM+CJS.
4
4
 
5
5
  ## Install
6
6
  ```bash
7
- pnpm install @major-tech/resource-client
7
+ pnpm add @major-tech/resource-client
8
8
  ```
9
9
 
10
- ## Usage
11
-
12
- **Config (all clients):**
10
+ ## Config (All Clients)
13
11
  ```typescript
14
12
  { baseUrl: string; applicationId: string; resourceId: string; majorJwtToken?: string; fetch?: typeof fetch }
15
13
  ```
16
14
 
17
- **Response:** `{ ok: true; requestId: string; result: T } | { ok: false; requestId: string; error: { message: string; httpStatus?: number } }`
15
+ ## Response Format
16
+ ```typescript
17
+ { ok: true; requestId: string; result: T } | { ok: false; requestId: string; error: { message: string; httpStatus?: number } }
18
+ ```
19
+
20
+ ## PostgresResourceClient
21
+
22
+ **Constructor:** `new PostgresResourceClient(config: BaseClientConfig)`
18
23
 
19
- **PostgreSQL:**
24
+ **Method:** `invoke(sql: string, params: DbParamPrimitive[] | undefined, invocationKey: string, timeoutMs?: number): Promise<DatabaseInvokeResponse>`
25
+
26
+ **Params:**
27
+ - `sql`: SQL query string
28
+ - `params`: `(string | number | boolean | null)[]` - positional params ($1, $2, etc)
29
+ - `invocationKey`: unique operation ID (regex: `[a-zA-Z0-9][a-zA-Z0-9._:-]*`)
30
+ - `timeoutMs`: optional timeout
31
+
32
+ **Result (ok=true):**
33
+ ```typescript
34
+ { kind: "database"; rows: Record<string, unknown>[]; rowsAffected?: number }
35
+ ```
36
+
37
+ **Example:**
20
38
  ```typescript
21
39
  import { PostgresResourceClient } from '@major-tech/resource-client';
22
- const client = new PostgresResourceClient({ baseUrl, applicationId, resourceId, majorJwtToken? });
23
- const res = await client.invoke('SELECT * FROM users WHERE id = $1', [123], 'fetch-user-by-id');
24
- // res.ok ? res.result.rows / res.result.rowsAffected : res.error.message
40
+ const c = new PostgresResourceClient({ baseUrl, applicationId, resourceId, majorJwtToken });
41
+ const r = await c.invoke('SELECT * FROM users WHERE id = $1', [123], 'fetch-user');
42
+ // r.ok ? r.result.rows : r.error.message
43
+ ```
44
+
45
+ ## CustomApiResourceClient
46
+
47
+ **Constructor:** `new CustomApiResourceClient(config: BaseClientConfig)`
48
+
49
+ **Method:** `invoke(method: HttpMethod, path: string, invocationKey: string, options?: { query?: QueryParams; headers?: Record<string, string>; body?: BodyPayload; timeoutMs?: number }): Promise<ApiInvokeResponse>`
50
+
51
+ **Params:**
52
+ - `method`: `"GET" | "POST" | "PUT" | "PATCH" | "DELETE"`
53
+ - `path`: URL path (appended to resource baseUrl)
54
+ - `invocationKey`: unique operation ID
55
+ - `options.query`: `Record<string, string | string[]>` - query params
56
+ - `options.headers`: `Record<string, string>` - additional headers
57
+ - `options.body`: `{ type: "json"; value: unknown } | { type: "text"; value: string } | { type: "bytes"; base64: string; contentType: string }`
58
+ - `options.timeoutMs`: timeout (default: 30000)
59
+
60
+ **Result (ok=true):**
61
+ ```typescript
62
+ { kind: "api"; status: number; body: { kind: "json"; value: unknown } | { kind: "text"; value: string } | { kind: "bytes"; base64: string; contentType: string } }
25
63
  ```
26
64
 
27
- **Custom API:**
65
+ **Example:**
28
66
  ```typescript
29
67
  import { CustomApiResourceClient } from '@major-tech/resource-client';
30
- const client = new CustomApiResourceClient({ baseUrl, applicationId, resourceId });
31
- const res = await client.invoke('POST', '/v1/payments', 'create-payment', {
32
- query: { currency: 'USD' }, headers: { 'X-Custom': 'value' },
33
- body: { type: 'json', value: { amount: 100 } }, timeoutMs: 5000
68
+ const c = new CustomApiResourceClient({ baseUrl, applicationId, resourceId });
69
+ const r = await c.invoke('POST', '/v1/pay', 'create-pay', {
70
+ query: { currency: 'USD' }, headers: { 'X-Key': 'val' },
71
+ body: { type: 'json', value: { amt: 100 } }, timeoutMs: 5000
34
72
  });
35
- // res.ok ? res.result.status / res.result.body : res.error
73
+ // r.ok ? r.result.status : r.error
36
74
  ```
37
75
 
38
- **HubSpot:**
76
+ ## HubSpotResourceClient
77
+
78
+ **Constructor:** `new HubSpotResourceClient(config: BaseClientConfig)`
79
+
80
+ **Method:** `invoke(method: HttpMethod, path: string, invocationKey: string, options?: { query?: QueryParams; body?: { type: "json"; value: unknown }; timeoutMs?: number }): Promise<ApiInvokeResponse>`
81
+
82
+ **Params:**
83
+ - `method`: `"GET" | "POST" | "PUT" | "PATCH" | "DELETE"`
84
+ - `path`: HubSpot API path
85
+ - `invocationKey`: unique operation ID
86
+ - `options.query`: `Record<string, string | string[]>`
87
+ - `options.body`: `{ type: "json"; value: unknown }` - JSON only
88
+ - `options.timeoutMs`: timeout (default: 30000)
89
+
90
+ **Result:** Same as CustomApiResourceClient
91
+
92
+ **Example:**
39
93
  ```typescript
40
94
  import { HubSpotResourceClient } from '@major-tech/resource-client';
41
- const client = new HubSpotResourceClient({ baseUrl, applicationId, resourceId });
42
- const res = await client.invoke('GET', '/crm/v3/objects/contacts', 'fetch-contacts', { query: { limit: '10' } });
43
- // res.ok && res.result.body.kind === 'json' ? res.result.body.value : res.error
95
+ const c = new HubSpotResourceClient({ baseUrl, applicationId, resourceId });
96
+ const r = await c.invoke('GET', '/crm/v3/objects/contacts', 'fetch-contacts', { query: { limit: '10' } });
97
+ // r.ok && r.result.body.kind === 'json' ? r.result.body.value : r.error
44
98
  ```
45
99
 
46
- **S3:**
100
+ ## S3ResourceClient
101
+
102
+ **Constructor:** `new S3ResourceClient(config: BaseClientConfig)`
103
+
104
+ **Method:** `invoke(command: S3Command, params: Record<string, unknown>, invocationKey: string, options?: { timeoutMs?: number }): Promise<StorageInvokeResponse>`
105
+
106
+ **Params:**
107
+ - `command`: `"ListObjectsV2" | "HeadObject" | "GetObjectTagging" | "PutObjectTagging" | "DeleteObject" | "DeleteObjects" | "CopyObject" | "ListBuckets" | "GetBucketLocation" | "GeneratePresignedUrl"`
108
+ - `params`: Command-specific params (e.g., `{ Bucket, Prefix, Key, expiresIn }`)
109
+ - `invocationKey`: unique operation ID
110
+ - `options.timeoutMs`: optional timeout
111
+
112
+ **Result (ok=true):**
113
+ ```typescript
114
+ { kind: "storage"; command: string; data: unknown } | { kind: "storage"; presignedUrl: string; expiresAt: string }
115
+ ```
116
+ - Standard commands return `{ kind: "storage"; command; data }`
117
+ - `GeneratePresignedUrl` returns `{ kind: "storage"; presignedUrl; expiresAt }`
118
+
119
+ **Example:**
47
120
  ```typescript
48
121
  import { S3ResourceClient } from '@major-tech/resource-client';
49
- const client = new S3ResourceClient({ baseUrl, applicationId, resourceId });
50
- const res = await client.invoke('ListObjectsV2', { Bucket: 'my-bucket', Prefix: 'uploads/' }, 'list-uploads');
51
- // res.ok ? res.result.data : res.error
52
- const url = await client.invoke('GeneratePresignedUrl', { Bucket: 'my-bucket', Key: 'file.pdf', expiresIn: 3600 }, 'presigned-url');
53
- // url.ok && 'presignedUrl' in url.result ? url.result.presignedUrl / url.result.expiresAt : url.error
122
+ const c = new S3ResourceClient({ baseUrl, applicationId, resourceId });
123
+ const r = await c.invoke('ListObjectsV2', { Bucket: 'my-bucket', Prefix: 'uploads/' }, 'list-uploads');
124
+ // r.ok ? r.result.data : r.error
125
+ const u = await c.invoke('GeneratePresignedUrl', { Bucket: 'my-bucket', Key: 'file.pdf', expiresIn: 3600 }, 'presigned');
126
+ // u.ok && 'presignedUrl' in u.result ? u.result.presignedUrl : u.error
54
127
  ```
55
128
 
56
- **Error Handling:**
129
+ ## Error Handling
57
130
  ```typescript
58
131
  import { ResourceInvokeError } from '@major-tech/resource-client';
59
132
  try { await client.invoke(...); }
60
133
  catch (e) { if (e instanceof ResourceInvokeError) { e.message, e.httpStatus, e.requestId } }
61
134
  ```
62
135
 
63
- **Invocation Keys:** Unique operation identifiers for tracking (format: `[a-zA-Z0-9][a-zA-Z0-9._:-]*`). Examples: `fetch-user-by-id`, `create-payment`, `hubspot:get-contacts`, `s3.list-uploads`
64
-
65
- **Types:** All exported: `BaseClientConfig`, `DatabaseInvokeResponse`, `ApiInvokeResponse`, `StorageInvokeResponse`, `HttpMethod`, `QueryParams`, `BodyPayload`, `S3Command`, etc.
136
+ ## CLI - Singleton Generator
66
137
 
67
- ## 🛠️ CLI Tool - Generate Singleton Clients
138
+ **Commands:**
139
+ - `npx major-client add <resourceId> <name> <type> <desc> <appId>` - Add resource, generate singleton
140
+ - `npx major-client list` - List all resources
141
+ - `npx major-client remove <name>` - Remove resource
142
+ - `npx major-client regenerate` - Regenerate all clients
68
143
 
69
- The package includes a CLI tool to generate pre-configured singleton clients for your resources:
144
+ **Types:** `database-postgresql | api-custom | api-hubspot | storage-s3`
70
145
 
71
- ```bash
72
- # Add a resource
73
- npx major-client add "resource-123" "orders-db" "database-postgresql" "Orders database" "app-456"
146
+ **Generated Files:**
147
+ - `resources.json` - Resource registry
148
+ - `src/clients/<name>.ts` - Singleton client
149
+ - `src/clients/index.ts` - Exports
74
150
 
75
- # List all resources
76
- npx major-client list
151
+ **Env Vars:** `MAJOR_API_BASE_URL`, `MAJOR_JWT_TOKEN`
77
152
 
78
- # Remove a resource
79
- npx major-client remove "orders-db"
153
+ **Example:**
154
+ ```bash
155
+ npx major-client add "res_123" "orders-db" "database-postgresql" "Orders DB" "app_456"
80
156
  ```
81
-
82
- This generates TypeScript files in `src/clients/` that you can import:
83
157
  ```typescript
84
158
  import { ordersDbClient } from './clients';
85
- const result = await ordersDbClient.invoke('SELECT * FROM orders', [], 'list-orders');
159
+ const r = await ordersDbClient.invoke('SELECT * FROM orders', [], 'list-orders');
86
160
  ```
87
161
 
88
- **Types:** `database-postgresql` | `api-custom` | `api-hubspot` | `storage-s3`
89
-
90
162
  MIT License
@@ -45,7 +45,7 @@ function clientTemplate(data) {
45
45
  * DO NOT EDIT - Auto-generated by @major-tech/resource-client
46
46
  */
47
47
 
48
- const BASE_URL = import.meta.env.MAJOR_API_BASE_URL || 'https://api.major.tech';
48
+ const BASE_URL = import.meta.env.MAJOR_API_BASE_URL || 'https://api.prod.major.build';
49
49
  const MAJOR_JWT_TOKEN = import.meta.env.MAJOR_JWT_TOKEN;
50
50
 
51
51
  class ${data.clientName}Singleton {
@@ -58,6 +58,7 @@ class ${data.clientName}Singleton {
58
58
  majorJwtToken: MAJOR_JWT_TOKEN,
59
59
  applicationId: '${data.applicationId}',
60
60
  resourceId: '${data.resourceId}',
61
+ fetch: (...args) => fetch(...args),
61
62
  });
62
63
  }
63
64
  return ${data.clientName}Singleton.instance;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@major-tech/resource-client",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "TypeScript client library for invoking Major resources (PostgreSQL, Custom APIs, HubSpot, S3)",
5
5
  "type": "module",
6
6
  "sideEffects": false,