@tollwyn/baukasten 0.0.2 → 1.2.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.
- package/README.md +254 -1
- package/dist/bin/check.d.ts +2 -0
- package/dist/bin/check.js +38 -0
- package/dist/bin/migrate.d.ts +2 -0
- package/dist/bin/migrate.js +111 -0
- package/dist/bin/stubs.d.ts +2 -0
- package/dist/bin/stubs.js +38 -0
- package/dist/bin/test-accounts.d.ts +2 -0
- package/dist/bin/test-accounts.js +62 -0
- package/dist/check.d.ts +20 -0
- package/dist/check.js +285 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +9 -0
- package/dist/product.d.ts +161 -0
- package/dist/product.js +152 -0
- package/dist/server/accounts.d.ts +128 -0
- package/dist/server/accounts.js +282 -0
- package/dist/server/adapter/db.d.ts +5 -0
- package/dist/server/adapter/db.js +63 -0
- package/dist/server/adapter/log.d.ts +3 -0
- package/dist/server/adapter/log.js +12 -0
- package/dist/server/adapter/mailer.d.ts +4 -0
- package/dist/server/adapter/mailer.js +56 -0
- package/dist/server/adapter/migrate.d.ts +21 -0
- package/dist/server/adapter/migrate.js +113 -0
- package/dist/server/adapter/secrets.d.ts +2 -0
- package/dist/server/adapter/secrets.js +40 -0
- package/dist/server/adapter/stripe.d.ts +11 -0
- package/dist/server/adapter/stripe.js +333 -0
- package/dist/server/api.d.ts +25 -0
- package/dist/server/api.js +98 -0
- package/dist/server/baukasten-migrations.d.ts +4 -0
- package/dist/server/baukasten-migrations.js +126 -0
- package/dist/server/billing.d.ts +94 -0
- package/dist/server/billing.js +349 -0
- package/dist/server/catalog.d.ts +39 -0
- package/dist/server/catalog.js +193 -0
- package/dist/server/config.d.ts +108 -0
- package/dist/server/config.js +244 -0
- package/dist/server/endpoints.d.ts +44 -0
- package/dist/server/endpoints.js +159 -0
- package/dist/server/fields.d.ts +7 -0
- package/dist/server/fields.js +18 -0
- package/dist/server/headers.d.ts +1 -0
- package/dist/server/headers.js +9 -0
- package/dist/server/health.d.ts +34 -0
- package/dist/server/health.js +116 -0
- package/dist/server/hook.d.ts +92 -0
- package/dist/server/hook.js +293 -0
- package/dist/server/index.d.ts +18 -0
- package/dist/server/index.js +11 -0
- package/dist/server/legal/de.d.ts +2 -0
- package/dist/server/legal/de.js +251 -0
- package/dist/server/legal/document.d.ts +37 -0
- package/dist/server/legal/document.js +30 -0
- package/dist/server/legal/en.d.ts +2 -0
- package/dist/server/legal/en.js +251 -0
- package/dist/server/legal/fleet.d.ts +114 -0
- package/dist/server/legal/fleet.js +89 -0
- package/dist/server/legal/index.d.ts +3 -0
- package/dist/server/legal/index.js +11 -0
- package/dist/server/limits.d.ts +58 -0
- package/dist/server/limits.js +76 -0
- package/dist/server/log.d.ts +26 -0
- package/dist/server/log.js +61 -0
- package/dist/server/machine.d.ts +4 -0
- package/dist/server/machine.js +57 -0
- package/dist/server/mail.d.ts +20 -0
- package/dist/server/mail.js +29 -0
- package/dist/server/messages.d.ts +105 -0
- package/dist/server/messages.js +232 -0
- package/dist/server/migrations.d.ts +28 -0
- package/dist/server/migrations.js +59 -0
- package/dist/server/openapi.d.ts +24 -0
- package/dist/server/openapi.js +173 -0
- package/dist/server/pages.d.ts +158 -0
- package/dist/server/pages.js +491 -0
- package/dist/server/ports.d.ts +273 -0
- package/dist/server/ports.js +1 -0
- package/dist/server/runs.d.ts +30 -0
- package/dist/server/runs.js +55 -0
- package/dist/server/sales.d.ts +38 -0
- package/dist/server/sales.js +132 -0
- package/dist/server/services.d.ts +57 -0
- package/dist/server/services.js +44 -0
- package/dist/server/start.d.ts +14 -0
- package/dist/server/start.js +65 -0
- package/dist/server/stripe.d.ts +33 -0
- package/dist/server/stripe.js +29 -0
- package/dist/server/terms.d.ts +7 -0
- package/dist/server/terms.js +9 -0
- package/dist/server/test-accounts.d.ts +28 -0
- package/dist/server/test-accounts.js +62 -0
- package/dist/server/via.d.ts +9 -0
- package/dist/server/via.js +15 -0
- package/dist/server/web.d.ts +48 -0
- package/dist/server/web.js +105 -0
- package/dist/shopify/adapter/shopify.d.ts +8 -0
- package/dist/shopify/adapter/shopify.js +232 -0
- package/dist/shopify/admin.d.ts +33 -0
- package/dist/shopify/admin.js +47 -0
- package/dist/shopify/app.d.ts +60 -0
- package/dist/shopify/app.js +67 -0
- package/dist/shopify/config.d.ts +53 -0
- package/dist/shopify/config.js +133 -0
- package/dist/shopify/constants.d.ts +27 -0
- package/dist/shopify/constants.js +27 -0
- package/dist/shopify/headers.d.ts +1 -0
- package/dist/shopify/headers.js +8 -0
- package/dist/shopify/hmac.d.ts +1 -0
- package/dist/shopify/hmac.js +9 -0
- package/dist/shopify/hook.d.ts +60 -0
- package/dist/shopify/hook.js +508 -0
- package/dist/shopify/id-token.d.ts +12 -0
- package/dist/shopify/id-token.js +66 -0
- package/dist/shopify/index.d.ts +19 -0
- package/dist/shopify/index.js +15 -0
- package/dist/shopify/legal/de.d.ts +3 -0
- package/dist/shopify/legal/de.js +123 -0
- package/dist/shopify/legal/en.d.ts +3 -0
- package/dist/shopify/legal/en.js +121 -0
- package/dist/shopify/legal/index.d.ts +19 -0
- package/dist/shopify/legal/index.js +8 -0
- package/dist/shopify/legal/shopify.d.ts +16 -0
- package/dist/shopify/legal/shopify.js +21 -0
- package/dist/shopify/migrations.d.ts +4 -0
- package/dist/shopify/migrations.js +67 -0
- package/dist/shopify/pages.d.ts +45 -0
- package/dist/shopify/pages.js +146 -0
- package/dist/shopify/ports.d.ts +77 -0
- package/dist/shopify/ports.js +1 -0
- package/dist/shopify/sales.d.ts +4 -0
- package/dist/shopify/sales.js +27 -0
- package/dist/shopify/scopes.d.ts +2 -0
- package/dist/shopify/scopes.js +13 -0
- package/dist/shopify/seal.d.ts +12 -0
- package/dist/shopify/seal.js +60 -0
- package/dist/shopify/shop.d.ts +4 -0
- package/dist/shopify/shop.js +15 -0
- package/dist/shopify/shops.d.ts +76 -0
- package/dist/shopify/shops.js +256 -0
- package/dist/shopify/sveltekit.d.ts +19 -0
- package/dist/shopify/sveltekit.js +18 -0
- package/dist/shopify/texts.d.ts +28 -0
- package/dist/shopify/texts.js +49 -0
- package/dist/shopify/toml.d.ts +22 -0
- package/dist/shopify/toml.js +125 -0
- package/dist/shopify/webhooks.d.ts +65 -0
- package/dist/shopify/webhooks.js +220 -0
- package/dist/stubs.d.ts +15 -0
- package/dist/stubs.js +287 -0
- package/dist/sveltekit.d.ts +20 -0
- package/dist/sveltekit.js +18 -0
- package/dist/testing/app.d.ts +36 -0
- package/dist/testing/app.js +155 -0
- package/dist/testing/browser.d.ts +21 -0
- package/dist/testing/browser.js +21 -0
- package/dist/testing/connection.d.ts +7 -0
- package/dist/testing/connection.js +303 -0
- package/dist/testing/database.d.ts +21 -0
- package/dist/testing/database.js +54 -0
- package/dist/testing/env-example.d.ts +4 -0
- package/dist/testing/env-example.js +33 -0
- package/dist/testing/index.d.ts +9 -0
- package/dist/testing/index.js +9 -0
- package/dist/testing/shopify-connection.d.ts +8 -0
- package/dist/testing/shopify-connection.js +313 -0
- package/dist/testing/shopify.d.ts +71 -0
- package/dist/testing/shopify.js +278 -0
- package/dist/testing/smtp.d.ts +38 -0
- package/dist/testing/smtp.js +165 -0
- package/dist/testing/stripe.d.ts +128 -0
- package/dist/testing/stripe.js +511 -0
- package/dist/texts.d.ts +139 -0
- package/dist/texts.js +265 -0
- package/dist/ui/AccountPage.svelte +143 -0
- package/dist/ui/AccountPage.svelte.d.ts +10 -0
- package/dist/ui/ConfirmEmailPage.svelte +21 -0
- package/dist/ui/ConfirmEmailPage.svelte.d.ts +10 -0
- package/dist/ui/ErrorPage.svelte +14 -0
- package/dist/ui/ErrorPage.svelte.d.ts +3 -0
- package/dist/ui/Field.svelte +12 -0
- package/dist/ui/Field.svelte.d.ts +10 -0
- package/dist/ui/ForgotPasswordPage.svelte +32 -0
- package/dist/ui/ForgotPasswordPage.svelte.d.ts +7 -0
- package/dist/ui/Form.svelte +30 -0
- package/dist/ui/Form.svelte.d.ts +11 -0
- package/dist/ui/Frame.svelte +84 -0
- package/dist/ui/Frame.svelte.d.ts +12 -0
- package/dist/ui/LegalPage.svelte +38 -0
- package/dist/ui/LegalPage.svelte.d.ts +9 -0
- package/dist/ui/Linked.svelte +5 -0
- package/dist/ui/Linked.svelte.d.ts +8 -0
- package/dist/ui/LoginPage.svelte +41 -0
- package/dist/ui/LoginPage.svelte.d.ts +10 -0
- package/dist/ui/LogoutPage.svelte +19 -0
- package/dist/ui/LogoutPage.svelte.d.ts +9 -0
- package/dist/ui/ResetPasswordPage.svelte +30 -0
- package/dist/ui/ResetPasswordPage.svelte.d.ts +10 -0
- package/dist/ui/SignupPage.svelte +52 -0
- package/dist/ui/SignupPage.svelte.d.ts +10 -0
- package/dist/ui/VerifyEmailPage.svelte +50 -0
- package/dist/ui/VerifyEmailPage.svelte.d.ts +10 -0
- package/dist/ui/base.css +287 -0
- package/dist/ui/data.d.ts +167 -0
- package/dist/ui/data.js +1 -0
- package/dist/ui/frame.d.ts +17 -0
- package/dist/ui/frame.js +27 -0
- package/dist/ui/index.d.ts +15 -0
- package/dist/ui/index.js +15 -0
- package/dist/variables.d.ts +20 -0
- package/dist/variables.js +62 -0
- package/package.json +88 -4
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface ReceivedMail {
|
|
2
|
+
/** The recipients of the envelope, in small letters. */
|
|
3
|
+
to: string[];
|
|
4
|
+
/** The From header, decoded: name and address. */
|
|
5
|
+
from: string;
|
|
6
|
+
subject: string;
|
|
7
|
+
/** The text with line feeds. */
|
|
8
|
+
text: string;
|
|
9
|
+
}
|
|
10
|
+
export interface SmtpDouble {
|
|
11
|
+
host: string;
|
|
12
|
+
port: number;
|
|
13
|
+
/** Every mail it took, in order. */
|
|
14
|
+
mails: ReceivedMail[];
|
|
15
|
+
/**
|
|
16
|
+
* The next mail to `to` (whose subject matches) that no earlier call took, as soon as it is here;
|
|
17
|
+
* it fails after `timeoutMs`.
|
|
18
|
+
*/
|
|
19
|
+
next(to: string, options?: {
|
|
20
|
+
subject?: RegExp;
|
|
21
|
+
timeoutMs?: number;
|
|
22
|
+
}): Promise<ReceivedMail>;
|
|
23
|
+
/** Refuses mail to `to` from now on, as a relay does with an address it cannot deliver. */
|
|
24
|
+
refuse(to: string): void;
|
|
25
|
+
/** Takes mail to `to` again. */
|
|
26
|
+
accept(to: string): void;
|
|
27
|
+
stop(): Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
/** Words like `=?UTF-8?Q?Gr=C3=BCezi?=` in a header; the space between two words goes with them. */
|
|
30
|
+
export declare function decodeWords(value: string): string;
|
|
31
|
+
/** The headers and the text of a plain-text message as SMTP carries it. */
|
|
32
|
+
export declare function parseMessage(raw: Buffer): {
|
|
33
|
+
headers: Map<string, string>;
|
|
34
|
+
text: string;
|
|
35
|
+
};
|
|
36
|
+
/** The first link in a text that starts with `prefix`. */
|
|
37
|
+
export declare function linkIn(text: string, prefix: string): string;
|
|
38
|
+
export declare function startSmtp(): Promise<SmtpDouble>;
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
// An SMTP server on a free local port that keeps every mail it takes, like the relay of the fleet:
|
|
2
|
+
// plain SMTP, without a login and without STARTTLS. The baukasten sends plain-text mails only, and
|
|
3
|
+
// the double reads exactly those: headers in RFC 2047 words, a body in 7bit, 8bit, quoted-printable
|
|
4
|
+
// or base64. Its server comes from smtp-server, which a product takes as a dev dependency: no image
|
|
5
|
+
// carries it.
|
|
6
|
+
import { EventEmitter } from 'node:events';
|
|
7
|
+
/** Words like `=?UTF-8?Q?Gr=C3=BCezi?=` in a header; the space between two words goes with them. */
|
|
8
|
+
export function decodeWords(value) {
|
|
9
|
+
return value
|
|
10
|
+
.replace(/(=\?[^?]+\?[QqBb]\?[^?]*\?=)\s+(?==\?)/g, '$1')
|
|
11
|
+
.replace(/=\?([^?]+)\?([QqBb])\?([^?]*)\?=/g, (_, charset, kind, text) => {
|
|
12
|
+
const bytes = kind.toUpperCase() === 'B'
|
|
13
|
+
? Buffer.from(text, 'base64')
|
|
14
|
+
: quotedPrintable(text.replaceAll('_', ' '));
|
|
15
|
+
return new TextDecoder(charset).decode(bytes);
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
function quotedPrintable(text) {
|
|
19
|
+
const bytes = [];
|
|
20
|
+
const soft = text.replace(/=\r?\n/g, '');
|
|
21
|
+
for (let i = 0; i < soft.length; i++) {
|
|
22
|
+
const hex = soft.slice(i + 1, i + 3);
|
|
23
|
+
if (soft[i] === '=' && /^[0-9A-Fa-f]{2}$/.test(hex)) {
|
|
24
|
+
bytes.push(parseInt(hex, 16));
|
|
25
|
+
i += 2;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
bytes.push(...Buffer.from(soft.charAt(i), 'latin1'));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return Buffer.from(bytes);
|
|
32
|
+
}
|
|
33
|
+
/** The headers and the text of a plain-text message as SMTP carries it. */
|
|
34
|
+
export function parseMessage(raw) {
|
|
35
|
+
const source = raw.toString('latin1');
|
|
36
|
+
const end = source.indexOf('\r\n\r\n');
|
|
37
|
+
if (end < 0)
|
|
38
|
+
throw new Error('the message has no end of its headers');
|
|
39
|
+
const headers = new Map();
|
|
40
|
+
for (const line of source
|
|
41
|
+
.slice(0, end)
|
|
42
|
+
.replace(/\r\n[ \t]+/g, ' ')
|
|
43
|
+
.split('\r\n')) {
|
|
44
|
+
const colon = line.indexOf(':');
|
|
45
|
+
if (colon > 0)
|
|
46
|
+
headers.set(line.slice(0, colon).trim().toLowerCase(), line.slice(colon + 1).trim());
|
|
47
|
+
}
|
|
48
|
+
const type = headers.get('content-type') ?? 'text/plain';
|
|
49
|
+
if (!type.toLowerCase().startsWith('text/plain')) {
|
|
50
|
+
throw new Error(`the double reads plain-text mails only, not ${type}`);
|
|
51
|
+
}
|
|
52
|
+
const charset = /charset="?([^";]+)"?/i.exec(type)?.[1] ?? 'utf-8';
|
|
53
|
+
const body = source.slice(end + 4);
|
|
54
|
+
const encoding = (headers.get('content-transfer-encoding') ?? '7bit').toLowerCase();
|
|
55
|
+
const bytes = encoding === 'base64'
|
|
56
|
+
? Buffer.from(body.replace(/\s+/g, ''), 'base64')
|
|
57
|
+
: encoding === 'quoted-printable'
|
|
58
|
+
? quotedPrintable(body)
|
|
59
|
+
: Buffer.from(body, 'latin1');
|
|
60
|
+
// SMTP ends every message with a line break, which the text did not have.
|
|
61
|
+
const text = new TextDecoder(charset).decode(bytes).replace(/\r\n/g, '\n').replace(/\n$/, '');
|
|
62
|
+
return {
|
|
63
|
+
headers: new Map([...headers].map(([name, value]) => [name, decodeWords(value)])),
|
|
64
|
+
text
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/** The first link in a text that starts with `prefix`. */
|
|
68
|
+
export function linkIn(text, prefix) {
|
|
69
|
+
const match = new RegExp(`${prefix.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\S+`).exec(text);
|
|
70
|
+
if (match === null)
|
|
71
|
+
throw new Error(`no link starting with ${prefix} in: ${text}`);
|
|
72
|
+
return match[0];
|
|
73
|
+
}
|
|
74
|
+
/** smtp-server, or a clear word on what is missing. */
|
|
75
|
+
async function smtpServer() {
|
|
76
|
+
try {
|
|
77
|
+
return (await import('smtp-server')).SMTPServer;
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
if (error instanceof Error && Reflect.get(error, 'code') === 'ERR_MODULE_NOT_FOUND') {
|
|
81
|
+
throw new Error('the SMTP double needs smtp-server among the devDependencies of the product: npm install --save-dev smtp-server', { cause: error });
|
|
82
|
+
}
|
|
83
|
+
throw error;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
export async function startSmtp() {
|
|
87
|
+
const Server = await smtpServer();
|
|
88
|
+
const mails = [];
|
|
89
|
+
const arrived = new EventEmitter();
|
|
90
|
+
const refused = new Set();
|
|
91
|
+
const taken = new Set();
|
|
92
|
+
const server = new Server({
|
|
93
|
+
authOptional: true,
|
|
94
|
+
disabledCommands: ['AUTH', 'STARTTLS'],
|
|
95
|
+
logger: false,
|
|
96
|
+
onRcptTo(address, _session, callback) {
|
|
97
|
+
if (refused.has(address.address.toLowerCase())) {
|
|
98
|
+
callback(new Error(`mailbox ${address.address} unavailable`));
|
|
99
|
+
}
|
|
100
|
+
else
|
|
101
|
+
callback();
|
|
102
|
+
},
|
|
103
|
+
onData(stream, session, callback) {
|
|
104
|
+
const chunks = [];
|
|
105
|
+
stream.on('data', (chunk) => chunks.push(chunk));
|
|
106
|
+
stream.on('end', () => {
|
|
107
|
+
try {
|
|
108
|
+
const { headers, text } = parseMessage(Buffer.concat(chunks));
|
|
109
|
+
const mail = {
|
|
110
|
+
to: session.envelope.rcptTo.map((rcpt) => rcpt.address.toLowerCase()),
|
|
111
|
+
from: headers.get('from') ?? '',
|
|
112
|
+
subject: headers.get('subject') ?? '',
|
|
113
|
+
text
|
|
114
|
+
};
|
|
115
|
+
mails.push(mail);
|
|
116
|
+
arrived.emit('mail', mail);
|
|
117
|
+
callback();
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
callback(error instanceof Error ? error : new Error(String(error)));
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
const host = '127.0.0.1';
|
|
126
|
+
await new Promise((resolve) => server.listen(0, host, resolve));
|
|
127
|
+
const address = server.server.address();
|
|
128
|
+
if (address === null || typeof address === 'string')
|
|
129
|
+
throw new Error('the SMTP double has no port');
|
|
130
|
+
return {
|
|
131
|
+
host,
|
|
132
|
+
port: address.port,
|
|
133
|
+
mails,
|
|
134
|
+
next(to, options = {}) {
|
|
135
|
+
const recipient = to.toLowerCase();
|
|
136
|
+
const fits = (mail) => !taken.has(mail) &&
|
|
137
|
+
mail.to.includes(recipient) &&
|
|
138
|
+
(options.subject?.test(mail.subject) ?? true);
|
|
139
|
+
return new Promise((resolve, reject) => {
|
|
140
|
+
const take = (mail) => {
|
|
141
|
+
taken.add(mail);
|
|
142
|
+
arrived.off('mail', listen);
|
|
143
|
+
clearTimeout(timer);
|
|
144
|
+
resolve(mail);
|
|
145
|
+
};
|
|
146
|
+
const listen = (mail) => {
|
|
147
|
+
if (fits(mail))
|
|
148
|
+
take(mail);
|
|
149
|
+
};
|
|
150
|
+
const timer = setTimeout(() => {
|
|
151
|
+
arrived.off('mail', listen);
|
|
152
|
+
reject(new Error(`no mail to ${to}; the double has ${JSON.stringify(mails)}`));
|
|
153
|
+
}, options.timeoutMs ?? 10_000);
|
|
154
|
+
const here = mails.find(fits);
|
|
155
|
+
if (here === undefined)
|
|
156
|
+
arrived.on('mail', listen);
|
|
157
|
+
else
|
|
158
|
+
take(here);
|
|
159
|
+
});
|
|
160
|
+
},
|
|
161
|
+
refuse: (to) => refused.add(to.toLowerCase()),
|
|
162
|
+
accept: (to) => refused.delete(to.toLowerCase()),
|
|
163
|
+
stop: () => new Promise((resolve) => server.close(() => resolve()))
|
|
164
|
+
};
|
|
165
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/** A value of the JSON the double answers. */
|
|
2
|
+
export type Json = string | number | boolean | null | Json[] | {
|
|
3
|
+
[key: string]: Json;
|
|
4
|
+
};
|
|
5
|
+
type JsonObject = {
|
|
6
|
+
[key: string]: Json;
|
|
7
|
+
};
|
|
8
|
+
export interface DoublePrice {
|
|
9
|
+
id: string;
|
|
10
|
+
object: 'price';
|
|
11
|
+
product: string;
|
|
12
|
+
lookup_key: string | null;
|
|
13
|
+
unit_amount: number;
|
|
14
|
+
currency: string;
|
|
15
|
+
active: boolean;
|
|
16
|
+
type: 'one_time' | 'recurring';
|
|
17
|
+
recurring: {
|
|
18
|
+
interval: string;
|
|
19
|
+
interval_count: number;
|
|
20
|
+
} | null;
|
|
21
|
+
}
|
|
22
|
+
export interface DoubleSubscription {
|
|
23
|
+
id: string;
|
|
24
|
+
object: 'subscription';
|
|
25
|
+
customer: string;
|
|
26
|
+
status: string;
|
|
27
|
+
latest_invoice: string | null;
|
|
28
|
+
items: {
|
|
29
|
+
object: 'list';
|
|
30
|
+
data: {
|
|
31
|
+
id: string;
|
|
32
|
+
object: 'subscription_item';
|
|
33
|
+
quantity: number;
|
|
34
|
+
price: DoublePrice;
|
|
35
|
+
}[];
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export interface DoubleSession {
|
|
39
|
+
id: string;
|
|
40
|
+
object: 'checkout.session';
|
|
41
|
+
mode: string;
|
|
42
|
+
customer: string;
|
|
43
|
+
url: string;
|
|
44
|
+
subscription: string | null;
|
|
45
|
+
payment_status: 'paid' | 'unpaid';
|
|
46
|
+
amount_total: number | null;
|
|
47
|
+
currency: string | null;
|
|
48
|
+
metadata: Record<string, string>;
|
|
49
|
+
success_url: string;
|
|
50
|
+
cancel_url: string;
|
|
51
|
+
/** The price, the quantity, and the most the customer may set, as Checkout got them. */
|
|
52
|
+
item: {
|
|
53
|
+
price: string;
|
|
54
|
+
quantity: number;
|
|
55
|
+
max: number | null;
|
|
56
|
+
};
|
|
57
|
+
/** The whole request, as the API got it. */
|
|
58
|
+
request: JsonObject;
|
|
59
|
+
}
|
|
60
|
+
export interface DoubleEndpoint {
|
|
61
|
+
id: string;
|
|
62
|
+
object: 'webhook_endpoint';
|
|
63
|
+
url: string;
|
|
64
|
+
status: 'enabled' | 'disabled';
|
|
65
|
+
}
|
|
66
|
+
export interface StripeDouble {
|
|
67
|
+
/** For STRIPE_API_BASE of the app. */
|
|
68
|
+
url: string;
|
|
69
|
+
/** The signing secret of the webhook: STRIPE_WEBHOOK_SECRET of the app. */
|
|
70
|
+
webhookSecret: string;
|
|
71
|
+
/** Where the events go: the webhook of the app, set by startApp. */
|
|
72
|
+
target: string | null;
|
|
73
|
+
products: Map<string, {
|
|
74
|
+
id: string;
|
|
75
|
+
object: 'product';
|
|
76
|
+
name: string;
|
|
77
|
+
active: boolean;
|
|
78
|
+
}>;
|
|
79
|
+
prices: Map<string, DoublePrice>;
|
|
80
|
+
/** The configurations of the customer portal; the default one is from the Dashboard. */
|
|
81
|
+
portals: Map<string, JsonObject>;
|
|
82
|
+
endpoints: Map<string, DoubleEndpoint>;
|
|
83
|
+
customers: Map<string, {
|
|
84
|
+
id: string;
|
|
85
|
+
object: 'customer';
|
|
86
|
+
email: string;
|
|
87
|
+
metadata: Record<string, string>;
|
|
88
|
+
livemode: boolean;
|
|
89
|
+
}>;
|
|
90
|
+
subscriptions: Map<string, DoubleSubscription>;
|
|
91
|
+
sessions: Map<string, DoubleSession>;
|
|
92
|
+
/** Every request that changed something, like "POST /v1/products". */
|
|
93
|
+
writes: string[];
|
|
94
|
+
/** How often a subscription was read back. */
|
|
95
|
+
retrieved: number;
|
|
96
|
+
/** A webhook endpoint of another product, as an account copied from it brings one. */
|
|
97
|
+
addEndpoint(url: string, status?: 'enabled' | 'disabled'): string;
|
|
98
|
+
/**
|
|
99
|
+
* The webhook of the app at `url`, as the delivery service sets it up for each start: the one it
|
|
100
|
+
* set up before is disabled. The events go to `target`, where the app listens.
|
|
101
|
+
*/
|
|
102
|
+
connect(url: string, target: string): void;
|
|
103
|
+
/** Signs an event of this type with this object and sends it to the target; its answer. */
|
|
104
|
+
send(type: string, object: Json | object, options?: {
|
|
105
|
+
id?: string;
|
|
106
|
+
secret?: string;
|
|
107
|
+
}): Promise<Response>;
|
|
108
|
+
/**
|
|
109
|
+
* What the Checkout page does when the customer pays: a subscription with its first invoice, or a
|
|
110
|
+
* purchase, paid at once or, `later`, by a payment that clears afterwards.
|
|
111
|
+
*/
|
|
112
|
+
pay(sessionId: string, options?: {
|
|
113
|
+
quantity?: number;
|
|
114
|
+
later?: boolean;
|
|
115
|
+
}): Promise<void>;
|
|
116
|
+
/**
|
|
117
|
+
* Waits until the events the double sends on its own time arrived, like the end of a subscription
|
|
118
|
+
* after the API ended it; fails when the app did not take one.
|
|
119
|
+
*/
|
|
120
|
+
idle(): Promise<void>;
|
|
121
|
+
stop(): Promise<void>;
|
|
122
|
+
}
|
|
123
|
+
/** What the Stripe-Signature header carries for this payload at this time. */
|
|
124
|
+
export declare function stripeSignature(payload: string, secret: string, seconds: number): string;
|
|
125
|
+
export declare function startStripe(options?: {
|
|
126
|
+
portal?: boolean;
|
|
127
|
+
}): Promise<StripeDouble>;
|
|
128
|
+
export {};
|