@samva/cli 0.6.1 → 0.7.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 (2) hide show
  1. package/dist/bin.mjs +66 -17
  2. package/package.json +7 -7
package/dist/bin.mjs CHANGED
@@ -13674,7 +13674,7 @@ var layer12 = /* @__PURE__ */ layer.pipe(/* @__PURE__ */ provideMerge(/* @__PURE
13674
13674
  // package.json
13675
13675
  var package_default = {
13676
13676
  name: "@samva/cli",
13677
- version: "0.6.1",
13677
+ version: "0.7.0",
13678
13678
  description: "Samva CLI \u2014 email and platform operations from your terminal",
13679
13679
  keywords: [
13680
13680
  "cli",
@@ -13722,8 +13722,8 @@ var package_default = {
13722
13722
  devDependencies: {
13723
13723
  "@effect/platform-bun": "catalog:effect",
13724
13724
  "@effect/vitest": "catalog:effect",
13725
- "@samva/markup": "workspace:0.11.0",
13726
- "@samva/vite": "workspace:0.11.0",
13725
+ "@samva/markup": "workspace:0.11.1",
13726
+ "@samva/vite": "workspace:0.11.1",
13727
13727
  "@types/node": "catalog:",
13728
13728
  "better-auth": "catalog:",
13729
13729
  effect: "catalog:effect",
@@ -13733,10 +13733,10 @@ var package_default = {
13733
13733
  vitest: "catalog:"
13734
13734
  },
13735
13735
  optionalDependencies: {
13736
- "@samva/cli-darwin-arm64": "workspace:0.6.1",
13737
- "@samva/cli-darwin-x64": "workspace:0.6.1",
13738
- "@samva/cli-linux-arm64": "workspace:0.6.1",
13739
- "@samva/cli-linux-x64": "workspace:0.6.1"
13736
+ "@samva/cli-darwin-arm64": "workspace:0.7.0",
13737
+ "@samva/cli-darwin-x64": "workspace:0.7.0",
13738
+ "@samva/cli-linux-arm64": "workspace:0.7.0",
13739
+ "@samva/cli-linux-x64": "workspace:0.7.0"
13740
13740
  },
13741
13741
  engines: {
13742
13742
  node: ">=18"
@@ -56684,9 +56684,13 @@ var missingOrgMessage = "No active organization. Run `samva org use <slug>` afte
56684
56684
  var provider = (config) => ({
56685
56685
  provide: (effect) => provide4(effect, layerFetch(config))
56686
56686
  });
56687
- var getClientProviderForContext = (context, baseUrl) => gen2(function* () {
56687
+ var getClientConfigForContext = (context, baseUrl) => gen2(function* () {
56688
56688
  if (context.apiKey) {
56689
- return provider({ apiKey: context.apiKey, baseUrl, headers: CLI_CLIENT_HEADERS });
56689
+ return {
56690
+ apiKey: context.apiKey,
56691
+ baseUrl,
56692
+ headers: CLI_CLIENT_HEADERS
56693
+ };
56690
56694
  }
56691
56695
  if (context.credentials) {
56692
56696
  if (isCredentialExpired(context.credentials, yield* currentTimeMillis2)) {
@@ -56703,18 +56707,38 @@ var getClientProviderForContext = (context, baseUrl) => gen2(function* () {
56703
56707
  message: missingOrgMessage
56704
56708
  });
56705
56709
  }
56706
- return provider({
56710
+ return {
56707
56711
  authToken,
56708
56712
  baseUrl,
56709
56713
  headers: { ...CLI_CLIENT_HEADERS, "x-org-slug": activeOrgSlug }
56710
- });
56714
+ };
56711
56715
  }
56712
56716
  return yield* new CliAuthError({
56713
56717
  code: "missing_credentials",
56714
56718
  message: "No credentials found. Run `samva login`, or set SAMVA_API_KEY for automation."
56715
56719
  });
56716
56720
  });
56717
- var getClientProvider = flatMap3(resolveExecutionContext, (context) => getClientProviderForContext(context, context.apiUrl));
56721
+ var getClientConfig = flatMap3(resolveExecutionContext, (context) => getClientConfigForContext(context, context.apiUrl));
56722
+ var getClientProvider = map6(getClientConfig, provider);
56723
+ var getAuthenticatedJsonForContext = fn2("CliClient.getAuthenticatedJson")(function* (context, path) {
56724
+ const config = yield* getClientConfigForContext(context, context.apiUrl);
56725
+ const headers = {
56726
+ ...config.headers,
56727
+ ...config.apiKey !== undefined ? { "x-api-key": config.apiKey } : { Authorization: `Bearer ${config.authToken}` }
56728
+ };
56729
+ const url = `${config.baseUrl.replace(/\/$/, "")}${path}`;
56730
+ return yield* tryPromise2({
56731
+ try: async (signal) => {
56732
+ const response = await fetch(url, { headers, signal });
56733
+ if (!response.ok) {
56734
+ throw new Error(`HTTP ${response.status}`);
56735
+ }
56736
+ return response.json();
56737
+ },
56738
+ catch: (cause) => new SamvaCliError({ message: `Request to ${url} failed: ${String(cause)}` })
56739
+ });
56740
+ });
56741
+ var getAuthenticatedJson = (path) => flatMap3(resolveExecutionContext, (context) => getAuthenticatedJsonForContext(context, path));
56718
56742
 
56719
56743
  // src/lib/output.ts
56720
56744
  var CLI_SCHEMA_VERSION = 1;
@@ -61024,7 +61048,7 @@ var resolvePublicAuthUrl = (basePath) => {
61024
61048
  } catch {}
61025
61049
  }
61026
61050
  };
61027
- var getClientConfig = (options, loadEnv) => {
61051
+ var getClientConfig2 = (options, loadEnv) => {
61028
61052
  const isCredentialsSupported = "credentials" in Request.prototype;
61029
61053
  const baseURL = getBaseURL(options?.baseURL, options?.basePath, undefined, loadEnv) ?? resolvePublicAuthUrl(options?.basePath) ?? "/api/auth";
61030
61054
  const pluginsFetchPlugins = options?.plugins?.flatMap((plugin) => plugin.fetchPlugins).filter((pl) => pl !== undefined) || [];
@@ -61226,7 +61250,7 @@ function createDynamicPathProxy(routes, client, knownPathMethods, atoms, atomLis
61226
61250
 
61227
61251
  // ../../node_modules/.bun/better-auth@1.7.5+e459c178ac81a797/node_modules/better-auth/dist/client/vanilla.mjs
61228
61252
  function createAuthClient(options) {
61229
- const { pluginPathMethods, pluginsActions, pluginsAtoms, hydrateSession, $fetch, atomListeners, $store } = getClientConfig(options);
61253
+ const { pluginPathMethods, pluginsActions, pluginsAtoms, hydrateSession, $fetch, atomListeners, $store } = getClientConfig2(options);
61230
61254
  const resolvedHooks = {};
61231
61255
  for (const [key, value] of Object.entries(pluginsAtoms))
61232
61256
  resolvedHooks[`use${capitalizeFirstLetter(key)}`] = value;
@@ -63141,7 +63165,11 @@ var digest2 = async (value) => {
63141
63165
  const bytes = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(value));
63142
63166
  return Array.from(new Uint8Array(bytes), (byte) => byte.toString(16).padStart(2, "0")).join("");
63143
63167
  };
63168
+ var StarterCatalog = Struct({
63169
+ items: ArraySchema(Struct({ id: String4, channel: String4 }))
63170
+ });
63144
63171
  var init = make27("init", {
63172
+ starter: String8("starter").pipe(withDescription2("Gallery starter id (see the template gallery)"), optional4),
63145
63173
  name: String8("name").pipe(withDescription2("Template name")),
63146
63174
  projectName: String8("project-name").pipe(withDescription2("Template project name"), optional4),
63147
63175
  slug: String8("slug").pipe(withDescription2("Template handle"), optional4),
@@ -63149,24 +63177,30 @@ var init = make27("init", {
63149
63177
  idempotencyKey: String8("idempotency-key").pipe(withDescription2("Stable retry key for project creation"), optional4),
63150
63178
  dryRun: Boolean6("dry-run").pipe(withDescription2("Show the project creation request without writing"), withDefault4(false)),
63151
63179
  json: jsonFlag
63152
- }).pipe(withDescription3("Create and clone the canonical Samva email starter"), withExamples([
63180
+ }).pipe(withDescription3("Create and clone a Samva email starter"), withExamples([
63153
63181
  {
63154
63182
  command: 'samva templates init --name "Welcome email"',
63155
63183
  description: "Create a remote project and clone its canonical starter"
63156
63184
  },
63185
+ {
63186
+ command: 'samva templates init --name "Product newsletter" --starter product-newsletter',
63187
+ description: "Create a project from a gallery starter"
63188
+ },
63157
63189
  {
63158
63190
  command: 'samva templates init --name "Welcome email" --slug welcome --dir welcome-email --json',
63159
63191
  description: "Create deterministically for CI or a coding agent"
63160
63192
  }
63161
- ]), withHandler(({ name, projectName, slug, dir, idempotencyKey, dryRun, json }) => gen2(function* () {
63193
+ ]), withHandler(({ name, projectName, slug, dir, starter, idempotencyKey, dryRun, json }) => gen2(function* () {
63162
63194
  const root = resolve8(getOrElse(dir, () => projectDirectory(name)));
63163
63195
  const key = getOrUndefined(idempotencyKey);
63164
63196
  const request = {
63165
63197
  name,
63166
63198
  projectName: getOrUndefined(projectName),
63199
+ galleryTemplateId: getOrUndefined(starter),
63167
63200
  slug: getOrUndefined(slug),
63168
63201
  idempotencyKey: key ?? `cli:init:${(yield* promise2(() => digest2(`${name}
63169
- ${root}`))).slice(0, 48)}`
63202
+ ${root}${isSome2(starter) ? `
63203
+ ${starter.value}` : ""}`))).slice(0, 48)}`
63170
63204
  };
63171
63205
  if (dryRun) {
63172
63206
  const result = { action: "templates.init", dryRun: true, dir: root, request };
@@ -63178,9 +63212,23 @@ ${root}`))).slice(0, 48)}`
63178
63212
  ["Name", request.name],
63179
63213
  ["Project", request.projectName ?? request.name],
63180
63214
  ["Slug", request.slug ?? "Generated by Samva"],
63215
+ ["Starter", request.galleryTemplateId ?? "Canonical email starter"],
63181
63216
  ["Idempotency key", request.idempotencyKey]
63182
63217
  ]);
63183
63218
  }
63219
+ if (request.galleryTemplateId !== undefined) {
63220
+ const response = yield* getAuthenticatedJson("/v1/starters/");
63221
+ const catalog = yield* decodeUnknownEffect2(StarterCatalog)(response).pipe(mapError2((error) => new SamvaCliError({
63222
+ message: formatApiError("Could not read starter catalog", error)
63223
+ })));
63224
+ const validIds = catalog.items.filter((item) => item.channel === "email").map((item) => item.id);
63225
+ if (!validIds.includes(request.galleryTemplateId)) {
63226
+ return yield* new CliUsageError({
63227
+ code: "unknown_starter",
63228
+ message: `Unknown email starter '${request.galleryTemplateId}'. Valid starter ids: ${validIds.join(", ") || "(none)"}.`
63229
+ });
63230
+ }
63231
+ }
63184
63232
  const client = yield* getClientProvider;
63185
63233
  const created = yield* create11(request).pipe(client.provide, mapError2((error) => new SamvaCliError({
63186
63234
  message: formatApiError("Could not create template project", error)
@@ -63192,6 +63240,7 @@ ${root}`))).slice(0, 48)}`
63192
63240
  yield* printFields([
63193
63241
  ["Template", payload.templateId],
63194
63242
  ["Project", payload.projectId],
63243
+ ["Starter", request.galleryTemplateId ?? "Canonical email starter"],
63195
63244
  ["Directory", payload.dir],
63196
63245
  ["Commit", payload.commit]
63197
63246
  ]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@samva/cli",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
4
4
  "description": "Samva CLI — email and platform operations from your terminal",
5
5
  "keywords": [
6
6
  "cli",
@@ -48,8 +48,8 @@
48
48
  "devDependencies": {
49
49
  "@effect/platform-bun": "4.0.0",
50
50
  "@effect/vitest": "4.0.0",
51
- "@samva/markup": "0.11.0",
52
- "@samva/vite": "0.11.0",
51
+ "@samva/markup": "0.11.1",
52
+ "@samva/vite": "0.11.1",
53
53
  "@types/node": "^26.6.2",
54
54
  "better-auth": "1.7.5",
55
55
  "effect": "4.0.0",
@@ -59,10 +59,10 @@
59
59
  "vitest": "^5.0.3"
60
60
  },
61
61
  "optionalDependencies": {
62
- "@samva/cli-darwin-arm64": "0.6.1",
63
- "@samva/cli-darwin-x64": "0.6.1",
64
- "@samva/cli-linux-arm64": "0.6.1",
65
- "@samva/cli-linux-x64": "0.6.1"
62
+ "@samva/cli-darwin-arm64": "0.7.0",
63
+ "@samva/cli-darwin-x64": "0.7.0",
64
+ "@samva/cli-linux-arm64": "0.7.0",
65
+ "@samva/cli-linux-x64": "0.7.0"
66
66
  },
67
67
  "engines": {
68
68
  "node": ">=18"