alchemy 0.2.5 → 0.3.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.
Files changed (151) hide show
  1. package/README.md +3 -3
  2. package/lib/ai/astro-file.d.ts +137 -0
  3. package/lib/ai/astro-file.js +173 -0
  4. package/lib/ai/client.d.ts +2 -10
  5. package/lib/ai/client.js +8 -24
  6. package/lib/ai/css-file.d.ts +131 -0
  7. package/lib/ai/css-file.js +158 -0
  8. package/lib/ai/data.d.ts +45 -5
  9. package/lib/ai/data.js +45 -10
  10. package/lib/ai/document.d.ts +44 -20
  11. package/lib/ai/document.js +95 -28
  12. package/lib/ai/html-file.d.ts +128 -0
  13. package/lib/ai/html-file.js +155 -0
  14. package/lib/ai/index.d.ts +7 -0
  15. package/lib/ai/index.js +7 -0
  16. package/lib/ai/json-file.d.ts +160 -0
  17. package/lib/ai/json-file.js +208 -0
  18. package/lib/ai/typescript-file.d.ts +140 -0
  19. package/lib/ai/typescript-file.js +176 -0
  20. package/lib/ai/vue-file.d.ts +126 -0
  21. package/lib/ai/vue-file.js +153 -0
  22. package/lib/ai/yaml-file.d.ts +169 -0
  23. package/lib/ai/yaml-file.js +236 -0
  24. package/lib/cloudflare/dns.d.ts +88 -0
  25. package/lib/cloudflare/dns.js +192 -0
  26. package/lib/cloudflare/index.d.ts +2 -1
  27. package/lib/cloudflare/index.js +2 -1
  28. package/lib/cloudflare/r2-rest-state-store.d.ts +125 -0
  29. package/lib/cloudflare/r2-rest-state-store.js +254 -0
  30. package/lib/cloudflare/response.d.ts +12 -0
  31. package/lib/cloudflare/response.js +0 -0
  32. package/lib/cloudflare/zone.d.ts +18 -0
  33. package/lib/cloudflare/zone.js +17 -4
  34. package/lib/dns/godaddy.d.ts +7 -0
  35. package/lib/dns/godaddy.js +21 -0
  36. package/lib/dns/import-dns.d.ts +82 -0
  37. package/lib/dns/import-dns.js +114 -0
  38. package/lib/dns/index.d.ts +2 -0
  39. package/lib/dns/index.js +2 -0
  40. package/lib/dns/record.d.ts +88 -0
  41. package/lib/dns/record.js +13 -0
  42. package/lib/fs/file-system-state-store.d.ts +17 -0
  43. package/lib/fs/file-system-state-store.js +87 -0
  44. package/lib/fs/folder.d.ts +10 -0
  45. package/lib/fs/folder.js +2 -2
  46. package/lib/fs/index.d.ts +4 -4
  47. package/lib/fs/index.js +4 -4
  48. package/lib/fs/{json-file.d.ts → static-json-file.d.ts} +2 -2
  49. package/lib/fs/static-json-file.js +14 -0
  50. package/lib/fs/{text-file.d.ts → static-text-file.d.ts} +2 -2
  51. package/lib/fs/{text-file.js → static-text-file.js} +1 -1
  52. package/lib/fs/{typescript-file.d.ts → static-typescript-file.d.ts} +2 -2
  53. package/lib/fs/{typescript-file.js → static-typescript-file.js} +1 -1
  54. package/lib/fs/{yaml-file.d.ts → static-yaml-file.d.ts} +2 -2
  55. package/lib/fs/{yaml-file.js → static-yaml-file.js} +1 -1
  56. package/lib/internal/getting-started.d.ts +10 -0
  57. package/lib/internal/getting-started.js +94 -0
  58. package/lib/internal/project.d.ts +13 -0
  59. package/lib/internal/project.js +101 -0
  60. package/lib/internal/providers.d.ts +23 -0
  61. package/lib/internal/providers.js +148 -0
  62. package/lib/resource.js +8 -1
  63. package/lib/scope.d.ts +1 -1
  64. package/lib/scope.js +4 -2
  65. package/lib/state.d.ts +1 -16
  66. package/lib/state.js +0 -87
  67. package/lib/test/bun.d.ts +11 -0
  68. package/lib/test/bun.js +36 -8
  69. package/lib/web/astro.d.ts +147 -0
  70. package/lib/web/astro.js +414 -0
  71. package/lib/{shadcn/component.js → web/shadcn-component.js} +2 -9
  72. package/lib/web/shadcn.d.ts +97 -0
  73. package/lib/web/shadcn.js +99 -0
  74. package/lib/web/tailwind.d.ts +64 -0
  75. package/lib/web/tailwind.js +97 -0
  76. package/lib/{vite → web}/vite.d.ts +5 -0
  77. package/lib/{vite → web}/vite.js +44 -44
  78. package/lib/web/vitepress/custom-theme.d.ts +173 -0
  79. package/lib/web/vitepress/custom-theme.js +336 -0
  80. package/lib/{vitepress → web/vitepress}/dependencies.d.ts +2 -2
  81. package/lib/{vitepress → web/vitepress}/dependencies.js +1 -1
  82. package/lib/web/vitepress/home-page.d.ts +244 -0
  83. package/lib/web/vitepress/home-page.js +134 -0
  84. package/lib/{vitepress → web/vitepress}/index.d.ts +1 -0
  85. package/lib/{vitepress → web/vitepress}/index.js +1 -0
  86. package/lib/{vitepress → web/vitepress}/vitepress.d.ts +10 -8
  87. package/lib/{vitepress → web/vitepress}/vitepress.js +11 -12
  88. package/package.json +6 -2
  89. package/src/ai/astro-file.ts +288 -0
  90. package/src/ai/client.ts +8 -28
  91. package/src/ai/css-file.ts +266 -0
  92. package/src/ai/data.ts +53 -16
  93. package/src/ai/document.ts +130 -33
  94. package/src/ai/html-file.ts +263 -0
  95. package/src/ai/index.ts +7 -0
  96. package/src/ai/json-file.ts +349 -0
  97. package/src/ai/typescript-file.ts +293 -0
  98. package/src/ai/vue-file.ts +261 -0
  99. package/src/ai/yaml-file.ts +368 -0
  100. package/src/apply.ts +0 -1
  101. package/src/cloudflare/dns.ts +344 -0
  102. package/src/cloudflare/index.ts +2 -1
  103. package/src/cloudflare/r2-rest-state-store.ts +353 -0
  104. package/src/cloudflare/response.ts +9 -0
  105. package/src/cloudflare/zone.ts +39 -23
  106. package/src/dns/godaddy.ts +29 -0
  107. package/src/dns/import-dns.ts +213 -0
  108. package/src/dns/index.ts +2 -0
  109. package/src/dns/record.ts +121 -0
  110. package/src/fs/file-system-state-store.ts +109 -0
  111. package/src/fs/folder.ts +14 -2
  112. package/src/fs/index.ts +4 -4
  113. package/src/fs/{json-file.ts → static-json-file.ts} +13 -3
  114. package/src/fs/{text-file.ts → static-text-file.ts} +5 -2
  115. package/src/fs/{typescript-file.ts → static-typescript-file.ts} +3 -3
  116. package/src/fs/{yaml-file.ts → static-yaml-file.ts} +5 -2
  117. package/src/internal/getting-started.ts +107 -0
  118. package/src/internal/project.ts +119 -0
  119. package/src/internal/providers.ts +209 -0
  120. package/src/resource.ts +10 -1
  121. package/src/scope.ts +5 -6
  122. package/src/state.ts +1 -111
  123. package/src/test/bun.ts +60 -10
  124. package/src/web/astro.ts +644 -0
  125. package/src/{shadcn/component.ts → web/shadcn-component.ts} +5 -13
  126. package/src/web/shadcn.ts +219 -0
  127. package/src/web/tailwind.ts +167 -0
  128. package/src/{vite → web}/vite.ts +54 -56
  129. package/src/web/vitepress/custom-theme.ts +514 -0
  130. package/src/{vitepress → web/vitepress}/dependencies.ts +2 -2
  131. package/src/web/vitepress/home-page.ts +363 -0
  132. package/src/{vitepress → web/vitepress}/index.ts +1 -0
  133. package/src/{vitepress → web/vitepress}/vitepress.ts +34 -27
  134. package/lib/cloudflare/state.d.ts +0 -82
  135. package/lib/cloudflare/state.js +0 -108
  136. package/lib/fs/json-file.js +0 -7
  137. package/lib/internal/docs.d.ts +0 -5
  138. package/lib/internal/docs.js +0 -287
  139. package/lib/shadcn/index.d.ts +0 -1
  140. package/lib/shadcn/index.js +0 -1
  141. package/lib/vite/index.d.ts +0 -1
  142. package/lib/vite/index.js +0 -1
  143. package/lib/vitepress/home-page.d.ts +0 -133
  144. package/lib/vitepress/home-page.js +0 -11
  145. package/src/cloudflare/state.ts +0 -138
  146. package/src/internal/docs.ts +0 -338
  147. package/src/shadcn/index.ts +0 -1
  148. package/src/vite/index.ts +0 -1
  149. package/src/vitepress/home-page.ts +0 -166
  150. /package/lib/{shadcn/component.d.ts → web/shadcn-component.d.ts} +0 -0
  151. /package/src/{vitepress → web/vitepress}/index.md +0 -0
package/lib/state.d.ts CHANGED
@@ -11,7 +11,7 @@ export interface State<Kind extends string = string, Props extends ResourceProps
11
11
  oldProps?: Props;
12
12
  output: Out;
13
13
  }
14
- export type StateStoreType = new (scope: Scope) => StateStore;
14
+ export type StateStoreType = (scope: Scope) => StateStore;
15
15
  export interface StateStore {
16
16
  /** Initialize the state container if one is required */
17
17
  init?(): Promise<void>;
@@ -27,18 +27,3 @@ export interface StateStore {
27
27
  set(key: string, value: State): Promise<void>;
28
28
  delete(key: string): Promise<void>;
29
29
  }
30
- export declare class FileSystemStateStore implements StateStore {
31
- readonly scope: Scope;
32
- readonly dir: string;
33
- constructor(scope: Scope);
34
- init(): Promise<void>;
35
- deinit(): Promise<void>;
36
- count(): Promise<number>;
37
- list(): Promise<string[]>;
38
- get(key: string): Promise<State | undefined>;
39
- set(key: string, value: State): Promise<void>;
40
- delete(key: string): Promise<void>;
41
- all(): Promise<Record<string, State>>;
42
- getBatch(ids: string[]): Promise<Record<string, State>>;
43
- private getPath;
44
- }
package/lib/state.js CHANGED
@@ -1,87 +0,0 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- import { ignore } from "./util/ignore";
4
- import { deserialize, serialize } from "./util/serde";
5
- const stateRootDir = path.join(process.cwd(), ".alchemy");
6
- export class FileSystemStateStore {
7
- scope;
8
- dir;
9
- constructor(scope) {
10
- this.scope = scope;
11
- this.dir = path.join(stateRootDir, ...scope.chain);
12
- }
13
- async init() {
14
- await fs.promises.mkdir(stateRootDir, { recursive: true });
15
- await fs.promises.mkdir(this.dir, { recursive: true });
16
- }
17
- async deinit() {
18
- await ignore("ENOENT", () => fs.promises.rmdir(this.dir));
19
- }
20
- async count() {
21
- return Object.keys(await this.list()).length;
22
- }
23
- async list() {
24
- try {
25
- const files = await fs.promises.readdir(this.dir, {
26
- withFileTypes: true,
27
- });
28
- return files
29
- .filter((dirent) => dirent.isFile() && dirent.name.endsWith(".json"))
30
- .map((dirent) => dirent.name.replace(/\.json$/, ""))
31
- .map((key) => key.replaceAll(":", "/"));
32
- }
33
- catch (error) {
34
- if (error.code === "ENOENT") {
35
- return [];
36
- }
37
- throw error;
38
- }
39
- }
40
- async get(key) {
41
- try {
42
- const content = await fs.promises.readFile(await this.getPath(key), "utf8");
43
- const state = (await deserialize(this.scope, JSON.parse(content)));
44
- if (state.output === undefined) {
45
- state.output = {};
46
- }
47
- state.output.Scope = this.scope;
48
- return state;
49
- }
50
- catch (error) {
51
- if (error.code === "ENOENT") {
52
- return undefined;
53
- }
54
- throw error;
55
- }
56
- }
57
- async set(key, value) {
58
- return fs.promises.writeFile(await this.getPath(key), JSON.stringify(await serialize(this.scope, value), null, 2));
59
- }
60
- async delete(key) {
61
- return fs.promises.unlink(await this.getPath(key));
62
- }
63
- async all() {
64
- return this.getBatch(await this.list());
65
- }
66
- async getBatch(ids) {
67
- return Object.fromEntries((await Promise.all(Array.from(ids).flatMap(async (id) => {
68
- const s = await this.get(id);
69
- if (s === undefined) {
70
- return [];
71
- }
72
- return [[id, s]];
73
- }))).flat());
74
- }
75
- async getPath(key) {
76
- if (key.includes(":")) {
77
- throw new Error(`ID cannot include colons: ${key}`);
78
- }
79
- if (key.includes("/")) {
80
- key = key.replaceAll("/", ":");
81
- }
82
- const file = path.join(this.dir, `${key}.json`);
83
- const dir = path.dirname(file);
84
- await fs.promises.mkdir(dir, { recursive: true });
85
- return file;
86
- }
87
- }
package/lib/test/bun.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { Scope } from "../scope";
2
+ import type { StateStoreType } from "../state";
2
3
  /**
3
4
  * Extend the Alchemy interface to include test functionality
4
5
  */
@@ -26,6 +27,14 @@ export interface TestOptions {
26
27
  * @default "test-password".
27
28
  */
28
29
  password?: string;
30
+ /**
31
+ * Override the default state store for the test.
32
+ */
33
+ stateStore?: StateStoreType;
34
+ /**
35
+ * Prefix to use for the scope to isolate tests and environments.
36
+ */
37
+ prefix?: string;
29
38
  }
30
39
  /**
31
40
  * Test function type definition with overloads
@@ -51,6 +60,8 @@ type test = {
51
60
  * @param condition If true, test will be skipped
52
61
  */
53
62
  skipIf(condition: boolean): test;
63
+ beforeAll(fn: (scope: Scope) => Promise<void>): void;
64
+ afterAll(fn: (scope: Scope) => Promise<void>): void;
54
65
  /**
55
66
  * Current test scope
56
67
  */
package/lib/test/bun.js CHANGED
@@ -1,16 +1,13 @@
1
1
  /// <reference types="bun" />
2
- import { afterAll, it } from "bun:test";
2
+ import { afterAll, beforeAll, it } from "bun:test";
3
3
  import path from "node:path";
4
4
  import { alchemy } from "../alchemy";
5
+ import { R2RestStateStore } from "../cloudflare";
5
6
  import { destroy } from "../destroy";
6
7
  /**
7
8
  * Add test functionality to alchemy instance
8
9
  */
9
10
  alchemy.test = test;
10
- /**
11
- * Global test scope for all tests
12
- */
13
- const globalTestScope = alchemy.scope("test");
14
11
  /**
15
12
  * Creates a test helper function that provides scoped resource management
16
13
  *
@@ -35,6 +32,16 @@ const globalTestScope = alchemy.scope("test");
35
32
  * ```
36
33
  */
37
34
  export function test(meta, defaultOptions) {
35
+ defaultOptions = defaultOptions ?? {};
36
+ if (defaultOptions.stateStore === undefined &&
37
+ // process.env.CI &&
38
+ process.env.ALCHEMY_STATE_STORE === "cloudflare") {
39
+ defaultOptions.stateStore = (scope) => new R2RestStateStore(scope, {
40
+ apiKey: process.env.CLOUDFLARE_API_KEY,
41
+ email: process.env.CLOUDFLARE_EMAIL,
42
+ bucketName: process.env.CLOUDFLARE_BUCKET_NAME,
43
+ });
44
+ }
38
45
  // Add skipIf functionality
39
46
  test.skipIf = (condition) => {
40
47
  if (condition) {
@@ -44,12 +51,29 @@ export function test(meta, defaultOptions) {
44
51
  return test;
45
52
  };
46
53
  // Create local test scope based on filename
47
- const localTestScope = alchemy.scope(path.basename(meta.filename), {
48
- parent: globalTestScope,
54
+ const localTestScope = alchemy.scope(`${defaultOptions.prefix ? `${defaultOptions.prefix}-` : ""}${path.basename(meta.filename)}`, {
55
+ // parent: globalTestScope,
56
+ stateStore: defaultOptions?.stateStore,
49
57
  });
50
58
  test.scope = localTestScope;
59
+ test.beforeAll = (fn) => {
60
+ return beforeAll(async () => {
61
+ test.scope.enter();
62
+ await fn(test.scope);
63
+ });
64
+ };
65
+ test.afterAll = (fn) => {
66
+ return afterAll(async () => {
67
+ test.scope.enter();
68
+ await fn(test.scope);
69
+ });
70
+ };
51
71
  // Clean up test scope after all tests complete
52
- afterAll(() => alchemy.destroy(test.scope));
72
+ afterAll(async () => {
73
+ if (defaultOptions?.destroy !== false) {
74
+ await alchemy.destroy(test.scope);
75
+ }
76
+ });
53
77
  return test;
54
78
  function test(...args) {
55
79
  const testName = args[0];
@@ -76,6 +100,10 @@ export function test(meta, defaultOptions) {
76
100
  try {
77
101
  await fn(scope);
78
102
  }
103
+ catch (err) {
104
+ console.error(err);
105
+ throw err;
106
+ }
79
107
  finally {
80
108
  if (options.destroy !== false) {
81
109
  await destroy(scope);
@@ -0,0 +1,147 @@
1
+ import type { Context } from "../context";
2
+ import { Resource } from "../resource";
3
+ /**
4
+ * Type of integrations that can be added to an Astro project
5
+ */
6
+ export type AstroIntegration = "react" | "preact" | "vue" | "svelte" | "solid" | "lit" | "tailwind" | "mdx" | "sitemap" | "partytown" | "markdoc";
7
+ /**
8
+ * Properties for creating an Astro project
9
+ */
10
+ export interface AstroProjectProps {
11
+ /**
12
+ * The name/path of the project
13
+ */
14
+ name: string;
15
+ /**
16
+ * The title of the site
17
+ * @default "Astro Site"
18
+ */
19
+ title?: string;
20
+ /**
21
+ * The description of the site
22
+ * @default "Welcome to my Astro site"
23
+ */
24
+ description?: string;
25
+ /**
26
+ * The directory to initialize the project in.
27
+ * @default {@link name}
28
+ */
29
+ dir?: string;
30
+ /**
31
+ * The integrations to add to the project
32
+ * @default []
33
+ */
34
+ integrations?: AstroIntegration[];
35
+ /**
36
+ * The TypeScript configuration
37
+ */
38
+ tsconfig?: {
39
+ /**
40
+ * Extends from this TypeScript configuration
41
+ */
42
+ extends?: string;
43
+ /**
44
+ * References to add to the tsconfig
45
+ */
46
+ references?: string[];
47
+ /**
48
+ * Compiler options to add to the tsconfig
49
+ */
50
+ compilerOptions?: Record<string, any>;
51
+ };
52
+ /**
53
+ * Whether to delete the project folder during the delete phase
54
+ * @default true
55
+ */
56
+ delete?: boolean;
57
+ /**
58
+ * Add Shadcn UI to the project
59
+ * @default false
60
+ */
61
+ shadcn?: {
62
+ /**
63
+ * The base color to use
64
+ * @default "neutral"
65
+ */
66
+ baseColor?: "neutral" | "gray" | "zinc" | "stone" | "slate";
67
+ /**
68
+ * Use default configuration
69
+ * @default false
70
+ */
71
+ defaults?: boolean;
72
+ /**
73
+ * Force overwrite of existing configuration
74
+ * @default false
75
+ */
76
+ force?: boolean;
77
+ /**
78
+ * Mute output
79
+ * @default false
80
+ */
81
+ silent?: boolean;
82
+ /**
83
+ * Use the src directory when creating a new project
84
+ * @default true
85
+ */
86
+ srcDir?: boolean;
87
+ /**
88
+ * Use css variables for theming
89
+ * @default true
90
+ */
91
+ cssVariables?: boolean;
92
+ /**
93
+ * The components to add
94
+ */
95
+ components?: string[];
96
+ };
97
+ /**
98
+ * The dependencies to install
99
+ */
100
+ dependencies?: Record<string, string>;
101
+ /**
102
+ * The dev dependencies to install
103
+ */
104
+ devDependencies?: Record<string, string>;
105
+ /**
106
+ * Additional scripts to add to package.json
107
+ */
108
+ scripts?: Record<string, string>;
109
+ }
110
+ /**
111
+ * Astro project resource
112
+ */
113
+ export interface AstroProject extends AstroProjectProps, Resource {
114
+ /**
115
+ * The name/path of the project
116
+ */
117
+ name: string;
118
+ }
119
+ /**
120
+ * Creates a new Astro project
121
+ *
122
+ * @example
123
+ * // Create a basic Astro project
124
+ * const basicProject = await AstroProject("my-astro-app", {
125
+ * title: "My Astro Site",
126
+ * description: "Built with Alchemy"
127
+ * });
128
+ *
129
+ * @example
130
+ * // Create an Astro project with React and Tailwind
131
+ * const reactProject = await AstroProject("astro-react", {
132
+ * title: "Astro + React",
133
+ * integrations: ["react", "tailwind"]
134
+ * });
135
+ *
136
+ * @example
137
+ * // Create an Astro project with Shadcn UI
138
+ * const shadcnProject = await AstroProject("astro-shadcn", {
139
+ * title: "Astro with Shadcn UI",
140
+ * integrations: ["react", "tailwind"],
141
+ * shadcn: {
142
+ * baseColor: "zinc",
143
+ * components: ["button", "card", "input"]
144
+ * }
145
+ * });
146
+ */
147
+ export declare const AstroProject: (((this: any, id: string, props?: {}) => never) & (new (_: never) => never)) | ((this: Context<AstroProject>, id: string, props: AstroProjectProps) => Promise<AstroProject>);