alchemy 0.2.2 → 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/ai/index.d.ts +2 -0
- package/lib/ai/index.js +2 -0
- package/lib/ai/object.d.ts +101 -0
- package/lib/ai/object.js +70 -0
- package/lib/alchemy.d.ts +84 -2
- package/lib/alchemy.js +114 -10
- package/lib/apply.d.ts +1 -1
- package/lib/apply.js +13 -10
- 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/context.d.ts +9 -4
- package/lib/context.js +4 -2
- package/lib/destroy.js +9 -8
- 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 +78 -5
- package/lib/fs/file.js +39 -3
- package/lib/fs/folder.d.ts +37 -5
- package/lib/fs/folder.js +28 -3
- 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 +2 -2
- package/lib/resource.js +4 -0
- package/lib/scope.d.ts +1 -1
- package/lib/scope.js +6 -6
- package/lib/secret.d.ts +67 -0
- package/lib/secret.js +67 -0
- package/lib/shadcn/component.d.ts +1 -1
- package/lib/state.d.ts +1 -1
- package/lib/state.js +8 -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.d.ts +3 -1
- package/lib/util/serde.js +20 -4
- package/lib/vite/vite.d.ts +1 -1
- package/lib/vitepress/dependencies.d.ts +12 -0
- package/lib/vitepress/dependencies.js +35 -0
- package/lib/vitepress/home-page.d.ts +133 -0
- package/lib/vitepress/home-page.js +11 -0
- package/lib/vitepress/index.d.ts +2 -0
- package/lib/vitepress/index.js +2 -0
- package/lib/vitepress/vitepress.d.ts +71 -0
- package/lib/vitepress/vitepress.js +266 -0
- package/package.json +22 -10
- package/src/ai/ark.ts +118 -0
- package/src/ai/client.ts +78 -0
- package/src/ai/document.ts +160 -0
- package/src/ai/index.ts +2 -0
- package/src/ai/object.ts +149 -0
- package/src/alchemy.ts +192 -17
- package/src/apply.ts +25 -13
- 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/context.ts +30 -10
- package/src/destroy.ts +11 -8
- 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 +107 -6
- package/src/fs/folder.ts +45 -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 +7 -2
- package/src/scope.ts +9 -9
- package/src/secret.ts +67 -0
- package/src/state.ts +9 -2
- 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 +30 -4
- package/src/vitepress/dependencies.ts +68 -0
- package/src/vitepress/home-page.ts +166 -0
- package/src/vitepress/index.md +75 -0
- package/src/vitepress/index.ts +2 -0
- package/src/vitepress/vitepress.ts +382 -0
- package/lib/project/vite.d.ts +0 -90
- package/lib/project/vite.js +0 -228
- package/src/project/vite.ts +0 -406
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.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import { Scope } from "../scope";
|
|
2
|
-
export declare function serialize(scope: Scope, value: any
|
|
2
|
+
export declare function serialize(scope: Scope, value: any, options?: {
|
|
3
|
+
encrypt?: boolean;
|
|
4
|
+
}): Promise<any>;
|
|
3
5
|
export declare function deserialize(scope: Scope, value: any): Promise<any>;
|
package/lib/util/serde.js
CHANGED
|
@@ -1,16 +1,29 @@
|
|
|
1
1
|
import { Scope } from "../scope";
|
|
2
2
|
import { Secret } from "../secret";
|
|
3
3
|
import { decryptWithKey, encryptWithKey } from "./encrypt";
|
|
4
|
-
|
|
4
|
+
// zero-dependency type guard for ArkType
|
|
5
|
+
function isType(value) {
|
|
6
|
+
return (value &&
|
|
7
|
+
typeof value === "object" &&
|
|
8
|
+
typeof value.toJsonSchema === "function");
|
|
9
|
+
}
|
|
10
|
+
export async function serialize(scope, value, options) {
|
|
5
11
|
if (Array.isArray(value)) {
|
|
6
|
-
return Promise.all(value.map((value) => serialize(scope, value)));
|
|
12
|
+
return Promise.all(value.map((value) => serialize(scope, value, options)));
|
|
7
13
|
}
|
|
8
14
|
else if (value instanceof Secret) {
|
|
9
15
|
if (!scope.password) {
|
|
10
16
|
throw new Error("Cannot serialize secret without password");
|
|
11
17
|
}
|
|
12
18
|
return {
|
|
13
|
-
"@secret":
|
|
19
|
+
"@secret": options?.encrypt !== false
|
|
20
|
+
? await encryptWithKey(value.unencrypted, scope.password)
|
|
21
|
+
: value.unencrypted,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
else if (isType(value)) {
|
|
25
|
+
return {
|
|
26
|
+
"@schema": value.toJSON(),
|
|
14
27
|
};
|
|
15
28
|
}
|
|
16
29
|
else if (value instanceof Scope) {
|
|
@@ -19,7 +32,7 @@ export async function serialize(scope, value) {
|
|
|
19
32
|
else if (value && typeof value === "object") {
|
|
20
33
|
return Object.fromEntries(await Promise.all(Object.entries(value).map(async ([key, value]) => [
|
|
21
34
|
key,
|
|
22
|
-
await serialize(scope, value),
|
|
35
|
+
await serialize(scope, value, options),
|
|
23
36
|
])));
|
|
24
37
|
}
|
|
25
38
|
return value;
|
|
@@ -35,6 +48,9 @@ export async function deserialize(scope, value) {
|
|
|
35
48
|
}
|
|
36
49
|
return new Secret(await decryptWithKey(value["@secret"], scope.password));
|
|
37
50
|
}
|
|
51
|
+
else if ("@schema" in value) {
|
|
52
|
+
return value["@schema"];
|
|
53
|
+
}
|
|
38
54
|
else {
|
|
39
55
|
return Object.fromEntries(await Promise.all(Object.entries(value).map(async ([key, value]) => [
|
|
40
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 {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Context } from "../context";
|
|
2
|
+
import { Resource } from "../resource";
|
|
3
|
+
export type InstallDependencies = Resource<"project::InstallDependencies">;
|
|
4
|
+
export declare const InstallDependencies: (((this: any, id: string, props?: {}) => never) & (new (_: never) => never)) | ((this: Context<InstallDependencies>, id: string, { cwd, dependencies, devDependencies, }: {
|
|
5
|
+
cwd: string;
|
|
6
|
+
dependencies?: Record<string, string>;
|
|
7
|
+
devDependencies?: Record<string, string>;
|
|
8
|
+
}) => Promise<InstallDependencies>);
|
|
9
|
+
export declare function fixedDependencies(dependencies?: Record<string, string>): {
|
|
10
|
+
[k: string]: string;
|
|
11
|
+
};
|
|
12
|
+
export declare function installDependencies(cwd: string, dependencies: Record<string, string> | undefined, ...args: string[]): Promise<void>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { exec } from "child_process";
|
|
2
|
+
import { promisify } from "util";
|
|
3
|
+
import { Resource } from "../resource";
|
|
4
|
+
const execAsync = promisify(exec);
|
|
5
|
+
export const InstallDependencies = Resource("project::InstallDependencies", {
|
|
6
|
+
alwaysUpdate: true,
|
|
7
|
+
}, async function (id, { cwd, dependencies, devDependencies, }) {
|
|
8
|
+
if (this.phase === "delete") {
|
|
9
|
+
return this.destroy();
|
|
10
|
+
}
|
|
11
|
+
await installDependencies(cwd, dependencies);
|
|
12
|
+
await installDependencies(cwd, devDependencies, "-D");
|
|
13
|
+
await execAsync("bun install", { cwd });
|
|
14
|
+
return this({});
|
|
15
|
+
});
|
|
16
|
+
function isInstallableVersion(version) {
|
|
17
|
+
// TODO: file:// ?
|
|
18
|
+
return !version.startsWith("workspace:");
|
|
19
|
+
}
|
|
20
|
+
export function fixedDependencies(dependencies) {
|
|
21
|
+
if (!dependencies)
|
|
22
|
+
return {};
|
|
23
|
+
return Object.fromEntries(Object.entries(dependencies).filter(([, value]) => !isInstallableVersion(value)));
|
|
24
|
+
}
|
|
25
|
+
export async function installDependencies(cwd, dependencies, ...args) {
|
|
26
|
+
if (!dependencies)
|
|
27
|
+
return;
|
|
28
|
+
const deps = Object.entries(dependencies)
|
|
29
|
+
.filter(([, value]) => isInstallableVersion(value))
|
|
30
|
+
.map(([pkg, version]) => `${pkg}@${version}`)
|
|
31
|
+
.join(" ");
|
|
32
|
+
const cmd = `bun add ${args.join(" ")} ${deps}`;
|
|
33
|
+
console.log(cmd);
|
|
34
|
+
await execAsync(cmd, { cwd });
|
|
35
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image that can be themed for light/dark mode
|
|
3
|
+
*/
|
|
4
|
+
export interface ThemeableImage {
|
|
5
|
+
/**
|
|
6
|
+
* Image source URL
|
|
7
|
+
*/
|
|
8
|
+
src?: string;
|
|
9
|
+
/**
|
|
10
|
+
* Image alt text
|
|
11
|
+
*/
|
|
12
|
+
alt?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Light theme image URL
|
|
15
|
+
*/
|
|
16
|
+
light?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Dark theme image URL
|
|
19
|
+
*/
|
|
20
|
+
dark?: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Hero action button configuration
|
|
24
|
+
*/
|
|
25
|
+
export interface HeroAction {
|
|
26
|
+
/**
|
|
27
|
+
* Color theme of the button
|
|
28
|
+
* @default "brand"
|
|
29
|
+
*/
|
|
30
|
+
theme?: "brand" | "alt";
|
|
31
|
+
/**
|
|
32
|
+
* Label of the button
|
|
33
|
+
*/
|
|
34
|
+
text: string;
|
|
35
|
+
/**
|
|
36
|
+
* Destination link of the button
|
|
37
|
+
*/
|
|
38
|
+
link: string;
|
|
39
|
+
/**
|
|
40
|
+
* Link target attribute
|
|
41
|
+
*/
|
|
42
|
+
target?: string;
|
|
43
|
+
/**
|
|
44
|
+
* Link rel attribute
|
|
45
|
+
*/
|
|
46
|
+
rel?: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Hero section configuration
|
|
50
|
+
*/
|
|
51
|
+
export interface Hero {
|
|
52
|
+
/**
|
|
53
|
+
* The string shown top of text. Comes with brand color
|
|
54
|
+
* and expected to be short, such as product name.
|
|
55
|
+
*/
|
|
56
|
+
name?: string;
|
|
57
|
+
/**
|
|
58
|
+
* The main text for the hero section. This will be defined
|
|
59
|
+
* as h1 tag.
|
|
60
|
+
*/
|
|
61
|
+
text: string;
|
|
62
|
+
/**
|
|
63
|
+
* Tagline displayed below text
|
|
64
|
+
*/
|
|
65
|
+
tagline?: string;
|
|
66
|
+
/**
|
|
67
|
+
* The image displayed next to the text and tagline area
|
|
68
|
+
*/
|
|
69
|
+
image?: string | ThemeableImage;
|
|
70
|
+
/**
|
|
71
|
+
* Action buttons to display in home hero section
|
|
72
|
+
*/
|
|
73
|
+
actions?: HeroAction[];
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Feature item configuration
|
|
77
|
+
*/
|
|
78
|
+
export interface Feature {
|
|
79
|
+
/**
|
|
80
|
+
* Show icon on each feature box
|
|
81
|
+
*/
|
|
82
|
+
icon?: string | ThemeableImage;
|
|
83
|
+
/**
|
|
84
|
+
* Title of the feature
|
|
85
|
+
*/
|
|
86
|
+
title: string;
|
|
87
|
+
/**
|
|
88
|
+
* Details of the feature
|
|
89
|
+
*/
|
|
90
|
+
details: string;
|
|
91
|
+
/**
|
|
92
|
+
* Link when clicked on feature component
|
|
93
|
+
*/
|
|
94
|
+
link?: string;
|
|
95
|
+
/**
|
|
96
|
+
* Link text to be shown inside feature component
|
|
97
|
+
*/
|
|
98
|
+
linkText?: string;
|
|
99
|
+
/**
|
|
100
|
+
* Link rel attribute
|
|
101
|
+
*/
|
|
102
|
+
rel?: string;
|
|
103
|
+
/**
|
|
104
|
+
* Link target attribute
|
|
105
|
+
*/
|
|
106
|
+
target?: string;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* VitePress home page configuration
|
|
110
|
+
*/
|
|
111
|
+
export interface HomePage {
|
|
112
|
+
/**
|
|
113
|
+
* Use home page layout
|
|
114
|
+
*/
|
|
115
|
+
layout: "home";
|
|
116
|
+
/**
|
|
117
|
+
* Hero section configuration
|
|
118
|
+
*/
|
|
119
|
+
hero?: Hero;
|
|
120
|
+
/**
|
|
121
|
+
* Features section configuration
|
|
122
|
+
*/
|
|
123
|
+
features?: Feature[];
|
|
124
|
+
/**
|
|
125
|
+
* Whether to apply default markdown styles
|
|
126
|
+
* @default true
|
|
127
|
+
*/
|
|
128
|
+
markdownStyles?: boolean;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Parse YAML frontmatter to home page config
|
|
132
|
+
*/
|
|
133
|
+
export declare function parseHomePage(content: string): HomePage;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import yaml from "yaml";
|
|
2
|
+
/**
|
|
3
|
+
* Parse YAML frontmatter to home page config
|
|
4
|
+
*/
|
|
5
|
+
export function parseHomePage(content) {
|
|
6
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
7
|
+
if (!match) {
|
|
8
|
+
throw new Error("Invalid frontmatter format");
|
|
9
|
+
}
|
|
10
|
+
return yaml.parse(match[1]);
|
|
11
|
+
}
|