alchemy 0.2.3 → 0.2.4
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/lib/ai/ark.d.ts +11 -0
- package/lib/ai/ark.js +86 -0
- package/lib/ai/client.d.ts +51 -0
- package/lib/ai/client.js +29 -0
- package/lib/ai/document.d.ts +97 -0
- package/lib/ai/document.js +82 -0
- package/lib/{docs → ai}/index.d.ts +1 -0
- package/lib/{docs → ai}/index.js +1 -0
- package/lib/ai/object.d.ts +101 -0
- package/lib/ai/object.js +70 -0
- package/lib/alchemy.d.ts +83 -2
- package/lib/alchemy.js +31 -3
- package/lib/aws/bucket.d.ts +87 -1
- package/lib/aws/bucket.js +48 -1
- package/lib/aws/function.d.ts +186 -1
- package/lib/aws/function.js +62 -8
- package/lib/aws/oidc/github-oidc-provider.d.ts +81 -0
- package/lib/aws/oidc/github-oidc-provider.js +68 -0
- package/lib/aws/oidc/oidc-provider.d.ts +14 -6
- package/lib/aws/oidc/oidc-provider.js +26 -5
- package/lib/aws/policy-attachment.d.ts +44 -1
- package/lib/aws/policy-attachment.js +31 -0
- package/lib/aws/policy.d.ts +160 -1
- package/lib/aws/policy.js +78 -0
- package/lib/aws/queue.d.ts +83 -1
- package/lib/aws/queue.js +39 -0
- package/lib/aws/role.d.ts +162 -1
- package/lib/aws/role.js +114 -0
- package/lib/aws/ses.d.ts +57 -2
- package/lib/aws/ses.js +42 -1
- package/lib/aws/table.d.ts +96 -1
- package/lib/aws/table.js +36 -0
- package/lib/cloudflare/asset-manifest.js +0 -1
- package/lib/cloudflare/bound.js +0 -1
- package/lib/cloudflare/bucket.d.ts +37 -1
- package/lib/cloudflare/bucket.js +36 -0
- package/lib/cloudflare/durable-object-namespace.d.ts +25 -0
- package/lib/cloudflare/durable-object-namespace.js +22 -0
- package/lib/cloudflare/kv-namespace.d.ts +37 -1
- package/lib/cloudflare/kv-namespace.js +36 -0
- package/lib/cloudflare/static-site.d.ts +53 -1
- package/lib/cloudflare/static-site.js +53 -1
- package/lib/cloudflare/worker-metadata.js +0 -1
- package/lib/cloudflare/worker.d.ts +64 -1
- package/lib/cloudflare/worker.js +63 -0
- package/lib/cloudflare/wrangler.json.d.ts +1 -1
- package/lib/cloudflare/zone-settings.js +0 -1
- package/lib/cloudflare/zone.d.ts +56 -1
- package/lib/cloudflare/zone.js +55 -0
- package/lib/destroy.js +1 -1
- package/lib/esbuild/bundle.d.ts +43 -4
- package/lib/esbuild/bundle.js +16 -0
- package/lib/fs/file-collection.d.ts +16 -0
- package/lib/fs/file-collection.js +6 -0
- package/lib/fs/file-ref.d.ts +14 -0
- package/lib/fs/file-ref.js +6 -0
- package/lib/fs/file.d.ts +71 -25
- package/lib/fs/file.js +20 -44
- package/lib/fs/folder.d.ts +37 -5
- package/lib/fs/folder.js +26 -2
- package/lib/fs/index.d.ts +6 -0
- package/lib/fs/index.js +6 -0
- package/lib/fs/json-file.d.ts +16 -0
- package/lib/fs/json-file.js +7 -0
- package/lib/fs/text-file.d.ts +12 -0
- package/lib/fs/text-file.js +7 -0
- package/lib/fs/typescript-file.d.ts +19 -0
- package/lib/fs/typescript-file.js +14 -0
- package/lib/fs/yaml-file.d.ts +19 -0
- package/lib/fs/yaml-file.js +8 -0
- package/lib/github/secret.d.ts +63 -2
- package/lib/github/secret.js +61 -1
- package/lib/internal/docs.d.ts +5 -0
- package/lib/internal/docs.js +324 -0
- package/lib/resource.d.ts +1 -1
- package/lib/secret.d.ts +67 -0
- package/lib/secret.js +67 -0
- package/lib/shadcn/component.d.ts +1 -1
- package/lib/stripe/price.d.ts +51 -1
- package/lib/stripe/price.js +50 -0
- package/lib/stripe/product.d.ts +39 -1
- package/lib/stripe/product.js +38 -0
- package/lib/stripe/webhook.d.ts +46 -1
- package/lib/stripe/webhook.js +45 -0
- package/lib/test/bun.d.ts +64 -0
- package/lib/test/bun.js +35 -3
- package/lib/util/serde.js +14 -0
- package/lib/vite/vite.d.ts +1 -1
- package/lib/vitepress/dependencies.d.ts +2 -6
- package/lib/vitepress/vitepress.d.ts +12 -1
- package/lib/vitepress/vitepress.js +29 -23
- package/package.json +8 -3
- package/src/ai/ark.ts +118 -0
- package/src/ai/client.ts +78 -0
- package/src/ai/document.ts +160 -0
- package/src/{docs → ai}/index.ts +1 -0
- package/src/ai/object.ts +149 -0
- package/src/alchemy.ts +88 -5
- package/src/aws/bucket.ts +111 -7
- package/src/aws/function.ts +231 -10
- package/src/aws/oidc/github-oidc-provider.ts +83 -0
- package/src/aws/oidc/oidc-provider.ts +39 -7
- package/src/aws/policy-attachment.ts +44 -1
- package/src/aws/policy.ts +177 -2
- package/src/aws/queue.ts +89 -0
- package/src/aws/role.ts +174 -2
- package/src/aws/ses.ts +56 -1
- package/src/aws/table.ts +103 -0
- package/src/cloudflare/bucket.ts +36 -0
- package/src/cloudflare/durable-object-namespace.ts +25 -0
- package/src/cloudflare/kv-namespace.ts +36 -0
- package/src/cloudflare/static-site.ts +53 -1
- package/src/cloudflare/worker.ts +63 -0
- package/src/cloudflare/zone.ts +55 -0
- package/src/destroy.ts +1 -1
- package/src/esbuild/bundle.ts +53 -3
- package/src/fs/file-collection.ts +24 -0
- package/src/fs/file-ref.ts +22 -0
- package/src/fs/file.ts +70 -77
- package/src/fs/folder.ts +44 -5
- package/src/fs/index.ts +6 -0
- package/src/fs/json-file.ts +23 -0
- package/src/fs/text-file.ts +19 -0
- package/src/fs/typescript-file.ts +36 -0
- package/src/fs/yaml-file.ts +26 -0
- package/src/github/secret.ts +65 -2
- package/src/internal/docs.ts +369 -0
- package/src/resource.ts +1 -1
- package/src/secret.ts +67 -0
- package/src/stripe/price.ts +50 -0
- package/src/stripe/product.ts +38 -0
- package/src/stripe/webhook.ts +45 -0
- package/src/test/bun.ts +83 -3
- package/src/util/serde.ts +17 -0
- package/src/vitepress/vitepress.ts +47 -26
- package/lib/docs/document.d.ts +0 -123
- package/lib/docs/document.js +0 -67
- package/src/docs/document.ts +0 -225
package/lib/stripe/price.js
CHANGED
|
@@ -1,5 +1,55 @@
|
|
|
1
1
|
import Stripe from "stripe";
|
|
2
2
|
import { Resource } from "../resource";
|
|
3
|
+
/**
|
|
4
|
+
* Create and manage Stripe prices for products
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* // Create a one-time fixed price for a product
|
|
8
|
+
* const oneTimePrice = await Price("basic-license", {
|
|
9
|
+
* currency: "usd",
|
|
10
|
+
* unitAmount: 2999, // $29.99
|
|
11
|
+
* product: "prod_xyz"
|
|
12
|
+
* });
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* // Create a recurring subscription price with fixed monthly billing
|
|
16
|
+
* const subscriptionPrice = await Price("pro-monthly", {
|
|
17
|
+
* currency: "usd",
|
|
18
|
+
* unitAmount: 1499, // $14.99/month
|
|
19
|
+
* product: "prod_xyz",
|
|
20
|
+
* recurring: {
|
|
21
|
+
* interval: "month",
|
|
22
|
+
* usageType: "licensed"
|
|
23
|
+
* }
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* // Create a metered price for usage-based billing
|
|
28
|
+
* const meteredPrice = await Price("storage", {
|
|
29
|
+
* currency: "usd",
|
|
30
|
+
* unitAmount: 25, // $0.25 per GB
|
|
31
|
+
* product: "prod_xyz",
|
|
32
|
+
* recurring: {
|
|
33
|
+
* interval: "month",
|
|
34
|
+
* usageType: "metered",
|
|
35
|
+
* aggregateUsage: "sum"
|
|
36
|
+
* }
|
|
37
|
+
* });
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* // Create a tiered price with tax behavior
|
|
41
|
+
* const tieredPrice = await Price("enterprise", {
|
|
42
|
+
* currency: "usd",
|
|
43
|
+
* unitAmount: 10000, // $100.00
|
|
44
|
+
* product: "prod_xyz",
|
|
45
|
+
* billingScheme: "tiered",
|
|
46
|
+
* taxBehavior: "exclusive",
|
|
47
|
+
* metadata: {
|
|
48
|
+
* tier: "enterprise",
|
|
49
|
+
* features: "all"
|
|
50
|
+
* }
|
|
51
|
+
* });
|
|
52
|
+
*/
|
|
3
53
|
export const Price = Resource("stripe::Price", async function (id, props) {
|
|
4
54
|
// Get Stripe API key from context or environment
|
|
5
55
|
const apiKey = process.env.STRIPE_API_KEY;
|
package/lib/stripe/product.d.ts
CHANGED
|
@@ -81,5 +81,43 @@ export interface Product extends Resource<"stripe::Product">, ProductProps {
|
|
|
81
81
|
width: number;
|
|
82
82
|
};
|
|
83
83
|
}
|
|
84
|
-
|
|
84
|
+
/**
|
|
85
|
+
* Create and manage Stripe products
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* // Create a basic digital product
|
|
89
|
+
* const digitalProduct = await Product("basic-software", {
|
|
90
|
+
* name: "Basic Software License",
|
|
91
|
+
* description: "Single-user license for basic software package",
|
|
92
|
+
* metadata: {
|
|
93
|
+
* type: "digital",
|
|
94
|
+
* features: "basic"
|
|
95
|
+
* }
|
|
96
|
+
* });
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* // Create a physical product with shipping details
|
|
100
|
+
* const physicalProduct = await Product("premium-hardware", {
|
|
101
|
+
* name: "Premium Hardware Kit",
|
|
102
|
+
* description: "Complete hardware kit with premium components",
|
|
103
|
+
* shippable: true,
|
|
104
|
+
* images: ["https://example.com/hardware-kit.jpg"],
|
|
105
|
+
* unitLabel: "kit",
|
|
106
|
+
* statementDescriptor: "PREMIUM HW KIT"
|
|
107
|
+
* });
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* // Create a service product with tax code
|
|
111
|
+
* const serviceProduct = await Product("consulting", {
|
|
112
|
+
* name: "Professional Consulting",
|
|
113
|
+
* description: "Expert consulting services",
|
|
114
|
+
* type: "service",
|
|
115
|
+
* taxCode: "txcd_10000000",
|
|
116
|
+
* metadata: {
|
|
117
|
+
* industry: "technology",
|
|
118
|
+
* expertise: "cloud"
|
|
119
|
+
* }
|
|
120
|
+
* });
|
|
121
|
+
*/
|
|
122
|
+
export declare const Product: (((this: any, id: string, props?: {}) => never) & (new (_: never) => never)) | ((this: Context<Product>, id: string, props: ProductProps) => Promise<Product>);
|
|
85
123
|
export {};
|
package/lib/stripe/product.js
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
import Stripe from "stripe";
|
|
2
2
|
import { Resource } from "../resource";
|
|
3
|
+
/**
|
|
4
|
+
* Create and manage Stripe products
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* // Create a basic digital product
|
|
8
|
+
* const digitalProduct = await Product("basic-software", {
|
|
9
|
+
* name: "Basic Software License",
|
|
10
|
+
* description: "Single-user license for basic software package",
|
|
11
|
+
* metadata: {
|
|
12
|
+
* type: "digital",
|
|
13
|
+
* features: "basic"
|
|
14
|
+
* }
|
|
15
|
+
* });
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* // Create a physical product with shipping details
|
|
19
|
+
* const physicalProduct = await Product("premium-hardware", {
|
|
20
|
+
* name: "Premium Hardware Kit",
|
|
21
|
+
* description: "Complete hardware kit with premium components",
|
|
22
|
+
* shippable: true,
|
|
23
|
+
* images: ["https://example.com/hardware-kit.jpg"],
|
|
24
|
+
* unitLabel: "kit",
|
|
25
|
+
* statementDescriptor: "PREMIUM HW KIT"
|
|
26
|
+
* });
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* // Create a service product with tax code
|
|
30
|
+
* const serviceProduct = await Product("consulting", {
|
|
31
|
+
* name: "Professional Consulting",
|
|
32
|
+
* description: "Expert consulting services",
|
|
33
|
+
* type: "service",
|
|
34
|
+
* taxCode: "txcd_10000000",
|
|
35
|
+
* metadata: {
|
|
36
|
+
* industry: "technology",
|
|
37
|
+
* expertise: "cloud"
|
|
38
|
+
* }
|
|
39
|
+
* });
|
|
40
|
+
*/
|
|
3
41
|
export const Product = Resource("stripe::Product", async function (id, props) {
|
|
4
42
|
// Get Stripe API key from context or environment
|
|
5
43
|
const apiKey = process.env.STRIPE_API_KEY;
|
package/lib/stripe/webhook.d.ts
CHANGED
|
@@ -68,4 +68,49 @@ export interface WebhookEndpoint extends Resource<"stripe::WebhookEndpoint">, We
|
|
|
68
68
|
*/
|
|
69
69
|
status: string;
|
|
70
70
|
}
|
|
71
|
-
|
|
71
|
+
/**
|
|
72
|
+
* Create and manage Stripe webhook endpoints
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* // Create a basic webhook for payment events
|
|
76
|
+
* const paymentWebhook = await WebhookEndpoint("payment-webhook", {
|
|
77
|
+
* url: "https://api.example.com/stripe/payments",
|
|
78
|
+
* enabledEvents: [
|
|
79
|
+
* "payment_intent.succeeded",
|
|
80
|
+
* "payment_intent.payment_failed"
|
|
81
|
+
* ],
|
|
82
|
+
* description: "Webhook for payment notifications"
|
|
83
|
+
* });
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* // Create a webhook for subscription management
|
|
87
|
+
* const subscriptionWebhook = await WebhookEndpoint("subscription-webhook", {
|
|
88
|
+
* url: "https://api.example.com/stripe/subscriptions",
|
|
89
|
+
* enabledEvents: [
|
|
90
|
+
* "customer.subscription.created",
|
|
91
|
+
* "customer.subscription.updated",
|
|
92
|
+
* "customer.subscription.deleted",
|
|
93
|
+
* "invoice.payment_succeeded",
|
|
94
|
+
* "invoice.payment_failed"
|
|
95
|
+
* ],
|
|
96
|
+
* description: "Webhook for subscription lifecycle events"
|
|
97
|
+
* });
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* // Create a webhook for Connect platform events
|
|
101
|
+
* const connectWebhook = await WebhookEndpoint("connect-webhook", {
|
|
102
|
+
* url: "https://api.example.com/stripe/connect",
|
|
103
|
+
* enabledEvents: [
|
|
104
|
+
* "account.updated",
|
|
105
|
+
* "account.application.deauthorized",
|
|
106
|
+
* "payout.created",
|
|
107
|
+
* "payout.failed"
|
|
108
|
+
* ],
|
|
109
|
+
* connect: true,
|
|
110
|
+
* metadata: {
|
|
111
|
+
* platform: "connect",
|
|
112
|
+
* environment: "production"
|
|
113
|
+
* }
|
|
114
|
+
* });
|
|
115
|
+
*/
|
|
116
|
+
export declare const WebhookEndpoint: (((this: any, id: string, props?: {}) => never) & (new (_: never) => never)) | ((this: Context<WebhookEndpoint>, id: string, props: WebhookEndpointProps) => Promise<WebhookEndpoint>);
|
package/lib/stripe/webhook.js
CHANGED
|
@@ -1,5 +1,50 @@
|
|
|
1
1
|
import Stripe from "stripe";
|
|
2
2
|
import { Resource } from "../resource";
|
|
3
|
+
/**
|
|
4
|
+
* Create and manage Stripe webhook endpoints
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* // Create a basic webhook for payment events
|
|
8
|
+
* const paymentWebhook = await WebhookEndpoint("payment-webhook", {
|
|
9
|
+
* url: "https://api.example.com/stripe/payments",
|
|
10
|
+
* enabledEvents: [
|
|
11
|
+
* "payment_intent.succeeded",
|
|
12
|
+
* "payment_intent.payment_failed"
|
|
13
|
+
* ],
|
|
14
|
+
* description: "Webhook for payment notifications"
|
|
15
|
+
* });
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* // Create a webhook for subscription management
|
|
19
|
+
* const subscriptionWebhook = await WebhookEndpoint("subscription-webhook", {
|
|
20
|
+
* url: "https://api.example.com/stripe/subscriptions",
|
|
21
|
+
* enabledEvents: [
|
|
22
|
+
* "customer.subscription.created",
|
|
23
|
+
* "customer.subscription.updated",
|
|
24
|
+
* "customer.subscription.deleted",
|
|
25
|
+
* "invoice.payment_succeeded",
|
|
26
|
+
* "invoice.payment_failed"
|
|
27
|
+
* ],
|
|
28
|
+
* description: "Webhook for subscription lifecycle events"
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* // Create a webhook for Connect platform events
|
|
33
|
+
* const connectWebhook = await WebhookEndpoint("connect-webhook", {
|
|
34
|
+
* url: "https://api.example.com/stripe/connect",
|
|
35
|
+
* enabledEvents: [
|
|
36
|
+
* "account.updated",
|
|
37
|
+
* "account.application.deauthorized",
|
|
38
|
+
* "payout.created",
|
|
39
|
+
* "payout.failed"
|
|
40
|
+
* ],
|
|
41
|
+
* connect: true,
|
|
42
|
+
* metadata: {
|
|
43
|
+
* platform: "connect",
|
|
44
|
+
* environment: "production"
|
|
45
|
+
* }
|
|
46
|
+
* });
|
|
47
|
+
*/
|
|
3
48
|
export const WebhookEndpoint = Resource("stripe::WebhookEndpoint", async function (id, props) {
|
|
4
49
|
// Get Stripe API key from context or environment
|
|
5
50
|
const apiKey = process.env.STRIPE_API_KEY;
|
package/lib/test/bun.d.ts
CHANGED
|
@@ -1,19 +1,83 @@
|
|
|
1
1
|
import type { Scope } from "../scope";
|
|
2
|
+
/**
|
|
3
|
+
* Extend the Alchemy interface to include test functionality
|
|
4
|
+
*/
|
|
2
5
|
declare module "../alchemy" {
|
|
3
6
|
interface Alchemy {
|
|
4
7
|
test: typeof test;
|
|
5
8
|
}
|
|
6
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Options for configuring test behavior
|
|
12
|
+
*/
|
|
7
13
|
export interface TestOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Whether to automatically destroy resources after test.
|
|
16
|
+
* @default true.
|
|
17
|
+
*/
|
|
8
18
|
destroy?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Whether to suppress logging output.
|
|
21
|
+
* @default false.
|
|
22
|
+
*/
|
|
9
23
|
quiet?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Password to use for test resources.
|
|
26
|
+
* @default "test-password".
|
|
27
|
+
*/
|
|
10
28
|
password?: string;
|
|
11
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Test function type definition with overloads
|
|
32
|
+
*/
|
|
12
33
|
type test = {
|
|
34
|
+
/**
|
|
35
|
+
* Create a test with default options
|
|
36
|
+
* @param name Test name
|
|
37
|
+
* @param fn Test function
|
|
38
|
+
* @param timeout Optional timeout in milliseconds
|
|
39
|
+
*/
|
|
13
40
|
(name: string, fn: (scope: Scope) => Promise<any>, timeout?: number): void;
|
|
41
|
+
/**
|
|
42
|
+
* Create a test with custom options
|
|
43
|
+
* @param name Test name
|
|
44
|
+
* @param options Test configuration options
|
|
45
|
+
* @param fn Test function
|
|
46
|
+
* @param timeout Optional timeout in milliseconds
|
|
47
|
+
*/
|
|
14
48
|
(name: string, options: TestOptions, fn: (scope: Scope) => Promise<any>, timeout?: number): void;
|
|
49
|
+
/**
|
|
50
|
+
* Skip test conditionally
|
|
51
|
+
* @param condition If true, test will be skipped
|
|
52
|
+
*/
|
|
15
53
|
skipIf(condition: boolean): test;
|
|
54
|
+
/**
|
|
55
|
+
* Current test scope
|
|
56
|
+
*/
|
|
16
57
|
scope: Scope;
|
|
17
58
|
};
|
|
59
|
+
/**
|
|
60
|
+
* Creates a test helper function that provides scoped resource management
|
|
61
|
+
*
|
|
62
|
+
* @param meta Import meta object from the test file
|
|
63
|
+
* @param defaultOptions Default options to apply to all tests
|
|
64
|
+
* @returns Test function with scope management
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```typescript
|
|
68
|
+
* const test = alchemy.test(import.meta);
|
|
69
|
+
*
|
|
70
|
+
* describe("My Resource", () => {
|
|
71
|
+
* test("create and delete", async (scope) => {
|
|
72
|
+
* try {
|
|
73
|
+
* const resource = await MyResource("test", { ... });
|
|
74
|
+
* expect(resource.id).toBeTruthy();
|
|
75
|
+
* } finally {
|
|
76
|
+
* await alchemy.destroy(scope);
|
|
77
|
+
* }
|
|
78
|
+
* });
|
|
79
|
+
* });
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
18
82
|
export declare function test(meta: ImportMeta, defaultOptions?: TestOptions): test;
|
|
19
83
|
export {};
|
package/lib/test/bun.js
CHANGED
|
@@ -3,9 +3,39 @@ import { afterAll, it } from "bun:test";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { alchemy } from "../alchemy";
|
|
5
5
|
import { destroy } from "../destroy";
|
|
6
|
+
/**
|
|
7
|
+
* Add test functionality to alchemy instance
|
|
8
|
+
*/
|
|
6
9
|
alchemy.test = test;
|
|
10
|
+
/**
|
|
11
|
+
* Global test scope for all tests
|
|
12
|
+
*/
|
|
7
13
|
const globalTestScope = alchemy.scope("test");
|
|
14
|
+
/**
|
|
15
|
+
* Creates a test helper function that provides scoped resource management
|
|
16
|
+
*
|
|
17
|
+
* @param meta Import meta object from the test file
|
|
18
|
+
* @param defaultOptions Default options to apply to all tests
|
|
19
|
+
* @returns Test function with scope management
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const test = alchemy.test(import.meta);
|
|
24
|
+
*
|
|
25
|
+
* describe("My Resource", () => {
|
|
26
|
+
* test("create and delete", async (scope) => {
|
|
27
|
+
* try {
|
|
28
|
+
* const resource = await MyResource("test", { ... });
|
|
29
|
+
* expect(resource.id).toBeTruthy();
|
|
30
|
+
* } finally {
|
|
31
|
+
* await alchemy.destroy(scope);
|
|
32
|
+
* }
|
|
33
|
+
* });
|
|
34
|
+
* });
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
8
37
|
export function test(meta, defaultOptions) {
|
|
38
|
+
// Add skipIf functionality
|
|
9
39
|
test.skipIf = (condition) => {
|
|
10
40
|
if (condition) {
|
|
11
41
|
// TODO: proxy through to bun:test.skipIf
|
|
@@ -13,10 +43,12 @@ export function test(meta, defaultOptions) {
|
|
|
13
43
|
}
|
|
14
44
|
return test;
|
|
15
45
|
};
|
|
46
|
+
// Create local test scope based on filename
|
|
16
47
|
const localTestScope = alchemy.scope(path.basename(meta.filename), {
|
|
17
48
|
parent: globalTestScope,
|
|
18
49
|
});
|
|
19
50
|
test.scope = localTestScope;
|
|
51
|
+
// Clean up test scope after all tests complete
|
|
20
52
|
afterAll(() => alchemy.destroy(test.scope));
|
|
21
53
|
return test;
|
|
22
54
|
function test(...args) {
|
|
@@ -25,8 +57,9 @@ export function test(meta, defaultOptions) {
|
|
|
25
57
|
const spread = (obj) => obj && typeof obj === "object"
|
|
26
58
|
? Object.fromEntries(Object.entries(obj).flatMap(([k, v]) => v !== undefined ? [[k, v]] : []))
|
|
27
59
|
: {};
|
|
60
|
+
// Merge options with defaults
|
|
28
61
|
const options = {
|
|
29
|
-
destroy:
|
|
62
|
+
destroy: true,
|
|
30
63
|
quiet: false,
|
|
31
64
|
password: "test-password",
|
|
32
65
|
...spread(defaultOptions),
|
|
@@ -38,14 +71,13 @@ export function test(meta, defaultOptions) {
|
|
|
38
71
|
parent: localTestScope,
|
|
39
72
|
}, async (scope) => {
|
|
40
73
|
return it(testName, async () => {
|
|
41
|
-
//
|
|
74
|
+
// Enter test scope since bun calls from different scope
|
|
42
75
|
scope.enter();
|
|
43
76
|
try {
|
|
44
77
|
await fn(scope);
|
|
45
78
|
}
|
|
46
79
|
finally {
|
|
47
80
|
if (options.destroy !== false) {
|
|
48
|
-
// TODO: auto-destroy resources
|
|
49
81
|
await destroy(scope);
|
|
50
82
|
}
|
|
51
83
|
}
|
package/lib/util/serde.js
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { Scope } from "../scope";
|
|
2
2
|
import { Secret } from "../secret";
|
|
3
3
|
import { decryptWithKey, encryptWithKey } from "./encrypt";
|
|
4
|
+
// zero-dependency type guard for ArkType
|
|
5
|
+
function isType(value) {
|
|
6
|
+
return (value &&
|
|
7
|
+
typeof value === "object" &&
|
|
8
|
+
typeof value.toJsonSchema === "function");
|
|
9
|
+
}
|
|
4
10
|
export async function serialize(scope, value, options) {
|
|
5
11
|
if (Array.isArray(value)) {
|
|
6
12
|
return Promise.all(value.map((value) => serialize(scope, value, options)));
|
|
@@ -15,6 +21,11 @@ export async function serialize(scope, value, options) {
|
|
|
15
21
|
: value.unencrypted,
|
|
16
22
|
};
|
|
17
23
|
}
|
|
24
|
+
else if (isType(value)) {
|
|
25
|
+
return {
|
|
26
|
+
"@schema": value.toJSON(),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
18
29
|
else if (value instanceof Scope) {
|
|
19
30
|
return undefined;
|
|
20
31
|
}
|
|
@@ -37,6 +48,9 @@ export async function deserialize(scope, value) {
|
|
|
37
48
|
}
|
|
38
49
|
return new Secret(await decryptWithKey(value["@secret"], scope.password));
|
|
39
50
|
}
|
|
51
|
+
else if ("@schema" in value) {
|
|
52
|
+
return value["@schema"];
|
|
53
|
+
}
|
|
40
54
|
else {
|
|
41
55
|
return Object.fromEntries(await Promise.all(Object.entries(value).map(async ([key, value]) => [
|
|
42
56
|
key,
|
package/lib/vite/vite.d.ts
CHANGED
|
@@ -86,5 +86,5 @@ export interface ViteProject extends ViteProjectProps, Resource {
|
|
|
86
86
|
*/
|
|
87
87
|
name: string;
|
|
88
88
|
}
|
|
89
|
-
export declare const ViteProject: ((this:
|
|
89
|
+
export declare const ViteProject: (((this: any, id: string, props?: {}) => never) & (new (_: never) => never)) | ((this: Context<ViteProject>, id: string, props: ViteProjectProps) => Promise<ViteProject>);
|
|
90
90
|
export {};
|
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
import type { Context } from "../context";
|
|
2
2
|
import { Resource } from "../resource";
|
|
3
3
|
export type InstallDependencies = Resource<"project::InstallDependencies">;
|
|
4
|
-
export declare const InstallDependencies: ((this: Context<InstallDependencies>, id: string, { cwd, dependencies, devDependencies, }: {
|
|
4
|
+
export declare const InstallDependencies: (((this: any, id: string, props?: {}) => never) & (new (_: never) => never)) | ((this: Context<InstallDependencies>, id: string, { cwd, dependencies, devDependencies, }: {
|
|
5
5
|
cwd: string;
|
|
6
6
|
dependencies?: Record<string, string>;
|
|
7
7
|
devDependencies?: Record<string, string>;
|
|
8
|
-
}) => Promise<InstallDependencies>)
|
|
9
|
-
cwd: string;
|
|
10
|
-
dependencies?: Record<string, string>;
|
|
11
|
-
devDependencies?: Record<string, string>;
|
|
12
|
-
} | undefined) => never) & (new (_: never) => never));
|
|
8
|
+
}) => Promise<InstallDependencies>);
|
|
13
9
|
export declare function fixedDependencies(dependencies?: Record<string, string>): {
|
|
14
10
|
[k: string]: string;
|
|
15
11
|
};
|
|
@@ -50,6 +50,17 @@ export interface VitePressProjectProps {
|
|
|
50
50
|
* The home page configuration
|
|
51
51
|
*/
|
|
52
52
|
home: HomePage;
|
|
53
|
+
/**
|
|
54
|
+
* Whether to delete the project folder during the delete phase
|
|
55
|
+
* @default true
|
|
56
|
+
*/
|
|
57
|
+
delete?: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* The directory to generate the docs in
|
|
60
|
+
*
|
|
61
|
+
* @default {@link name}
|
|
62
|
+
*/
|
|
63
|
+
dir?: string;
|
|
53
64
|
}
|
|
54
65
|
export interface VitePressProject extends VitePressProjectProps, Resource {
|
|
55
66
|
/**
|
|
@@ -57,4 +68,4 @@ export interface VitePressProject extends VitePressProjectProps, Resource {
|
|
|
57
68
|
*/
|
|
58
69
|
name: string;
|
|
59
70
|
}
|
|
60
|
-
export declare const VitePressProject: ((this:
|
|
71
|
+
export declare const VitePressProject: (((this: any, id: string, props?: {}) => never) & (new (_: never) => never)) | ((this: Context<VitePressProject>, id: string, props: VitePressProjectProps) => Promise<VitePressProject>);
|
|
@@ -10,11 +10,14 @@ const execAsync = promisify(exec);
|
|
|
10
10
|
export const VitePressProject = Resource("project::VitePressProject", {
|
|
11
11
|
alwaysUpdate: true,
|
|
12
12
|
}, async function (id, props) {
|
|
13
|
+
const dir = props.dir ?? props.name;
|
|
13
14
|
if (this.phase === "delete") {
|
|
14
15
|
try {
|
|
15
|
-
if (
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
if (props.delete !== false) {
|
|
17
|
+
if (await fs.exists(dir)) {
|
|
18
|
+
// Delete the entire project directory
|
|
19
|
+
await execAsync(`rm -rf ${dir}`);
|
|
20
|
+
}
|
|
18
21
|
}
|
|
19
22
|
}
|
|
20
23
|
catch (error) {
|
|
@@ -22,7 +25,10 @@ export const VitePressProject = Resource("project::VitePressProject", {
|
|
|
22
25
|
}
|
|
23
26
|
return this.destroy();
|
|
24
27
|
}
|
|
25
|
-
const cwd = (await Folder(
|
|
28
|
+
const cwd = (await Folder("dir", {
|
|
29
|
+
path: dir,
|
|
30
|
+
delete: props.delete,
|
|
31
|
+
})).path;
|
|
26
32
|
// Initialize package.json
|
|
27
33
|
await JsonFile(path.join(cwd, "package.json"), {
|
|
28
34
|
name: props.name,
|
|
@@ -57,25 +63,25 @@ export const VitePressProject = Resource("project::VitePressProject", {
|
|
|
57
63
|
compilerOptions: props.tsconfig?.compilerOptions,
|
|
58
64
|
}),
|
|
59
65
|
TextFile(path.join(cwd, "index.md"), `---\n${yaml.stringify(props.home)}---\n`),
|
|
60
|
-
TypeScriptFile(
|
|
61
|
-
|
|
62
|
-
import
|
|
63
|
-
import
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const docs = await Folder(path.join("alchemy.run", "docs"));
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
66
|
+
// TypeScriptFile(
|
|
67
|
+
// path.join(cwd, "alchemy.run.ts"),
|
|
68
|
+
// `import alchemy from "alchemy";
|
|
69
|
+
// import { Folder } from "alchemy/fs";
|
|
70
|
+
// import { Document } from "alchemy/docs";
|
|
71
|
+
// import path from "path";
|
|
72
|
+
// await using _ = alchemy("alchemy.run", {
|
|
73
|
+
// stage: "prod",
|
|
74
|
+
// phase: process.argv.includes("--destroy") ? "destroy" : "up",
|
|
75
|
+
// password: process.env.SECRET_PASSPHRASE,
|
|
76
|
+
// quiet: !process.argv.includes("--verbose"),
|
|
77
|
+
// });
|
|
78
|
+
// const docs = await Folder(path.join("alchemy.run", "docs"));
|
|
79
|
+
// await Document("home.md", {
|
|
80
|
+
// path: path.join(docs.path, "home.md"),
|
|
81
|
+
// prompt: await alchemy\`Generate a landing page.\`,
|
|
82
|
+
// });
|
|
83
|
+
// `,
|
|
84
|
+
// ),
|
|
79
85
|
TypeScriptFile(path.join(cwd, ".vitepress", "theme", "index.ts"), `import TwoslashFloatingVue from "@shikijs/vitepress-twoslash/client";
|
|
80
86
|
import "@shikijs/vitepress-twoslash/style.css";
|
|
81
87
|
import type { Theme as ThemeConfig } from "vitepress";
|
package/package.json
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "alchemy",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"module": "./lib/index.js",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"publish:npm": "cp ../README.md . && rm -rf ./*.tsbuildinfo && rm -rf ./lib && tsc -b && npm publish && rm README.md"
|
|
7
|
+
"publish:npm": "cp ../README.md . && rm -rf ./*.tsbuildinfo && rm -rf ./lib && tsc -b && npm publish && rm README.md",
|
|
8
|
+
"docs:gen": "rm -rf ./docs && typedoc"
|
|
8
9
|
},
|
|
9
10
|
"files": ["lib", "src"],
|
|
10
11
|
"exports": {
|
|
11
12
|
".": "./lib/index.js",
|
|
13
|
+
"./ai": "./lib/ai/index.js",
|
|
12
14
|
"./aws": "./lib/aws/index.js",
|
|
13
15
|
"./aws/oidc": "./lib/aws/oidc/index.js",
|
|
14
16
|
"./cloudflare": "./lib/cloudflare/index.js",
|
|
15
|
-
"./docs": "./lib/docs/index.js",
|
|
16
17
|
"./esbuild": "./lib/esbuild/index.js",
|
|
17
18
|
"./fs": "./lib/fs/index.js",
|
|
18
19
|
"./github": "./lib/github/index.js",
|
|
@@ -33,6 +34,7 @@
|
|
|
33
34
|
"@aws-sdk/client-sesv2": "^3.0.0",
|
|
34
35
|
"@aws-sdk/client-sqs": "^3.0.0",
|
|
35
36
|
"@aws-sdk/client-sts": "^3.0.0",
|
|
37
|
+
"arktype": "^2.0.0",
|
|
36
38
|
"prettier": "^3.0.0",
|
|
37
39
|
"@octokit/rest": "^21.1.1",
|
|
38
40
|
"ai": "^4.0.0",
|
|
@@ -59,11 +61,14 @@
|
|
|
59
61
|
"@types/node": "latest",
|
|
60
62
|
"@types/turndown": "^5.0.5",
|
|
61
63
|
"ai": "^4.1.16",
|
|
64
|
+
"arktype": "^2.1.16",
|
|
62
65
|
"change-case": "^5.4.4",
|
|
63
66
|
"libsodium-wrappers": "^0.7.15",
|
|
64
67
|
"openpgp": "^6.1.0",
|
|
65
68
|
"prettier": "^3.5.3",
|
|
66
69
|
"turndown": "^7.2.0",
|
|
70
|
+
"typedoc": "^0.28.1",
|
|
71
|
+
"typedoc-plugin-markdown": "^4.6.0",
|
|
67
72
|
"typescript": "latest",
|
|
68
73
|
"vite": "^6.0.7",
|
|
69
74
|
"vitepress": "^1.6.3",
|