@newhomestar/sdk 0.8.16 → 0.8.18
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 +1187 -1187
- package/dist/credentials.js +48 -0
- package/dist/events.js +18 -0
- package/package.json +64 -64
package/dist/credentials.js
CHANGED
|
@@ -190,6 +190,54 @@ async function performTokenExchange(slug, params) {
|
|
|
190
190
|
async function fetchCredentialsFromAuthServer(authBaseUrl, slug, bearerToken, forceRefresh = false) {
|
|
191
191
|
const url = `${authBaseUrl}/api/integrations/${encodeURIComponent(slug)}/credentials`;
|
|
192
192
|
console.log(`[nova-sdk] 🌐 Fetching credentials via HTTP: GET ${url}${forceRefresh ? " (force-refresh)" : ""}`);
|
|
193
|
+
// ── Outgoing bearer-token preview ──────────────────────────────────────────
|
|
194
|
+
// We log the JWT's structural claims (NOT the signature, NOT secrets) so we
|
|
195
|
+
// can correlate the SDK's outgoing token against what the auth server says
|
|
196
|
+
// it received on the other side. This is invaluable when diagnosing 401s
|
|
197
|
+
// from `resolveCredentialsViaServiceToken` (the relay path).
|
|
198
|
+
try {
|
|
199
|
+
const parts = bearerToken.split(".");
|
|
200
|
+
if (parts.length === 3) {
|
|
201
|
+
// base64url → JSON. atob handles base64; we normalize url-safe chars first.
|
|
202
|
+
const b64urlDecode = (s) => {
|
|
203
|
+
const b64 = s.replace(/-/g, "+").replace(/_/g, "/");
|
|
204
|
+
// Pad to a multiple of 4
|
|
205
|
+
const padded = b64 + "=".repeat((4 - (b64.length % 4)) % 4);
|
|
206
|
+
if (typeof Buffer !== "undefined") {
|
|
207
|
+
return Buffer.from(padded, "base64").toString("utf8");
|
|
208
|
+
}
|
|
209
|
+
// Browser-safe fallback
|
|
210
|
+
// eslint-disable-next-line no-undef
|
|
211
|
+
return decodeURIComponent(escape(atob(padded)));
|
|
212
|
+
};
|
|
213
|
+
const header = JSON.parse(b64urlDecode(parts[0]));
|
|
214
|
+
const payload = JSON.parse(b64urlDecode(parts[1]));
|
|
215
|
+
console.log(`[nova-sdk] 🪪 Outgoing bearer header:`, {
|
|
216
|
+
alg: header.alg,
|
|
217
|
+
typ: header.typ,
|
|
218
|
+
kid: header.kid,
|
|
219
|
+
});
|
|
220
|
+
console.log(`[nova-sdk] 🪪 Outgoing bearer payload preview:`, {
|
|
221
|
+
iss: payload.iss,
|
|
222
|
+
aud: payload.aud,
|
|
223
|
+
sub: payload.sub,
|
|
224
|
+
client_id: payload.client_id,
|
|
225
|
+
scope: payload.scope,
|
|
226
|
+
service_name: payload.service_name,
|
|
227
|
+
exp: payload.exp,
|
|
228
|
+
iat: payload.iat,
|
|
229
|
+
secondsUntilExp: typeof payload.exp === "number"
|
|
230
|
+
? payload.exp - Math.floor(Date.now() / 1000)
|
|
231
|
+
: null,
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
console.log(`[nova-sdk] 🪪 Outgoing bearer is NOT a 3-part JWT (parts=${parts.length}, length=${bearerToken.length}). This is expected if the SDK is using INTERNAL_API_SECRET as a service token.`);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
catch (decodeErr) {
|
|
239
|
+
console.warn(`[nova-sdk] ⚠️ Failed to decode outgoing bearer for preview:`, decodeErr instanceof Error ? decodeErr.message : String(decodeErr));
|
|
240
|
+
}
|
|
193
241
|
const headers = {
|
|
194
242
|
Authorization: `Bearer ${bearerToken}`,
|
|
195
243
|
Accept: "application/json",
|
package/dist/events.js
CHANGED
|
@@ -257,9 +257,21 @@ export async function withServiceEventOutbox(db, reqOrCallback, maybeCallback) {
|
|
|
257
257
|
for (const staged of stagedEmits) {
|
|
258
258
|
// Pass the topic directly as event_slug — no decomposition needed.
|
|
259
259
|
// The Events Service uses event_slug to look up the event_type and fan-out.
|
|
260
|
+
//
|
|
261
|
+
// Auto-derive entity_id from attributes.id when the producer's mapRow()
|
|
262
|
+
// puts the row's primary key there. This is the convention used across
|
|
263
|
+
// every Nova service route handler ({ id: row.id, ... }) and downstream
|
|
264
|
+
// consumers (integration write-back, decision logging) rely on entity_id
|
|
265
|
+
// to PATCH the correct row. Falls back to undefined when there is no
|
|
266
|
+
// string-typed `id` in the attributes (e.g. composite-key entities or
|
|
267
|
+
// system-level events).
|
|
268
|
+
const entityId = typeof staged.payload?.id === 'string'
|
|
269
|
+
? staged.payload.id
|
|
270
|
+
: undefined;
|
|
260
271
|
const fullPayload = {
|
|
261
272
|
event_slug: staged.topic,
|
|
262
273
|
source_service: serviceSlug ?? undefined,
|
|
274
|
+
entity_id: entityId,
|
|
263
275
|
attributes: staged.payload,
|
|
264
276
|
metadata: {
|
|
265
277
|
source: xSource,
|
|
@@ -582,9 +594,15 @@ export async function withWebhookEvent(db, opts, handler) {
|
|
|
582
594
|
result = await handler(tx, emit);
|
|
583
595
|
// ── 4. Write outbox rows for staged events ────────────────────────
|
|
584
596
|
for (const staged of stagedEmits) {
|
|
597
|
+
// Auto-derive entity_id from attributes.id — see the matching
|
|
598
|
+
// comment in withServiceEventOutbox for rationale.
|
|
599
|
+
const entityId = typeof staged.payload?.id === 'string'
|
|
600
|
+
? staged.payload.id
|
|
601
|
+
: undefined;
|
|
585
602
|
const fullPayload = {
|
|
586
603
|
event_slug: staged.topic,
|
|
587
604
|
source_service: serviceSlug ?? undefined,
|
|
605
|
+
entity_id: entityId,
|
|
588
606
|
attributes: staged.payload,
|
|
589
607
|
metadata: { source: 'webhook' },
|
|
590
608
|
};
|
package/package.json
CHANGED
|
@@ -1,64 +1,64 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@newhomestar/sdk",
|
|
3
|
-
"version": "0.8.
|
|
4
|
-
"description": "Type-safe SDK for building Nova pipelines (workers & functions)",
|
|
5
|
-
"homepage": "https://github.com/newhomestar/nova-node-sdk#readme",
|
|
6
|
-
"bugs": {
|
|
7
|
-
"url": "https://github.com/newhomestar/nova-node-sdk/issues"
|
|
8
|
-
},
|
|
9
|
-
"repository": {
|
|
10
|
-
"type": "git",
|
|
11
|
-
"url": "git+https://github.com/newhomestar/nova-node-sdk.git"
|
|
12
|
-
},
|
|
13
|
-
"license": "ISC",
|
|
14
|
-
"author": "Christian Gomez",
|
|
15
|
-
"type": "module",
|
|
16
|
-
"main": "dist/index.js",
|
|
17
|
-
"types": "dist/index.d.ts",
|
|
18
|
-
"exports": {
|
|
19
|
-
".": {
|
|
20
|
-
"import": "./dist/index.js",
|
|
21
|
-
"types": "./dist/index.d.ts"
|
|
22
|
-
},
|
|
23
|
-
"./next": {
|
|
24
|
-
"import": "./dist/next.js",
|
|
25
|
-
"types": "./dist/next.d.ts"
|
|
26
|
-
},
|
|
27
|
-
"./events": {
|
|
28
|
-
"import": "./dist/events.js",
|
|
29
|
-
"types": "./dist/events.d.ts"
|
|
30
|
-
},
|
|
31
|
-
"./connections": {
|
|
32
|
-
"import": "./dist/connections.js",
|
|
33
|
-
"types": "./dist/connections.d.ts"
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
|
-
"files": [
|
|
37
|
-
"dist"
|
|
38
|
-
],
|
|
39
|
-
"scripts": {
|
|
40
|
-
"build": "tsc"
|
|
41
|
-
},
|
|
42
|
-
"dependencies": {
|
|
43
|
-
"@openfga/sdk": "^0.9.0",
|
|
44
|
-
"@orpc/openapi": "1.7.4",
|
|
45
|
-
"@orpc/server": "1.7.4",
|
|
46
|
-
"@supabase/supabase-js": "^2.39.0",
|
|
47
|
-
"body-parser": "^1.20.2",
|
|
48
|
-
"cors": "^2.8.6",
|
|
49
|
-
"dotenv": "^16.4.3",
|
|
50
|
-
"express": "^4.18.2",
|
|
51
|
-
"express-oauth2-jwt-bearer": "^1.7.4",
|
|
52
|
-
"undici": "^7.24.4",
|
|
53
|
-
"yaml": "^2.7.1"
|
|
54
|
-
},
|
|
55
|
-
"peerDependencies": {
|
|
56
|
-
"zod": ">=4.0.0"
|
|
57
|
-
},
|
|
58
|
-
"devDependencies": {
|
|
59
|
-
"@types/cors": "^2.8.19",
|
|
60
|
-
"@types/node": "^20.11.17",
|
|
61
|
-
"typescript": "^5.4.4",
|
|
62
|
-
"zod": "^4.3.0"
|
|
63
|
-
}
|
|
64
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@newhomestar/sdk",
|
|
3
|
+
"version": "0.8.18",
|
|
4
|
+
"description": "Type-safe SDK for building Nova pipelines (workers & functions)",
|
|
5
|
+
"homepage": "https://github.com/newhomestar/nova-node-sdk#readme",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/newhomestar/nova-node-sdk/issues"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/newhomestar/nova-node-sdk.git"
|
|
12
|
+
},
|
|
13
|
+
"license": "ISC",
|
|
14
|
+
"author": "Christian Gomez",
|
|
15
|
+
"type": "module",
|
|
16
|
+
"main": "dist/index.js",
|
|
17
|
+
"types": "dist/index.d.ts",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"import": "./dist/index.js",
|
|
21
|
+
"types": "./dist/index.d.ts"
|
|
22
|
+
},
|
|
23
|
+
"./next": {
|
|
24
|
+
"import": "./dist/next.js",
|
|
25
|
+
"types": "./dist/next.d.ts"
|
|
26
|
+
},
|
|
27
|
+
"./events": {
|
|
28
|
+
"import": "./dist/events.js",
|
|
29
|
+
"types": "./dist/events.d.ts"
|
|
30
|
+
},
|
|
31
|
+
"./connections": {
|
|
32
|
+
"import": "./dist/connections.js",
|
|
33
|
+
"types": "./dist/connections.d.ts"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"dist"
|
|
38
|
+
],
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsc"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@openfga/sdk": "^0.9.0",
|
|
44
|
+
"@orpc/openapi": "1.7.4",
|
|
45
|
+
"@orpc/server": "1.7.4",
|
|
46
|
+
"@supabase/supabase-js": "^2.39.0",
|
|
47
|
+
"body-parser": "^1.20.2",
|
|
48
|
+
"cors": "^2.8.6",
|
|
49
|
+
"dotenv": "^16.4.3",
|
|
50
|
+
"express": "^4.18.2",
|
|
51
|
+
"express-oauth2-jwt-bearer": "^1.7.4",
|
|
52
|
+
"undici": "^7.24.4",
|
|
53
|
+
"yaml": "^2.7.1"
|
|
54
|
+
},
|
|
55
|
+
"peerDependencies": {
|
|
56
|
+
"zod": ">=4.0.0"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@types/cors": "^2.8.19",
|
|
60
|
+
"@types/node": "^20.11.17",
|
|
61
|
+
"typescript": "^5.4.4",
|
|
62
|
+
"zod": "^4.3.0"
|
|
63
|
+
}
|
|
64
|
+
}
|