@layers/amba 1.0.0 → 1.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/README.md CHANGED
@@ -1,13 +1,11 @@
1
- # `@layers/amba` — the amba CLI
1
+ # @layers/amba
2
2
 
3
- amba is an agent-native backend-as-a-service for mobile apps: functions,
4
- collections, storage, AI gateway, queues, and static sites — one CLI,
5
- per-tenant Postgres + edge runtime.
3
+ Amba is the agent-native backend-as-a-service for mobile and web apps. This package is the `amba` command-line interface.
6
4
 
7
5
  ## Install
8
6
 
9
7
  ```bash
10
- npm install -g @layers/amba
8
+ npm install -g @layers/amba@1.0.1
11
9
  ```
12
10
 
13
11
  …or run on demand:
@@ -16,40 +14,65 @@ npm install -g @layers/amba
16
14
  npx @layers/amba init
17
15
  ```
18
16
 
19
- ## Quick start
17
+ Requires Node.js 22 or newer.
18
+
19
+ ## Agent mode (recommended)
20
+
21
+ For AI coding agents (Claude Code, Cursor, Windsurf): one command, no
22
+ browser, no prompts.
20
23
 
21
24
  ```bash
22
- amba init # mint a personal dev project and scaffold context
23
- amba login # authenticate (browser flow)
24
- amba projects list # list projects you own
25
- amba projects create --name my-app
25
+ npx @layers/amba init --sandbox
26
+ ```
27
+
28
+ This signs up an agent-mode developer account, provisions a project,
29
+ writes `.env.local` + `AMBA.md`, auto-wires `mcpServers.amba` into
30
+ every MCP client config it finds on disk, and installs the
31
+ `/amba-build` Claude Code skill at `.claude/skills/amba-build/SKILL.md`.
32
+
33
+ After restarting your MCP client, paste:
34
+
35
+ ```
36
+ /amba-build <design-url-or-description>
37
+ ```
38
+
39
+ …to scaffold a full Expo app with Amba as the only backend. The skill
40
+ fetches the canonical prompt from
41
+ <https://docs.amba.dev/docs/prompts/expo-build> at invocation time and
42
+ falls back to an inlined snapshot when offline. Use `--no-skills` to
43
+ skip the skill install.
44
+
45
+ ## Configure + first call
46
+
47
+ ```bash
48
+ amba init # mint a personal project and write .amba/ config
49
+ amba login # browser-based auth (skip with --token / AMBA_PAT)
50
+ amba projects list
51
+ ```
52
+
53
+ Track your first event from the CLI:
54
+
55
+ ```bash
56
+ amba events track app_opened --prop source=cli
26
57
  ```
27
58
 
28
59
  ## Common commands
29
60
 
30
61
  ```bash
31
62
  amba functions deploy ./functions/hello.ts
32
- amba functions list
33
- amba functions schedule hello "0 * * * *" --tz UTC
34
-
35
63
  amba collections create messages --field user_id:uuid --field body:text
36
- amba collections list
37
- amba types generate # emit .amba/types.d.ts
38
-
64
+ amba types generate # emits .amba/types.d.ts
39
65
  amba secrets set OPENAI_KEY --function hello --from-stdin
40
-
41
66
  amba sites deploy ./out --name marketing
42
- amba sites domain add marketing.example.com --site marketing
43
67
  ```
44
68
 
45
69
  ## Headless / CI
46
70
 
47
- Pass a personal access token via `--token <pat>` or the `AMBA_PAT` env
48
- var to skip the browser-based login flow.
71
+ Pass a Personal Access Token via `--token <pat>` or `AMBA_PAT` to skip the browser login.
49
72
 
50
- ## Requirements
73
+ ## Docs
51
74
 
52
- - Node.js 22+
75
+ Full reference: <https://docs.amba.dev/cli>.
53
76
 
54
77
  ## License
55
78
 
@@ -245,16 +245,16 @@ export interface FunctionDeploymentRow {
245
245
  project_id: string;
246
246
  name: string;
247
247
  version: number;
248
- cf_script_name: string;
249
- cf_dispatch_namespace: string;
248
+ runtime_script_name: string;
249
+ runtime_namespace: string;
250
250
  bundle_sha: string;
251
251
  status: 'active' | 'superseded' | 'disabled';
252
252
  created_at: string;
253
253
  }
254
254
  export declare function recordFunctionDeployment(projectId: string, input: {
255
255
  name: string;
256
- cf_script_name: string;
257
- cf_dispatch_namespace: string;
256
+ runtime_script_name: string;
257
+ runtime_namespace: string;
258
258
  bundle_sha: string;
259
259
  /**
260
260
  * Optional declarative rate-limit. The CLI passes a validated
@@ -298,13 +298,6 @@ export interface FunctionDeployContext {
298
298
  * step skips the storage binding in that case.
299
299
  */
300
300
  r2_bucket_name: string | null;
301
- /**
302
- * Cloudflare Hyperdrive config id. NULL until storage provisioning
303
- * completes; deploy step skips the Hyperdrive binding when null and
304
- * `ctx.collections` returns `tenant_unavailable` until the column is
305
- * populated.
306
- */
307
- cf_hyperdrive_config_id: string | null;
308
301
  }
309
302
  export declare function getFunctionDispatchNamespace(projectId: string): Promise<ApiResponse<FunctionDeployContext>>;
310
303
  export interface InternalCredentialsResponse {
@@ -548,7 +541,7 @@ export interface SiteRow {
548
541
  id: string;
549
542
  project_id: string;
550
543
  name: string;
551
- cf_pages_project_name: string;
544
+ slug: string;
552
545
  status: 'active' | 'disabled' | 'archived';
553
546
  created_at: string;
554
547
  updated_at: string;
@@ -557,7 +550,7 @@ export interface SiteDomainRow {
557
550
  id: string;
558
551
  site_id: string;
559
552
  hostname: string;
560
- cf_hostname_id: string | null;
553
+ provider_hostname_id: string | null;
561
554
  cert_status: 'pending_validation' | 'pending_issuance' | 'pending_deployment' | 'active' | 'error';
562
555
  created_at: string;
563
556
  updated_at: string;
@@ -589,18 +582,18 @@ export declare function archiveSite(projectId: string, name: string, confirm: st
589
582
  /** Cascade summary returned by site/function delete proxies. */
590
583
  export interface DeleteCascadeSummary {
591
584
  domains_removed?: number;
592
- cf_pages_project_deleted?: boolean;
593
- cf_dispatch_script_deleted?: boolean;
585
+ site_runtime_removed?: boolean;
586
+ runtime_script_removed?: boolean;
594
587
  function_deployments_marked_disabled?: number;
595
588
  }
596
589
  /**
597
590
  * Add a custom domain to a site. The server-side proxy registers the
598
- * custom hostname, persists the resulting `cf_hostname_id`, and returns
591
+ * custom hostname, persists the resulting `provider_hostname_id`, and returns
599
592
  * the CNAME target the customer should point their DNS at.
600
593
  */
601
594
  export declare function addSiteDomainViaApi(projectId: string, siteName: string, hostname: string): Promise<ApiResponse<{
602
595
  hostname: string;
603
- cf_hostname_id: string;
596
+ provider_hostname_id: string;
604
597
  cert_status: SiteDomainRow["cert_status"];
605
598
  dns_target: string;
606
599
  created_at: string;
@@ -615,10 +608,10 @@ export declare function removeSiteDomainViaApi(projectId: string, siteName: stri
615
608
  deleted: true;
616
609
  }>>;
617
610
  /**
618
- * Roll a live CF Pages deployment back to a prior `deployment_id`. CF's
619
- * rollback creates a NEW deployment that serves the prior bundle (git-
620
- * revert semantics, not git-reset), so the response shape mirrors
621
- * `DeploySiteResult` and the new `deployment_id` is what's now live.
611
+ * Roll a live deployment back to a prior `deployment_id`. Rollback creates
612
+ * a NEW deployment that serves the prior bundle (git-revert semantics,
613
+ * not git-reset), so the response shape mirrors `DeploySiteResult` and
614
+ * the new `deployment_id` is what's now live.
622
615
  */
623
616
  export declare function rollbackSiteViaApi(projectId: string, siteName: string, deploymentId: string): Promise<ApiResponse<DeploySiteResult>>;
624
617
  /**
@@ -650,12 +643,12 @@ export declare function deleteFunctionViaApi(projectId: string, functionName: st
650
643
  }>>;
651
644
  export declare function attachSiteDomain(projectId: string, siteName: string, input: {
652
645
  hostname: string;
653
- cf_hostname_id?: string;
646
+ provider_hostname_id?: string;
654
647
  }): Promise<ApiResponse<SiteDomainRow>>;
655
648
  export declare function listSiteDomains(projectId: string, siteName: string): Promise<ApiListResponse<SiteDomainRow>>;
656
649
  export declare function updateSiteDomain(projectId: string, siteName: string, hostname: string, patch: {
657
650
  cert_status: SiteDomainRow['cert_status'];
658
- cf_hostname_id?: string;
651
+ provider_hostname_id?: string;
659
652
  }): Promise<ApiResponse<SiteDomainRow>>;
660
653
  export declare function detachSiteDomain(projectId: string, siteName: string, hostname: string): Promise<ApiResponse<{
661
654
  deleted: boolean;
@@ -32,11 +32,36 @@ export declare function functionsDeleteCommand(name: string, options?: {
32
32
  export declare function functionsScheduleCommand(name: string, cron: string, options?: {
33
33
  tz?: string;
34
34
  }): Promise<void>;
35
+ export interface DevOptions {
36
+ /** Local port. Default 8787 (overridable per project). */
37
+ port?: number;
38
+ /** Don't watch the file for changes. Default false. */
39
+ noWatch?: boolean;
40
+ }
35
41
  /**
36
- * `amba functions dev`not configured in this release. Use
37
- * `amba functions deploy <file>` to deploy via the platform API.
42
+ * `amba functions dev <file>` run the function locally with file-change
43
+ * hot reload.
44
+ *
45
+ * Architecture: the CLI process owns the file watcher + bundler; the
46
+ * actual HTTP server lives in a child Node process that imports the
47
+ * bundle and binds to the user's port. On file change, the parent kills
48
+ * the child, writes a fresh bundle, and respawns. This bounds memory
49
+ * (each rebuild = fresh V8 heap) and isolates customer-handler crashes
50
+ * from the CLI. Brief downtime per rebuild (~100ms while the port is
51
+ * released and re-bound); incoming connections during the swap queue
52
+ * at the TCP listen backlog and complete once the new child is up.
53
+ *
54
+ * The bundler is the same esbuild pipeline `amba functions deploy` uses
55
+ * — externalization rules, size cap, and source-map handling are
56
+ * identical so dev → prod parity is automatic.
57
+ *
58
+ * Handler shape: `export default async function (req: Request): Promise<Response>`.
59
+ * `.env.local` values in the customer's working directory are passed
60
+ * through to the child process so the handler can read them via
61
+ * `process.env.MY_KEY`. Existing values in the parent's env take
62
+ * priority (so `MY_KEY=x amba functions dev …` wins).
38
63
  */
39
- export declare function functionsDevCommand(_entryPoint: string): Promise<void>;
64
+ export declare function functionsDevCommand(entryPoint: string, options?: DevOptions): Promise<void>;
40
65
  /**
41
66
  * `amba functions consume <queue> <function>` — bind a function as the
42
67
  * consumer for a queue. Customers send to a queue with `ctx.queue.send`;
@@ -1,3 +1,4 @@
1
+ import { type SandboxResult } from '../sandbox.js';
1
2
  export interface InitOptions {
2
3
  withExample?: boolean;
3
4
  /**
@@ -8,5 +9,73 @@ export interface InitOptions {
8
9
  * minted via `amba projects create --env production` by automation).
9
10
  */
10
11
  env?: 'development' | 'production';
12
+ /**
13
+ * Headless agentic mode. Skips browser auth + interactive prompts:
14
+ * the CLI generates a sandbox email + password, posts to
15
+ * `/v1/auth/developer/signup`, writes credentials everywhere
16
+ * (`~/.amba/credentials.json` + `.env.local` + `AMBA.md`), and
17
+ * auto-wires the Amba MCP server into every detected MCP client
18
+ * config. Designed to be invoked unattended by an AI coding agent
19
+ * that pasted the homepage 3-line prompt.
20
+ */
21
+ sandbox?: boolean;
22
+ /** Override the auto-generated sandbox email. Only meaningful with `--sandbox`. */
23
+ sandboxEmail?: string;
24
+ /** Skip MCP-client-config writes. Mostly for testing. */
25
+ noMcpConfig?: boolean;
26
+ /**
27
+ * Skip installing the `/amba-build` Claude Code skill into
28
+ * `.claude/skills/amba-build/SKILL.md`. Default behavior (when
29
+ * `--sandbox` is on) is to install the skill — pass `--no-skills`
30
+ * to opt out (e.g. in a CI run that doesn't want stray files).
31
+ */
32
+ noSkills?: boolean;
33
+ /** Emit a machine-readable JSON summary instead of human-readable lines. */
34
+ json?: boolean;
35
+ /** Override `~/` resolution. Test seam — production code never sets this. */
36
+ homeDir?: string;
11
37
  }
12
38
  export declare function initCommand(options?: InitOptions): Promise<void>;
39
+ export declare function runSandboxInit(cwd: string, options: {
40
+ sandboxEmail?: string;
41
+ noMcpConfig?: boolean;
42
+ /**
43
+ * Skip the project-local `/amba-build` Claude Code skill install.
44
+ * Default is to install (the skill is what makes the agentic
45
+ * "/amba-build <design>" invocation work). Set true in CI or
46
+ * during tests that don't want stray files written into the
47
+ * caller's CWD.
48
+ */
49
+ noSkills?: boolean;
50
+ json?: boolean;
51
+ /**
52
+ * Override `~/` resolution. The CLI itself never passes this — it's
53
+ * the seam tests use to avoid touching the developer's actual home
54
+ * directory. (vi.spyOn can't intercept `os.homedir` under ESM, so
55
+ * dependency injection is the cleanest substitute.)
56
+ */
57
+ homeDir?: string;
58
+ }): Promise<SandboxResult>;
59
+ /**
60
+ * Build the plaintext (no ANSI) success-output block printed at the
61
+ * end of `amba init --sandbox`. Pure function — exported only for the
62
+ * vitest cases that assert on per-line content. The CLI wraps each
63
+ * line with picocolors in `printSandboxNextSteps` below.
64
+ *
65
+ * Structure (in order):
66
+ * 1. Per-artifact checklist (`✓ ...` lines)
67
+ * 2. SDK install + configure hint
68
+ * 3. "Done." + per-client restart bullets — ONLY for clients we
69
+ * actually wrote configs to. Never instruct the user to "restart
70
+ * Cursor" if we only touched `~/.claude.json`. When no config
71
+ * was written (manual-paste path), falls back to a generic
72
+ * "quit + reopen" line.
73
+ * 4. Tail-line resume hint + sandbox limits + verify URL.
74
+ *
75
+ * We intentionally do NOT print any "kill -HUP / SIGHUP" advanced
76
+ * workaround. Telling the agent to surface a clean "restart your MCP
77
+ * client" instruction to the human is the whole optimization — adding
78
+ * an experimental fallback just dilutes the signal and risks the
79
+ * agent surfacing the workaround instead.
80
+ */
81
+ export declare function buildSandboxNextStepsLines(r: SandboxResult): string[];