@layers/amba 4.0.3 → 4.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
@@ -5,7 +5,7 @@ Amba is the agent-native backend-as-a-service for mobile and web apps. This pack
5
5
  ## Install
6
6
 
7
7
  ```bash
8
- npm install -g @layers/amba@1.0.1
8
+ npm install -g @layers/amba
9
9
  ```
10
10
 
11
11
  …or run on demand:
@@ -50,10 +50,10 @@ amba login # browser-based auth (skip with --token / AMBA_PAT)
50
50
  amba projects list
51
51
  ```
52
52
 
53
- Track your first event from the CLI:
53
+ Check the project is live:
54
54
 
55
55
  ```bash
56
- amba events track app_opened --prop source=cli
56
+ amba status --detailed
57
57
  ```
58
58
 
59
59
  ## Common commands
@@ -277,6 +277,9 @@ export interface FunctionDeploymentRow {
277
277
  bundle_sha: string;
278
278
  status: 'active' | 'superseded' | 'disabled';
279
279
  created_at: string;
280
+ /** Opt-in public flag (#17). True = X-Api-Key gate skipped for this
281
+ * function so external webhook senders can reach it. Default false. */
282
+ is_public?: boolean;
280
283
  }
281
284
  export declare function recordFunctionDeployment(projectId: string, input: {
282
285
  name: string;
@@ -310,6 +313,13 @@ export declare function deployFunctionViaApi(projectId: string, input: {
310
313
  max: number;
311
314
  key: 'user_id' | 'ip';
312
315
  } | null;
316
+ /**
317
+ * Opt-in public flag (#17). When true, the edge runtime skips the
318
+ * X-Api-Key gate for this function so third-party webhook senders can
319
+ * reach it. Default false (private). The customer verifies the webhook
320
+ * HMAC inside the handler.
321
+ */
322
+ public?: boolean;
313
323
  }): Promise<DeployFunctionResult>;
314
324
  export declare function listFunctionDeployments(projectId: string, options?: {
315
325
  activeOnly?: boolean;
@@ -374,11 +384,15 @@ export interface FunctionLogsResponse {
374
384
  truncated: boolean;
375
385
  since: string;
376
386
  until: string;
387
+ /** Present when `since_request_id` anchored the range — the anchor event's timestamp. */
388
+ anchor?: string;
377
389
  }
378
390
  export declare function getFunctionLogs(projectId: string, functionName: string, options?: {
379
391
  since?: string;
380
392
  until?: string;
381
393
  limit?: number;
394
+ requestId?: string;
395
+ sinceRequestId?: string;
382
396
  }): Promise<ApiResponse<FunctionLogsResponse>>;
383
397
  export interface QueueBinding {
384
398
  queue_name: string;
@@ -465,7 +479,7 @@ export declare function deleteSecretViaApi(projectId: string, name: string, opti
465
479
  deleted: true;
466
480
  }>>;
467
481
  /** Closed set of column types the server accepts. */
468
- export type CollectionColumnType = 'uuid' | 'text' | 'integer' | 'bigint' | 'numeric' | 'boolean' | 'timestamptz' | 'date' | 'jsonb' | 'vector';
482
+ export type CollectionColumnType = 'uuid' | 'text' | 'integer' | 'bigint' | 'numeric' | 'boolean' | 'timestamptz' | 'date' | 'jsonb' | 'vector' | 'text[]' | 'integer[]' | 'bigint[]' | 'numeric[]' | 'boolean[]' | 'uuid[]';
469
483
  export interface CollectionColumn {
470
484
  name: string;
471
485
  type: CollectionColumnType;
@@ -757,6 +771,27 @@ export declare function updateSiteDomain(projectId: string, siteName: string, ho
757
771
  export declare function detachSiteDomain(projectId: string, siteName: string, hostname: string): Promise<ApiResponse<{
758
772
  deleted: boolean;
759
773
  }>>;
774
+ /** A declarative promotion bundle. Section keys are all optional. */
775
+ export interface PromotionBundleWire {
776
+ version: number;
777
+ exported_at: string;
778
+ [section: string]: unknown;
779
+ }
780
+ /** `{ created, updated, skipped }` counts for one bundle section. */
781
+ export interface PromotionSectionSummary {
782
+ created: number;
783
+ updated: number;
784
+ skipped: number;
785
+ }
786
+ export type PromotionImportMode = 'merge' | 'skip_existing';
787
+ export interface PromotionImportResult {
788
+ mode: PromotionImportMode;
789
+ summary: Record<string, PromotionSectionSummary>;
790
+ }
791
+ /** GET the current project's declarative configuration bundle. */
792
+ export declare function exportPromotionBundle(projectId: string): Promise<ApiResponse<PromotionBundleWire>>;
793
+ /** POST a declarative bundle to import it into the project. */
794
+ export declare function importPromotionBundle(projectId: string, bundle: PromotionBundleWire, mode: PromotionImportMode): Promise<ApiResponse<PromotionImportResult>>;
760
795
  export declare function validateApiKey(apiKey: string): Promise<{
761
796
  valid: false;
762
797
  error: string;
package/dist/bundle.d.ts CHANGED
@@ -23,6 +23,25 @@
23
23
  * empty; customer code is expected to be self-contained.
24
24
  */
25
25
  import { type BuildOptions } from 'esbuild';
26
+ /**
27
+ * Conventional entry-point filenames probed (in order) when
28
+ * `amba functions deploy <dir>` is pointed at a directory rather than a
29
+ * single file. Mirrors the Node / bundler convention (`index.*`) so a
30
+ * developer can `amba functions deploy ./my-fn` with an `index.ts` inside.
31
+ */
32
+ export declare const FUNCTION_ENTRY_CANDIDATES: readonly string[];
33
+ /**
34
+ * Resolve the bundler entry point from a deploy target that may be either a
35
+ * single file OR a directory.
36
+ *
37
+ * - File → returned as-is (single-file back-compat path).
38
+ * - Dir → resolved by convention to `index.{ts,js,mjs}`, or to an
39
+ * explicit `entry` (relative to the directory) when provided.
40
+ *
41
+ * Throws an actionable error when the target doesn't exist, or when a
42
+ * directory has no resolvable entry point (and no `--entry` was passed).
43
+ */
44
+ export declare function resolveFunctionEntry(target: string, explicitEntry?: string): Promise<string>;
26
45
  /**
27
46
  * Modules the bundler treats as `external` by default. The Amba
28
47
  * function runtime exposes zero npm packages — there is no "platform
@@ -46,6 +65,62 @@ export declare class BundleSizeError extends Error {
46
65
  readonly maxBytes: number;
47
66
  constructor(sizeBytes: number, maxBytes: number);
48
67
  }
68
+ /**
69
+ * The single source-of-truth message for the wrong-handler-shape failure.
70
+ * Shared between the CLI bundler (pre-upload), the local `dev` runner, and
71
+ * the server-side deploy hint so dev / deploy / prod all describe the fix
72
+ * identically. Customer functions run as Module Workers; the legacy
73
+ * service-worker shape (`export default async function (req) { … }`) is
74
+ * rejected by the runtime at upload, so we reject it before the round-trip.
75
+ */
76
+ export declare const HANDLER_SHAPE_FIX_MESSAGE: string;
77
+ /** Message used when the entry file has no `export default` at all. */
78
+ export declare const HANDLER_SHAPE_MISSING_DEFAULT_MESSAGE: string;
79
+ /** Message used when the default export is present but has no `fetch` method. */
80
+ export declare const HANDLER_SHAPE_NO_FETCH_MESSAGE: string;
81
+ /**
82
+ * Thrown when the bundled entry's `export default` is not the Module Worker
83
+ * shape (`{ fetch(req, env, ctx) }`). Raised BEFORE any upload so a wrong
84
+ * handler shape fails fast on the developer's machine with an actionable
85
+ * message instead of an opaque upstream rejection at deploy time.
86
+ */
87
+ export declare class HandlerShapeError extends Error {
88
+ readonly kind: 'plain-function' | 'missing-default' | 'no-fetch';
89
+ constructor(message: string, kind: 'plain-function' | 'missing-default' | 'no-fetch');
90
+ }
91
+ /**
92
+ * Inspect an already-imported module namespace and assert it has the
93
+ * Module Worker handler shape: a default export that is an object (or
94
+ * function-with-properties) carrying a callable `fetch`.
95
+ *
96
+ * Pure + side-effect free — it only reads the shape of `mod.default`, never
97
+ * invokes `fetch`. This is the unit-testable core; `assertModuleWorkerShape`
98
+ * wraps the import-from-code plumbing around it.
99
+ *
100
+ * Throws `HandlerShapeError` on:
101
+ * - no default export (`missing-default`)
102
+ * - a default-exported plain function — the legacy service-worker shape
103
+ * (`plain-function`)
104
+ * - a default export with no callable `fetch` (`no-fetch`)
105
+ */
106
+ export declare function assertHandlerShape(mod: {
107
+ default?: unknown;
108
+ }): void;
109
+ /**
110
+ * Validate that the bundled customer code exports the Module Worker handler
111
+ * shape, by importing it in isolation and inspecting `mod.default`.
112
+ *
113
+ * Mechanism: write the bundle to a throwaway temp `.mjs` and dynamic-import
114
+ * it, then hand the namespace to `assertHandlerShape`. This is the same
115
+ * import-and-inspect approach the local `dev` runner uses
116
+ * (`functions.ts` DEV_RUNNER_SOURCE) — reused here so the pre-upload check
117
+ * and the dev runner agree on what "valid shape" means. Importing runs the
118
+ * module's top-level code (unavoidable to read the export), but the handler
119
+ * itself is NEVER invoked — we only read the shape of the exported object.
120
+ *
121
+ * The temp file is always cleaned up (best-effort) before returning.
122
+ */
123
+ export declare function assertModuleWorkerShape(code: string): Promise<void>;
49
124
  export interface BundleResult {
50
125
  /** The bundled JS source (UTF-8). */
51
126
  code: string;
@@ -67,6 +142,17 @@ export interface BundleOptions {
67
142
  extraExternals?: string[];
68
143
  /** Source map handling. Default: inline. */
69
144
  sourcemap?: BuildOptions['sourcemap'];
145
+ /**
146
+ * Validate the bundled entry exports the Module Worker handler shape
147
+ * (`export default { async fetch(req, env, ctx) { … } }`) before
148
+ * returning, throwing `HandlerShapeError` if not. Default: true.
149
+ *
150
+ * The check imports the bundle in isolation to inspect `mod.default`;
151
+ * it never invokes the handler. Both `deploy` and `dev` leave this on so
152
+ * a function that bundles in `dev` cannot fail the shape check in
153
+ * `deploy` (dev / prod parity).
154
+ */
155
+ validateHandlerShape?: boolean;
70
156
  }
71
157
  /**
72
158
  * Bundle a customer function file for upload to a Workers dispatch
@@ -20,6 +20,7 @@
20
20
  * Multi-op alters are issued sequentially so the operator audit trail
21
21
  * stays one-to-one with developer actions.
22
22
  */
23
+ import { type CollectionColumn, type CollectionIndex } from '../api-client.js';
23
24
  export interface CollectionsCreateOptions {
24
25
  /** Field specs in `name:type[:nullable]` form. May repeat. */
25
26
  field: string[];
@@ -46,3 +47,57 @@ export declare function collectionsListCommand(): Promise<void>;
46
47
  export declare function collectionsDropCommand(name: string, options?: {
47
48
  confirm?: string;
48
49
  }): Promise<void>;
50
+ /**
51
+ * Parse a `--field` spec into a `CollectionColumn`.
52
+ *
53
+ * Accepted grammars:
54
+ *
55
+ * 1. **Plain column:** `name:type[:nullable]`
56
+ * Examples: `letter_id:uuid`, `parsed:jsonb:nullable`, `tags:text[]`,
57
+ * `scores:integer[]:nullable`. Array types (`text[]`, `integer[]`,
58
+ * `bigint[]`, `numeric[]`, `boolean[]`, `uuid[]`) follow the same
59
+ * grammar as scalars and unlock the contains/containedBy/overlaps
60
+ * query operators.
61
+ *
62
+ * 2. **Foreign key:** `name:type:fk(<table>[.<column>][:onDelete])`
63
+ * Examples:
64
+ * `plan_id:uuid:fk(plans)` — references `plans(id)`, default no-action
65
+ * `plan_id:uuid:fk(plans.id)` — explicit column
66
+ * `plan_id:uuid:fk(plans.id:cascade)` — ON DELETE CASCADE
67
+ * `parent_id:uuid:fk(comments:set_null)` — ON DELETE SET NULL
68
+ *
69
+ * Note: a `user_id` FK to `app_users(id)` is auto-emitted on every
70
+ * collection server-side. Customers don't need to declare it.
71
+ *
72
+ * 3. **Vector:** `name:vector:<dim>` or `name:vector(<dim>)`
73
+ * Examples:
74
+ * `embedding:vector:1536` — OpenAI text-embedding-3-small
75
+ * `embedding:vector(384)` — sentence-transformers / all-MiniLM
76
+ * Dimension is validated client-side as 1..4096. For an HNSW /
77
+ * IVFFlat index on the column, supply `--index 'embedding'`
78
+ * separately.
79
+ *
80
+ * 4. **Vector + nullable:** `name:vector:<dim>:nullable`
81
+ * Vector columns can be nullable for "embedding generated lazily".
82
+ *
83
+ * Multi-arg combinations (e.g. fk + nullable on the same column) parse
84
+ * left-to-right: the third segment is the FK / vector / nullable
85
+ * marker; if it's an FK or vector, the optional fourth segment is
86
+ * `nullable`. Plain columns put `nullable` in slot 3.
87
+ *
88
+ * Exported for tests.
89
+ */
90
+ export declare function parseColumnSpec(spec: string): CollectionColumn;
91
+ /**
92
+ * Parse an index spec into the wire shape data's API expects.
93
+ *
94
+ * Input syntax (CLI-friendly): `"col1 [asc|desc], col2 [asc|desc]"`.
95
+ * Wire shape (per data's contract): `{ columns: ['col1 desc', 'col2 asc'] }` —
96
+ * direction is embedded in each column string and parsed by the DDL emit.
97
+ *
98
+ * Bare column names (no direction) are passed through verbatim; the
99
+ * default sort direction is the DDL emit's responsibility.
100
+ *
101
+ * Exported for tests.
102
+ */
103
+ export declare function parseIndexSpec(spec: string): CollectionIndex;
@@ -6,6 +6,10 @@
6
6
  * - `--tail`: print the last hour's events, then poll every 3s for
7
7
  * new events past the highest seen `EventTimestampMs`. Ctrl+C to stop.
8
8
  *
9
+ * `--since-request-id <r_...>` anchors the range start at the oldest event
10
+ * mentioning that request id ("show me everything from this request
11
+ * onward") — the server resolves the anchor; works in both modes.
12
+ *
9
13
  * Output formatting:
10
14
  * - `--json`: NDJSON to stdout (one event per line) so `| jq` works.
11
15
  * - default: human-readable lines:
@@ -26,5 +30,14 @@ export interface FunctionsLogsOptions {
26
30
  tail?: boolean;
27
31
  /** NDJSON output. */
28
32
  json?: boolean;
33
+ /** Only show events whose log/exception text mentions this request id (`r_...`). */
34
+ requestId?: string;
35
+ /**
36
+ * Anchor the range start at the oldest event mentioning this request id
37
+ * ("everything from this request onward"). Searched within the last 24h
38
+ * (or within --since/--until when given). Composes with --requestId, which
39
+ * filters instead of anchoring. Works with --tail (anchors the backfill).
40
+ */
41
+ sinceRequestId?: string;
29
42
  }
30
43
  export declare function functionsLogsCommand(functionName: string, options?: FunctionsLogsOptions): Promise<void>;
@@ -9,8 +9,19 @@
9
9
  */
10
10
  import { type RateLimitConfig } from '../_internal/shared.js';
11
11
  export interface DeployOptions {
12
- /** Override the function name. Default: filename without extension. */
12
+ /**
13
+ * Override the function name. Default: when a file is deployed, the
14
+ * filename without extension; when a directory is deployed, the
15
+ * directory's leaf name (NOT the resolved `index` entry's name).
16
+ */
13
17
  name?: string;
18
+ /**
19
+ * Entry file when the deploy target is a DIRECTORY (relative to it).
20
+ * Only valid with a directory target; ignored for single-file deploys.
21
+ * When omitted, a directory resolves its entry by convention
22
+ * (`index.ts` / `index.js` / `index.mjs`).
23
+ */
24
+ entry?: string;
14
25
  /** Print bundle report but skip the CF API + DB write. Useful for size triage. */
15
26
  dryRun?: boolean;
16
27
  /**
@@ -23,8 +34,16 @@ export interface DeployOptions {
23
34
  rateLimitWindow?: string;
24
35
  rateLimitMax?: number;
25
36
  rateLimitKey?: string;
37
+ /**
38
+ * Opt-in public flag (#17). Deploy the function WITHOUT the X-Api-Key
39
+ * gate so third-party webhook senders (Stripe, RevenueCat, GitHub,
40
+ * Slack) that can't attach a custom header can reach it. Default false
41
+ * (private). The customer MUST verify the webhook HMAC signature inside
42
+ * the handler — public skips the credential gate only.
43
+ */
44
+ public?: boolean;
26
45
  }
27
- export declare function functionsDeployCommand(entryPoint: string, options?: DeployOptions): Promise<void>;
46
+ export declare function functionsDeployCommand(target: string, options?: DeployOptions): Promise<void>;
28
47
  export declare function functionsListCommand(): Promise<void>;
29
48
  export declare function functionsDeleteCommand(name: string, options?: {
30
49
  confirm?: string;
@@ -0,0 +1,116 @@
1
+ /**
2
+ * `amba apply` / `amba diff` / `amba export` — declarative
3
+ * infrastructure-as-code for a project's reusable configuration.
4
+ *
5
+ * A declarative bundle (default `amba.config.json`) captures the entities a
6
+ * developer hand-builds once and wants to stand up identically elsewhere:
7
+ * remote configs, collection schemas, content libraries + items, currencies,
8
+ * achievements, streaks, challenges, leaderboards, and xp_rules. It carries
9
+ * CONFIGURATION ONLY — no secrets, no per-user data.
10
+ *
11
+ * These commands wrap the platform's promotion endpoints:
12
+ * GET /v1/admin/projects/:p/promotion/export
13
+ * POST /v1/admin/projects/:p/promotion/import (mode=skip_existing|merge)
14
+ *
15
+ * - `amba export [file]` writes the current project's bundle to disk.
16
+ * - `amba apply [file]` POSTs the local bundle to the import endpoint and
17
+ * prints a `{ created, updated, skipped }` summary
18
+ * per section (the server's authoritative result).
19
+ * - `amba diff [file]` shows what `apply` WOULD change without writing.
20
+ * The import route has NO server-side dry-run, so
21
+ * `diff` exports the current project and computes the
22
+ * created/updated/skipped per section LOCALLY.
23
+ */
24
+ import { type PromotionBundleWire, type PromotionImportMode } from '../api-client.js';
25
+ /** Default declarative bundle filename when no `[file]` is passed. */
26
+ export declare const DEFAULT_BUNDLE_FILE = "amba.config.json";
27
+ export interface ApplyOptions {
28
+ project?: string;
29
+ /** `skip_existing` (default) no-ops on conflict; `merge` refreshes. */
30
+ mode?: PromotionImportMode;
31
+ }
32
+ export interface DiffOptions {
33
+ project?: string;
34
+ mode?: PromotionImportMode;
35
+ }
36
+ export interface ExportOptions {
37
+ project?: string;
38
+ }
39
+ /** Per-section, per-key diff outcome. */
40
+ export interface SectionDiff {
41
+ created: number;
42
+ updated: number;
43
+ skipped: number;
44
+ }
45
+ export type LocalDiff = Record<string, SectionDiff>;
46
+ /**
47
+ * Read + parse a declarative bundle from disk. JSON only — we deliberately
48
+ * don't pull in a YAML dependency the CLI doesn't already ship (the package
49
+ * has no YAML lib), so `.yaml`/`.yml` files are rejected with a clear hint
50
+ * rather than silently mis-parsed.
51
+ */
52
+ export declare function readBundleFile(file: string): Promise<PromotionBundleWire>;
53
+ /**
54
+ * Pure section-by-section diff of a desired bundle against the current
55
+ * project's exported bundle. The classification MIRRORS the server's import
56
+ * (`apps/api/src/lib/promotion-bundle.ts`) so `amba diff` agrees with what
57
+ * `amba apply` will report:
58
+ * - created — natural key absent in current.
59
+ * - updated — natural key present AND `mode === 'merge'`. The server runs an
60
+ * UNCONDITIONAL update for every existing key in merge mode and
61
+ * increments `updated` — it does NOT compare field values, so we
62
+ * don't either (a local field comparison made `diff` under-report).
63
+ * - skipped — natural key present under `skip_existing`; OR an existing
64
+ * collection (always — collections are create-if-absent, never
65
+ * merged); OR a `remote_configs` row flagged `is_system: true`
66
+ * (the server always skips those before any existence check); OR
67
+ * a desired row with no valid natural key (can't be matched
68
+ * against the export, and the server import dedups by that key —
69
+ * so it is never a reliable create).
70
+ *
71
+ * Within one bundle section, the server walks rows sequentially and each
72
+ * insert mutates the DB, so a SECOND row sharing a natural key already created
73
+ * by an EARLIER row in the same section is seen as existing (→ skip under
74
+ * skip_existing, update under merge) rather than created a second time. We
75
+ * track already-seen keys per section to mirror that, so duplicate-keyed local
76
+ * rows don't inflate the `created` total versus what `apply` does.
77
+ */
78
+ export declare function computeLocalDiff(desired: PromotionBundleWire, current: PromotionBundleWire, mode: PromotionImportMode): LocalDiff;
79
+ declare function totalOf(s: {
80
+ created: number;
81
+ updated: number;
82
+ skipped: number;
83
+ }): number;
84
+ /** Roll a per-section diff up into grand totals across every section. */
85
+ export declare function summarizeDiff(diff: Record<string, SectionDiff>): SectionDiff;
86
+ /**
87
+ * `amba export [file]` — write the current project's declarative bundle to
88
+ * disk so it can be checked in, diffed, and re-applied.
89
+ */
90
+ export declare function exportConfigCommand(file?: string, options?: ExportOptions): Promise<void>;
91
+ /**
92
+ * `amba apply [file]` — read a local declarative bundle and POST it to the
93
+ * import endpoint. Prints the server's authoritative `{ created, updated,
94
+ * skipped }` per section.
95
+ */
96
+ export declare function applyConfigCommand(file?: string, options?: ApplyOptions): Promise<void>;
97
+ /**
98
+ * `amba diff [file]` — show what `apply` WOULD change without writing.
99
+ *
100
+ * The import route has no server-side dry-run, so this fetches the current
101
+ * project's exported bundle and computes the diff LOCALLY. Output mirrors the
102
+ * `apply` summary shape so the two read identically.
103
+ */
104
+ export declare function diffConfigCommand(file?: string, options?: DiffOptions): Promise<void>;
105
+ /** Test-only re-export of internal helpers. Not a public API. */
106
+ export declare const __testHelpers: {
107
+ computeLocalDiff: typeof computeLocalDiff;
108
+ summarizeDiff: typeof summarizeDiff;
109
+ readBundleFile: typeof readBundleFile;
110
+ BUNDLE_SECTIONS: readonly {
111
+ key: string;
112
+ naturalKey: string;
113
+ }[];
114
+ totalOf: typeof totalOf;
115
+ };
116
+ export {};
@@ -0,0 +1,46 @@
1
+ /**
2
+ * `amba monetization *` subcommands — CLI access to the monetization control
3
+ * plane behind `/v1/admin/projects/:id/monetization/*`.
4
+ *
5
+ * amba monetization plan — three-way diff (declared vs adopted baseline
6
+ * vs live provider) + store-floor preflight +
7
+ * drift. READ-ONLY — previews; applies nothing.
8
+ * amba monetization drift — out-of-band changes to Amba-managed objects.
9
+ * amba monetization export — snapshot the live config to a declarative
10
+ * bundle (the `monetization` section), to stdout
11
+ * or a file.
12
+ * amba monetization adopt — record the live config as the managed baseline
13
+ * so the next plan is a no-op. Writes ONLY Amba's
14
+ * own state — never the provider. Idempotent.
15
+ * amba monetization apply — push the declared config to the provider.
16
+ * DURABLE: the API returns a pollable
17
+ * operation_id and the CLI polls it to a
18
+ * terminal state. Additive changes apply
19
+ * automatically; destructive changes run only
20
+ * behind --confirm (which approves the exact
21
+ * plan_hash — a pending apply awaiting
22
+ * confirmation is approved by re-running with
23
+ * --confirm). STORE-PRODUCT steps (creating
24
+ * declared products in the provider and, for
25
+ * App Store products with push intent, in App
26
+ * Store Connect) ALWAYS wait for an explicit
27
+ * approval of the started apply — an up-front
28
+ * --confirm never auto-runs them. Refuses if
29
+ * the provider drifted since the plan.
30
+ *
31
+ * Project is resolved via `loadProjectConfig` — same pattern as the other
32
+ * project-scoped CLI commands.
33
+ */
34
+ export declare function monetizationPlanCommand(): Promise<void>;
35
+ export declare function monetizationDriftCommand(): Promise<void>;
36
+ export declare function monetizationExportCommand(options?: {
37
+ file?: string;
38
+ }): Promise<void>;
39
+ export declare function monetizationAdoptCommand(options?: {
40
+ all?: boolean;
41
+ }): Promise<void>;
42
+ export declare function monetizationApplyCommand(options?: {
43
+ confirm?: boolean;
44
+ allowDetachLive?: boolean;
45
+ reconcile?: string;
46
+ }): Promise<void>;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * `amba payments *` subcommands — CLI access to the Amba Payments (Stripe
3
+ * Connect platform) surface at `/v1/admin/projects/:id/payments/*`
4
+ * (tracker #10).
5
+ *
6
+ * Amba is the payments rail for the developer's app: the app is the seller,
7
+ * Amba takes a platform fee, Stripe carries money-transmission. This is the
8
+ * developer-facing onboarding + config + reporting surface, so naming Stripe
9
+ * here is by intent (same as `amba billing`).
10
+ *
11
+ * amba payments setup — create the connected account +
12
+ * print the hosted onboarding URL.
13
+ * amba payments status — onboarding stage + capability flags.
14
+ * amba payments set-fee <bps|off> — default platform fee (basis points).
15
+ * amba payments balance — connected-account balance.
16
+ * amba payments payouts — recent payouts.
17
+ *
18
+ * Every live call is gated by the platform's PAYMENTS_CONNECT_LIVE
19
+ * kill-switch — when off the API returns PAYMENTS_NOT_ENABLED, surfaced
20
+ * verbatim here. Project resolved via loadProjectConfig (same as billing).
21
+ */
22
+ export declare function paymentsSetupCommand(input: {
23
+ country?: string;
24
+ email?: string;
25
+ }): Promise<void>;
26
+ export declare function paymentsStatusCommand(): Promise<void>;
27
+ export declare function paymentsSetFeeCommand(input: {
28
+ bps: number | null;
29
+ }): Promise<void>;
30
+ export declare function paymentsBalanceCommand(): Promise<void>;
31
+ export declare function paymentsPayoutsCommand(input: {
32
+ limit?: number;
33
+ }): Promise<void>;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * `amba ship` — take this Expo app from code-complete to live on the App Store
3
+ * and Google Play, and `amba ship init` to scaffold its config.
4
+ *
5
+ * amba ship run the full pipeline (preflight → monetization →
6
+ * build → submit → metadata → release)
7
+ * amba ship --phase build run a single phase
8
+ * amba ship --dry-run print the plan; touch nothing
9
+ * amba ship init scaffold amba.ship.json
10
+ *
11
+ * Build/submit/release shell out to `eas` (the Expo toolchain owns the build,
12
+ * the signing credentials, and the store submit). Monetization delegates to the
13
+ * Amba control plane (`amba monetization`). Steps no API can do — create the
14
+ * store app record, the Apple Paid-Apps agreement, screenshots, store review —
15
+ * are detected and surfaced as manual gates with the exact console action.
16
+ */
17
+ import { type ShipConfig } from '../ship/config.js';
18
+ import { type Executor } from '../ship/exec.js';
19
+ export interface ShipCommandOptions {
20
+ phase?: string;
21
+ platform?: string;
22
+ dryRun?: boolean;
23
+ force?: boolean;
24
+ config?: string;
25
+ }
26
+ /** Test seam: override the cloud-touching + clock dependencies. */
27
+ export interface ShipCommandDeps {
28
+ exec?: Executor;
29
+ resolveProjectId?: () => Promise<string | null>;
30
+ adminGet?: <T>(path: string) => Promise<{
31
+ data: T;
32
+ }>;
33
+ now?: () => string;
34
+ sleep?: (ms: number) => Promise<void>;
35
+ stateBaseDir?: string;
36
+ releasePollMs?: number;
37
+ releaseMaxWaitMs?: number;
38
+ }
39
+ /** Read + parse + validate a ship config file. Throws with every error joined. */
40
+ export declare function loadShipConfig(file: string): Promise<ShipConfig>;
41
+ export declare function shipCommand(options?: ShipCommandOptions, deps?: ShipCommandDeps): Promise<void>;
42
+ export interface ShipInitOptions {
43
+ config?: string;
44
+ force?: boolean;
45
+ slug?: string;
46
+ }
47
+ export declare function shipInitCommand(options?: ShipInitOptions): Promise<void>;