bunderstack 0.23.3 → 0.24.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.
- package/CHANGELOG.md +68 -0
- package/README.md +6 -4
- package/dist/api/builder.d.ts +13 -11
- package/dist/api/builder.d.ts.map +1 -1
- package/dist/api/builder.js.map +1 -1
- package/dist/api/context.d.ts +6 -6
- package/dist/api/context.d.ts.map +1 -1
- package/dist/api/context.js +1 -1
- package/dist/api/context.js.map +1 -1
- package/dist/api/crud-router.d.ts +6 -6
- package/dist/api/realtime-router.d.ts +1 -1
- package/dist/api/storage-router.d.ts +5 -5
- package/dist/backend-internals.d.ts +5 -13
- package/dist/backend-internals.d.ts.map +1 -1
- package/dist/backend-internals.js.map +1 -1
- package/dist/backend.d.ts +39 -5
- package/dist/backend.d.ts.map +1 -1
- package/dist/backend.js +37 -46
- package/dist/backend.js.map +1 -1
- package/dist/blueprint-generator.d.ts +1 -0
- package/dist/blueprint-generator.d.ts.map +1 -1
- package/dist/blueprint-generator.js +29 -1
- package/dist/blueprint-generator.js.map +1 -1
- package/dist/blueprint.d.ts +2 -1
- package/dist/blueprint.d.ts.map +1 -1
- package/dist/blueprint.js +9 -2
- package/dist/blueprint.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +14 -2
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +13 -19
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/email/smtp.d.ts +7 -1
- package/dist/email/smtp.d.ts.map +1 -1
- package/dist/email/smtp.js +5 -1
- package/dist/email/smtp.js.map +1 -1
- package/dist/email.d.ts +3 -29
- package/dist/email.d.ts.map +1 -1
- package/dist/email.js +1 -194
- package/dist/email.js.map +1 -1
- package/dist/env-probe.d.ts +9 -0
- package/dist/env-probe.d.ts.map +1 -0
- package/dist/env-probe.js +73 -0
- package/dist/env-probe.js.map +1 -0
- package/dist/env.d.ts +2 -5
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +2 -9
- package/dist/env.js.map +1 -1
- package/dist/hosted-contract.d.ts +11 -0
- package/dist/hosted-contract.d.ts.map +1 -0
- package/dist/hosted-contract.js +46 -0
- package/dist/hosted-contract.js.map +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/inspect.d.ts +15 -0
- package/dist/inspect.d.ts.map +1 -0
- package/dist/inspect.js +43 -0
- package/dist/inspect.js.map +1 -0
- package/dist/internal-tables-pg.d.ts +43 -94
- package/dist/internal-tables-pg.d.ts.map +1 -1
- package/dist/internal-tables-pg.js +15 -17
- package/dist/internal-tables-pg.js.map +1 -1
- package/dist/internal-tables.d.ts +213 -488
- package/dist/internal-tables.d.ts.map +1 -1
- package/dist/internal-tables.js +34 -33
- package/dist/internal-tables.js.map +1 -1
- package/dist/jobs/define.d.ts +20 -20
- package/dist/jobs/define.d.ts.map +1 -1
- package/dist/jobs/define.js.map +1 -1
- package/dist/jobs/worker.d.ts.map +1 -1
- package/dist/jobs/worker.js +34 -22
- package/dist/jobs/worker.js.map +1 -1
- package/dist/manifest-diff.d.ts +6 -0
- package/dist/manifest-diff.d.ts.map +1 -0
- package/dist/manifest-diff.js +42 -0
- package/dist/manifest-diff.js.map +1 -0
- package/dist/manifest.d.ts +10 -2
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +27 -29
- package/dist/manifest.js.map +1 -1
- package/dist/messaging/email.d.ts +16 -0
- package/dist/messaging/email.d.ts.map +1 -0
- package/dist/messaging/email.js +8 -0
- package/dist/messaging/email.js.map +1 -0
- package/dist/messaging/index.d.ts +8 -0
- package/dist/messaging/index.d.ts.map +1 -0
- package/dist/messaging/index.js +4 -0
- package/dist/messaging/index.js.map +1 -0
- package/dist/messaging/journal.d.ts +4 -0
- package/dist/messaging/journal.d.ts.map +1 -0
- package/dist/messaging/journal.js +19 -0
- package/dist/messaging/journal.js.map +1 -0
- package/dist/messaging/runtime.d.ts +16 -0
- package/dist/messaging/runtime.d.ts.map +1 -0
- package/dist/messaging/runtime.js +213 -0
- package/dist/messaging/runtime.js.map +1 -0
- package/dist/messaging/standalone.d.ts +27 -0
- package/dist/messaging/standalone.d.ts.map +1 -0
- package/dist/messaging/standalone.js +18 -0
- package/dist/messaging/standalone.js.map +1 -0
- package/dist/messaging/telegram.d.ts +16 -0
- package/dist/messaging/telegram.d.ts.map +1 -0
- package/dist/messaging/telegram.js +5 -0
- package/dist/messaging/telegram.js.map +1 -0
- package/dist/messaging/types.d.ts +22 -0
- package/dist/messaging/types.d.ts.map +1 -0
- package/dist/messaging/types.js +17 -0
- package/dist/messaging/types.js.map +1 -0
- package/dist/runtime.d.ts +11 -10
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +19 -31
- package/dist/runtime.js.map +1 -1
- package/dist/schema-export-pg.d.ts +1 -1
- package/dist/schema-export-pg.d.ts.map +1 -1
- package/dist/schema-export-pg.js +1 -1
- package/dist/schema-export-pg.js.map +1 -1
- package/dist/schema-export.d.ts +1 -1
- package/dist/schema-export.d.ts.map +1 -1
- package/dist/schema-export.js +1 -1
- package/dist/schema-export.js.map +1 -1
- package/dist/testing/fixture.d.ts +2 -2
- package/dist/testing/fixture.d.ts.map +1 -1
- package/dist/testing/fixture.js +11 -9
- package/dist/testing/fixture.js.map +1 -1
- package/dist/testing/messaging.d.ts +21 -0
- package/dist/testing/messaging.d.ts.map +1 -0
- package/dist/testing/messaging.js +34 -0
- package/dist/testing/messaging.js.map +1 -0
- package/dist/testing.d.ts +1 -0
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js.map +1 -1
- package/package.json +6 -2
- package/skills/creating-bunderstack-apps/references/application-structure.md +16 -7
- package/skills/migrating-to-bunderstack/SKILL.md +72 -50
- package/skills/migrating-to-bunderstack/references/audit-checklist.md +2 -2
- package/skills/migrating-to-bunderstack/references/runtime-replacements.md +16 -12
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"journal.d.ts","sourceRoot":"","sources":["../../src/messaging/journal.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAIvC,wBAAsB,aAAa,CACjC,EAAE,EAAE,KAAK,GAAG,SAAS,EACrB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,iBAI/B;AAED,wBAAsB,aAAa,CACjC,EAAE,EAAE,KAAK,GAAG,SAAS,EACrB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,cAAc,CAAC,EAAE,MAAM,iBAYxB"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { and, eq } from 'drizzle-orm';
|
|
2
|
+
import { messagesTableFor } from '../internal-tables.js';
|
|
3
|
+
export async function insertMessage(db, value) {
|
|
4
|
+
if (!db)
|
|
5
|
+
return;
|
|
6
|
+
await db.insert(messagesTableFor(db)).values(value);
|
|
7
|
+
}
|
|
8
|
+
export async function updateMessage(db, id, value, expectedStatus) {
|
|
9
|
+
if (!db)
|
|
10
|
+
return;
|
|
11
|
+
const table = messagesTableFor(db);
|
|
12
|
+
await db
|
|
13
|
+
.update(table)
|
|
14
|
+
.set(value)
|
|
15
|
+
.where(expectedStatus
|
|
16
|
+
? and(eq(table.id, id), eq(table.status, expectedStatus))
|
|
17
|
+
: eq(table.id, id));
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=journal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"journal.js","sourceRoot":"","sources":["../../src/messaging/journal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,aAAa,CAAA;AAIrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAErD,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,EAAqB,EACrB,KAA8B;IAE9B,IAAI,CAAC,EAAE;QAAE,OAAM;IACf,MAAM,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AACrD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,EAAqB,EACrB,EAAU,EACV,KAA8B,EAC9B,cAAuB;IAEvB,IAAI,CAAC,EAAE;QAAE,OAAM;IACf,MAAM,KAAK,GAAG,gBAAgB,CAAC,EAAE,CAAC,CAAA;IAClC,MAAM,EAAE;SACL,MAAM,CAAC,KAAK,CAAC;SACb,GAAG,CAAC,KAAK,CAAC;SACV,KAAK,CACJ,cAAc;QACZ,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;QACzD,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CACrB,CAAA;AACL,CAAC","sourcesContent":["import { and, eq } from 'drizzle-orm'\n\nimport type { AnyDb } from '../dialect'\n\nimport { messagesTableFor } from '../internal-tables'\n\nexport async function insertMessage(\n db: AnyDb | undefined,\n value: Record<string, unknown>,\n) {\n if (!db) return\n await db.insert(messagesTableFor(db)).values(value)\n}\n\nexport async function updateMessage(\n db: AnyDb | undefined,\n id: string,\n value: Record<string, unknown>,\n expectedStatus?: string,\n) {\n if (!db) return\n const table = messagesTableFor(db)\n await db\n .update(table)\n .set(value)\n .where(\n expectedStatus\n ? and(eq(table.id, id), eq(table.status, expectedStatus))\n : eq(table.id, id),\n )\n}\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AnyDb } from '../dialect.js';
|
|
2
|
+
import type { BaseEnv } from '../env.js';
|
|
3
|
+
import type { MessagingConfig, MessagingFacades } from './types.js';
|
|
4
|
+
export type MessagingAdapter = {
|
|
5
|
+
send(input: any): Promise<{
|
|
6
|
+
id?: string;
|
|
7
|
+
}>;
|
|
8
|
+
};
|
|
9
|
+
export type CreateMessagingOptions = {
|
|
10
|
+
env: BaseEnv;
|
|
11
|
+
db?: AnyDb;
|
|
12
|
+
fetchFn?: typeof fetch;
|
|
13
|
+
adapterOverrides?: Record<string, MessagingAdapter>;
|
|
14
|
+
};
|
|
15
|
+
export declare function createMessaging<const TConfig extends MessagingConfig>(config: TConfig, options: CreateMessagingOptions): MessagingFacades<TConfig>;
|
|
16
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/messaging/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAEvC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AAErC,OAAO,KAAK,EAEV,eAAe,EACf,gBAAgB,EACjB,MAAM,SAAS,CAAA;AAKhB,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAC3C,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,GAAG,EAAE,OAAO,CAAA;IACZ,EAAE,CAAC,EAAE,KAAK,CAAA;IACV,OAAO,CAAC,EAAE,OAAO,KAAK,CAAA;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;CACpD,CAAA;AA+ID,wBAAgB,eAAe,CAAC,KAAK,CAAC,OAAO,SAAS,eAAe,EACnE,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,sBAAsB,GAC9B,gBAAgB,CAAC,OAAO,CAAC,CA6H3B"}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { insertMessage, updateMessage } from './journal.js';
|
|
2
|
+
import { isMessagingDescriptor } from './types.js';
|
|
3
|
+
const nonEmpty = (value) => typeof value === 'string' && value.trim().length > 0;
|
|
4
|
+
const array = (value) => value === undefined ? [] : Array.isArray(value) ? value : [value];
|
|
5
|
+
function managedConfig(raw) {
|
|
6
|
+
if (!nonEmpty(raw))
|
|
7
|
+
return {};
|
|
8
|
+
let value;
|
|
9
|
+
try {
|
|
10
|
+
value = JSON.parse(raw);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
throw new Error('[bunderstack] BUNDERSTACK_MESSAGING_CONFIG must be valid JSON');
|
|
14
|
+
}
|
|
15
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
16
|
+
throw new Error('[bunderstack] BUNDERSTACK_MESSAGING_CONFIG must be an object');
|
|
17
|
+
}
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
20
|
+
function consoleCapture(channel, kind, input) {
|
|
21
|
+
console.log(`\n${'─'.repeat(60)}\n` +
|
|
22
|
+
`💬 ${channel} (${kind}, captured — not sent)\n` +
|
|
23
|
+
`${'─'.repeat(60)}\n` +
|
|
24
|
+
`${JSON.stringify(input, null, 2)}\n` +
|
|
25
|
+
`${'─'.repeat(60)}`);
|
|
26
|
+
}
|
|
27
|
+
function emailContent(input, from) {
|
|
28
|
+
return {
|
|
29
|
+
recipients: {
|
|
30
|
+
to: array(input.to),
|
|
31
|
+
cc: array(input.cc),
|
|
32
|
+
bcc: array(input.bcc),
|
|
33
|
+
},
|
|
34
|
+
content: {
|
|
35
|
+
subject: input.subject,
|
|
36
|
+
html: input.html,
|
|
37
|
+
text: input.text,
|
|
38
|
+
from,
|
|
39
|
+
replyTo: input.replyTo,
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function telegramContent(input) {
|
|
44
|
+
return {
|
|
45
|
+
recipients: { to: [String(input.to)] },
|
|
46
|
+
content: { text: input.text, parseMode: input.parseMode },
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function createResendAdapter(apiKey, fetchFn) {
|
|
50
|
+
return {
|
|
51
|
+
async send(input) {
|
|
52
|
+
const response = await fetchFn('https://api.resend.com/emails', {
|
|
53
|
+
method: 'POST',
|
|
54
|
+
headers: {
|
|
55
|
+
Authorization: `Bearer ${apiKey}`,
|
|
56
|
+
'Content-Type': 'application/json',
|
|
57
|
+
},
|
|
58
|
+
body: JSON.stringify({
|
|
59
|
+
from: input.from,
|
|
60
|
+
to: array(input.to),
|
|
61
|
+
subject: input.subject,
|
|
62
|
+
html: input.html,
|
|
63
|
+
text: input.text,
|
|
64
|
+
reply_to: input.replyTo,
|
|
65
|
+
cc: array(input.cc),
|
|
66
|
+
bcc: array(input.bcc),
|
|
67
|
+
tags: input.tags,
|
|
68
|
+
}),
|
|
69
|
+
});
|
|
70
|
+
if (!response.ok) {
|
|
71
|
+
throw new Error(`resend API error (${response.status}): ${await response.text()}`);
|
|
72
|
+
}
|
|
73
|
+
return (await response.json());
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function createTelegramAdapter(token, fetchFn) {
|
|
78
|
+
return {
|
|
79
|
+
async send(input) {
|
|
80
|
+
const response = await fetchFn(`https://api.telegram.org/bot${token}/sendMessage`, {
|
|
81
|
+
method: 'POST',
|
|
82
|
+
headers: { 'Content-Type': 'application/json' },
|
|
83
|
+
body: JSON.stringify({
|
|
84
|
+
chat_id: input.to,
|
|
85
|
+
text: input.text,
|
|
86
|
+
parse_mode: input.parseMode,
|
|
87
|
+
}),
|
|
88
|
+
});
|
|
89
|
+
if (!response.ok) {
|
|
90
|
+
throw new Error(`telegram API error (${response.status}): ${await response.text()}`);
|
|
91
|
+
}
|
|
92
|
+
const body = (await response.json());
|
|
93
|
+
return { id: body.result?.message_id?.toString() };
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function providerConfig(descriptor, managed) {
|
|
98
|
+
const merged = { ...managed[descriptor.provider] };
|
|
99
|
+
for (const [key, value] of Object.entries(descriptor.config)) {
|
|
100
|
+
if (typeof value === 'string' ? nonEmpty(value) : value !== undefined) {
|
|
101
|
+
merged[key] = value;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return merged;
|
|
105
|
+
}
|
|
106
|
+
export function createMessaging(config, options) {
|
|
107
|
+
const managed = managedConfig(options.env.BUNDERSTACK_MESSAGING_CONFIG);
|
|
108
|
+
const entries = Object.entries(config).map(([channel, descriptor]) => {
|
|
109
|
+
if (!channel.trim())
|
|
110
|
+
throw new Error('[bunderstack] messaging channel names cannot be empty');
|
|
111
|
+
if (!isMessagingDescriptor(descriptor)) {
|
|
112
|
+
throw new Error(`[bunderstack] messaging.${channel} is not a provider descriptor`);
|
|
113
|
+
}
|
|
114
|
+
const merged = providerConfig(descriptor, managed);
|
|
115
|
+
const override = options.adapterOverrides?.[channel];
|
|
116
|
+
let adapter = override;
|
|
117
|
+
let source = override ? 'capture' : 'explicit';
|
|
118
|
+
let from;
|
|
119
|
+
if (!adapter &&
|
|
120
|
+
descriptor.kind === 'email' &&
|
|
121
|
+
descriptor.provider === 'resend') {
|
|
122
|
+
const own = descriptor.config;
|
|
123
|
+
const apiKey = merged.apiKey;
|
|
124
|
+
from = nonEmpty(merged.from) ? merged.from : undefined;
|
|
125
|
+
if (nonEmpty(apiKey) && from) {
|
|
126
|
+
source = nonEmpty(own.apiKey) ? 'explicit' : 'managed';
|
|
127
|
+
adapter = createResendAdapter(apiKey, options.fetchFn ?? fetch);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
else if (!adapter && descriptor.kind === 'email') {
|
|
131
|
+
const own = descriptor.config;
|
|
132
|
+
from = nonEmpty(merged.from) ? merged.from : undefined;
|
|
133
|
+
if (own.adapter && from) {
|
|
134
|
+
adapter =
|
|
135
|
+
typeof own.adapter === 'function'
|
|
136
|
+
? { send: own.adapter }
|
|
137
|
+
: own.adapter;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
else if (!adapter && descriptor.kind === 'telegram') {
|
|
141
|
+
const own = descriptor.config;
|
|
142
|
+
const token = merged.botToken;
|
|
143
|
+
if (nonEmpty(token)) {
|
|
144
|
+
source = nonEmpty(own.botToken) ? 'explicit' : 'managed';
|
|
145
|
+
adapter = createTelegramAdapter(token, options.fetchFn ?? fetch);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
const capture = !adapter || Boolean(override);
|
|
149
|
+
if (capture)
|
|
150
|
+
source = 'capture';
|
|
151
|
+
return [
|
|
152
|
+
channel,
|
|
153
|
+
{
|
|
154
|
+
async send(input) {
|
|
155
|
+
if (descriptor.kind === 'email' &&
|
|
156
|
+
!input.html &&
|
|
157
|
+
!input.text) {
|
|
158
|
+
throw new Error('email message needs html or text content');
|
|
159
|
+
}
|
|
160
|
+
const resolvedFrom = descriptor.kind === 'email'
|
|
161
|
+
? (input.from ?? from ?? 'unknown@localhost')
|
|
162
|
+
: undefined;
|
|
163
|
+
const normalized = descriptor.kind === 'email'
|
|
164
|
+
? emailContent(input, resolvedFrom)
|
|
165
|
+
: telegramContent(input);
|
|
166
|
+
const id = `message_${crypto.randomUUID()}`;
|
|
167
|
+
const now = Date.now();
|
|
168
|
+
await insertMessage(options.db, {
|
|
169
|
+
id,
|
|
170
|
+
channel,
|
|
171
|
+
kind: descriptor.kind,
|
|
172
|
+
provider: descriptor.provider,
|
|
173
|
+
credentialSource: source,
|
|
174
|
+
status: capture ? 'captured' : 'sending',
|
|
175
|
+
recipientsJson: JSON.stringify(normalized.recipients),
|
|
176
|
+
contentJson: JSON.stringify(normalized.content),
|
|
177
|
+
createdAt: now,
|
|
178
|
+
updatedAt: now,
|
|
179
|
+
});
|
|
180
|
+
if (capture) {
|
|
181
|
+
await adapter?.send(input);
|
|
182
|
+
if (!override && !options.env.BUNDERHOST_ENVIRONMENT_ID) {
|
|
183
|
+
consoleCapture(channel, descriptor.kind, input);
|
|
184
|
+
}
|
|
185
|
+
return { id };
|
|
186
|
+
}
|
|
187
|
+
try {
|
|
188
|
+
const outgoing = descriptor.kind === 'email'
|
|
189
|
+
? { ...input, from: resolvedFrom }
|
|
190
|
+
: input;
|
|
191
|
+
const sent = await adapter.send(outgoing);
|
|
192
|
+
await updateMessage(options.db, id, {
|
|
193
|
+
providerId: sent.id || undefined,
|
|
194
|
+
status: 'sent',
|
|
195
|
+
updatedAt: Date.now(),
|
|
196
|
+
}, 'sending');
|
|
197
|
+
return { id, providerId: sent.id || undefined };
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
await updateMessage(options.db, id, {
|
|
201
|
+
status: 'failed',
|
|
202
|
+
error: error instanceof Error ? error.message : String(error),
|
|
203
|
+
updatedAt: Date.now(),
|
|
204
|
+
}, 'sending');
|
|
205
|
+
throw error;
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
];
|
|
210
|
+
});
|
|
211
|
+
return Object.fromEntries(entries);
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/messaging/runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AnyDb } from '../dialect'\nimport type { EmailAdapter, EmailMessage } from '../email'\nimport type { BaseEnv } from '../env'\nimport type { TelegramMessage } from './telegram'\nimport type {\n AnyMessagingDescriptor,\n MessagingConfig,\n MessagingFacades,\n} from './types'\n\nimport { insertMessage, updateMessage } from './journal'\nimport { isMessagingDescriptor } from './types'\n\nexport type MessagingAdapter = {\n send(input: any): Promise<{ id?: string }>\n}\n\nexport type CreateMessagingOptions = {\n env: BaseEnv\n db?: AnyDb\n fetchFn?: typeof fetch\n adapterOverrides?: Record<string, MessagingAdapter>\n}\n\ntype ManagedConfig = Record<string, Record<string, unknown>>\ntype CredentialSource = 'explicit' | 'managed' | 'capture'\n\nconst nonEmpty = (value: unknown): value is string =>\n typeof value === 'string' && value.trim().length > 0\n\nconst array = (value: string | string[] | undefined) =>\n value === undefined ? [] : Array.isArray(value) ? value : [value]\n\nfunction managedConfig(raw: string | undefined): ManagedConfig {\n if (!nonEmpty(raw)) return {}\n let value: unknown\n try {\n value = JSON.parse(raw)\n } catch {\n throw new Error(\n '[bunderstack] BUNDERSTACK_MESSAGING_CONFIG must be valid JSON',\n )\n }\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error(\n '[bunderstack] BUNDERSTACK_MESSAGING_CONFIG must be an object',\n )\n }\n return value as ManagedConfig\n}\n\nfunction consoleCapture(channel: string, kind: string, input: unknown) {\n console.log(\n `\\n${'─'.repeat(60)}\\n` +\n `💬 ${channel} (${kind}, captured — not sent)\\n` +\n `${'─'.repeat(60)}\\n` +\n `${JSON.stringify(input, null, 2)}\\n` +\n `${'─'.repeat(60)}`,\n )\n}\n\nfunction emailContent(input: EmailMessage, from: string) {\n return {\n recipients: {\n to: array(input.to),\n cc: array(input.cc),\n bcc: array(input.bcc),\n },\n content: {\n subject: input.subject,\n html: input.html,\n text: input.text,\n from,\n replyTo: input.replyTo,\n },\n }\n}\n\nfunction telegramContent(input: TelegramMessage) {\n return {\n recipients: { to: [String(input.to)] },\n content: { text: input.text, parseMode: input.parseMode },\n }\n}\n\nfunction createResendAdapter(\n apiKey: string,\n fetchFn: typeof fetch,\n): MessagingAdapter {\n return {\n async send(input: EmailMessage & { from: string; tags?: unknown }) {\n const response = await fetchFn('https://api.resend.com/emails', {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n from: input.from,\n to: array(input.to),\n subject: input.subject,\n html: input.html,\n text: input.text,\n reply_to: input.replyTo,\n cc: array(input.cc),\n bcc: array(input.bcc),\n tags: input.tags,\n }),\n })\n if (!response.ok) {\n throw new Error(\n `resend API error (${response.status}): ${await response.text()}`,\n )\n }\n return (await response.json()) as { id?: string }\n },\n }\n}\n\nfunction createTelegramAdapter(\n token: string,\n fetchFn: typeof fetch,\n): MessagingAdapter {\n return {\n async send(input: TelegramMessage) {\n const response = await fetchFn(\n `https://api.telegram.org/bot${token}/sendMessage`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n chat_id: input.to,\n text: input.text,\n parse_mode: input.parseMode,\n }),\n },\n )\n if (!response.ok) {\n throw new Error(\n `telegram API error (${response.status}): ${await response.text()}`,\n )\n }\n const body = (await response.json()) as {\n result?: { message_id?: number }\n }\n return { id: body.result?.message_id?.toString() }\n },\n }\n}\n\nfunction providerConfig(\n descriptor: AnyMessagingDescriptor,\n managed: ManagedConfig,\n): Record<string, unknown> {\n const merged = { ...managed[descriptor.provider] }\n for (const [key, value] of Object.entries(\n descriptor.config as Record<string, unknown>,\n )) {\n if (typeof value === 'string' ? nonEmpty(value) : value !== undefined) {\n merged[key] = value\n }\n }\n return merged\n}\n\nexport function createMessaging<const TConfig extends MessagingConfig>(\n config: TConfig,\n options: CreateMessagingOptions,\n): MessagingFacades<TConfig> {\n const managed = managedConfig(options.env.BUNDERSTACK_MESSAGING_CONFIG)\n const entries = Object.entries(config).map(([channel, descriptor]) => {\n if (!channel.trim())\n throw new Error('[bunderstack] messaging channel names cannot be empty')\n if (!isMessagingDescriptor(descriptor)) {\n throw new Error(\n `[bunderstack] messaging.${channel} is not a provider descriptor`,\n )\n }\n const merged = providerConfig(descriptor, managed)\n const override = options.adapterOverrides?.[channel]\n let adapter: MessagingAdapter | undefined = override\n let source: CredentialSource = override ? 'capture' : 'explicit'\n let from: string | undefined\n if (\n !adapter &&\n descriptor.kind === 'email' &&\n descriptor.provider === 'resend'\n ) {\n const own = descriptor.config as { apiKey?: string; from?: string }\n const apiKey = merged.apiKey\n from = nonEmpty(merged.from) ? merged.from : undefined\n if (nonEmpty(apiKey) && from) {\n source = nonEmpty(own.apiKey) ? 'explicit' : 'managed'\n adapter = createResendAdapter(apiKey, options.fetchFn ?? fetch)\n }\n } else if (!adapter && descriptor.kind === 'email') {\n const own = descriptor.config as {\n adapter?: EmailAdapter | EmailAdapter['send']\n from?: string\n }\n from = nonEmpty(merged.from) ? merged.from : undefined\n if (own.adapter && from) {\n adapter =\n typeof own.adapter === 'function'\n ? { send: own.adapter }\n : own.adapter\n }\n } else if (!adapter && descriptor.kind === 'telegram') {\n const own = descriptor.config as { botToken?: string }\n const token = merged.botToken\n if (nonEmpty(token)) {\n source = nonEmpty(own.botToken) ? 'explicit' : 'managed'\n adapter = createTelegramAdapter(token, options.fetchFn ?? fetch)\n }\n }\n const capture = !adapter || Boolean(override)\n if (capture) source = 'capture'\n\n return [\n channel,\n {\n async send(input: EmailMessage | TelegramMessage) {\n if (\n descriptor.kind === 'email' &&\n !(input as EmailMessage).html &&\n !(input as EmailMessage).text\n ) {\n throw new Error('email message needs html or text content')\n }\n const resolvedFrom =\n descriptor.kind === 'email'\n ? ((input as EmailMessage).from ?? from ?? 'unknown@localhost')\n : undefined\n const normalized =\n descriptor.kind === 'email'\n ? emailContent(input as EmailMessage, resolvedFrom!)\n : telegramContent(input as TelegramMessage)\n const id = `message_${crypto.randomUUID()}`\n const now = Date.now()\n await insertMessage(options.db, {\n id,\n channel,\n kind: descriptor.kind,\n provider: descriptor.provider,\n credentialSource: source,\n status: capture ? 'captured' : 'sending',\n recipientsJson: JSON.stringify(normalized.recipients),\n contentJson: JSON.stringify(normalized.content),\n createdAt: now,\n updatedAt: now,\n })\n if (capture) {\n await adapter?.send(input)\n if (!override && !options.env.BUNDERHOST_ENVIRONMENT_ID) {\n consoleCapture(channel, descriptor.kind, input)\n }\n return { id }\n }\n try {\n const outgoing =\n descriptor.kind === 'email'\n ? { ...input, from: resolvedFrom }\n : input\n const sent = await adapter!.send(outgoing)\n await updateMessage(\n options.db,\n id,\n {\n providerId: sent.id || undefined,\n status: 'sent',\n updatedAt: Date.now(),\n },\n 'sending',\n )\n return { id, providerId: sent.id || undefined }\n } catch (error) {\n await updateMessage(\n options.db,\n id,\n {\n status: 'failed',\n error: error instanceof Error ? error.message : String(error),\n updatedAt: Date.now(),\n },\n 'sending',\n )\n throw error\n }\n },\n },\n ]\n })\n return Object.fromEntries(entries) as MessagingFacades<TConfig>\n}\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { AnyDb } from '../dialect.js';
|
|
2
|
+
import type { BaseEnv } from '../env.js';
|
|
3
|
+
import type { MessagingConfig, MessagingFacades } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* What a standalone messaging facade needs. `db` is the application's own
|
|
6
|
+
* connection: pass it so captured and sent messages reach the same journal the
|
|
7
|
+
* app writes, and omit it only when there is no database to write to.
|
|
8
|
+
*/
|
|
9
|
+
export type MessagingContext = {
|
|
10
|
+
env: BaseEnv;
|
|
11
|
+
db?: AnyDb;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Builds channel facades outside a started app, for code that runs before or
|
|
15
|
+
* beside it — a Better Auth builder sending an invitation, a script, a
|
|
16
|
+
* one-off worker. Channels behave exactly as they do on `app.messaging`,
|
|
17
|
+
* capture included.
|
|
18
|
+
*
|
|
19
|
+
* ```ts
|
|
20
|
+
* export const auth = defineAuth(schema, ({ db, env }) => {
|
|
21
|
+
* const messaging = createMessaging({ email: resend({ from: env.EMAIL_FROM }) }, { env, db })
|
|
22
|
+
* return { …, sendInvitation: (to) => messaging.email.send({ to, … }) }
|
|
23
|
+
* })
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare function createMessaging<const TConfig extends MessagingConfig>(channels: TConfig, context: MessagingContext): MessagingFacades<TConfig>;
|
|
27
|
+
//# sourceMappingURL=standalone.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"standalone.d.ts","sourceRoot":"","sources":["../../src/messaging/standalone.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AACvC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAIhE;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,GAAG,EAAE,OAAO,CAAA;IACZ,EAAE,CAAC,EAAE,KAAK,CAAA;CACX,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,KAAK,CAAC,OAAO,SAAS,eAAe,EACnE,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE,gBAAgB,GACxB,gBAAgB,CAAC,OAAO,CAAC,CAE3B"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createMessaging as materialize } from './runtime.js';
|
|
2
|
+
/**
|
|
3
|
+
* Builds channel facades outside a started app, for code that runs before or
|
|
4
|
+
* beside it — a Better Auth builder sending an invitation, a script, a
|
|
5
|
+
* one-off worker. Channels behave exactly as they do on `app.messaging`,
|
|
6
|
+
* capture included.
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* export const auth = defineAuth(schema, ({ db, env }) => {
|
|
10
|
+
* const messaging = createMessaging({ email: resend({ from: env.EMAIL_FROM }) }, { env, db })
|
|
11
|
+
* return { …, sendInvitation: (to) => messaging.email.send({ to, … }) }
|
|
12
|
+
* })
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export function createMessaging(channels, context) {
|
|
16
|
+
return materialize(channels, { env: context.env, db: context.db });
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=standalone.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"standalone.js","sourceRoot":"","sources":["../../src/messaging/standalone.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,eAAe,IAAI,WAAW,EAAE,MAAM,WAAW,CAAA;AAY1D;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAiB,EACjB,OAAyB;IAEzB,OAAO,WAAW,CAAC,QAAQ,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAA;AACpE,CAAC","sourcesContent":["import type { AnyDb } from '../dialect'\nimport type { BaseEnv } from '../env'\nimport type { MessagingConfig, MessagingFacades } from './types'\n\nimport { createMessaging as materialize } from './runtime'\n\n/**\n * What a standalone messaging facade needs. `db` is the application's own\n * connection: pass it so captured and sent messages reach the same journal the\n * app writes, and omit it only when there is no database to write to.\n */\nexport type MessagingContext = {\n env: BaseEnv\n db?: AnyDb\n}\n\n/**\n * Builds channel facades outside a started app, for code that runs before or\n * beside it — a Better Auth builder sending an invitation, a script, a\n * one-off worker. Channels behave exactly as they do on `app.messaging`,\n * capture included.\n *\n * ```ts\n * export const auth = defineAuth(schema, ({ db, env }) => {\n * const messaging = createMessaging({ email: resend({ from: env.EMAIL_FROM }) }, { env, db })\n * return { …, sendInvitation: (to) => messaging.email.send({ to, … }) }\n * })\n * ```\n */\nexport function createMessaging<const TConfig extends MessagingConfig>(\n channels: TConfig,\n context: MessagingContext,\n): MessagingFacades<TConfig> {\n return materialize(channels, { env: context.env, db: context.db })\n}\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type MessagingDescriptor } from './types.js';
|
|
2
|
+
export type TelegramMessage = {
|
|
3
|
+
to: string | number;
|
|
4
|
+
text: string;
|
|
5
|
+
parseMode?: 'HTML' | 'MarkdownV2';
|
|
6
|
+
};
|
|
7
|
+
export type SentTelegramMessage = {
|
|
8
|
+
id?: string;
|
|
9
|
+
providerId?: string;
|
|
10
|
+
};
|
|
11
|
+
export type TelegramConfig = {
|
|
12
|
+
botToken?: string;
|
|
13
|
+
};
|
|
14
|
+
export type TelegramDescriptor = MessagingDescriptor<'telegram', 'telegram', TelegramMessage, SentTelegramMessage, TelegramConfig>;
|
|
15
|
+
export declare function telegram(config?: TelegramConfig): TelegramDescriptor;
|
|
16
|
+
//# sourceMappingURL=telegram.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telegram.d.ts","sourceRoot":"","sources":["../../src/messaging/telegram.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,mBAAmB,EAAE,MAAM,SAAS,CAAA;AAE9D,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,GAAG,YAAY,CAAA;CAClC,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAElD,MAAM,MAAM,kBAAkB,GAAG,mBAAmB,CAClD,UAAU,EACV,UAAU,EACV,eAAe,EACf,mBAAmB,EACnB,cAAc,CACf,CAAA;AAED,wBAAgB,QAAQ,CAAC,MAAM,GAAE,cAAmB,GAAG,kBAAkB,CAExE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telegram.js","sourceRoot":"","sources":["../../src/messaging/telegram.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA4B,MAAM,SAAS,CAAA;AAuB9D,MAAM,UAAU,QAAQ,CAAC,SAAyB,EAAE;IAClD,OAAO,UAAU,CAAC,UAAU,EAAE,UAAU,EAAE,MAAM,CAAC,CAAA;AACnD,CAAC","sourcesContent":["import { descriptor, type MessagingDescriptor } from './types'\n\nexport type TelegramMessage = {\n to: string | number\n text: string\n parseMode?: 'HTML' | 'MarkdownV2'\n}\n\nexport type SentTelegramMessage = {\n id?: string\n providerId?: string\n}\n\nexport type TelegramConfig = { botToken?: string }\n\nexport type TelegramDescriptor = MessagingDescriptor<\n 'telegram',\n 'telegram',\n TelegramMessage,\n SentTelegramMessage,\n TelegramConfig\n>\n\nexport function telegram(config: TelegramConfig = {}): TelegramDescriptor {\n return descriptor('telegram', 'telegram', config)\n}\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare const MESSAGING_DESCRIPTOR: unique symbol;
|
|
2
|
+
export type MessagingDescriptor<TKind extends string, TProvider extends string, TInput, TResult, TConfig = unknown> = {
|
|
3
|
+
readonly kind: TKind;
|
|
4
|
+
readonly provider: TProvider;
|
|
5
|
+
readonly config: Readonly<TConfig>;
|
|
6
|
+
readonly [MESSAGING_DESCRIPTOR]: {
|
|
7
|
+
readonly input: TInput;
|
|
8
|
+
readonly result: TResult;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
export type AnyMessagingDescriptor = MessagingDescriptor<string, string, any, any, any>;
|
|
12
|
+
export type MessagingConfig = Record<string, AnyMessagingDescriptor>;
|
|
13
|
+
export type MessagingFacade<TDescriptor extends AnyMessagingDescriptor> = {
|
|
14
|
+
send(input: TDescriptor[typeof MESSAGING_DESCRIPTOR]['input']): Promise<TDescriptor[typeof MESSAGING_DESCRIPTOR]['result']>;
|
|
15
|
+
};
|
|
16
|
+
export type MessagingFacades<TConfig extends MessagingConfig> = {
|
|
17
|
+
readonly [K in keyof TConfig]: MessagingFacade<TConfig[K]>;
|
|
18
|
+
};
|
|
19
|
+
export type MessagingFacadesFor<TConfig extends MessagingConfig | undefined> = TConfig extends MessagingConfig ? MessagingFacades<TConfig> : Record<never, never>;
|
|
20
|
+
export declare function descriptor<TKind extends string, TProvider extends string, TInput, TResult, TConfig>(kind: TKind, provider: TProvider, config: TConfig): MessagingDescriptor<TKind, TProvider, TInput, TResult, TConfig>;
|
|
21
|
+
export declare function isMessagingDescriptor(value: unknown): value is AnyMessagingDescriptor;
|
|
22
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/messaging/types.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,EAAE,OAAO,MAEzC,CAAA;AAED,MAAM,MAAM,mBAAmB,CAC7B,KAAK,SAAS,MAAM,EACpB,SAAS,SAAS,MAAM,EACxB,MAAM,EACN,OAAO,EACP,OAAO,GAAG,OAAO,IACf;IACF,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAA;IACpB,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAA;IAC5B,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;IAClC,QAAQ,CAAC,CAAC,oBAAoB,CAAC,EAAE;QAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;QACtB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;KACzB,CAAA;CACF,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG,mBAAmB,CACtD,MAAM,EACN,MAAM,EACN,GAAG,EACH,GAAG,EACH,GAAG,CACJ,CAAA;AAED,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAA;AAEpE,MAAM,MAAM,eAAe,CAAC,WAAW,SAAS,sBAAsB,IAAI;IACxE,IAAI,CACF,KAAK,EAAE,WAAW,CAAC,OAAO,oBAAoB,CAAC,CAAC,OAAO,CAAC,GACvD,OAAO,CAAC,WAAW,CAAC,OAAO,oBAAoB,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAA;CAC/D,CAAA;AAED,MAAM,MAAM,gBAAgB,CAAC,OAAO,SAAS,eAAe,IAAI;IAC9D,QAAQ,EAAE,CAAC,IAAI,MAAM,OAAO,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;CAC3D,CAAA;AAED,MAAM,MAAM,mBAAmB,CAAC,OAAO,SAAS,eAAe,GAAG,SAAS,IACzE,OAAO,SAAS,eAAe,GAC3B,gBAAgB,CAAC,OAAO,CAAC,GACzB,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;AAE1B,wBAAgB,UAAU,CACxB,KAAK,SAAS,MAAM,EACpB,SAAS,SAAS,MAAM,EACxB,MAAM,EACN,OAAO,EACP,OAAO,EAEP,IAAI,EAAE,KAAK,EACX,QAAQ,EAAE,SAAS,EACnB,MAAM,EAAE,OAAO,GACd,mBAAmB,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAOjE;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,sBAAsB,CAQjC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const MESSAGING_DESCRIPTOR = Symbol.for('bunderstack.messaging-descriptor');
|
|
2
|
+
export function descriptor(kind, provider, config) {
|
|
3
|
+
return Object.freeze({
|
|
4
|
+
kind,
|
|
5
|
+
provider,
|
|
6
|
+
config: Object.freeze({ ...config }),
|
|
7
|
+
[MESSAGING_DESCRIPTOR]: undefined,
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
export function isMessagingDescriptor(value) {
|
|
11
|
+
return (typeof value === 'object' &&
|
|
12
|
+
value !== null &&
|
|
13
|
+
MESSAGING_DESCRIPTOR in value &&
|
|
14
|
+
typeof value.kind === 'string' &&
|
|
15
|
+
typeof value.provider === 'string');
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/messaging/types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAkB,MAAM,CAAC,GAAG,CAC3D,kCAAkC,CACnC,CAAA;AA2CD,MAAM,UAAU,UAAU,CAOxB,IAAW,EACX,QAAmB,EACnB,MAAe;IAEf,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,IAAI;QACJ,QAAQ;QACR,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC;QACpC,CAAC,oBAAoB,CAAC,EAAE,SAAkB;KAC3C,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,KAAc;IAEd,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,oBAAoB,IAAI,KAAK;QAC7B,OAAQ,KAAgC,CAAC,IAAI,KAAK,QAAQ;QAC1D,OAAQ,KAAgC,CAAC,QAAQ,KAAK,QAAQ,CAC/D,CAAA;AACH,CAAC","sourcesContent":["export const MESSAGING_DESCRIPTOR: unique symbol = Symbol.for(\n 'bunderstack.messaging-descriptor',\n)\n\nexport type MessagingDescriptor<\n TKind extends string,\n TProvider extends string,\n TInput,\n TResult,\n TConfig = unknown,\n> = {\n readonly kind: TKind\n readonly provider: TProvider\n readonly config: Readonly<TConfig>\n readonly [MESSAGING_DESCRIPTOR]: {\n readonly input: TInput\n readonly result: TResult\n }\n}\n\nexport type AnyMessagingDescriptor = MessagingDescriptor<\n string,\n string,\n any,\n any,\n any\n>\n\nexport type MessagingConfig = Record<string, AnyMessagingDescriptor>\n\nexport type MessagingFacade<TDescriptor extends AnyMessagingDescriptor> = {\n send(\n input: TDescriptor[typeof MESSAGING_DESCRIPTOR]['input'],\n ): Promise<TDescriptor[typeof MESSAGING_DESCRIPTOR]['result']>\n}\n\nexport type MessagingFacades<TConfig extends MessagingConfig> = {\n readonly [K in keyof TConfig]: MessagingFacade<TConfig[K]>\n}\n\nexport type MessagingFacadesFor<TConfig extends MessagingConfig | undefined> =\n TConfig extends MessagingConfig\n ? MessagingFacades<TConfig>\n : Record<never, never>\n\nexport function descriptor<\n TKind extends string,\n TProvider extends string,\n TInput,\n TResult,\n TConfig,\n>(\n kind: TKind,\n provider: TProvider,\n config: TConfig,\n): MessagingDescriptor<TKind, TProvider, TInput, TResult, TConfig> {\n return Object.freeze({\n kind,\n provider,\n config: Object.freeze({ ...config }),\n [MESSAGING_DESCRIPTOR]: undefined as never,\n })\n}\n\nexport function isMessagingDescriptor(\n value: unknown,\n): value is AnyMessagingDescriptor {\n return (\n typeof value === 'object' &&\n value !== null &&\n MESSAGING_DESCRIPTOR in value &&\n typeof (value as AnyMessagingDescriptor).kind === 'string' &&\n typeof (value as AnyMessagingDescriptor).provider === 'string'\n )\n}\n"]}
|
package/dist/runtime.d.ts
CHANGED
|
@@ -7,11 +7,12 @@ import type { RuntimeTestingHandle } from './backend-internals.js';
|
|
|
7
7
|
import type { DatabaseConnection } from './database/adapter.js';
|
|
8
8
|
import type { DbFor } from './db.js';
|
|
9
9
|
import type { BunderstackJobsBuilder, JobsDefs, JobsFacade, StartWorkerOptions, WorkerHandle } from './jobs/index.js';
|
|
10
|
+
import type { MessagingConfig, MessagingFacadesFor } from './messaging/index.js';
|
|
11
|
+
import type { MessagingAdapter } from './messaging/runtime.js';
|
|
10
12
|
import type { ResolvedStorageBuckets, StorageConfigInput } from './storage/buckets.js';
|
|
11
13
|
import type { StorageAdapter } from './storage/index.js';
|
|
12
14
|
import { createAuth } from './auth.js';
|
|
13
15
|
import { type BunderstackConfig } from './config.js';
|
|
14
|
-
import { type EmailAdapter, type EmailFacade } from './email.js';
|
|
15
16
|
import { type EnvConfigInput, type ValidatedEnv } from './env.js';
|
|
16
17
|
import { type LifecycleStatus } from './lifecycle.js';
|
|
17
18
|
import { type BunderstackLogger } from './logging.js';
|
|
@@ -20,7 +21,7 @@ export type AuthInstance = ReturnType<typeof createAuth>;
|
|
|
20
21
|
export type RuntimeOverrides = {
|
|
21
22
|
database?: DatabaseConnection;
|
|
22
23
|
resolvedStorage?: ResolvedStorageBuckets;
|
|
23
|
-
|
|
24
|
+
messagingAdapters?: Record<string, MessagingAdapter>;
|
|
24
25
|
forceMemoryRealtime?: boolean;
|
|
25
26
|
backgroundAutoStart?: false;
|
|
26
27
|
authResolver?: AuthSessionResolver;
|
|
@@ -76,15 +77,15 @@ export type AppRunWorkerOptions = AppStartWorkerOptions & {
|
|
|
76
77
|
export type BucketNamesOf<TStorage> = TStorage extends {
|
|
77
78
|
buckets: infer B extends Record<string, unknown>;
|
|
78
79
|
} ? keyof B & string : string;
|
|
79
|
-
export type BunderstackApp<TSchema extends Record<string, unknown>, TAccess extends Record<string, TableAccessInput> | undefined = undefined, TBuckets extends string = string, TEnv extends EnvConfigInput | undefined = undefined, TJobsDefs extends JobsDefs | undefined = undefined, TCustomApiRouter extends AnyORPCRouter | undefined = undefined, TRealtime = undefined> = {
|
|
80
|
+
export type BunderstackApp<TSchema extends Record<string, unknown>, TAccess extends Record<string, TableAccessInput> | undefined = undefined, TBuckets extends string = string, TEnv extends EnvConfigInput | undefined = undefined, TJobsDefs extends JobsDefs | undefined = undefined, TCustomApiRouter extends AnyORPCRouter | undefined = undefined, TRealtime = undefined, TMessaging extends MessagingConfig | undefined = undefined> = {
|
|
80
81
|
handler: (req: Request) => Promise<Response>;
|
|
81
82
|
db: DbFor<TSchema>;
|
|
82
83
|
auth: AuthInstance;
|
|
83
84
|
storage: StorageFacade;
|
|
84
85
|
/** Validated env: bunderstack's base vars plus the config's `env` extension. */
|
|
85
86
|
env: ValidatedEnv<TEnv>;
|
|
86
|
-
/**
|
|
87
|
-
|
|
87
|
+
/** Named, provider-specific outbound messaging channels. */
|
|
88
|
+
messaging: MessagingFacadesFor<TMessaging>;
|
|
88
89
|
/** Job queue facade; always present — enqueue throws when jobs aren't configured. */
|
|
89
90
|
jobs: JobsFacade<TJobsDefs extends JobsDefs ? TJobsDefs : Record<never, never>>;
|
|
90
91
|
/** Typed custom row publication; enabled=false/no-op when realtime is off. */
|
|
@@ -112,10 +113,11 @@ export type BunderstackApp<TSchema extends Record<string, unknown>, TAccess exte
|
|
|
112
113
|
] extends [false | undefined] ? {} : RealtimeApiRouter>;
|
|
113
114
|
};
|
|
114
115
|
};
|
|
115
|
-
export declare function materializeBunderstack<TSchema extends Record<string, unknown>, const TAccess extends Record<string, TableAccessInput> | undefined = undefined, const TStorage extends StorageConfigInput | undefined = undefined, const TEnv extends EnvConfigInput | undefined = undefined, const TJobsDefs extends JobsDefs | undefined = undefined, TCustomApiRouter extends AnyORPCRouter | undefined = undefined, const TRealtime extends BunderstackConfig<TSchema, TAccess, TStorage, TEnv, TCustomApiRouter>['realtime'] = undefined>(options: BunderstackConfig<TSchema, TAccess, TStorage, TEnv, TCustomApiRouter> & {
|
|
116
|
+
export declare function materializeBunderstack<TSchema extends Record<string, unknown>, const TAccess extends Record<string, TableAccessInput> | undefined = undefined, const TStorage extends StorageConfigInput | undefined = undefined, const TEnv extends EnvConfigInput | undefined = undefined, const TJobsDefs extends JobsDefs | undefined = undefined, TCustomApiRouter extends AnyORPCRouter | undefined = undefined, const TRealtime extends BunderstackConfig<TSchema, TAccess, TStorage, TEnv, TCustomApiRouter>['realtime'] = undefined, const TMessaging extends MessagingConfig | undefined = undefined>(options: BunderstackConfig<TSchema, TAccess, TStorage, TEnv, TCustomApiRouter> & {
|
|
116
117
|
realtime?: TRealtime;
|
|
117
|
-
|
|
118
|
-
|
|
118
|
+
messaging?: TMessaging;
|
|
119
|
+
jobs?: TJobsDefs | ((j: BunderstackJobsBuilder<TSchema, ValidatedEnv<TEnv>, TMessaging>) => TJobsDefs);
|
|
120
|
+
}, source: Record<string, string | undefined>, overrides?: RuntimeOverrides, env?: ValidatedEnv<TEnv>): Promise<BunderstackApp<TSchema, TAccess, BucketNamesOf<TStorage>, TEnv, TJobsDefs, TCustomApiRouter, TRealtime, TMessaging>>;
|
|
119
121
|
export { listSpec } from './api/list-spec.js';
|
|
120
122
|
export type { ListSpecOptions } from './api/list-spec.js';
|
|
121
123
|
export type { BunderstackDb, BunderstackTx } from './db.js';
|
|
@@ -128,8 +130,7 @@ export { validateEnv, createClientEnv, BunderstackEnvError } from './env.js';
|
|
|
128
130
|
export type { EnvConfigInput, BaseEnv, ValidatedEnv } from './env.js';
|
|
129
131
|
export { buildManifest, parseManifest } from './manifest.js';
|
|
130
132
|
export type { BunderstackManifest, ManifestEnvVar } from './manifest.js';
|
|
131
|
-
export {
|
|
132
|
-
export type { EmailMessage, EmailAdapter, EmailConfigInput, EmailFacade, } from './email.js';
|
|
133
|
+
export type { EmailMessage, EmailAdapter } from './email.js';
|
|
133
134
|
export { createJobsBuilder } from './jobs/index.js';
|
|
134
135
|
export type { BunderstackJobContext, BunderstackJobsBuilder, BackgroundDefinition, BackgroundDefs, CronDefinition, CronInvocation, EnqueueOptions, JobContext, JobDefinition, JobsDefs, JobsFacade, JobsRuntimeFacade, QueueJobDefinition, QueueJobKeys, RunWorkerOptions, StartWorkerOptions, WorkerHandle, } from './jobs/index.js';
|
|
135
136
|
export { defineAccess, validateAndResolveAccess, checkAccess, AUTH_TABLE_NAMES, } from './access.js';
|
package/dist/runtime.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,cAAc,CAAA;AAS9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAChD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
|