@absolutejs/billing 0.6.0 → 0.8.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/ledger.js CHANGED
@@ -73,13 +73,13 @@ var creditGate = (input) => {
73
73
  };
74
74
  var isGrantableCredits = (credits) => Number.isFinite(credits) && credits > 0;
75
75
  export {
76
- isPeriodLapsed,
77
- isGrantableCredits,
78
- creditsFor,
79
- creditGate,
76
+ createUsageLedger,
80
77
  creditBalanceFrom,
81
- createUsageLedger
78
+ creditGate,
79
+ creditsFor,
80
+ isGrantableCredits,
81
+ isPeriodLapsed
82
82
  };
83
83
 
84
- //# debugId=C0A752957B46E2F564756E2164756E21
84
+ //# debugId=CB2DC54F3ACBA03564756E2164756E21
85
85
  //# sourceMappingURL=ledger.js.map
@@ -5,6 +5,6 @@
5
5
  "// The layer between a meter and an invoice: every metered event gets priced,\n// converted to the customer's credit unit, written to an append-only ledger,\n// debited against a balance, and folded into a daily rollup that a spend cap\n// can read. Every app billing a metered API rebuilds this, and each one\n// rediscovers the same three traps:\n//\n// - Money in floats. Summing float ledger rows drifts; one real deployment\n// lost 2 cents across 25,740 rows before anyone noticed. Amounts here are\n// integer sub-units (see Plan.denomination) and are only ever added.\n// - The debit and the ledger row diverging. If the row is written but the\n// balance is not debited, a customer gets free usage; the reverse\n// over-charges. They must land together, so the store commits them as one\n// unit — this module never splits them.\n// - The rollup being treated as truth. It is a derived index, rebuildable\n// from the ledger, so a rollup failure must never fail the charge.\n//\n// Storage stays the host's business (Postgres, ClickHouse, anything). This\n// owns the policy and the arithmetic, which is the part that is identical\n// everywhere — and the part that is worth getting wrong only once.\n\n/** One priced, metered event, ready to persist. */\nexport type LedgerEntry = {\n /** Charge in integer sub-units of the plan's denomination (see\n * `Plan.denomination`) — never a float. */\n amount: number;\n /** What the customer is billed in the product's own unit. */\n credits: number;\n /** Product-level grouping (\"chat\", \"voice\"), not the vendor's. */\n feature?: string | null;\n model?: string;\n /** \"llm\" | \"tts\" | \"embedding\" | whatever the product meters. */\n operation: string;\n provider: string;\n /** Idempotency handle for at-least-once callers. */\n requestId?: string;\n /** Null for system/background work with nobody to bill. */\n tenant?: string | null;\n};\n\nexport type LedgerCommit = {\n /** Append the row AND debit `entry.credits` from the tenant's balance in a\n * single atomic unit. Called with tenant null for unattributed work, where\n * there is nothing to debit. */\n commit: (entry: LedgerEntry) => Promise<void>;\n /** Fold the entry into a derived daily aggregate. Best-effort by contract:\n * this module swallows its failures. */\n rollup?: (entry: LedgerEntry) => Promise<void>;\n /** Total sub-units charged since `since`, for the spend cap. */\n spentSince?: (since: Date) => Promise<number>;\n};\n\nexport type UsageLedgerOptions = {\n /** Sub-units per credit. A peg of 1_000 with micros means 1 credit =\n * $0.001. Required for credit conversion; omit to bill in raw amounts. */\n creditPegSubUnits?: number;\n /** Reported when a rollup fails. The charge already succeeded. */\n onRollupError?: (error: unknown, entry: LedgerEntry) => void;\n store: LedgerCommit;\n};\n\n/**\n * Credits for a charge. Ceiling, not rounding: a product that sells credits\n * must never hand out a fraction it cannot deduct, and rounding down means\n * the smallest calls are free — which is how a \"cheap\" endpoint becomes an\n * unmetered one.\n */\nexport const creditsFor = (amount: number, pegSubUnits: number) => {\n if (pegSubUnits <= 0) return 0;\n\n return Math.ceil(amount / pegSubUnits);\n};\n\nexport type UsageLedger = {\n /** Price-agnostic: hand it an amount already in sub-units. Returns what was\n * written, including the credits it derived. */\n record: (\n entry: Omit<LedgerEntry, \"credits\"> & { credits?: number },\n ) => Promise<LedgerEntry>;\n /** True once spend since `since` reaches `capSubUnits`. Fails OPEN — a\n * broken cap must not take down paid features, and the per-provider\n * budgets are still in front. */\n overCap: (capSubUnits: number, since: Date) => Promise<boolean>;\n};\n\nexport const createUsageLedger = (options: UsageLedgerOptions): UsageLedger => {\n const { creditPegSubUnits, onRollupError, store } = options;\n\n return {\n overCap: async (capSubUnits, since) => {\n if (!store.spentSince) return false;\n try {\n return (await store.spentSince(since)) >= capSubUnits;\n } catch {\n return false;\n }\n },\n record: async (input) => {\n const credits =\n input.credits ??\n (creditPegSubUnits === undefined\n ? 0\n : creditsFor(input.amount, creditPegSubUnits));\n const entry: LedgerEntry = { ...input, credits };\n // The charge is the thing that must not be lost; it is awaited and its\n // failure propagates to the caller.\n await store.commit(entry);\n // The rollup is a derived index — rebuildable from the ledger — so its\n // failure is reported, never raised.\n if (store.rollup) {\n await store.rollup(entry).catch((error: unknown) => {\n onRollupError?.(error, entry);\n });\n }\n\n return entry;\n },\n };\n};\n\n// -----------------------------------------------------------------------------\n// Credit balances\n// -----------------------------------------------------------------------------\n\n// A credit-based product needs the same four decisions no matter what it\n// sells: what the customer may spend, whether the period has rolled, whether\n// this call is allowed, and whether a grant is real. The lookups behind them\n// (subscriptions, comps, plan tables) are the host's; the arithmetic is not,\n// and it is the part where an off-by-one hands out free usage.\n\nexport type CreditBalanceInput = {\n /** Granted credits that SURVIVE a period reset (referrals, goodwill). */\n bonusCredits: number;\n consumed: number;\n /** Credits the plan grants for the current period. */\n periodAllowance: number;\n periodEnd?: Date | null;\n};\n\nexport type CreditBalance = {\n /** periodAllowance + bonusCredits — the spendable ceiling this period. */\n allowance: number;\n bonusCredits: number;\n consumed: number;\n periodAllowance: number;\n periodEnd: Date | null;\n /** Never negative: an over-spend reads as zero left, not a debt. */\n remaining: number;\n};\n\n/** Derive the spendable view of a stored balance row. */\nexport const creditBalanceFrom = (row: CreditBalanceInput): CreditBalance => {\n const allowance = row.periodAllowance + row.bonusCredits;\n\n return {\n allowance,\n bonusCredits: row.bonusCredits,\n consumed: row.consumed,\n periodAllowance: row.periodAllowance,\n periodEnd: row.periodEnd ?? null,\n remaining: Math.max(0, allowance - row.consumed),\n };\n};\n\n/** Whether the billing window has closed and the allowance should re-snapshot.\n * A null end date means \"no window\" — an unbounded balance never lapses. */\nexport const isPeriodLapsed = (\n periodEnd: Date | null | undefined,\n now = new Date(),\n) =>\n periodEnd !== null &&\n periodEnd !== undefined &&\n periodEnd.getTime() <= now.getTime();\n\n/**\n * How hard the gate bites. `off` skips the balance read entirely, `warn`\n * always allows but reports `low` so the UI can say so, `block` refuses once\n * the remaining balance cannot cover the estimate.\n */\nexport type CreditEnforcementMode = \"block\" | \"off\" | \"warn\";\n\nexport type CreditGate = {\n allowance: number;\n allowed: boolean;\n /** True when the balance cannot cover the estimate, in ANY mode — the\n * signal a product surfaces before it starts refusing work. */\n low: boolean;\n mode: CreditEnforcementMode;\n remaining: number;\n};\n\nexport type CreditGateInput = {\n allowance: number;\n estimatedCredits?: number;\n mode: CreditEnforcementMode;\n remaining: number;\n};\n\n/** Decide whether a metered call proceeds. Pure — the caller does the reads. */\nexport const creditGate = (input: CreditGateInput): CreditGate => {\n const { allowance, estimatedCredits = 1, mode, remaining } = input;\n if (mode === \"off\") {\n return { allowance: 0, allowed: true, low: false, mode, remaining: 0 };\n }\n const sufficient = remaining >= estimatedCredits;\n\n return {\n allowance,\n allowed: mode === \"block\" ? sufficient : true,\n low: !sufficient,\n mode,\n remaining,\n };\n};\n\n/** Whether a bonus grant is worth writing — guards against NaN and negatives\n * quietly corrupting a balance. */\nexport const isGrantableCredits = (credits: number) =>\n Number.isFinite(credits) && credits > 0;\n"
6
6
  ],
7
7
  "mappings": ";;;;;;;;;;;;;;;;;AAkEO,IAAM,aAAa,CAAC,QAAgB,gBAAwB;AAAA,EACjE,IAAI,eAAe;AAAA,IAAG,OAAO;AAAA,EAE7B,OAAO,KAAK,KAAK,SAAS,WAAW;AAAA;AAehC,IAAM,oBAAoB,CAAC,YAA6C;AAAA,EAC7E,QAAQ,mBAAmB,eAAe,UAAU;AAAA,EAEpD,OAAO;AAAA,IACL,SAAS,OAAO,aAAa,UAAU;AAAA,MACrC,IAAI,CAAC,MAAM;AAAA,QAAY,OAAO;AAAA,MAC9B,IAAI;AAAA,QACF,OAAQ,MAAM,MAAM,WAAW,KAAK,KAAM;AAAA,QAC1C,MAAM;AAAA,QACN,OAAO;AAAA;AAAA;AAAA,IAGX,QAAQ,OAAO,UAAU;AAAA,MACvB,MAAM,UACJ,MAAM,YACL,sBAAsB,YACnB,IACA,WAAW,MAAM,QAAQ,iBAAiB;AAAA,MAChD,MAAM,QAAqB,KAAK,OAAO,QAAQ;AAAA,MAG/C,MAAM,MAAM,OAAO,KAAK;AAAA,MAGxB,IAAI,MAAM,QAAQ;AAAA,QAChB,MAAM,MAAM,OAAO,KAAK,EAAE,MAAM,CAAC,UAAmB;AAAA,UAClD,gBAAgB,OAAO,KAAK;AAAA,SAC7B;AAAA,MACH;AAAA,MAEA,OAAO;AAAA;AAAA,EAEX;AAAA;AAkCK,IAAM,oBAAoB,CAAC,QAA2C;AAAA,EAC3E,MAAM,YAAY,IAAI,kBAAkB,IAAI;AAAA,EAE5C,OAAO;AAAA,IACL;AAAA,IACA,cAAc,IAAI;AAAA,IAClB,UAAU,IAAI;AAAA,IACd,iBAAiB,IAAI;AAAA,IACrB,WAAW,IAAI,aAAa;AAAA,IAC5B,WAAW,KAAK,IAAI,GAAG,YAAY,IAAI,QAAQ;AAAA,EACjD;AAAA;AAKK,IAAM,iBAAiB,CAC5B,WACA,MAAM,IAAI,SAEV,cAAc,QACd,cAAc,aACd,UAAU,QAAQ,KAAK,IAAI,QAAQ;AA2B9B,IAAM,aAAa,CAAC,UAAuC;AAAA,EAChE,QAAQ,WAAW,mBAAmB,GAAG,MAAM,cAAc;AAAA,EAC7D,IAAI,SAAS,OAAO;AAAA,IAClB,OAAO,EAAE,WAAW,GAAG,SAAS,MAAM,KAAK,OAAO,MAAM,WAAW,EAAE;AAAA,EACvE;AAAA,EACA,MAAM,aAAa,aAAa;AAAA,EAEhC,OAAO;AAAA,IACL;AAAA,IACA,SAAS,SAAS,UAAU,aAAa;AAAA,IACzC,KAAK,CAAC;AAAA,IACN;AAAA,IACA;AAAA,EACF;AAAA;AAKK,IAAM,qBAAqB,CAAC,YACjC,OAAO,SAAS,OAAO,KAAK,UAAU;",
8
- "debugId": "C0A752957B46E2F564756E2164756E21",
8
+ "debugId": "CB2DC54F3ACBA03564756E2164756E21",
9
9
  "names": []
10
10
  }
package/dist/manifest.js CHANGED
@@ -588,22 +588,22 @@ var TypeSystemPolicy;
588
588
  // node_modules/@sinclair/typebox/build/esm/type/guard/value.mjs
589
589
  var exports_value = {};
590
590
  __export(exports_value, {
591
- IsUndefined: () => IsUndefined2,
592
- IsUint8Array: () => IsUint8Array,
593
- IsSymbol: () => IsSymbol,
594
- IsString: () => IsString,
595
- IsRegExp: () => IsRegExp,
596
- IsObject: () => IsObject2,
597
- IsNumber: () => IsNumber2,
598
- IsNull: () => IsNull,
599
- IsIterator: () => IsIterator,
600
- IsFunction: () => IsFunction,
601
- IsDate: () => IsDate,
602
- IsBoolean: () => IsBoolean,
603
- IsBigInt: () => IsBigInt,
604
- IsAsyncIterator: () => IsAsyncIterator,
591
+ HasPropertyKey: () => HasPropertyKey,
605
592
  IsArray: () => IsArray2,
606
- HasPropertyKey: () => HasPropertyKey
593
+ IsAsyncIterator: () => IsAsyncIterator,
594
+ IsBigInt: () => IsBigInt,
595
+ IsBoolean: () => IsBoolean,
596
+ IsDate: () => IsDate,
597
+ IsFunction: () => IsFunction,
598
+ IsIterator: () => IsIterator,
599
+ IsNull: () => IsNull,
600
+ IsNumber: () => IsNumber2,
601
+ IsObject: () => IsObject2,
602
+ IsRegExp: () => IsRegExp,
603
+ IsString: () => IsString,
604
+ IsSymbol: () => IsSymbol,
605
+ IsUint8Array: () => IsUint8Array,
606
+ IsUndefined: () => IsUndefined2
607
607
  });
608
608
  function HasPropertyKey(value, key) {
609
609
  return key in value;
@@ -1208,7 +1208,7 @@ function Literal(value, options) {
1208
1208
  }
1209
1209
 
1210
1210
  // node_modules/@sinclair/typebox/build/esm/type/boolean/boolean.mjs
1211
- function Boolean(options) {
1211
+ function Boolean2(options) {
1212
1212
  return CreateType({ [Kind]: "Boolean", type: "boolean" }, options);
1213
1213
  }
1214
1214
 
@@ -1230,7 +1230,7 @@ function String2(options) {
1230
1230
  // node_modules/@sinclair/typebox/build/esm/type/template-literal/syntax.mjs
1231
1231
  function* FromUnion(syntax) {
1232
1232
  const trim = syntax.trim().replace(/"|'/g, "");
1233
- return trim === "boolean" ? yield Boolean() : trim === "number" ? yield Number2() : trim === "bigint" ? yield BigInt() : trim === "string" ? yield String2() : yield (() => {
1233
+ return trim === "boolean" ? yield Boolean2() : trim === "number" ? yield Number2() : trim === "bigint" ? yield BigInt() : trim === "string" ? yield String2() : yield (() => {
1234
1234
  const literals = trim.split("|").map((literal) => Literal(literal.trim()));
1235
1235
  return literals.length === 0 ? Never() : literals.length === 1 ? literals[0] : UnionEvaluated(literals);
1236
1236
  })();
@@ -1622,57 +1622,57 @@ function Unknown(options) {
1622
1622
  // node_modules/@sinclair/typebox/build/esm/type/guard/type.mjs
1623
1623
  var exports_type = {};
1624
1624
  __export(exports_type, {
1625
- TypeGuardUnknownTypeError: () => TypeGuardUnknownTypeError,
1626
- IsVoid: () => IsVoid2,
1627
- IsUnsafe: () => IsUnsafe2,
1628
- IsUnknown: () => IsUnknown2,
1629
- IsUnionLiteral: () => IsUnionLiteral,
1630
- IsUnion: () => IsUnion2,
1631
- IsUndefined: () => IsUndefined4,
1632
- IsUint8Array: () => IsUint8Array3,
1633
- IsTuple: () => IsTuple2,
1634
- IsTransform: () => IsTransform2,
1635
- IsThis: () => IsThis2,
1636
- IsTemplateLiteral: () => IsTemplateLiteral2,
1637
- IsSymbol: () => IsSymbol3,
1638
- IsString: () => IsString3,
1639
- IsSchema: () => IsSchema2,
1640
- IsRegExp: () => IsRegExp3,
1641
- IsRef: () => IsRef2,
1642
- IsRecursive: () => IsRecursive,
1643
- IsRecord: () => IsRecord2,
1644
- IsReadonly: () => IsReadonly2,
1645
- IsProperties: () => IsProperties,
1646
- IsPromise: () => IsPromise2,
1647
- IsOptional: () => IsOptional2,
1648
- IsObject: () => IsObject4,
1649
- IsNumber: () => IsNumber4,
1650
- IsNull: () => IsNull3,
1651
- IsNot: () => IsNot2,
1652
- IsNever: () => IsNever2,
1653
- IsMappedResult: () => IsMappedResult2,
1654
- IsMappedKey: () => IsMappedKey2,
1655
- IsLiteralValue: () => IsLiteralValue2,
1656
- IsLiteralString: () => IsLiteralString,
1657
- IsLiteralNumber: () => IsLiteralNumber,
1658
- IsLiteralBoolean: () => IsLiteralBoolean,
1659
- IsLiteral: () => IsLiteral2,
1660
- IsKindOf: () => IsKindOf2,
1661
- IsKind: () => IsKind2,
1662
- IsIterator: () => IsIterator3,
1663
- IsIntersect: () => IsIntersect2,
1664
- IsInteger: () => IsInteger2,
1665
- IsImport: () => IsImport,
1666
- IsFunction: () => IsFunction3,
1667
- IsDate: () => IsDate3,
1668
- IsConstructor: () => IsConstructor2,
1669
- IsComputed: () => IsComputed2,
1670
- IsBoolean: () => IsBoolean3,
1671
- IsBigInt: () => IsBigInt3,
1672
- IsAsyncIterator: () => IsAsyncIterator3,
1673
- IsArray: () => IsArray4,
1625
+ IsAny: () => IsAny2,
1674
1626
  IsArgument: () => IsArgument2,
1675
- IsAny: () => IsAny2
1627
+ IsArray: () => IsArray4,
1628
+ IsAsyncIterator: () => IsAsyncIterator3,
1629
+ IsBigInt: () => IsBigInt3,
1630
+ IsBoolean: () => IsBoolean3,
1631
+ IsComputed: () => IsComputed2,
1632
+ IsConstructor: () => IsConstructor2,
1633
+ IsDate: () => IsDate3,
1634
+ IsFunction: () => IsFunction3,
1635
+ IsImport: () => IsImport,
1636
+ IsInteger: () => IsInteger2,
1637
+ IsIntersect: () => IsIntersect2,
1638
+ IsIterator: () => IsIterator3,
1639
+ IsKind: () => IsKind2,
1640
+ IsKindOf: () => IsKindOf2,
1641
+ IsLiteral: () => IsLiteral2,
1642
+ IsLiteralBoolean: () => IsLiteralBoolean,
1643
+ IsLiteralNumber: () => IsLiteralNumber,
1644
+ IsLiteralString: () => IsLiteralString,
1645
+ IsLiteralValue: () => IsLiteralValue2,
1646
+ IsMappedKey: () => IsMappedKey2,
1647
+ IsMappedResult: () => IsMappedResult2,
1648
+ IsNever: () => IsNever2,
1649
+ IsNot: () => IsNot2,
1650
+ IsNull: () => IsNull3,
1651
+ IsNumber: () => IsNumber4,
1652
+ IsObject: () => IsObject4,
1653
+ IsOptional: () => IsOptional2,
1654
+ IsPromise: () => IsPromise2,
1655
+ IsProperties: () => IsProperties,
1656
+ IsReadonly: () => IsReadonly2,
1657
+ IsRecord: () => IsRecord2,
1658
+ IsRecursive: () => IsRecursive,
1659
+ IsRef: () => IsRef2,
1660
+ IsRegExp: () => IsRegExp3,
1661
+ IsSchema: () => IsSchema2,
1662
+ IsString: () => IsString3,
1663
+ IsSymbol: () => IsSymbol3,
1664
+ IsTemplateLiteral: () => IsTemplateLiteral2,
1665
+ IsThis: () => IsThis2,
1666
+ IsTransform: () => IsTransform2,
1667
+ IsTuple: () => IsTuple2,
1668
+ IsUint8Array: () => IsUint8Array3,
1669
+ IsUndefined: () => IsUndefined4,
1670
+ IsUnion: () => IsUnion2,
1671
+ IsUnionLiteral: () => IsUnionLiteral,
1672
+ IsUnknown: () => IsUnknown2,
1673
+ IsUnsafe: () => IsUnsafe2,
1674
+ IsVoid: () => IsVoid2,
1675
+ TypeGuardUnknownTypeError: () => TypeGuardUnknownTypeError
1676
1676
  });
1677
1677
  class TypeGuardUnknownTypeError extends TypeBoxError {
1678
1678
  }
@@ -3023,68 +3023,68 @@ function Void(options) {
3023
3023
  // node_modules/@sinclair/typebox/build/esm/type/type/type.mjs
3024
3024
  var exports_type2 = {};
3025
3025
  __export(exports_type2, {
3026
- Void: () => Void,
3027
- Uppercase: () => Uppercase,
3028
- Unsafe: () => Unsafe,
3029
- Unknown: () => Unknown,
3030
- Union: () => Union,
3031
- Undefined: () => Undefined,
3032
- Uncapitalize: () => Uncapitalize,
3033
- Uint8Array: () => Uint8Array2,
3034
- Tuple: () => Tuple,
3035
- Transform: () => Transform,
3036
- TemplateLiteral: () => TemplateLiteral,
3037
- Symbol: () => Symbol2,
3038
- String: () => String2,
3039
- ReturnType: () => ReturnType,
3040
- Rest: () => Rest,
3041
- Required: () => Required,
3042
- RegExp: () => RegExp2,
3043
- Ref: () => Ref,
3044
- Recursive: () => Recursive,
3045
- Record: () => Record,
3046
- ReadonlyOptional: () => ReadonlyOptional,
3047
- Readonly: () => Readonly,
3048
- Promise: () => Promise2,
3049
- Pick: () => Pick,
3050
- Partial: () => Partial,
3051
- Parameters: () => Parameters,
3052
- Optional: () => Optional,
3053
- Omit: () => Omit,
3054
- Object: () => Object2,
3055
- Number: () => Number2,
3056
- Null: () => Null,
3057
- Not: () => Not,
3058
- Never: () => Never,
3059
- Module: () => Module,
3060
- Mapped: () => Mapped,
3061
- Lowercase: () => Lowercase,
3062
- Literal: () => Literal,
3063
- KeyOf: () => KeyOf,
3064
- Iterator: () => Iterator,
3065
- Intersect: () => Intersect,
3066
- Integer: () => Integer,
3067
- Instantiate: () => Instantiate,
3068
- InstanceType: () => InstanceType,
3069
- Index: () => Index,
3070
- Function: () => Function,
3071
- Extract: () => Extract,
3072
- Extends: () => Extends,
3073
- Exclude: () => Exclude,
3074
- Enum: () => Enum,
3075
- Date: () => Date2,
3076
- ConstructorParameters: () => ConstructorParameters,
3077
- Constructor: () => Constructor,
3078
- Const: () => Const,
3079
- Composite: () => Composite,
3080
- Capitalize: () => Capitalize,
3081
- Boolean: () => Boolean,
3082
- BigInt: () => BigInt,
3083
- Awaited: () => Awaited,
3084
- AsyncIterator: () => AsyncIterator,
3085
- Array: () => Array2,
3026
+ Any: () => Any,
3086
3027
  Argument: () => Argument,
3087
- Any: () => Any
3028
+ Array: () => Array2,
3029
+ AsyncIterator: () => AsyncIterator,
3030
+ Awaited: () => Awaited,
3031
+ BigInt: () => BigInt,
3032
+ Boolean: () => Boolean2,
3033
+ Capitalize: () => Capitalize,
3034
+ Composite: () => Composite,
3035
+ Const: () => Const,
3036
+ Constructor: () => Constructor,
3037
+ ConstructorParameters: () => ConstructorParameters,
3038
+ Date: () => Date2,
3039
+ Enum: () => Enum,
3040
+ Exclude: () => Exclude,
3041
+ Extends: () => Extends,
3042
+ Extract: () => Extract,
3043
+ Function: () => Function,
3044
+ Index: () => Index,
3045
+ InstanceType: () => InstanceType,
3046
+ Instantiate: () => Instantiate,
3047
+ Integer: () => Integer,
3048
+ Intersect: () => Intersect,
3049
+ Iterator: () => Iterator,
3050
+ KeyOf: () => KeyOf,
3051
+ Literal: () => Literal,
3052
+ Lowercase: () => Lowercase,
3053
+ Mapped: () => Mapped,
3054
+ Module: () => Module,
3055
+ Never: () => Never,
3056
+ Not: () => Not,
3057
+ Null: () => Null,
3058
+ Number: () => Number2,
3059
+ Object: () => Object2,
3060
+ Omit: () => Omit,
3061
+ Optional: () => Optional,
3062
+ Parameters: () => Parameters,
3063
+ Partial: () => Partial,
3064
+ Pick: () => Pick,
3065
+ Promise: () => Promise2,
3066
+ Readonly: () => Readonly,
3067
+ ReadonlyOptional: () => ReadonlyOptional,
3068
+ Record: () => Record,
3069
+ Recursive: () => Recursive,
3070
+ Ref: () => Ref,
3071
+ RegExp: () => RegExp2,
3072
+ Required: () => Required,
3073
+ Rest: () => Rest,
3074
+ ReturnType: () => ReturnType,
3075
+ String: () => String2,
3076
+ Symbol: () => Symbol2,
3077
+ TemplateLiteral: () => TemplateLiteral,
3078
+ Transform: () => Transform,
3079
+ Tuple: () => Tuple,
3080
+ Uint8Array: () => Uint8Array2,
3081
+ Uncapitalize: () => Uncapitalize,
3082
+ Undefined: () => Undefined,
3083
+ Union: () => Union,
3084
+ Unknown: () => Unknown,
3085
+ Unsafe: () => Unsafe,
3086
+ Uppercase: () => Uppercase,
3087
+ Void: () => Void
3088
3088
  });
3089
3089
 
3090
3090
  // node_modules/@sinclair/typebox/build/esm/type/type/index.mjs
@@ -3252,6 +3252,79 @@ var serializedTool = Type.Object({
3252
3252
  input: jsonSchemaObject,
3253
3253
  kind: Type.Union([Type.Literal("runtime"), Type.Literal("workspace")])
3254
3254
  });
3255
+ var productId = Type.String({ pattern: "^[a-z][a-z0-9_-]{0,63}$" });
3256
+ var productCopy = {
3257
+ description: Type.String({ minLength: 1 }),
3258
+ id: productId,
3259
+ title: Type.String({ minLength: 1 })
3260
+ };
3261
+ var productOperation = Type.Union([
3262
+ Type.Literal("aggregate"),
3263
+ Type.Literal("create"),
3264
+ Type.Literal("delete"),
3265
+ Type.Literal("detail"),
3266
+ Type.Literal("list"),
3267
+ Type.Literal("update")
3268
+ ]);
3269
+ var productProjection = Type.Object({
3270
+ blocks: Type.Optional(Type.Array(Type.Object({
3271
+ ...productCopy,
3272
+ category: Type.String({ minLength: 1 }),
3273
+ componentExport: Type.String({ minLength: 1 }),
3274
+ frameworks: Type.Optional(Type.Array(Type.Union(clientFrameworks.map((framework) => Type.Literal(framework))))),
3275
+ props: jsonSchemaObject
3276
+ }))),
3277
+ connections: Type.Optional(Type.Array(Type.Object({
3278
+ ...productCopy,
3279
+ envKeys: Type.Optional(Type.Array(Type.String({ minLength: 1 }))),
3280
+ kind: Type.Union([
3281
+ Type.Literal("none"),
3282
+ Type.Literal("oauth"),
3283
+ Type.Literal("secret")
3284
+ ]),
3285
+ setupTool: Type.Optional(Type.String({ pattern: TOOL_NAME_PATTERN.source })),
3286
+ testTool: Type.Optional(Type.String({ pattern: TOOL_NAME_PATTERN.source }))
3287
+ }))),
3288
+ dataSources: Type.Optional(Type.Array(Type.Object({
3289
+ ...productCopy,
3290
+ operations: Type.Array(productOperation, { minItems: 1 }),
3291
+ schema: jsonSchemaObject,
3292
+ tools: Type.Optional(Type.Partial(Type.Object({
3293
+ aggregate: Type.String({ pattern: TOOL_NAME_PATTERN.source }),
3294
+ create: Type.String({ pattern: TOOL_NAME_PATTERN.source }),
3295
+ delete: Type.String({ pattern: TOOL_NAME_PATTERN.source }),
3296
+ detail: Type.String({ pattern: TOOL_NAME_PATTERN.source }),
3297
+ list: Type.String({ pattern: TOOL_NAME_PATTERN.source }),
3298
+ update: Type.String({ pattern: TOOL_NAME_PATTERN.source })
3299
+ })))
3300
+ }))),
3301
+ events: Type.Optional(Type.Array(Type.Object({
3302
+ ...productCopy,
3303
+ schema: jsonSchemaObject,
3304
+ source: Type.Union([
3305
+ Type.Literal("data"),
3306
+ Type.Literal("package"),
3307
+ Type.Literal("ui"),
3308
+ Type.Literal("webhook")
3309
+ ])
3310
+ }))),
3311
+ healthChecks: Type.Optional(Type.Array(Type.Object({
3312
+ ...productCopy,
3313
+ tool: Type.String({ pattern: TOOL_NAME_PATTERN.source })
3314
+ }))),
3315
+ releaseChecks: Type.Optional(Type.Array(Type.Object({
3316
+ ...productCopy,
3317
+ healthCheckIds: Type.Optional(Type.Array(productId)),
3318
+ severity: Type.Union([
3319
+ Type.Literal("blocking"),
3320
+ Type.Literal("warning")
3321
+ ])
3322
+ }))),
3323
+ workflowActions: Type.Optional(Type.Array(Type.Object({
3324
+ ...productCopy,
3325
+ tool: Type.String({ pattern: TOOL_NAME_PATTERN.source })
3326
+ })))
3327
+ });
3255
3328
  var manifestSchema = Type.Object({
3256
3329
  contract: Type.Union([Type.Literal(1), Type.Literal(2)]),
3257
3330
  discovery: Type.Optional(Type.Object({
@@ -3277,6 +3350,14 @@ var manifestSchema = Type.Object({
3277
3350
  tagline: Type.String({ minLength: 1 })
3278
3351
  }),
3279
3352
  implements: Type.Optional(Type.Array(adapterImplementation)),
3353
+ integration: Type.Optional(Type.Object({
3354
+ description: Type.Optional(Type.String({ minLength: 1 })),
3355
+ mode: Type.Union([
3356
+ Type.Literal("adapter"),
3357
+ Type.Literal("code-first"),
3358
+ Type.Literal("recipe")
3359
+ ])
3360
+ })),
3280
3361
  lifecycle: Type.Optional(Type.Array(lifecycleStep)),
3281
3362
  presets: Type.Optional(Type.Array(Type.Object({
3282
3363
  description: Type.Optional(Type.String()),
@@ -3284,6 +3365,7 @@ var manifestSchema = Type.Object({
3284
3365
  title: Type.String(),
3285
3366
  values: Type.Record(Type.String(), Type.Unknown())
3286
3367
  }))),
3368
+ product: Type.Optional(productProjection),
3287
3369
  requires: Type.Optional(manifestRequirements),
3288
3370
  settings: jsonSchemaObject,
3289
3371
  slots: Type.Optional(Type.Record(Type.String(), adapterSlot)),
@@ -3455,5 +3537,5 @@ export {
3455
3537
  manifest
3456
3538
  };
3457
3539
 
3458
- //# debugId=FB56701BA9401D2A64756E2164756E21
3540
+ //# debugId=2A4F7A6A88D9528264756E2164756E21
3459
3541
  //# sourceMappingURL=manifest.js.map