@hanzogui/recipes 7.3.1 → 8.1.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/dist/admin.js CHANGED
@@ -11,7 +11,11 @@ function resolveBaseUrl(override) {
11
11
  }
12
12
 
13
13
  // src/admin.ts
14
- async function authAdmin({ baseUrl, email, password }) {
14
+ async function authAdmin({
15
+ baseUrl,
16
+ email,
17
+ password
18
+ }) {
15
19
  const url = `${resolveBaseUrl(baseUrl)}/v1/base/admins/auth-with-password`;
16
20
  const res = await fetch(url, {
17
21
  method: "POST",
@@ -27,7 +31,9 @@ async function authAdmin({ baseUrl, email, password }) {
27
31
  async function ensureCollection(auth) {
28
32
  const base = resolveBaseUrl(auth.baseUrl);
29
33
  const headers = { Authorization: auth.token, "Content-Type": "application/json" };
30
- const probe = await fetch(`${base}/v1/base/collections/${RECIPES_COLLECTION}`, { headers });
34
+ const probe = await fetch(`${base}/v1/base/collections/${RECIPES_COLLECTION}`, {
35
+ headers
36
+ });
31
37
  if (probe.ok)
32
38
  return "existed";
33
39
  const schema = {
@@ -42,7 +48,9 @@ async function ensureCollection(auth) {
42
48
  { name: "recipeDeps", type: "json", required: false, options: {} },
43
49
  { name: "files", type: "json", required: true, options: {} }
44
50
  ],
45
- indexes: [`CREATE UNIQUE INDEX idx_${RECIPES_COLLECTION}_slug ON ${RECIPES_COLLECTION} (slug)`],
51
+ indexes: [
52
+ `CREATE UNIQUE INDEX idx_${RECIPES_COLLECTION}_slug ON ${RECIPES_COLLECTION} (slug)`
53
+ ],
46
54
  listRule: "",
47
55
  viewRule: "",
48
56
  createRule: null,
package/dist/index.js CHANGED
@@ -45,35 +45,6 @@ function resolveInstallDir(root, config) {
45
45
  return path.join(root, config.installDir ?? DEFAULT_INSTALL_DIR);
46
46
  }
47
47
 
48
- // src/write.ts
49
- import { existsSync as existsSync2, promises as fs2 } from "node:fs";
50
- import path2 from "node:path";
51
- async function getInstallDir(opts) {
52
- if (opts.installDir)
53
- return opts.installDir;
54
- const root = await findProjectRoot(opts.cwd);
55
- return resolveInstallDir(root, await readConfig(root));
56
- }
57
- async function installRecipe(recipe, opts = {}) {
58
- const installDir = await getInstallDir(opts);
59
- const written = [];
60
- for (const file of recipe.files) {
61
- const dest = path2.join(installDir, file.path);
62
- const dir = path2.dirname(dest);
63
- if (!existsSync2(dir))
64
- await fs2.mkdir(dir, { recursive: true });
65
- await fs2.writeFile(dest, file.source);
66
- written.push(dest);
67
- }
68
- return written;
69
- }
70
- async function installPlan(plan, opts = {}) {
71
- const written = [];
72
- for (const r of [plan.recipe, ...plan.transitiveRecipes]) {
73
- written.push(...await installRecipe(r, opts));
74
- }
75
- return written;
76
- }
77
48
  // src/read.ts
78
49
  async function getJSON(url) {
79
50
  const res = await fetch(url, { headers: { Accept: "application/json" } });
@@ -122,13 +93,17 @@ async function resolveRecipe(slug, opts = {}) {
122
93
  })();
123
94
  const recipe = seen.get(slug);
124
95
  const transitiveRecipes = Array.from(seen.values()).filter((r) => r.slug !== slug);
125
- const path3 = await import("node:path");
126
- const targetPaths = [recipe, ...transitiveRecipes].flatMap((r) => r.files.map((f) => path3.join(installDir, f.path)));
96
+ const path2 = await import("node:path");
97
+ const targetPaths = [recipe, ...transitiveRecipes].flatMap((r) => r.files.map((f) => path2.join(installDir, f.path)));
127
98
  return { recipe, transitiveRecipes, targetPaths };
128
99
  }
129
100
 
130
101
  // src/admin.ts
131
- async function authAdmin({ baseUrl, email, password }) {
102
+ async function authAdmin({
103
+ baseUrl,
104
+ email,
105
+ password
106
+ }) {
132
107
  const url = `${resolveBaseUrl(baseUrl)}/v1/base/admins/auth-with-password`;
133
108
  const res = await fetch(url, {
134
109
  method: "POST",
@@ -144,7 +119,9 @@ async function authAdmin({ baseUrl, email, password }) {
144
119
  async function ensureCollection(auth) {
145
120
  const base = resolveBaseUrl(auth.baseUrl);
146
121
  const headers = { Authorization: auth.token, "Content-Type": "application/json" };
147
- const probe = await fetch(`${base}/v1/base/collections/${RECIPES_COLLECTION}`, { headers });
122
+ const probe = await fetch(`${base}/v1/base/collections/${RECIPES_COLLECTION}`, {
123
+ headers
124
+ });
148
125
  if (probe.ok)
149
126
  return "existed";
150
127
  const schema = {
@@ -159,7 +136,9 @@ async function ensureCollection(auth) {
159
136
  { name: "recipeDeps", type: "json", required: false, options: {} },
160
137
  { name: "files", type: "json", required: true, options: {} }
161
138
  ],
162
- indexes: [`CREATE UNIQUE INDEX idx_${RECIPES_COLLECTION}_slug ON ${RECIPES_COLLECTION} (slug)`],
139
+ indexes: [
140
+ `CREATE UNIQUE INDEX idx_${RECIPES_COLLECTION}_slug ON ${RECIPES_COLLECTION} (slug)`
141
+ ],
163
142
  listRule: "",
164
143
  viewRule: "",
165
144
  createRule: null,
@@ -205,6 +184,35 @@ async function upsertRecipe(auth, recipe) {
205
184
  throw new Error(`POST ${recipe.slug}: ${res.status} ${await res.text()}`);
206
185
  return "created";
207
186
  }
187
+ // src/write.ts
188
+ import { existsSync as existsSync2, promises as fs2 } from "node:fs";
189
+ import path2 from "node:path";
190
+ async function getInstallDir(opts) {
191
+ if (opts.installDir)
192
+ return opts.installDir;
193
+ const root = await findProjectRoot(opts.cwd);
194
+ return resolveInstallDir(root, await readConfig(root));
195
+ }
196
+ async function installRecipe(recipe, opts = {}) {
197
+ const installDir = await getInstallDir(opts);
198
+ const written = [];
199
+ for (const file of recipe.files) {
200
+ const dest = path2.join(installDir, file.path);
201
+ const dir = path2.dirname(dest);
202
+ if (!existsSync2(dir))
203
+ await fs2.mkdir(dir, { recursive: true });
204
+ await fs2.writeFile(dest, file.source);
205
+ written.push(dest);
206
+ }
207
+ return written;
208
+ }
209
+ async function installPlan(plan, opts = {}) {
210
+ const written = [];
211
+ for (const r of [plan.recipe, ...plan.transitiveRecipes]) {
212
+ written.push(...await installRecipe(r, opts));
213
+ }
214
+ return written;
215
+ }
208
216
  export {
209
217
  upsertRecipe,
210
218
  resolveRecipe,
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@hanzogui/recipes",
3
- "version": "7.3.1",
3
+ "version": "8.1.0",
4
4
  "description": "Hanzo GUI recipe library: read from Base, resolve transitive deps, install into a project.",
5
5
  "license": "BSD-3-Clause",
6
6
  "author": "Hanzo AI <dev@hanzo.ai>",
7
7
  "homepage": "https://gui.hanzo.ai",
8
8
  "repository": {
9
9
  "type": "git",
10
- "url": "https://github.com/hanzoai/gui.git",
10
+ "url": "git+https://github.com/hanzoai/gui.git",
11
11
  "directory": "pkgs/recipes"
12
12
  },
13
13
  "type": "module",
package/src/admin.ts CHANGED
@@ -13,7 +13,11 @@ export type AdminPasswordAuth = {
13
13
  }
14
14
 
15
15
  /** Exchanges admin email+password for a Base session token. */
16
- export async function authAdmin({ baseUrl, email, password }: AdminPasswordAuth): Promise<string> {
16
+ export async function authAdmin({
17
+ baseUrl,
18
+ email,
19
+ password,
20
+ }: AdminPasswordAuth): Promise<string> {
17
21
  const url = `${resolveBaseUrl(baseUrl)}/v1/base/admins/auth-with-password`
18
22
  const res = await fetch(url, {
19
23
  method: 'POST',
@@ -31,7 +35,9 @@ export async function authAdmin({ baseUrl, email, password }: AdminPasswordAuth)
31
35
  export async function ensureCollection(auth: AdminAuth): Promise<'created' | 'existed'> {
32
36
  const base = resolveBaseUrl(auth.baseUrl)
33
37
  const headers = { Authorization: auth.token, 'Content-Type': 'application/json' }
34
- const probe = await fetch(`${base}/v1/base/collections/${RECIPES_COLLECTION}`, { headers })
38
+ const probe = await fetch(`${base}/v1/base/collections/${RECIPES_COLLECTION}`, {
39
+ headers,
40
+ })
35
41
  if (probe.ok) return 'existed'
36
42
 
37
43
  const schema = {
@@ -46,7 +52,9 @@ export async function ensureCollection(auth: AdminAuth): Promise<'created' | 'ex
46
52
  { name: 'recipeDeps', type: 'json', required: false, options: {} },
47
53
  { name: 'files', type: 'json', required: true, options: {} },
48
54
  ],
49
- indexes: [`CREATE UNIQUE INDEX idx_${RECIPES_COLLECTION}_slug ON ${RECIPES_COLLECTION} (slug)`],
55
+ indexes: [
56
+ `CREATE UNIQUE INDEX idx_${RECIPES_COLLECTION}_slug ON ${RECIPES_COLLECTION} (slug)`,
57
+ ],
50
58
  listRule: '',
51
59
  viewRule: '',
52
60
  createRule: null,
@@ -90,7 +98,8 @@ export async function upsertRecipe(
90
98
  `${base}/v1/base/collections/${RECIPES_COLLECTION}/records/${existing}`,
91
99
  { method: 'PATCH', headers, body }
92
100
  )
93
- if (!res.ok) throw new Error(`PATCH ${recipe.slug}: ${res.status} ${await res.text()}`)
101
+ if (!res.ok)
102
+ throw new Error(`PATCH ${recipe.slug}: ${res.status} ${await res.text()}`)
94
103
  return 'updated'
95
104
  }
96
105
  const res = await fetch(`${base}/v1/base/collections/${RECIPES_COLLECTION}/records`, {
package/src/project.ts CHANGED
@@ -11,7 +11,8 @@ export async function findProjectRoot(start: string = process.cwd()): Promise<st
11
11
  if (existsSync(pkgPath)) {
12
12
  try {
13
13
  const pkg = JSON.parse(await fs.readFile(pkgPath, 'utf8'))
14
- if (pkg.workspaces || existsSync(path.join(dir, 'pnpm-workspace.yaml'))) return dir
14
+ if (pkg.workspaces || existsSync(path.join(dir, 'pnpm-workspace.yaml')))
15
+ return dir
15
16
  } catch {}
16
17
  }
17
18
  if (existsSync(path.join(dir, '.git'))) return dir
package/src/read.ts CHANGED
@@ -17,9 +17,12 @@ export type ReaderOptions = {
17
17
  async function getJSON<T>(url: string): Promise<T> {
18
18
  const res = await fetch(url, { headers: { Accept: 'application/json' } })
19
19
  if (!res.ok) {
20
- throw Object.assign(new Error(`Base request failed: ${res.status} ${res.statusText}`), {
21
- status: res.status,
22
- })
20
+ throw Object.assign(
21
+ new Error(`Base request failed: ${res.status} ${res.statusText}`),
22
+ {
23
+ status: res.status,
24
+ }
25
+ )
23
26
  }
24
27
  return (await res.json()) as T
25
28
  }
@@ -53,7 +56,10 @@ export type ResolveOptions = ReaderOptions & {
53
56
  }
54
57
 
55
58
  /** Walks recipeDeps transitively, computes target paths under the resolved install dir. */
56
- export async function resolveRecipe(slug: string, opts: ResolveOptions = {}): Promise<InstallPlan> {
59
+ export async function resolveRecipe(
60
+ slug: string,
61
+ opts: ResolveOptions = {}
62
+ ): Promise<InstallPlan> {
57
63
  const seen = new Map<string, Recipe>()
58
64
  const queue = [slug]
59
65
  while (queue.length) {
package/src/types.ts CHANGED
@@ -21,7 +21,10 @@ export type RecipeSummary = Pick<
21
21
  'id' | 'slug' | 'name' | 'description' | 'category'
22
22
  >
23
23
 
24
- export type RecipeInput = Pick<Recipe, 'slug' | 'name' | 'description' | 'category' | 'npmDeps' | 'recipeDeps' | 'files'>
24
+ export type RecipeInput = Pick<
25
+ Recipe,
26
+ 'slug' | 'name' | 'description' | 'category' | 'npmDeps' | 'recipeDeps' | 'files'
27
+ >
25
28
 
26
29
  export type InstallPlan = {
27
30
  recipe: Recipe
package/src/write.ts CHANGED
@@ -17,7 +17,10 @@ async function getInstallDir(opts: WriteOptions): Promise<string> {
17
17
  }
18
18
 
19
19
  /** Writes one recipe's files. Returns absolute paths written. */
20
- export async function installRecipe(recipe: Recipe, opts: WriteOptions = {}): Promise<string[]> {
20
+ export async function installRecipe(
21
+ recipe: Recipe,
22
+ opts: WriteOptions = {}
23
+ ): Promise<string[]> {
21
24
  const installDir = await getInstallDir(opts)
22
25
  const written: string[] = []
23
26
  for (const file of recipe.files) {
@@ -31,7 +34,10 @@ export async function installRecipe(recipe: Recipe, opts: WriteOptions = {}): Pr
31
34
  }
32
35
 
33
36
  /** Writes a recipe and all its transitive dependents from a resolved plan. */
34
- export async function installPlan(plan: InstallPlan, opts: WriteOptions = {}): Promise<string[]> {
37
+ export async function installPlan(
38
+ plan: InstallPlan,
39
+ opts: WriteOptions = {}
40
+ ): Promise<string[]> {
35
41
  const written: string[] = []
36
42
  for (const r of [plan.recipe, ...plan.transitiveRecipes]) {
37
43
  written.push(...(await installRecipe(r, opts)))