alchemy 0.65.0 → 0.66.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/bin/alchemy.js +134 -80
- package/bin/commands/init.ts +6 -3
- package/bin/services/cdp-manager/server.ts +3 -2
- package/bin/services/execute-alchemy.ts +33 -3
- package/bin/services/find-workspace-root.ts +48 -0
- package/lib/alchemy.d.ts +14 -3
- package/lib/alchemy.d.ts.map +1 -1
- package/lib/alchemy.js +17 -5
- package/lib/alchemy.js.map +1 -1
- package/lib/apply.d.ts.map +1 -1
- package/lib/apply.js +51 -1
- package/lib/apply.js.map +1 -1
- package/lib/cloudflare/bucket.js +1 -1
- package/lib/cloudflare/bucket.js.map +1 -1
- package/lib/cloudflare/bundle/plugin-node-compat.js +2 -2
- package/lib/cloudflare/bundle/plugin-node-compat.js.map +1 -1
- package/lib/cloudflare/cloudflare-env-proxy.js +3 -3
- package/lib/cloudflare/cloudflare-env-proxy.js.map +1 -1
- package/lib/cloudflare/compatibility-date.gen.d.ts +1 -1
- package/lib/cloudflare/compatibility-date.gen.js +1 -1
- package/lib/cloudflare/d1-database.d.ts.map +1 -1
- package/lib/cloudflare/d1-database.js +2 -1
- package/lib/cloudflare/d1-database.js.map +1 -1
- package/lib/cloudflare/d1-local-migrations.d.ts +1 -0
- package/lib/cloudflare/d1-local-migrations.d.ts.map +1 -1
- package/lib/cloudflare/d1-local-migrations.js +3 -2
- package/lib/cloudflare/d1-local-migrations.js.map +1 -1
- package/lib/cloudflare/kv-namespace.js +1 -1
- package/lib/cloudflare/kv-namespace.js.map +1 -1
- package/lib/cloudflare/miniflare/delete.d.ts +3 -2
- package/lib/cloudflare/miniflare/delete.d.ts.map +1 -1
- package/lib/cloudflare/miniflare/delete.js +13 -12
- package/lib/cloudflare/miniflare/delete.js.map +1 -1
- package/lib/cloudflare/miniflare/miniflare-controller.d.ts.map +1 -1
- package/lib/cloudflare/miniflare/miniflare-controller.js +5 -4
- package/lib/cloudflare/miniflare/miniflare-controller.js.map +1 -1
- package/lib/cloudflare/miniflare/paths.d.ts +4 -4
- package/lib/cloudflare/miniflare/paths.d.ts.map +1 -1
- package/lib/cloudflare/miniflare/paths.js +10 -4
- package/lib/cloudflare/miniflare/paths.js.map +1 -1
- package/lib/cloudflare/miniflare/symlink-miniflare-state.d.ts +2 -0
- package/lib/cloudflare/miniflare/symlink-miniflare-state.d.ts.map +1 -0
- package/lib/cloudflare/miniflare/symlink-miniflare-state.js +19 -0
- package/lib/cloudflare/miniflare/symlink-miniflare-state.js.map +1 -0
- package/lib/cloudflare/next.js +2 -2
- package/lib/cloudflare/next.js.map +1 -1
- package/lib/cloudflare/nuxt/plugin.d.ts.map +1 -1
- package/lib/cloudflare/nuxt/plugin.js +3 -3
- package/lib/cloudflare/nuxt/plugin.js.map +1 -1
- package/lib/cloudflare/redwood/plugin.js +2 -2
- package/lib/cloudflare/redwood/plugin.js.map +1 -1
- package/lib/cloudflare/vite/plugin.d.ts.map +1 -1
- package/lib/cloudflare/vite/plugin.js +6 -3
- package/lib/cloudflare/vite/plugin.js.map +1 -1
- package/lib/cloudflare/website.d.ts.map +1 -1
- package/lib/cloudflare/website.js +5 -16
- package/lib/cloudflare/website.js.map +1 -1
- package/lib/cloudflare/worker.d.ts.map +1 -1
- package/lib/cloudflare/worker.js +4 -2
- package/lib/cloudflare/worker.js.map +1 -1
- package/lib/cloudflare/wrangler.json.js +1 -0
- package/lib/cloudflare/wrangler.json.js.map +1 -1
- package/lib/scope.d.ts +16 -0
- package/lib/scope.d.ts.map +1 -1
- package/lib/scope.js +10 -5
- package/lib/scope.js.map +1 -1
- package/lib/state/file-system-state-store.d.ts.map +1 -1
- package/lib/state/file-system-state-store.js +1 -2
- package/lib/state/file-system-state-store.js.map +1 -1
- package/lib/state/sqlite-state-store.d.ts +11 -0
- package/lib/state/sqlite-state-store.d.ts.map +1 -1
- package/lib/state/sqlite-state-store.js +22 -14
- package/lib/state/sqlite-state-store.js.map +1 -1
- package/lib/stripe/customer.d.ts +0 -8
- package/lib/stripe/customer.d.ts.map +1 -1
- package/lib/stripe/customer.js +0 -6
- package/lib/stripe/customer.js.map +1 -1
- package/lib/stripe/price.d.ts +23 -23
- package/lib/stripe/price.d.ts.map +1 -1
- package/lib/stripe/price.js +6 -22
- package/lib/stripe/price.js.map +1 -1
- package/lib/test/vitest.d.ts.map +1 -1
- package/lib/test/vitest.js +1 -1
- package/lib/test/vitest.js.map +1 -1
- package/lib/util/assert-never.js +1 -1
- package/lib/util/assert-never.js.map +1 -1
- package/lib/util/cli.d.ts.map +1 -1
- package/lib/util/cli.js +12 -13
- package/lib/util/cli.js.map +1 -1
- package/lib/util/memoize.d.ts +1 -1
- package/lib/util/memoize.d.ts.map +1 -1
- package/lib/util/memoize.js +2 -2
- package/lib/util/memoize.js.map +1 -1
- package/lib/util/root-dir.d.ts +2 -0
- package/lib/util/root-dir.d.ts.map +1 -0
- package/lib/util/root-dir.js +2 -0
- package/lib/util/root-dir.js.map +1 -0
- package/package.json +4 -4
- package/src/alchemy.ts +36 -8
- package/src/apply.ts +58 -3
- package/src/cloudflare/bucket.ts +1 -1
- package/src/cloudflare/bundle/plugin-node-compat.ts +2 -2
- package/src/cloudflare/cloudflare-env-proxy.ts +5 -5
- package/src/cloudflare/compatibility-date.gen.ts +1 -1
- package/src/cloudflare/d1-database.ts +2 -1
- package/src/cloudflare/d1-local-migrations.ts +10 -6
- package/src/cloudflare/kv-namespace.ts +1 -1
- package/src/cloudflare/miniflare/delete.ts +19 -11
- package/src/cloudflare/miniflare/miniflare-controller.ts +10 -6
- package/src/cloudflare/miniflare/paths.ts +11 -7
- package/src/cloudflare/miniflare/symlink-miniflare-state.ts +19 -0
- package/src/cloudflare/next.ts +3 -3
- package/src/cloudflare/nuxt/plugin.ts +12 -3
- package/src/cloudflare/redwood/plugin.ts +2 -2
- package/src/cloudflare/vite/plugin.ts +8 -3
- package/src/cloudflare/website.ts +5 -19
- package/src/cloudflare/worker.ts +4 -2
- package/src/cloudflare/wrangler.json.ts +1 -0
- package/src/scope.ts +26 -5
- package/src/state/file-system-state-store.ts +1 -2
- package/src/state/sqlite-state-store.ts +41 -14
- package/src/stripe/customer.ts +0 -14
- package/src/stripe/price.ts +59 -56
- package/src/test/vitest.ts +4 -1
- package/src/util/assert-never.ts +1 -1
- package/src/util/cli.ts +15 -13
- package/src/util/memoize.ts +2 -2
- package/src/util/root-dir.ts +1 -0
- package/templates/nextjs/alchemy.run.ts +2 -2
- package/workers/cloudflare-state-store.js +1 -1
|
@@ -6,7 +6,6 @@ import { deserialize, serialize } from "../serde.ts";
|
|
|
6
6
|
import type { State, StateStore } from "../state.ts";
|
|
7
7
|
import { ignore } from "../util/ignore.ts";
|
|
8
8
|
|
|
9
|
-
const stateRootDir = path.join(process.cwd(), ".alchemy");
|
|
10
9
|
const ALCHEMY_SEPERATOR_CHAR = process.platform === "win32" ? "-" : ":";
|
|
11
10
|
|
|
12
11
|
export class FileSystemStateStore implements StateStore {
|
|
@@ -18,7 +17,7 @@ export class FileSystemStateStore implements StateStore {
|
|
|
18
17
|
rootDir?: string;
|
|
19
18
|
},
|
|
20
19
|
) {
|
|
21
|
-
this.dir = path.join(options?.rootDir ??
|
|
20
|
+
this.dir = path.join(options?.rootDir ?? scope.dotAlchemy, ...scope.chain);
|
|
22
21
|
}
|
|
23
22
|
|
|
24
23
|
async init(): Promise<void> {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Config as LibSQLConfig } from "@libsql/client";
|
|
2
|
-
import fs from "node:fs";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import type { Scope } from "../scope.ts";
|
|
5
|
+
import { exists } from "../util/exists.ts";
|
|
5
6
|
import { memoize } from "../util/memoize.ts";
|
|
6
7
|
import { importPeer } from "../util/peer.ts";
|
|
7
8
|
import { MIGRATIONS_DIRECTORY } from "./migrations.ts";
|
|
@@ -27,6 +28,7 @@ interface BunSQLiteStateStoreOptions {
|
|
|
27
28
|
readwrite?: boolean;
|
|
28
29
|
safeIntegers?: boolean;
|
|
29
30
|
strict?: boolean;
|
|
31
|
+
dotAlchemy?: string;
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
interface LibSQLStateStoreOptions extends Omit<LibSQLConfig, "url"> {
|
|
@@ -50,6 +52,11 @@ interface LibSQLStateStoreOptions extends Omit<LibSQLConfig, "url"> {
|
|
|
50
52
|
* https://github.com/libsql/libsql-client-ts#supported-urls
|
|
51
53
|
*/
|
|
52
54
|
url?: string;
|
|
55
|
+
/**
|
|
56
|
+
* The path to the .alchemy directory.
|
|
57
|
+
* @default "./.alchemy"
|
|
58
|
+
*/
|
|
59
|
+
dotAlchemy?: string;
|
|
53
60
|
}
|
|
54
61
|
|
|
55
62
|
interface AutoSQLiteStateStoreOptions {
|
|
@@ -64,6 +71,12 @@ interface AutoSQLiteStateStoreOptions {
|
|
|
64
71
|
* @default ".alchemy/state.sqlite"
|
|
65
72
|
*/
|
|
66
73
|
filename?: string;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* The path to the .alchemy directory.
|
|
77
|
+
* @default "./.alchemy"
|
|
78
|
+
*/
|
|
79
|
+
dotAlchemy?: string;
|
|
67
80
|
}
|
|
68
81
|
|
|
69
82
|
type SQLiteStateStoreOptions =
|
|
@@ -80,7 +93,10 @@ export class SQLiteStateStore extends StateStoreProxy {
|
|
|
80
93
|
}
|
|
81
94
|
|
|
82
95
|
async provision(): Promise<StateStoreProxy.Dispatch> {
|
|
83
|
-
const db = await createDatabase(
|
|
96
|
+
const db = await createDatabase({
|
|
97
|
+
...(this.options ?? {}),
|
|
98
|
+
dotAlchemy: this.scope.dotAlchemy,
|
|
99
|
+
});
|
|
84
100
|
const { SQLiteStateStoreOperations } = await import("./operations.js");
|
|
85
101
|
const operations = new SQLiteStateStoreOperations(db, {
|
|
86
102
|
chain: this.scope.chain,
|
|
@@ -97,17 +113,23 @@ const createDatabase = memoize(
|
|
|
97
113
|
case "libsql":
|
|
98
114
|
return await createLibSQLDatabase(options);
|
|
99
115
|
default: {
|
|
100
|
-
return await createDefaultDatabase(
|
|
116
|
+
return await createDefaultDatabase(
|
|
117
|
+
options?.filename,
|
|
118
|
+
options?.dotAlchemy,
|
|
119
|
+
);
|
|
101
120
|
}
|
|
102
121
|
}
|
|
103
122
|
},
|
|
104
123
|
);
|
|
105
124
|
|
|
106
|
-
async function createDefaultDatabase(
|
|
125
|
+
async function createDefaultDatabase(
|
|
126
|
+
filename: string | undefined,
|
|
127
|
+
dotAlchemy: string | undefined,
|
|
128
|
+
) {
|
|
107
129
|
if ("Bun" in globalThis) {
|
|
108
|
-
return createBunSQLiteDatabase({ engine: "bun", filename });
|
|
130
|
+
return createBunSQLiteDatabase({ engine: "bun", filename, dotAlchemy });
|
|
109
131
|
}
|
|
110
|
-
return createLibSQLDatabase({ engine: "libsql", filename });
|
|
132
|
+
return createLibSQLDatabase({ engine: "libsql", filename, dotAlchemy });
|
|
111
133
|
}
|
|
112
134
|
|
|
113
135
|
async function createBunSQLiteDatabase(
|
|
@@ -122,8 +144,8 @@ async function createBunSQLiteDatabase(
|
|
|
122
144
|
const filename =
|
|
123
145
|
options?.filename ??
|
|
124
146
|
process.env.ALCHEMY_STATE_FILE ??
|
|
125
|
-
".alchemy
|
|
126
|
-
ensureDirectory(filename);
|
|
147
|
+
path.join(options?.dotAlchemy ?? ".alchemy", "state.sqlite");
|
|
148
|
+
await ensureDirectory(filename);
|
|
127
149
|
const { Database } = await import("bun:sqlite");
|
|
128
150
|
const { drizzle } = await importPeer(
|
|
129
151
|
import("drizzle-orm/bun-sqlite"),
|
|
@@ -135,7 +157,11 @@ async function createBunSQLiteDatabase(
|
|
|
135
157
|
// options are passed in, so here's some ugly destructuring!
|
|
136
158
|
const { engine: _engine, filename: _filename, ...rest } = options ?? {};
|
|
137
159
|
const bunOptions = Object.keys(rest).length > 0 ? rest : undefined;
|
|
138
|
-
const client = new Database(filename,
|
|
160
|
+
const client = new Database(filename, {
|
|
161
|
+
readwrite: true,
|
|
162
|
+
create: true,
|
|
163
|
+
...bunOptions,
|
|
164
|
+
});
|
|
139
165
|
client.exec("PRAGMA journal_mode = WAL;");
|
|
140
166
|
const db = drizzle(client, {
|
|
141
167
|
schema,
|
|
@@ -149,10 +175,11 @@ async function createLibSQLDatabase(
|
|
|
149
175
|
) {
|
|
150
176
|
const url =
|
|
151
177
|
options?.url ??
|
|
152
|
-
`file:${options?.filename ?? process.env.ALCHEMY_STATE_FILE ?? ".alchemy
|
|
178
|
+
`file:${options?.filename ?? process.env.ALCHEMY_STATE_FILE ?? path.join(options?.dotAlchemy ?? ".alchemy", "state.sqlite")}`;
|
|
179
|
+
|
|
153
180
|
const filename = url.startsWith("file:") ? url.slice(5) : undefined;
|
|
154
181
|
if (filename) {
|
|
155
|
-
ensureDirectory(filename);
|
|
182
|
+
await ensureDirectory(filename);
|
|
156
183
|
}
|
|
157
184
|
const { drizzle } = await importPeer(
|
|
158
185
|
import("drizzle-orm/libsql"),
|
|
@@ -173,9 +200,9 @@ async function createLibSQLDatabase(
|
|
|
173
200
|
return db;
|
|
174
201
|
}
|
|
175
202
|
|
|
176
|
-
const ensureDirectory = (filename: string) => {
|
|
203
|
+
const ensureDirectory = async (filename: string) => {
|
|
177
204
|
const dir = path.dirname(filename);
|
|
178
|
-
if (!
|
|
179
|
-
fs.
|
|
205
|
+
if (!(await exists(dir))) {
|
|
206
|
+
await fs.mkdir(dir, { recursive: true });
|
|
180
207
|
}
|
|
181
208
|
};
|
package/src/stripe/customer.ts
CHANGED
|
@@ -92,10 +92,6 @@ export interface CustomerProps {
|
|
|
92
92
|
* An integer amount in cents that represents the customer's current balance
|
|
93
93
|
*/
|
|
94
94
|
balance?: number;
|
|
95
|
-
/**
|
|
96
|
-
* If you provide a coupon code, the customer will have a discount applied on all recurring charges
|
|
97
|
-
*/
|
|
98
|
-
coupon?: string;
|
|
99
95
|
/**
|
|
100
96
|
* An arbitrary string attached to the object
|
|
101
97
|
*/
|
|
@@ -136,10 +132,6 @@ export interface CustomerProps {
|
|
|
136
132
|
* Customer's preferred languages, ordered by preference
|
|
137
133
|
*/
|
|
138
134
|
preferredLocales?: string[];
|
|
139
|
-
/**
|
|
140
|
-
* The ID of a promotion code to apply to the customer
|
|
141
|
-
*/
|
|
142
|
-
promotionCode?: string;
|
|
143
135
|
/**
|
|
144
136
|
* The customer's shipping information
|
|
145
137
|
*/
|
|
@@ -311,7 +303,6 @@ export const Customer = Resource(
|
|
|
311
303
|
}
|
|
312
304
|
: undefined,
|
|
313
305
|
balance: props.balance,
|
|
314
|
-
coupon: props.coupon,
|
|
315
306
|
description: props.description,
|
|
316
307
|
email: props.email,
|
|
317
308
|
invoice_prefix: props.invoicePrefix,
|
|
@@ -320,7 +311,6 @@ export const Customer = Resource(
|
|
|
320
311
|
next_invoice_sequence: props.nextInvoiceSequence,
|
|
321
312
|
phone: props.phone,
|
|
322
313
|
preferred_locales: props.preferredLocales,
|
|
323
|
-
promotion_code: props.promotionCode,
|
|
324
314
|
shipping: props.shipping as any,
|
|
325
315
|
source: props.source,
|
|
326
316
|
tax_exempt: props.taxExempt,
|
|
@@ -354,7 +344,6 @@ export const Customer = Resource(
|
|
|
354
344
|
}
|
|
355
345
|
: undefined,
|
|
356
346
|
balance: props.balance,
|
|
357
|
-
coupon: props.coupon,
|
|
358
347
|
description: props.description,
|
|
359
348
|
email: props.email,
|
|
360
349
|
invoice_prefix: props.invoicePrefix,
|
|
@@ -364,7 +353,6 @@ export const Customer = Resource(
|
|
|
364
353
|
payment_method: props.paymentMethod,
|
|
365
354
|
phone: props.phone,
|
|
366
355
|
preferred_locales: props.preferredLocales,
|
|
367
|
-
promotion_code: props.promotionCode,
|
|
368
356
|
shipping: props.shipping as any,
|
|
369
357
|
source: props.source,
|
|
370
358
|
tax_exempt: props.taxExempt,
|
|
@@ -404,7 +392,6 @@ export const Customer = Resource(
|
|
|
404
392
|
}
|
|
405
393
|
: undefined,
|
|
406
394
|
balance: props.balance,
|
|
407
|
-
coupon: props.coupon,
|
|
408
395
|
description: props.description,
|
|
409
396
|
email: props.email,
|
|
410
397
|
invoice_prefix: props.invoicePrefix,
|
|
@@ -413,7 +400,6 @@ export const Customer = Resource(
|
|
|
413
400
|
next_invoice_sequence: props.nextInvoiceSequence,
|
|
414
401
|
phone: props.phone,
|
|
415
402
|
preferred_locales: props.preferredLocales,
|
|
416
|
-
promotion_code: props.promotionCode,
|
|
417
403
|
shipping: props.shipping as any,
|
|
418
404
|
source: props.source,
|
|
419
405
|
tax_exempt: props.taxExempt,
|
package/src/stripe/price.ts
CHANGED
|
@@ -4,41 +4,60 @@ import { Resource } from "../resource.ts";
|
|
|
4
4
|
import type { Secret } from "../secret.ts";
|
|
5
5
|
import { logger } from "../util/logger.ts";
|
|
6
6
|
import { createStripeClient, handleStripeDeleteError } from "./client.ts";
|
|
7
|
+
import type { Meter } from "./meter.ts";
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Properties for price recurring configuration
|
|
10
11
|
*/
|
|
11
|
-
export
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
12
|
+
export type PriceRecurring =
|
|
13
|
+
// If usageType is 'metered', meter is required
|
|
14
|
+
| {
|
|
15
|
+
/**
|
|
16
|
+
* Specifies billing frequency. Either 'day', 'week', 'month' or 'year'.
|
|
17
|
+
*/
|
|
18
|
+
interval: Stripe.PriceCreateParams.Recurring.Interval;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The number of intervals between subscription billings. For example, interval=month and interval_count=3 bills every 3 months.
|
|
22
|
+
*/
|
|
23
|
+
intervalCount?: number;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Configures how the quantity per period should be determined, can be either 'metered' or 'licensed'.
|
|
27
|
+
* 'metered' will aggregate the total usage based on usage records.
|
|
28
|
+
*/
|
|
29
|
+
usageType: "metered";
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The ID of the billing meter this price is associated with.
|
|
33
|
+
* Required when usageType = 'metered'.
|
|
34
|
+
*/
|
|
35
|
+
meter: string | Meter;
|
|
36
|
+
}
|
|
37
|
+
// If usageType is 'licensed' or not provided, meter is not allowed
|
|
38
|
+
| {
|
|
39
|
+
/**
|
|
40
|
+
* Specifies billing frequency. Either 'day', 'week', 'month' or 'year'.
|
|
41
|
+
*/
|
|
42
|
+
interval: Stripe.PriceCreateParams.Recurring.Interval;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The number of intervals between subscription billings. For example, interval=month and interval_count=3 bills every 3 months.
|
|
46
|
+
*/
|
|
47
|
+
intervalCount?: number;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Configures how the quantity per period should be determined, can be either 'metered' or 'licensed'.
|
|
51
|
+
* 'licensed' will automatically bill the quantity set for a plan when adding it to a subscription.
|
|
52
|
+
*/
|
|
53
|
+
usageType?: "licensed" | undefined;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The ID of the billing meter this price is associated with.
|
|
57
|
+
* Not applicable when usageType is not 'metered'.
|
|
58
|
+
*/
|
|
59
|
+
meter?: never;
|
|
60
|
+
};
|
|
42
61
|
|
|
43
62
|
type TaxBehavior = Stripe.PriceCreateParams.TaxBehavior;
|
|
44
63
|
type BillingScheme = Stripe.PriceCreateParams.BillingScheme;
|
|
@@ -262,19 +281,6 @@ export interface Price extends Resource<"stripe::Price">, PriceProps {
|
|
|
262
281
|
* });
|
|
263
282
|
*
|
|
264
283
|
* @example
|
|
265
|
-
* // Create a metered price for usage-based billing
|
|
266
|
-
* const meteredPrice = await Price("storage", {
|
|
267
|
-
* currency: "usd",
|
|
268
|
-
* unitAmount: 25, // $0.25 per GB
|
|
269
|
-
* product: "prod_xyz",
|
|
270
|
-
* recurring: {
|
|
271
|
-
* interval: "month",
|
|
272
|
-
* usageType: "metered",
|
|
273
|
-
* aggregateUsage: "sum"
|
|
274
|
-
* }
|
|
275
|
-
* });
|
|
276
|
-
*
|
|
277
|
-
* @example
|
|
278
284
|
* // Create a graduated tiered price with usage-based billing
|
|
279
285
|
* const tieredPrice = await Price("api-usage", {
|
|
280
286
|
* currency: "usd",
|
|
@@ -428,22 +434,21 @@ export const Price = Resource(
|
|
|
428
434
|
interval: props.recurring.interval,
|
|
429
435
|
interval_count: props.recurring.intervalCount,
|
|
430
436
|
usage_type: props.recurring.usageType,
|
|
431
|
-
aggregate_usage: props.recurring.aggregateUsage,
|
|
432
437
|
};
|
|
433
438
|
|
|
434
439
|
// Add meter to recurring if present (only for metered usage type)
|
|
435
|
-
if (
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
);
|
|
440
|
-
}
|
|
441
|
-
// Extend the recurring params with meter
|
|
440
|
+
if (
|
|
441
|
+
props.recurring.usageType === "metered" &&
|
|
442
|
+
props.recurring.meter
|
|
443
|
+
) {
|
|
442
444
|
(
|
|
443
445
|
createParams.recurring as Stripe.PriceCreateParams.Recurring & {
|
|
444
446
|
meter: string;
|
|
445
447
|
}
|
|
446
|
-
).meter =
|
|
448
|
+
).meter =
|
|
449
|
+
typeof props.recurring.meter === "string"
|
|
450
|
+
? props.recurring.meter
|
|
451
|
+
: props.recurring.meter.id;
|
|
447
452
|
}
|
|
448
453
|
}
|
|
449
454
|
|
|
@@ -514,8 +519,6 @@ export const Price = Resource(
|
|
|
514
519
|
intervalCount: price.recurring.interval_count,
|
|
515
520
|
usageType: price.recurring
|
|
516
521
|
.usage_type as Stripe.PriceCreateParams.Recurring.UsageType,
|
|
517
|
-
aggregateUsage: price.recurring
|
|
518
|
-
.aggregate_usage as Stripe.PriceCreateParams.Recurring.AggregateUsage,
|
|
519
522
|
meter: (
|
|
520
523
|
price.recurring as Stripe.Price.Recurring & { meter?: string }
|
|
521
524
|
).meter,
|
|
@@ -552,7 +555,7 @@ export const Price = Resource(
|
|
|
552
555
|
active: price.active,
|
|
553
556
|
billingScheme: price.billing_scheme as BillingScheme,
|
|
554
557
|
nickname: price.nickname || undefined,
|
|
555
|
-
recurring: recurring,
|
|
558
|
+
recurring: recurring as PriceRecurring,
|
|
556
559
|
metadata: price.metadata || undefined,
|
|
557
560
|
taxBehavior: price.tax_behavior as TaxBehavior,
|
|
558
561
|
createdAt: price.created,
|
package/src/test/vitest.ts
CHANGED
|
@@ -112,7 +112,10 @@ export function test(
|
|
|
112
112
|
return new D1StateStore(scope);
|
|
113
113
|
default:
|
|
114
114
|
return new SQLiteStateStore(scope, {
|
|
115
|
-
filename:
|
|
115
|
+
filename: path.join(
|
|
116
|
+
scope.dotAlchemy,
|
|
117
|
+
`${path.relative(process.cwd(), meta.filename)}.sqlite`,
|
|
118
|
+
),
|
|
116
119
|
});
|
|
117
120
|
}
|
|
118
121
|
};
|
package/src/util/assert-never.ts
CHANGED
package/src/util/cli.ts
CHANGED
|
@@ -55,16 +55,16 @@ interface AlchemyInfo {
|
|
|
55
55
|
appName: string;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
let
|
|
58
|
+
let loggers: {
|
|
59
|
+
[appName: string]: LoggerApi;
|
|
60
|
+
} = {};
|
|
61
|
+
|
|
59
62
|
export const createLoggerInstance = (
|
|
60
63
|
alchemyInfo: AlchemyInfo,
|
|
61
64
|
customLogger?: LoggerApi,
|
|
62
65
|
) => {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
// Use custom logger if provided, otherwise use the basic fallback logger
|
|
66
|
-
loggerApi = customLogger ?? createFallbackLogger(alchemyInfo);
|
|
67
|
-
return loggerApi;
|
|
66
|
+
return (loggers[alchemyInfo.appName] ??=
|
|
67
|
+
customLogger ?? createFallbackLogger(alchemyInfo));
|
|
68
68
|
};
|
|
69
69
|
|
|
70
70
|
export const createDummyLogger = (): LoggerApi => {
|
|
@@ -79,13 +79,15 @@ export const createDummyLogger = (): LoggerApi => {
|
|
|
79
79
|
};
|
|
80
80
|
|
|
81
81
|
export const createFallbackLogger = (alchemyInfo: AlchemyInfo): LoggerApi => {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
82
|
+
if (alchemyInfo.phase !== "read") {
|
|
83
|
+
console.log(dedent`
|
|
84
|
+
${colorize("Alchemy", "cyanBright")} (v${packageJson.version})
|
|
85
|
+
App: ${alchemyInfo.appName}
|
|
86
|
+
Phase: ${alchemyInfo.phase}
|
|
87
|
+
Stage: ${alchemyInfo.stage}
|
|
88
|
+
|
|
89
|
+
`);
|
|
90
|
+
}
|
|
89
91
|
|
|
90
92
|
return {
|
|
91
93
|
log: console.log,
|
package/src/util/memoize.ts
CHANGED
|
@@ -25,7 +25,7 @@ export function memoize<F extends (...args: any[]) => Promise<any>>(
|
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
export
|
|
28
|
+
export function defaultKeyFn(...args: any[]): string {
|
|
29
29
|
return createHash("sha256")
|
|
30
30
|
.update(
|
|
31
31
|
JSON.stringify(args, (_, value) => {
|
|
@@ -38,4 +38,4 @@ export const defaultKeyFn = (...args: any[]) => {
|
|
|
38
38
|
}),
|
|
39
39
|
)
|
|
40
40
|
.digest("hex");
|
|
41
|
-
}
|
|
41
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const ALCHEMY_ROOT = process.env.ALCHEMY_ROOT ?? process.cwd();
|
|
@@ -5,12 +5,12 @@ import { Nextjs } from "alchemy/cloudflare";
|
|
|
5
5
|
|
|
6
6
|
const app = await alchemy("{projectName}");
|
|
7
7
|
|
|
8
|
-
export const
|
|
8
|
+
export const worker = await Nextjs("website", {
|
|
9
9
|
name: `${app.name}-${app.stage}-website`,
|
|
10
10
|
});
|
|
11
11
|
|
|
12
12
|
console.log({
|
|
13
|
-
url:
|
|
13
|
+
url: worker.url,
|
|
14
14
|
});
|
|
15
15
|
|
|
16
16
|
await app.finalize();
|
|
@@ -5397,7 +5397,7 @@ var migrations_default = {
|
|
|
5397
5397
|
|
|
5398
5398
|
// src/util/assert-never.ts
|
|
5399
5399
|
function assertNever(value, message) {
|
|
5400
|
-
throw new Error(message ?? `Unexpected value: ${value}`);
|
|
5400
|
+
throw new Error(message ?? `Unexpected value: ${JSON.stringify(value)}`);
|
|
5401
5401
|
}
|
|
5402
5402
|
|
|
5403
5403
|
// src/state/schema.ts
|