@appforge-ci/core 0.1.1

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 (62) hide show
  1. package/LICENSE +21 -0
  2. package/dist/agent-readiness.d.ts +163 -0
  3. package/dist/agent-readiness.d.ts.map +1 -0
  4. package/dist/agent-readiness.js +179 -0
  5. package/dist/agent-readiness.js.map +1 -0
  6. package/dist/agent-readiness.test.d.ts +2 -0
  7. package/dist/agent-readiness.test.d.ts.map +1 -0
  8. package/dist/agent-readiness.test.js +177 -0
  9. package/dist/agent-readiness.test.js.map +1 -0
  10. package/dist/api-client.d.ts +529 -0
  11. package/dist/api-client.d.ts.map +1 -0
  12. package/dist/api-client.js +551 -0
  13. package/dist/api-client.js.map +1 -0
  14. package/dist/api-client.test.d.ts +2 -0
  15. package/dist/api-client.test.d.ts.map +1 -0
  16. package/dist/api-client.test.js +305 -0
  17. package/dist/api-client.test.js.map +1 -0
  18. package/dist/build-cost.test.d.ts +2 -0
  19. package/dist/build-cost.test.d.ts.map +1 -0
  20. package/dist/build-cost.test.js +21 -0
  21. package/dist/build-cost.test.js.map +1 -0
  22. package/dist/index.d.ts +8 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +8 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/ota-artifact.d.ts +41 -0
  27. package/dist/ota-artifact.d.ts.map +1 -0
  28. package/dist/ota-artifact.js +43 -0
  29. package/dist/ota-artifact.js.map +1 -0
  30. package/dist/ota-artifact.test.d.ts +2 -0
  31. package/dist/ota-artifact.test.d.ts.map +1 -0
  32. package/dist/ota-artifact.test.js +44 -0
  33. package/dist/ota-artifact.test.js.map +1 -0
  34. package/dist/ota-bundle-hash.d.ts +38 -0
  35. package/dist/ota-bundle-hash.d.ts.map +1 -0
  36. package/dist/ota-bundle-hash.js +40 -0
  37. package/dist/ota-bundle-hash.js.map +1 -0
  38. package/dist/ota-bundle-hash.test.d.ts +2 -0
  39. package/dist/ota-bundle-hash.test.d.ts.map +1 -0
  40. package/dist/ota-bundle-hash.test.js +28 -0
  41. package/dist/ota-bundle-hash.test.js.map +1 -0
  42. package/dist/ota-rollout.d.ts +38 -0
  43. package/dist/ota-rollout.d.ts.map +1 -0
  44. package/dist/ota-rollout.js +53 -0
  45. package/dist/ota-rollout.js.map +1 -0
  46. package/dist/ota-rollout.test.d.ts +2 -0
  47. package/dist/ota-rollout.test.d.ts.map +1 -0
  48. package/dist/ota-rollout.test.js +48 -0
  49. package/dist/ota-rollout.test.js.map +1 -0
  50. package/dist/schemas.d.ts +776 -0
  51. package/dist/schemas.d.ts.map +1 -0
  52. package/dist/schemas.js +538 -0
  53. package/dist/schemas.js.map +1 -0
  54. package/dist/token-packs.test.d.ts +2 -0
  55. package/dist/token-packs.test.d.ts.map +1 -0
  56. package/dist/token-packs.test.js +34 -0
  57. package/dist/token-packs.test.js.map +1 -0
  58. package/dist/types.d.ts +445 -0
  59. package/dist/types.d.ts.map +1 -0
  60. package/dist/types.js +80 -0
  61. package/dist/types.js.map +1 -0
  62. package/package.json +35 -0
@@ -0,0 +1,445 @@
1
+ /**
2
+ * Shared domain types used by the API, dashboard, CLI, and agent.
3
+ * These mirror (but do not import from) the Prisma schema in packages/db,
4
+ * so packages that never need a DB connection don't need Prisma as a dep.
5
+ */
6
+ export type Platform = "ios" | "android" | "flutter" | "react-native";
7
+ export type BuildStatus = "queued" | "leased" | "running" | "succeeded" | "failed" | "canceled";
8
+ export type AgentStatus = "online" | "offline" | "draining" | "building";
9
+ export interface User {
10
+ id: string;
11
+ email: string;
12
+ name: string | null;
13
+ createdAt: string;
14
+ /** True for the platform operator, not a per-org role — fleet
15
+ * management (enrolling/draining/rebooting Mac minis) is an
16
+ * AppForge-the-service concern, the same way Codemagic customers never
17
+ * manage Codemagic's own build machines. Regular org
18
+ * owners/admins/members never see or touch fleet endpoints regardless
19
+ * of their org role. */
20
+ isPlatformAdmin: boolean;
21
+ /** Set once `POST /auth/verify-email` redeems the token from the
22
+ * signup verification email (`apps/api/src/lib/email-verification.ts`),
23
+ * `null` until then. Purely informational — nothing in this app gates
24
+ * on it (see that route's own docblock), so this is safe to ignore
25
+ * entirely; it exists so a dashboard page can show verification status
26
+ * and offer a resend. */
27
+ emailVerifiedAt: string | null;
28
+ /** TOTP 2FA status (apps/api/src/routes/two-factor.ts) — whether a
29
+ * confirmed authenticator is required at login, not just enrolled. */
30
+ twoFactorEnabled: boolean;
31
+ /** How many single-use recovery codes are still unconsumed — the only
32
+ * self-service fallback if the authenticator itself is lost, so
33
+ * running out silently is a real lockout risk. `null` whenever 2FA
34
+ * isn't enabled (there's nothing to count); always a fresh 10 right
35
+ * after enrollment or a regenerate, since both replace the whole set
36
+ * (see `packages/db`'s `replaceTotpRecoveryCodes`/
37
+ * `countUnusedTotpRecoveryCodes`). */
38
+ unusedRecoveryCodeCount: number | null;
39
+ }
40
+ export type BillingMode = "prepaid" | "postpaid_monthly";
41
+ export interface Org {
42
+ id: string;
43
+ name: string;
44
+ slug: string;
45
+ /** Prepaid build tokens. Unused once billingMode is postpaid_monthly. See TOKEN_PACKS / BUILD_COST_TOKENS below. */
46
+ tokenBalance: number;
47
+ billingMode: BillingMode;
48
+ /** Opt-in outgoing webhook, POSTed on every terminal build report for
49
+ * any app in this org — see `apps/admin-api/src/lib/build-webhook.ts`.
50
+ * null means disabled (the default). */
51
+ buildWebhookUrl: string | null;
52
+ createdAt: string;
53
+ }
54
+ /** LHV Paytech is the only postpaid payment provider on this instance —
55
+ * Stripe support was removed entirely (#516) rather than left unwired. */
56
+ export type PaymentProvider = "lhv";
57
+ export interface BillingUsage {
58
+ billingMode: BillingMode;
59
+ tokenBalance: number;
60
+ buildCostTokens: number;
61
+ /** Only meaningful when billingMode is "postpaid_monthly". */
62
+ accruedUnbilledTokens: number;
63
+ estimatedAmountCents: number;
64
+ monthlyInvoiceDay: number;
65
+ billingPastDue: boolean;
66
+ lastInvoicedAt: string | null;
67
+ /** True if LHV has a saved payment method — the only postpaid provider
68
+ * left after Stripe's removal (#516); currently always equal to
69
+ * `hasLhvCard`, kept as a separate field since it's what the
70
+ * dashboard/CLI actually gate "switch to monthly billing" on. */
71
+ hasPaymentMethod: boolean;
72
+ hasLhvCard: boolean;
73
+ lhvCardLastFour: string | null;
74
+ postpaidProvider: PaymentProvider | null;
75
+ }
76
+ export type MonthlyInvoiceStatus = "pending" | "paid" | "failed";
77
+ export interface MonthlyInvoice {
78
+ id: string;
79
+ orgId: string;
80
+ periodStart: string;
81
+ periodEnd: string;
82
+ tokens: number;
83
+ amountCents: number;
84
+ status: MonthlyInvoiceStatus;
85
+ provider: PaymentProvider;
86
+ createdAt: string;
87
+ paidAt: string | null;
88
+ }
89
+ export interface Membership {
90
+ userId: string;
91
+ orgId: string;
92
+ role: "owner" | "admin" | "member";
93
+ }
94
+ export interface App {
95
+ id: string;
96
+ orgId: string;
97
+ name: string;
98
+ platform: Platform;
99
+ repoUrl: string;
100
+ defaultBranch: string;
101
+ createdAt: string;
102
+ /** Whether an OTA app key has ever been generated for this app — not
103
+ * the key itself (that's never exposed once hashed), just enough to
104
+ * tell whether clicking "Generate/rotate" is a first-time mint or a
105
+ * destructive rotation that invalidates every build already
106
+ * embedding the old key. See `appforge ota app-key`. */
107
+ hasOtaAppKey: boolean;
108
+ }
109
+ /** Public shape of `GET /orgs/:orgId/tokens` — deliberately never
110
+ * includes the token value or its hash (see docs/security.md); once
111
+ * minted, the raw token is only ever shown once, at creation time. */
112
+ export interface ApiTokenInfo {
113
+ id: string;
114
+ label: string;
115
+ createdAt: string;
116
+ lastUsedAt: string | null;
117
+ }
118
+ export interface Build {
119
+ id: string;
120
+ appId: string;
121
+ orgId: string;
122
+ status: BuildStatus;
123
+ /** The `appforge.yaml` workflow name this build ran (or was queued to
124
+ * run) — `"default"` unless a caller passed `--workflow`/`workflow:`
125
+ * explicitly. Was silently dropped by `serializeBuild`
126
+ * (`apps/api/src/routes/builds.ts`) despite being a real, always-
127
+ * present column (`BuildRow.workflow`, `packages/db/src/types.ts`)
128
+ * set at trigger time — this repo's own "no client can ever see
129
+ * it" bug shape (see `defaultBranch`'s and `triggeredBy`'s own
130
+ * fix history in ROADMAP.md). */
131
+ workflow: string;
132
+ branch: string;
133
+ commitSha: string | null;
134
+ triggeredBy: "manual" | "webhook" | "cli";
135
+ /** Only meaningful when status is "failed" — see BuildResult.
136
+ * failureKind's docblock (packages/agent/src/lib/builder.ts) and
137
+ * docs/billing.md for what "infra" means and that it drives an
138
+ * automatic refund. Null for a succeeded/canceled build, or a failed
139
+ * one reported by an agent that predates this field. */
140
+ failureKind: "user" | "infra" | null;
141
+ agentId: string | null;
142
+ costTokens: number;
143
+ queuedAt: string;
144
+ startedAt: string | null;
145
+ finishedAt: string | null;
146
+ artifacts: BuildArtifact[];
147
+ /** One entry per smoke-test screenshot this build produced (up to 3 on
148
+ * Android's fixed-walk v1, at most 1 on iOS today — see
149
+ * packages/agent/src/lib/android-smoke-test.ts/ios-smoke-test.ts),
150
+ * index-ordered. Empty when `smokeTest: true` wasn't set, or the
151
+ * smoke test itself couldn't run (no device/Simulator attached). */
152
+ smokeTestResults: SmokeTestScreenshotResult[];
153
+ }
154
+ /** Per-screenshot smoke-test state — see `Build.smokeTestResults`. */
155
+ export interface SmokeTestScreenshotResult {
156
+ screenshotIndex: number;
157
+ fileName: string;
158
+ downloadUrl: string;
159
+ /** Set once automatic analysis (triggered by `GET /builds/:id` — see
160
+ * apps/api/src/routes/builds.ts) or a manual "Analyze smoke test"
161
+ * click succeeds for this screenshot. Null until then. */
162
+ verdict: SmokeTestVerdict | null;
163
+ /** True while automatic analysis of this screenshot is claimed but not
164
+ * yet resolved either way — the dashboard polls a bit longer while
165
+ * any screenshot is still analyzing instead of stopping the moment
166
+ * the build itself reaches a terminal status. */
167
+ analyzing: boolean;
168
+ /** Set if automatic analysis of this screenshot was attempted and
169
+ * failed (e.g. `ANTHROPIC_API_KEY` isn't configured on this
170
+ * deployment) — distinct from `verdict` being null because nothing's
171
+ * run yet. */
172
+ error: string | null;
173
+ }
174
+ export interface BuildArtifact {
175
+ id: string;
176
+ buildId: string;
177
+ fileName: string;
178
+ sizeBytes: number;
179
+ downloadUrl: string;
180
+ }
181
+ /**
182
+ * AI triage of a failed build's log — see apps/api/src/lib/ai-triage.ts.
183
+ * Best-effort: `confidence: "low"` (or the whole feature 501ing when
184
+ * ANTHROPIC_API_KEY isn't configured) is expected, not a bug — this is a
185
+ * starting point for debugging, not a guaranteed diagnosis.
186
+ */
187
+ export interface BuildFailureExplanation {
188
+ summary: string;
189
+ likelyCause: string;
190
+ suggestedFix: string;
191
+ confidence: "low" | "medium" | "high";
192
+ }
193
+ export interface AgentInfo {
194
+ id: string;
195
+ orgId: string;
196
+ name: string;
197
+ status: AgentStatus;
198
+ /** The Mac's hardware UUID — stable per machine. Null for agents
199
+ * enrolled before this field existed (until they next re-enroll) and
200
+ * for non-Mac hosts. See @appforge-ci/db's upsertAgent. */
201
+ machineId: string | null;
202
+ hostname: string;
203
+ macOsVersion: string;
204
+ xcodeVersion: string | null;
205
+ flutterVersion: string | null;
206
+ javaVersion: string | null;
207
+ androidSdkVersion: string | null;
208
+ cocoapodsVersion: string | null;
209
+ cpuModel: string;
210
+ /** This Mac's own packages/agent daemon version, self-reported at
211
+ * enroll/heartbeat. Null until it (re-)enrolls or heartbeats on a
212
+ * build that sends it — see isAgentVersionCurrent in
213
+ * ./agent-readiness.js, the fleet-wide "is this row current" check. */
214
+ agentVersion: string | null;
215
+ /** Whether macOS Screen Sharing (the built-in VNC server) is enabled on
216
+ * this Mac, self-reported at enroll/heartbeat — see
217
+ * @appforge-ci/agent's system-info.ts. Null until it (re-)enrolls or
218
+ * heartbeats on a build that sends it. 0/1/null, not a real boolean —
219
+ * this is passed straight through from the D1 row (see
220
+ * apps/admin-api/src/routes/fleet.ts), not re-serialized. */
221
+ screenSharingEnabled: number | null;
222
+ /** Whether a platform admin has authorized forwarding mouse/keyboard
223
+ * input into this Mac's VNC session, not just watching it — see
224
+ * @appforge/db's migrations/0024_agent_remote_control.sql. Unlike
225
+ * screenSharingEnabled just above, this is never self-reported by the
226
+ * agent; it only changes via `PATCH /orgs/:orgId/agents/:agentId/
227
+ * remote-control` (apps/admin-api) or `appforge-admin agents
228
+ * allow-remote-control`. 0/1/null, passed straight through from the
229
+ * D1 row same as screenSharingEnabled — but null and 0 both mean "not
230
+ * granted" (fail closed), the opposite of screenSharingEnabled's
231
+ * permissive-on-null convention, since this gates actual control of
232
+ * hardware, not just a read. */
233
+ remoteControlEnabled: number | null;
234
+ cpuUsagePercent: number;
235
+ memUsagePercent: number;
236
+ diskFreeGb: number;
237
+ tailscaleHostname: string | null;
238
+ currentBuildId: string | null;
239
+ /** How many builds this Mac will run at once, self-reported at every
240
+ * heartbeat. 1 for a row an as-yet-unupgraded agent binary has never
241
+ * reported this on. See migrations/0017_agent_concurrency.sql. */
242
+ maxConcurrentBuilds: number;
243
+ /** JSON array of build ids this agent is running right now (e.g.
244
+ * '["bld_a","bld_b"]'), '[]' when idle — passed straight through from
245
+ * the D1 row (see apps/admin-api/src/routes/fleet.ts), not
246
+ * re-serialized, same as screenSharingEnabled just above. */
247
+ activeBuildIds: string;
248
+ lastSeenAt: string;
249
+ }
250
+ export type AgentCommandType = "DRAIN" | "RESUME" | "REBOOT_HOST" | "RESTART_AGENT" | "RUN_MAINTENANCE_SCRIPT" | "UPDATE_AGENT" | "CANCEL_BUILD";
251
+ export interface AgentCommand {
252
+ id: string;
253
+ agentId: string;
254
+ type: AgentCommandType;
255
+ /** Only used for RUN_MAINTENANCE_SCRIPT — must match a name in the agent's allowlist. */
256
+ scriptName?: string;
257
+ /** Only used for CANCEL_BUILD — which of this agent's (possibly several
258
+ * concurrent) builds to kill. See migrations/0018_cancel_build_command.sql. */
259
+ buildId?: string;
260
+ /** Only used for UPDATE_AGENT — an npm version (e.g. "0.2.0") or, for a
261
+ * repo-checkout install, a git ref (tag/sha) to check out. Undefined
262
+ * means "whatever the agent's own self-update step treats as latest"
263
+ * (npm dist-tag `latest` / the checkout's default branch) — see
264
+ * packages/agent/src/lib/self-update.ts. */
265
+ targetVersion?: string;
266
+ /** Only meaningful for UPDATE_AGENT — 1 when the fleet's own OTA
267
+ * Phase 4 auto-rollback issued this command after detecting a stuck
268
+ * self-update, distinct from one a human or Phase 3's ordinary
269
+ * auto-update policy issued. Null/0/undefined all mean "not an
270
+ * auto-rollback" — same nullable-number-as-boolean convention as
271
+ * `AgentInfo.remoteControlEnabled` above; see @appforge/db's
272
+ * AgentCommandRow.isAutoRollback for the full story. */
273
+ isAutoRollback?: number | null;
274
+ status: "pending" | "acked" | "done" | "failed";
275
+ createdAt: string;
276
+ result?: string;
277
+ /** The admin who issued this command — `GET /agents/:agentId/commands`
278
+ * (`packages/db/src/agents.ts`'s `listAgentCommands`) always joins it
279
+ * in, but this field was missing from this type even though the
280
+ * route/DB layer already returned it: `null` only for a command
281
+ * issued before this was tracked, or a since-deleted account — same
282
+ * convention as `VncSession.issuedByEmail` above. */
283
+ issuedByEmail?: string | null;
284
+ }
285
+ /** One VNC "Connect" session request — the audit trail's read side (see
286
+ * `apps/admin-api`'s `GET /orgs/:orgId/agents/:agentId/vnc-sessions`).
287
+ * `issuedByEmail` is null only for a since-deleted account. */
288
+ export interface VncSession {
289
+ id: string;
290
+ agentId: string;
291
+ issuedByEmail: string | null;
292
+ /** "view" (screen visibility only) or "control" (also forwards
293
+ * mouse/keyboard input) — see @appforge/db's
294
+ * migrations/0025_vnc_session_mode.sql. */
295
+ mode: "view" | "control";
296
+ /** Whether this request actually succeeded — 0 for a "control"
297
+ * request refused because the agent's `remoteControlEnabled` flag
298
+ * wasn't on (still recorded, not silently dropped — see
299
+ * @appforge/db's migrations/0027_vnc_session_audit_granted.sql). */
300
+ granted: number;
301
+ createdAt: string;
302
+ }
303
+ /**
304
+ * appforge.yaml — the build config a repo owner commits alongside their app.
305
+ * Intentionally similar in shape to codemagic.yaml / GitHub Actions so it's
306
+ * easy to port an existing pipeline.
307
+ */
308
+ export interface AppforgeConfig {
309
+ platform: Platform;
310
+ workflows: Record<string, AppforgeWorkflow>;
311
+ }
312
+ export interface AppforgeWorkflow {
313
+ name?: string;
314
+ environment?: {
315
+ node?: string;
316
+ flutter?: string;
317
+ xcode?: string;
318
+ vars?: Record<string, string>;
319
+ };
320
+ triggers?: {
321
+ push?: {
322
+ branch: string[];
323
+ };
324
+ };
325
+ scripts: {
326
+ name?: string;
327
+ script: string;
328
+ }[];
329
+ artifacts?: string[];
330
+ /** Opt-in post-build smoke test (#9 v1) — off by default. */
331
+ smokeTest?: boolean;
332
+ /** Opt-in OTA (over-the-air) code-push update publishing. Off by default. */
333
+ ota?: {
334
+ channel?: string;
335
+ mandatory?: boolean;
336
+ };
337
+ }
338
+ export interface OtaRelease {
339
+ id: string;
340
+ appId: string;
341
+ channel: string;
342
+ platform: Platform;
343
+ buildId: string | null;
344
+ bundleHash: string;
345
+ r2Key: string;
346
+ mandatory: boolean;
347
+ rollout: number;
348
+ createdAt: string;
349
+ bundleUrl?: string;
350
+ }
351
+ export interface OtaChannel {
352
+ channel: string;
353
+ activeReleaseId: string | null;
354
+ activeRelease: OtaRelease | null;
355
+ updatedAt: string;
356
+ }
357
+ export interface OtaManifest {
358
+ releaseId: string;
359
+ appId: string;
360
+ channel: string;
361
+ platform: Platform;
362
+ bundleUrl: string;
363
+ bundleHash: string;
364
+ mandatory: boolean;
365
+ rollout: number;
366
+ createdAt: string;
367
+ }
368
+ /** Verdict from analyzing a build's smoke-test screenshot (#9) — see
369
+ * apps/api/src/lib/smoke-test-vision.ts. Best-effort, same "confidence"
370
+ * honesty as BuildFailureExplanation: a vision model looking at one
371
+ * screenshot can't be certain, so it isn't asked to pretend to be. */
372
+ export interface SmokeTestVerdict {
373
+ looksOk: boolean;
374
+ explanation: string;
375
+ }
376
+ export type LedgerReason = "topup" | "build_charge" | "refund" | "adjustment" | "invoice";
377
+ export interface LedgerEntry {
378
+ id: string;
379
+ orgId: string;
380
+ buildId: string | null;
381
+ deltaTokens: number;
382
+ reason: LedgerReason;
383
+ note: string | null;
384
+ createdAt: string;
385
+ }
386
+ /**
387
+ * Billing runs on tokens, not direct EUR-per-build, specifically so a
388
+ * bigger top-up can be cheaper per token without ever changing what a
389
+ * build costs. `BUILD_COST_TOKENS` is the default/baseline cost — same
390
+ * as every platform's actual cost today (see `BUILD_COST_TOKENS_BY_PLATFORM`
391
+ * below), so this PR ships the *mechanism* for per-platform pricing
392
+ * without changing anyone's bill; a maintainer who actually wants e.g. a
393
+ * bigger/faster iOS build machine to cost more tokens than a default
394
+ * Android one (the way Codemagic prices different machine types
395
+ * differently per minute) edits the map below, the same one-constant
396
+ * edit `TOKEN_PACKS` already is — no further code change needed.
397
+ */
398
+ export declare const BUILD_COST_TOKENS = 100;
399
+ /** Every platform costs `BUILD_COST_TOKENS` today — see the note above.
400
+ * Kept as an explicit per-platform map (not a single constant) so that
401
+ * changing one platform's price is a one-line edit here, not a search
402
+ * for every `BUILD_COST_TOKENS` call site. */
403
+ export declare const BUILD_COST_TOKENS_BY_PLATFORM: Record<Platform, number>;
404
+ /**
405
+ * What a build on this platform actually costs. Takes the DB's storage
406
+ * format directly (`react_native`, underscore — matches the SQL CHECK
407
+ * constraint on `App.platform`) rather than making every caller convert
408
+ * to this module's hyphenated `Platform` type first; falls back to the
409
+ * flat default for anything unrecognized rather than throwing, since a
410
+ * charge must never hard-fail over a pricing lookup.
411
+ */
412
+ export declare function getBuildCostTokens(dbPlatform: string): number;
413
+ export interface TokenPack {
414
+ id: string;
415
+ label: string;
416
+ tokens: number;
417
+ priceCents: number;
418
+ }
419
+ /**
420
+ * Fixed volume-discount packs, in ascending size. `BUILD_COST_TOKENS`
421
+ * tokens = 1 build regardless of which pack they came from, so the
422
+ * discount is purely "pay less per token by buying a bigger pack" —
423
+ * never a cheaper build.
424
+ */
425
+ export declare const TOKEN_PACKS: TokenPack[];
426
+ /**
427
+ * The smallest pack's rate, used as: (a) the baseline every other pack's discount
428
+ * is computed against, and (b) the postpaid-monthly invoicing rate — monthly
429
+ * billing has no volume discount (same as Codemagic's pay-as-you-go minutes,
430
+ * which are priced flat per machine-type regardless of usage volume), so it
431
+ * always bills at list price.
432
+ */
433
+ export declare const LIST_PRICE_PER_TOKEN_CENTS: number;
434
+ export declare function tokenPackDisplay(pack: TokenPack): {
435
+ priceEur: number;
436
+ pricePerTokenCents: number;
437
+ buildsIncluded: number;
438
+ discountPercent: number;
439
+ id: string;
440
+ label: string;
441
+ tokens: number;
442
+ priceCents: number;
443
+ };
444
+ export declare function findTokenPack(packId: string): TokenPack | undefined;
445
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Shared domain types used by the API, dashboard, CLI, and agent.
3
+ * These mirror (but do not import from) the Prisma schema in packages/db,
4
+ * so packages that never need a DB connection don't need Prisma as a dep.
5
+ */
6
+ /**
7
+ * Billing runs on tokens, not direct EUR-per-build, specifically so a
8
+ * bigger top-up can be cheaper per token without ever changing what a
9
+ * build costs. `BUILD_COST_TOKENS` is the default/baseline cost — same
10
+ * as every platform's actual cost today (see `BUILD_COST_TOKENS_BY_PLATFORM`
11
+ * below), so this PR ships the *mechanism* for per-platform pricing
12
+ * without changing anyone's bill; a maintainer who actually wants e.g. a
13
+ * bigger/faster iOS build machine to cost more tokens than a default
14
+ * Android one (the way Codemagic prices different machine types
15
+ * differently per minute) edits the map below, the same one-constant
16
+ * edit `TOKEN_PACKS` already is — no further code change needed.
17
+ */
18
+ export const BUILD_COST_TOKENS = 100;
19
+ /** Every platform costs `BUILD_COST_TOKENS` today — see the note above.
20
+ * Kept as an explicit per-platform map (not a single constant) so that
21
+ * changing one platform's price is a one-line edit here, not a search
22
+ * for every `BUILD_COST_TOKENS` call site. */
23
+ export const BUILD_COST_TOKENS_BY_PLATFORM = {
24
+ ios: BUILD_COST_TOKENS,
25
+ android: BUILD_COST_TOKENS,
26
+ flutter: BUILD_COST_TOKENS,
27
+ "react-native": BUILD_COST_TOKENS,
28
+ };
29
+ /**
30
+ * What a build on this platform actually costs. Takes the DB's storage
31
+ * format directly (`react_native`, underscore — matches the SQL CHECK
32
+ * constraint on `App.platform`) rather than making every caller convert
33
+ * to this module's hyphenated `Platform` type first; falls back to the
34
+ * flat default for anything unrecognized rather than throwing, since a
35
+ * charge must never hard-fail over a pricing lookup.
36
+ */
37
+ export function getBuildCostTokens(dbPlatform) {
38
+ const platform = dbPlatform.replace("_", "-");
39
+ return BUILD_COST_TOKENS_BY_PLATFORM[platform] ?? BUILD_COST_TOKENS;
40
+ }
41
+ function pricePerTokenCents(pack) {
42
+ return pack.priceCents / pack.tokens;
43
+ }
44
+ /** List price is the smallest pack's per-token rate — every larger pack is defined as a discount off it. */
45
+ function discountPercent(pack, listPricePerToken) {
46
+ return Math.round((1 - pricePerTokenCents(pack) / listPricePerToken) * 100);
47
+ }
48
+ /**
49
+ * Fixed volume-discount packs, in ascending size. `BUILD_COST_TOKENS`
50
+ * tokens = 1 build regardless of which pack they came from, so the
51
+ * discount is purely "pay less per token by buying a bigger pack" —
52
+ * never a cheaper build.
53
+ */
54
+ export const TOKEN_PACKS = [
55
+ { id: "starter", label: "Starter", tokens: 1_000, priceCents: 1_000 }, // €10.00 — 10 builds, list price
56
+ { id: "growth", label: "Growth", tokens: 6_000, priceCents: 5_400 }, // €54.00 — 60 builds, 10% off
57
+ { id: "scale", label: "Scale", tokens: 30_000, priceCents: 24_000 }, // €240.00 — 300 builds, 20% off
58
+ { id: "studio", label: "Studio", tokens: 120_000, priceCents: 84_000 }, // €840.00 — 1200 builds, 30% off
59
+ ];
60
+ /**
61
+ * The smallest pack's rate, used as: (a) the baseline every other pack's discount
62
+ * is computed against, and (b) the postpaid-monthly invoicing rate — monthly
63
+ * billing has no volume discount (same as Codemagic's pay-as-you-go minutes,
64
+ * which are priced flat per machine-type regardless of usage volume), so it
65
+ * always bills at list price.
66
+ */
67
+ export const LIST_PRICE_PER_TOKEN_CENTS = pricePerTokenCents(TOKEN_PACKS[0]);
68
+ export function tokenPackDisplay(pack) {
69
+ return {
70
+ ...pack,
71
+ priceEur: pack.priceCents / 100,
72
+ pricePerTokenCents: pricePerTokenCents(pack),
73
+ buildsIncluded: Math.floor(pack.tokens / BUILD_COST_TOKENS),
74
+ discountPercent: discountPercent(pack, LIST_PRICE_PER_TOKEN_CENTS),
75
+ };
76
+ }
77
+ export function findTokenPack(packId) {
78
+ return TOKEN_PACKS.find((p) => p.id === packId);
79
+ }
80
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA0aH;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAErC;;;+CAG+C;AAC/C,MAAM,CAAC,MAAM,6BAA6B,GAA6B;IACrE,GAAG,EAAE,iBAAiB;IACtB,OAAO,EAAE,iBAAiB;IAC1B,OAAO,EAAE,iBAAiB;IAC1B,cAAc,EAAE,iBAAiB;CAClC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,UAAkB;IACnD,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAa,CAAC;IAC1D,OAAO,6BAA6B,CAAC,QAAQ,CAAC,IAAI,iBAAiB,CAAC;AACtE,CAAC;AASD,SAAS,kBAAkB,CAAC,IAAe;IACzC,OAAO,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC;AACvC,CAAC;AAED,4GAA4G;AAC5G,SAAS,eAAe,CAAC,IAAe,EAAE,iBAAyB;IACjE,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,kBAAkB,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,GAAG,GAAG,CAAC,CAAC;AAC9E,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAAgB;IACtC,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,iCAAiC;IACxG,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,8BAA8B;IACnG,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,gCAAgC;IACrG,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,iCAAiC;CAC1G,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,kBAAkB,CAAC,WAAW,CAAC,CAAC,CAAE,CAAC,CAAC;AAE9E,MAAM,UAAU,gBAAgB,CAAC,IAAe;IAC9C,OAAO;QACL,GAAG,IAAI;QACP,QAAQ,EAAE,IAAI,CAAC,UAAU,GAAG,GAAG;QAC/B,kBAAkB,EAAE,kBAAkB,CAAC,IAAI,CAAC;QAC5C,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,iBAAiB,CAAC;QAC3D,eAAe,EAAE,eAAe,CAAC,IAAI,EAAE,0BAA0B,CAAC;KACnE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC;AAClD,CAAC"}
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@appforge-ci/core",
3
+ "version": "0.1.1",
4
+ "license": "MIT",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "type": "module",
12
+ "main": "./dist/index.js",
13
+ "types": "./dist/index.d.ts",
14
+ "exports": {
15
+ ".": {
16
+ "types": "./dist/index.d.ts",
17
+ "default": "./dist/index.js"
18
+ }
19
+ },
20
+ "dependencies": {
21
+ "zod": "^3.23.8"
22
+ },
23
+ "devDependencies": {
24
+ "@types/node": "^20.16.5",
25
+ "tsx": "^4.23.13",
26
+ "typescript": "^5.6.3"
27
+ },
28
+ "scripts": {
29
+ "build": "tsc -p tsconfig.json",
30
+ "dev": "tsc -p tsconfig.json --watch",
31
+ "typecheck": "tsc -p tsconfig.json --noEmit",
32
+ "lint": "echo 'no lint configured for core'",
33
+ "test": "tsx --import ../../scripts/test-home-sandbox.mjs --test $(find src -name '*.test.ts') --concurrency=4"
34
+ }
35
+ }