@volter/twin-twilio 0.1.1 → 0.1.3
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.
|
@@ -24,12 +24,14 @@
|
|
|
24
24
|
// a genuinely empty response. The server is one line of Bun.serve around that same closure.
|
|
25
25
|
import { serveHttp } from '@volter/world-core';
|
|
26
26
|
import { handleTwilioTwinRequest } from "./twilio-twin.js";
|
|
27
|
-
import { createTwinFetchFromHandler, statefulTwinManifest } from '@volter/world-core';
|
|
27
|
+
import { createTwinFetchFromHandler, statefulTwinManifest, withRequestScopes } from '@volter/world-core';
|
|
28
28
|
export function createTwilioTwinFetch(options = {}) {
|
|
29
|
-
|
|
29
|
+
// a read-only request (x-volter-read-only) is a request to a read-only twin: a virgin World is not
|
|
30
|
+
// seeded with the presented credentials, nothing is sent (withRequestScopes: the pack opts in)
|
|
31
|
+
return withRequestScopes(createTwinFetchFromHandler(handleTwilioTwinRequest, {
|
|
30
32
|
...options,
|
|
31
33
|
manifest: statefulTwinManifest({ vendor: 'twilio', twinOf: 'the Twilio messaging API', stores: 'sent messages progressing queued→sending→sent→delivered, with signed status callbacks' }),
|
|
32
|
-
});
|
|
34
|
+
}));
|
|
33
35
|
}
|
|
34
36
|
export async function createTwilioTwinServer(options = {}) {
|
|
35
37
|
const server = await serveHttp({
|
package/dist/src/twilio-twin.js
CHANGED
|
@@ -307,7 +307,10 @@ async function handleMessageGet(accountSid, sid, req) {
|
|
|
307
307
|
const existing = getRow('message', sid, req.root);
|
|
308
308
|
if (!existing)
|
|
309
309
|
return notFound();
|
|
310
|
-
|
|
310
|
+
// ADVANCE ON POLL — a read-only twin (a World's read token) answers the message's current status and
|
|
311
|
+
// never advances it: the app's next poll sees exactly what it would have without the viewer.
|
|
312
|
+
if (!req.readOnly)
|
|
313
|
+
await progressMessageOnce(sid, req);
|
|
311
314
|
const row = getRow('message', sid, req.root);
|
|
312
315
|
return { status: 200, body: { ...sidView(row), ...messageUrls(accountSid, sid) } };
|
|
313
316
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/twin-twilio",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Local Twilio twin for the messaging/telephony surface (Messages send + delivery-status lifecycle, Verify start/check, Lookup, IncomingPhoneNumbers, X-Twilio-Signature-signed webhooks) built on @volter/world-core.",
|
|
5
5
|
"author": "Volter (https://github.com/volter-ai)",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -35,12 +35,12 @@
|
|
|
35
35
|
"postpack": "node ../../../scripts/publish/prepare-publish.mjs postpack"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
|
-
"@volter/world-core": "2.0.
|
|
38
|
+
"@volter/world-core": "2.0.3"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/bun": "^1.2.20",
|
|
42
42
|
"@types/node": "^24.0.0",
|
|
43
|
-
"@volter/world-core": "2.0.
|
|
43
|
+
"@volter/world-core": "2.0.3",
|
|
44
44
|
"@volter/world-tooling": "0.1.0",
|
|
45
45
|
"twilio": "6.0.2",
|
|
46
46
|
"typescript": "^5.9.0"
|
package/src/twilio-server.ts
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
// a genuinely empty response. The server is one line of Bun.serve around that same closure.
|
|
25
25
|
import { serveHttp } from '@volter/world-core';
|
|
26
26
|
import { handleTwilioTwinRequest } from './twilio-twin.ts';
|
|
27
|
-
import { createTwinFetchFromHandler, statefulTwinManifest } from '@volter/world-core';
|
|
27
|
+
import { createTwinFetchFromHandler, statefulTwinManifest, withRequestScopes } from '@volter/world-core';
|
|
28
28
|
|
|
29
29
|
/** Options every Twilio-twin HTTP surface needs, independent of who owns the socket. */
|
|
30
30
|
export interface TwilioTwinFetchOptions {
|
|
@@ -33,10 +33,12 @@ export interface TwilioTwinFetchOptions {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
export function createTwilioTwinFetch(options: TwilioTwinFetchOptions = {}): (request: Request) => Promise<Response> {
|
|
36
|
-
|
|
36
|
+
// a read-only request (x-volter-read-only) is a request to a read-only twin: a virgin World is not
|
|
37
|
+
// seeded with the presented credentials, nothing is sent (withRequestScopes: the pack opts in)
|
|
38
|
+
return withRequestScopes(createTwinFetchFromHandler(handleTwilioTwinRequest, {
|
|
37
39
|
...options,
|
|
38
40
|
manifest: statefulTwinManifest({ vendor: 'twilio', twinOf: 'the Twilio messaging API', stores: 'sent messages progressing queued→sending→sent→delivered, with signed status callbacks' }),
|
|
39
|
-
});
|
|
41
|
+
}));
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
export async function createTwilioTwinServer(options: { root?: string; port?: number; readOnly?: boolean } = {}): Promise<{ port: number; stop: () => void }> {
|
package/src/twilio-twin.ts
CHANGED
|
@@ -345,7 +345,9 @@ async function progressMessageOnce(sid: string, req: TwilioRequest): Promise<voi
|
|
|
345
345
|
async function handleMessageGet(accountSid: string, sid: string, req: TwilioRequest): Promise<TwilioResponse> {
|
|
346
346
|
const existing = getRow('message', sid, req.root);
|
|
347
347
|
if (!existing) return notFound();
|
|
348
|
-
|
|
348
|
+
// ADVANCE ON POLL — a read-only twin (a World's read token) answers the message's current status and
|
|
349
|
+
// never advances it: the app's next poll sees exactly what it would have without the viewer.
|
|
350
|
+
if (!req.readOnly) await progressMessageOnce(sid, req);
|
|
349
351
|
const row = getRow('message', sid, req.root)!;
|
|
350
352
|
return { status: 200, body: { ...sidView(row), ...messageUrls(accountSid, sid) } };
|
|
351
353
|
}
|