@volter/twin-hubspot 0.1.0 → 0.1.2
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.
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
// PURE FRONTEND (R3): the mirror imports no handler and no twin internals — it MOUNTS the pack's
|
|
14
14
|
// fetch adapter as its API backend and reads every byte of state back over the wire.
|
|
15
15
|
import { readFile } from 'node:fs/promises';
|
|
16
|
-
import { bundleClient, fileResponse } from '@volter/world-core';
|
|
16
|
+
import { bundleClient, fileResponse, filePathOf } from '@volter/world-core';
|
|
17
17
|
import { serveHttp } from '@volter/world-core';
|
|
18
18
|
import { createHubspotTwinFetch } from "./hubspot-server.js";
|
|
19
|
-
const CLIENT_ENTRY = () => new URL('../client/hubspot-mirror.tsx', import.meta.url)
|
|
20
|
-
const CLIENT_CSS = () => new URL('../client/hubspot-mirror.css', import.meta.url)
|
|
19
|
+
const CLIENT_ENTRY = () => filePathOf(new URL('../client/hubspot-mirror.tsx', import.meta.url)); // lazy: workerd rejects top-level relative URL from import.meta.url (bundled via pack index)
|
|
20
|
+
const CLIENT_CSS = () => filePathOf(new URL('../client/hubspot-mirror.css', import.meta.url)); // lazy: workerd rejects top-level relative URL from import.meta.url (bundled via pack index)
|
|
21
21
|
/** The four record sections the mirror shows, keyed by HubSpot's own object-type path segment. */
|
|
22
22
|
export const MIRROR_SECTIONS = [
|
|
23
23
|
{ key: 'contacts', label: 'Contacts', path: '/crm/v3/objects/contacts?limit=100&properties=email,firstname,lastname,phone,lifecyclestage' },
|
package/dist/src/webhooks.js
CHANGED
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
// call and `API` otherwise, and `sourceId` is `userId:<id>` or `<appId>`; the v1 signature is sent on every event, which
|
|
25
25
|
// the page does not promise for a developer-platform app's `object.*` event.
|
|
26
26
|
import { createHash, createHmac } from 'node:crypto';
|
|
27
|
+
import { appDestination, appFetch } from '@volter/world-core/app-route';
|
|
27
28
|
import { worldEgressRefusal } from '@volter/world-core/network-policy';
|
|
28
29
|
import { appById, installsIn, keep, stored } from "./accounts.js";
|
|
29
30
|
import { currentPortal } from "./portal.js";
|
|
@@ -64,8 +65,9 @@ async function deliver(to, secret, events, hub, root, at) {
|
|
|
64
65
|
};
|
|
65
66
|
const n = stored('_webhook_delivery', root).length + 1;
|
|
66
67
|
await keep('_webhook_delivery', `delivery:${n}`, { n, to, portalId: hub, body, headers, delivered_at: at }, root, at);
|
|
67
|
-
|
|
68
|
-
|
|
68
|
+
// the application's own hostnames reach it inside the World; elsewhere, the World's egress rule decides
|
|
69
|
+
if (appDestination(to) || worldEgressRefusal(to) === null)
|
|
70
|
+
await appFetch(to, { method: 'POST', headers, body }).then((r) => r.text()).catch(() => undefined);
|
|
69
71
|
}
|
|
70
72
|
/** GET /_twin/deliveries?to=<url>: what an app's server received from HubSpot, oldest first — each request's headers,
|
|
71
73
|
* its body as sent, and the events in it. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/twin-hubspot",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Local HubSpot CRM twin — a faithful, stateful local HubSpot v3/v4 CRM API your @hubspot/api-client integration talks to unmodified. Mirror, simulate, and fork. Built on @volter/world-core.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"twin",
|
|
@@ -52,15 +52,15 @@
|
|
|
52
52
|
"postpack": "node ../../../scripts/publish/prepare-publish.mjs postpack"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@volter/world-ui": "0.1.
|
|
55
|
+
"@volter/world-ui": "0.1.2",
|
|
56
56
|
"react": "^19.2.7",
|
|
57
57
|
"react-dom": "^19.2.7"
|
|
58
58
|
},
|
|
59
59
|
"peerDependencies": {
|
|
60
|
-
"@volter/world-core": "2.0.
|
|
60
|
+
"@volter/world-core": "2.0.2"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
|
-
"@volter/world-core": "2.0.
|
|
63
|
+
"@volter/world-core": "2.0.2",
|
|
64
64
|
"@volter/world-tooling": "0.1.0",
|
|
65
65
|
"@hubspot/api-client": "^14.0.1",
|
|
66
66
|
"@types/bun": "^1.2.20",
|
package/src/hubspot-mirror-ui.ts
CHANGED
|
@@ -13,12 +13,12 @@
|
|
|
13
13
|
// PURE FRONTEND (R3): the mirror imports no handler and no twin internals — it MOUNTS the pack's
|
|
14
14
|
// fetch adapter as its API backend and reads every byte of state back over the wire.
|
|
15
15
|
import { readFile } from 'node:fs/promises';
|
|
16
|
-
import { bundleClient, fileResponse } from '@volter/world-core';
|
|
16
|
+
import { bundleClient, fileResponse, filePathOf } from '@volter/world-core';
|
|
17
17
|
import { serveHttp } from '@volter/world-core';
|
|
18
18
|
import { createHubspotTwinFetch } from './hubspot-server.ts';
|
|
19
19
|
|
|
20
|
-
const CLIENT_ENTRY = () => new URL('../client/hubspot-mirror.tsx', import.meta.url)
|
|
21
|
-
const CLIENT_CSS = () => new URL('../client/hubspot-mirror.css', import.meta.url)
|
|
20
|
+
const CLIENT_ENTRY = () => filePathOf(new URL('../client/hubspot-mirror.tsx', import.meta.url)); // lazy: workerd rejects top-level relative URL from import.meta.url (bundled via pack index)
|
|
21
|
+
const CLIENT_CSS = () => filePathOf(new URL('../client/hubspot-mirror.css', import.meta.url)); // lazy: workerd rejects top-level relative URL from import.meta.url (bundled via pack index)
|
|
22
22
|
|
|
23
23
|
// ---------------------------------------------------------------------------
|
|
24
24
|
// Pure, dependency-free render/format helpers (importable by the React client; Bun
|
package/src/webhooks.ts
CHANGED
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
// call and `API` otherwise, and `sourceId` is `userId:<id>` or `<appId>`; the v1 signature is sent on every event, which
|
|
25
25
|
// the page does not promise for a developer-platform app's `object.*` event.
|
|
26
26
|
import { createHash, createHmac } from 'node:crypto';
|
|
27
|
+
import { appDestination, appFetch } from '@volter/world-core/app-route';
|
|
27
28
|
import { worldEgressRefusal } from '@volter/world-core/network-policy';
|
|
28
29
|
import { appById, installsIn, keep, stored, type Row } from './accounts.ts';
|
|
29
30
|
import { currentPortal } from './portal.ts';
|
|
@@ -67,7 +68,8 @@ async function deliver(to: string, secret: string, events: Row[], hub: number, r
|
|
|
67
68
|
};
|
|
68
69
|
const n = stored('_webhook_delivery', root).length + 1;
|
|
69
70
|
await keep('_webhook_delivery', `delivery:${n}`, { n, to, portalId: hub, body, headers, delivered_at: at }, root, at);
|
|
70
|
-
|
|
71
|
+
// the application's own hostnames reach it inside the World; elsewhere, the World's egress rule decides
|
|
72
|
+
if (appDestination(to) || worldEgressRefusal(to) === null) await appFetch(to, { method: 'POST', headers, body }).then((r) => r.text()).catch(() => undefined);
|
|
71
73
|
}
|
|
72
74
|
|
|
73
75
|
/** GET /_twin/deliveries?to=<url>: what an app's server received from HubSpot, oldest first — each request's headers,
|