wip
This commit is contained in:
@@ -26,6 +26,7 @@ Write integration tests for the Autumn billing system using the `initScenario` p
|
||||
- Use `Decimal.js` for balance calculations in track tests
|
||||
- Unique `customerId` per test
|
||||
- Use generic types with `AutumnInt`: `autumnV1.customers.get<ApiCustomerV3>()`, `autumnV1.check<CheckResponseV1>()`
|
||||
- **USE UTILITY FUNCTIONS WHENEVER POSSIBLE** - the shorter the code, the better. Check `server/tests/integration/billing/utils/` for existing utilities like `expectCustomerProducts`, `expectProductScheduled`, `expectCustomerInvoiceCorrect`, etc.
|
||||
|
||||
**DON'T:**
|
||||
- Use `describe/beforeAll/test` (legacy pattern)
|
||||
@@ -33,6 +34,7 @@ Write integration tests for the Autumn billing system using the `initScenario` p
|
||||
- Share state between tests
|
||||
- Use raw arithmetic for balance calculations (floating point errors)
|
||||
- Use `as unknown as Type` casting - use generic types instead
|
||||
- Write manual assertion loops when a utility function exists
|
||||
|
||||
## AutumnInt Response Types
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#!/usr/bin/env node
|
||||
import { randomBytes } from "crypto";
|
||||
import { writeFileSync, copyFileSync, readFileSync } from "fs";
|
||||
import inquirer from "inquirer";
|
||||
import { spawnSync } from "child_process";
|
||||
import chalk from "chalk";
|
||||
import { spawnSync } from "child_process";
|
||||
import { randomBytes } from "crypto";
|
||||
import { copyFileSync, readFileSync, writeFileSync } from "fs";
|
||||
import inquirer from "inquirer";
|
||||
|
||||
const genUrlSafeBase64 = (bytes) => {
|
||||
return randomBytes(bytes)
|
||||
@@ -253,7 +253,7 @@ async function main() {
|
||||
};
|
||||
|
||||
let databaseUrl = "";
|
||||
let stripeWebhookVars = [];
|
||||
const stripeWebhookVars = [];
|
||||
|
||||
databaseUrl = await handleDatabaseSetup();
|
||||
// stripeWebhookVars = await handleLocalRunSetup();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env node
|
||||
import { randomBytes } from "crypto";
|
||||
import { writeFileSync, copyFileSync } from "fs";
|
||||
import chalk from "chalk";
|
||||
import { randomBytes } from "crypto";
|
||||
import { copyFileSync, writeFileSync } from "fs";
|
||||
|
||||
const genUrlSafeBase64 = (bytes) => {
|
||||
return randomBytes(bytes)
|
||||
@@ -26,8 +26,8 @@ async function main() {
|
||||
STRIPE_WEBHOOK_URL: process.env.STRIPE_WEBHOOK_URL,
|
||||
};
|
||||
|
||||
let databaseUrl = process.env.DATABASE_URL;
|
||||
let stripeWebhookVars = [];
|
||||
const databaseUrl = process.env.DATABASE_URL;
|
||||
const stripeWebhookVars = [];
|
||||
// stripeWebhookVars = await handleLocalRunSetup();
|
||||
|
||||
// Step 11: Write to server/.env
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import inquirer from "inquirer";
|
||||
import chalk from "chalk";
|
||||
import inquirer from "inquirer";
|
||||
|
||||
/**
|
||||
* Prompts user for Stripe test API key
|
||||
@@ -111,7 +111,9 @@ export async function setupTunnelUrl(): Promise<string> {
|
||||
),
|
||||
);
|
||||
console.log(
|
||||
chalk.cyan("You can use tools like ngrok, localtunnel, or Cloudflare Tunnel."),
|
||||
chalk.cyan(
|
||||
"You can use tools like ngrok, localtunnel, or Cloudflare Tunnel.",
|
||||
),
|
||||
);
|
||||
console.log(chalk.cyan("Example: https://your-subdomain.ngrok.io\n"));
|
||||
|
||||
|
||||
@@ -9,9 +9,15 @@ import postgres from "postgres";
|
||||
export const client = postgres(process.env.DATABASE_URL!);
|
||||
export const db = drizzle(client, { schema });
|
||||
|
||||
export const initDrizzle = (params?: { maxConnections?: number, replica?: boolean }) => {
|
||||
export const initDrizzle = (params?: {
|
||||
maxConnections?: number;
|
||||
replica?: boolean;
|
||||
}) => {
|
||||
const maxConnections = params?.maxConnections || 10;
|
||||
const dbUrl = (params?.replica ? process.env.DATABASE_REPLICA_URL : process.env.DATABASE_URL) ?? "";
|
||||
const dbUrl =
|
||||
(params?.replica
|
||||
? process.env.DATABASE_REPLICA_URL
|
||||
: process.env.DATABASE_URL) ?? "";
|
||||
const client = postgres(dbUrl, {
|
||||
max: maxConnections,
|
||||
});
|
||||
|
||||
1
server/src/external/redis/initUpstash.ts
vendored
1
server/src/external/redis/initUpstash.ts
vendored
@@ -1,6 +1,5 @@
|
||||
import { Redis } from "@upstash/redis";
|
||||
|
||||
|
||||
const upstash = new Redis({
|
||||
url: process.env.CLOUD_UPSTASH_REDIS_REST_URL,
|
||||
token: process.env.CLOUD_UPSTASH_REDIS_REST_TOKEN,
|
||||
|
||||
@@ -124,7 +124,6 @@ export function createRoute<
|
||||
middlewares.push(validator("json", opts.body));
|
||||
}
|
||||
|
||||
|
||||
// Same for query
|
||||
if (opts.versionedQuery && opts.resource) {
|
||||
middlewares.push(
|
||||
@@ -143,7 +142,6 @@ export function createRoute<
|
||||
middlewares.push(validator("param", opts.params));
|
||||
}
|
||||
|
||||
|
||||
// Add expand middleware after query validation
|
||||
if (opts.query || opts.versionedQuery) {
|
||||
middlewares.push(expandMiddleware());
|
||||
|
||||
@@ -32,4 +32,3 @@ export const handleGetOrgMember = createRoute({
|
||||
return c.json({ userId: orgMember.userId });
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { isFreeProduct } from "@/internal/products/productUtils.js";
|
||||
import {
|
||||
AttachBranch,
|
||||
AttachPreview,
|
||||
type AttachPreview,
|
||||
AttachScenario,
|
||||
FullProduct,
|
||||
type FullProduct,
|
||||
} from "@autumn/shared";
|
||||
import { isFreeProduct } from "@/internal/products/productUtils.js";
|
||||
|
||||
export const getAttachScenario = async ({
|
||||
preview,
|
||||
@@ -13,7 +13,7 @@ export const getAttachScenario = async ({
|
||||
preview: AttachPreview;
|
||||
product: FullProduct;
|
||||
}) => {
|
||||
let branch = preview.branch;
|
||||
const branch = preview.branch;
|
||||
|
||||
if (
|
||||
branch == AttachBranch.New ||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {
|
||||
fullCustomerToCustomerEntitlements,
|
||||
type FullCustomer,
|
||||
findCustomerEntitlementById,
|
||||
fullCustomerToCustomerEntitlements,
|
||||
} from "@autumn/shared";
|
||||
import type { AutumnContext } from "@/honoUtils/HonoEnv.js";
|
||||
import type { DeductionUpdate } from "../types/deductionUpdate.js";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {
|
||||
cusEntToStartingBalance,
|
||||
fullCustomerToCustomerEntitlements,
|
||||
type FullCustomer,
|
||||
fullCustomerToCustomerEntitlements,
|
||||
getMaxOverage,
|
||||
getRelevantFeatures,
|
||||
isAllocatedCustomerEntitlement,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { Customer, customers } from "@autumn/shared";
|
||||
import { type Customer, customers } from "@autumn/shared";
|
||||
import { inArray } from "drizzle-orm";
|
||||
import type { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
|
||||
export class CusReadService {
|
||||
static async getInInternalIds({
|
||||
|
||||
@@ -527,7 +527,10 @@ export class CusSearchService {
|
||||
}
|
||||
|
||||
// Call searchByProduct if we have version filters OR status filters
|
||||
if ((filters?.version && filters?.version.length > 0) || (filters?.status && filters?.status.length > 0)) {
|
||||
if (
|
||||
(filters?.version && filters?.version.length > 0) ||
|
||||
(filters?.status && filters?.status.length > 0)
|
||||
) {
|
||||
return await CusSearchService.searchByProduct({
|
||||
db,
|
||||
orgId,
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { getExistingCusProducts } from "@/internal/customers/cusProducts/cusProductUtils/getExistingCusProducts.js";
|
||||
import { ItemSet } from "@/utils/models/ItemSet.js";
|
||||
import {
|
||||
AttachConfig,
|
||||
FullCusProduct,
|
||||
type AttachConfig,
|
||||
type FullCusProduct,
|
||||
getCusProductMinQuantity,
|
||||
ProductOptions,
|
||||
type ProductOptions,
|
||||
} from "@autumn/shared";
|
||||
import { getStripeSubItems2 } from "@/external/stripe/stripeSubUtils/getStripeSubItems.js";
|
||||
import type { AttachParams } from "@/internal/customers/cusProducts/AttachParams.js";
|
||||
import { getExistingCusProducts } from "@/internal/customers/cusProducts/cusProductUtils/getExistingCusProducts.js";
|
||||
import type { ItemSet } from "@/utils/models/ItemSet.js";
|
||||
import { mergeItemSets } from "./mergeItemSets.js";
|
||||
import { AttachParams } from "@/internal/customers/cusProducts/AttachParams.js";
|
||||
|
||||
export const getProdListWithoutEntities = ({
|
||||
attachParams,
|
||||
@@ -19,7 +19,7 @@ export const getProdListWithoutEntities = ({
|
||||
}) => {
|
||||
const newProdList = structuredClone(productsList);
|
||||
for (let i = 0; i < newProdList.length; i++) {
|
||||
let productOptions = newProdList[i];
|
||||
const productOptions = newProdList[i];
|
||||
newProdList[i] = {
|
||||
...productOptions,
|
||||
quantity:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ItemSet } from "@/utils/models/ItemSet.js";
|
||||
import type { ItemSet } from "@/utils/models/ItemSet.js";
|
||||
|
||||
export const mergeItemSets = ({
|
||||
curItemSet,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type Stripe from "stripe";
|
||||
import { subToPeriodStartEnd } from "@/external/stripe/stripeSubUtils/convertSubUtils.js";
|
||||
import Stripe from "stripe";
|
||||
|
||||
export const getNextCycle = (stripeSubs: Stripe.Subscription[]) => {
|
||||
const { end } = subToPeriodStartEnd({ sub: stripeSubs[0] });
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Stripe from "stripe";
|
||||
import type Stripe from "stripe";
|
||||
|
||||
export const shouldCancelSub = ({
|
||||
sub,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { EntitlementWithFeature } from "@autumn/shared";
|
||||
import { Price } from "@autumn/shared";
|
||||
import type { EntitlementWithFeature, Price } from "@autumn/shared";
|
||||
|
||||
export const hasPriceIdsChanged = ({
|
||||
oldPrices,
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
import { AttachParams } from "@/internal/customers/cusProducts/AttachParams.js";
|
||||
import { constructPreviewItem } from "@/internal/invoices/previewItemUtils/constructPreviewItem.js";
|
||||
import { Proration } from "@/internal/invoices/prorationUtils.js";
|
||||
import { getUsageFromBalance } from "@/internal/products/prices/priceUtils/arrearProratedUtils/getPrevAndNewUsages.js";
|
||||
import { generateId } from "@/utils/genUtils.js";
|
||||
import {
|
||||
FullEntitlement,
|
||||
FullCustomerEntitlement,
|
||||
PreviewLineItem,
|
||||
Price,
|
||||
AttachReplaceableSchema,
|
||||
type FullCustomerEntitlement,
|
||||
type FullEntitlement,
|
||||
type PreviewLineItem,
|
||||
type Price,
|
||||
usageToFeatureName,
|
||||
} from "@autumn/shared";
|
||||
|
||||
import { attachParamsToProduct } from "../convertAttachParams.js";
|
||||
import type { AttachParams } from "@/internal/customers/cusProducts/AttachParams.js";
|
||||
import { constructPreviewItem } from "@/internal/invoices/previewItemUtils/constructPreviewItem.js";
|
||||
import type { Proration } from "@/internal/invoices/prorationUtils.js";
|
||||
import { getUsageFromBalance } from "@/internal/products/prices/priceUtils/arrearProratedUtils/getPrevAndNewUsages.js";
|
||||
import { priceToInvoiceItem } from "@/internal/products/prices/priceUtils/priceToInvoiceItem.js";
|
||||
import { AttachReplaceableSchema } from "@autumn/shared";
|
||||
import { generateId } from "@/utils/genUtils.js";
|
||||
import { attachParamsToProduct } from "../convertAttachParams.js";
|
||||
|
||||
export const getContUseDowngradeItems = async ({
|
||||
price,
|
||||
@@ -34,31 +33,31 @@ export const getContUseDowngradeItems = async ({
|
||||
proration?: Proration;
|
||||
logger: any;
|
||||
}) => {
|
||||
let prevInvoiceItem = curItem;
|
||||
let prevBalance = prevCusEnt.entitlement.allowance! - curUsage;
|
||||
const prevInvoiceItem = curItem;
|
||||
const prevBalance = prevCusEnt.entitlement.allowance! - curUsage;
|
||||
const product = attachParamsToProduct({ attachParams });
|
||||
const feature = prevCusEnt.entitlement.feature;
|
||||
|
||||
let { usage: prevUsage, overage: prevOverage } = getUsageFromBalance({
|
||||
const { usage: prevUsage, overage: prevOverage } = getUsageFromBalance({
|
||||
ent: prevCusEnt.entitlement,
|
||||
price,
|
||||
balance: prevBalance,
|
||||
});
|
||||
|
||||
let { usage: newUsage, overage: newOverage } = getUsageFromBalance({
|
||||
const { usage: newUsage, overage: newOverage } = getUsageFromBalance({
|
||||
ent,
|
||||
price,
|
||||
balance: prevBalance,
|
||||
});
|
||||
|
||||
if (prevOverage == 0) {
|
||||
let { usage: newUsage } = getUsageFromBalance({
|
||||
const { usage: newUsage } = getUsageFromBalance({
|
||||
ent,
|
||||
price,
|
||||
balance: ent.allowance! - curUsage,
|
||||
});
|
||||
|
||||
let newItem = priceToInvoiceItem({
|
||||
const newItem = priceToInvoiceItem({
|
||||
price,
|
||||
ent,
|
||||
org: attachParams.org,
|
||||
@@ -87,9 +86,9 @@ export const getContUseDowngradeItems = async ({
|
||||
now: attachParams.now,
|
||||
});
|
||||
|
||||
let numReplaceables = newUsage - prevUsage;
|
||||
const numReplaceables = newUsage - prevUsage;
|
||||
|
||||
let replaceables = Array.from({ length: numReplaceables }, (_, i) =>
|
||||
const replaceables = Array.from({ length: numReplaceables }, (_, i) =>
|
||||
AttachReplaceableSchema.parse({
|
||||
ent: ent,
|
||||
id: generateId("rep"),
|
||||
@@ -103,7 +102,7 @@ export const getContUseDowngradeItems = async ({
|
||||
feature,
|
||||
});
|
||||
|
||||
let replaceableItem = constructPreviewItem({
|
||||
const replaceableItem = constructPreviewItem({
|
||||
priceStr: `${numReplaceables} free ${featureName}`,
|
||||
price,
|
||||
description: `${product.name} - ${featureName}`,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import type { Entitlement, Price } from "@autumn/shared";
|
||||
import type { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { EntitlementService } from "@/internal/products/entitlements/EntitlementService.js";
|
||||
import { PriceService } from "@/internal/products/prices/PriceService.js";
|
||||
import { Entitlement, Price } from "@autumn/shared";
|
||||
|
||||
export const insertCustomItems = async ({
|
||||
db,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Stripe from "stripe";
|
||||
import type Stripe from "stripe";
|
||||
|
||||
// Normalize items for comparison (order-agnostic, price id as string)
|
||||
const normalizePhaseItems = (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { differenceInDays } from "date-fns";
|
||||
import Stripe from "stripe";
|
||||
import type Stripe from "stripe";
|
||||
|
||||
export const phaseAndUnixMatch = ({
|
||||
phase,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AttachBranch } from "@autumn/shared";
|
||||
import type { AttachBranch } from "@autumn/shared";
|
||||
|
||||
export enum ProrationBehavior {
|
||||
Immediately = "immediately",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { AttachConfig, CusProductStatus } from "@autumn/shared";
|
||||
import { AttachParams } from "../../cusProducts/AttachParams.js";
|
||||
import { type AttachConfig, CusProductStatus } from "@autumn/shared";
|
||||
import type { AttachParams } from "../../cusProducts/AttachParams.js";
|
||||
|
||||
export const handleUnifiedAttach = async ({
|
||||
req,
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { InsertReplaceable, Replaceable, replaceables } from "@autumn/shared";
|
||||
import {
|
||||
type InsertReplaceable,
|
||||
type Replaceable,
|
||||
replaceables,
|
||||
} from "@autumn/shared";
|
||||
import { eq, inArray } from "drizzle-orm";
|
||||
import type { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
|
||||
export class RepService {
|
||||
static async insert({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// 1. Get min next reset at cus ent
|
||||
|
||||
import { Feature, FullCustomerEntitlement } from "@autumn/shared";
|
||||
import type { Feature, FullCustomerEntitlement } from "@autumn/shared";
|
||||
|
||||
export const getMinNextResetAtCusEnt = ({
|
||||
cusEnts,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import {
|
||||
type CustomerEntitlement,
|
||||
type EntitlementWithFeature,
|
||||
type FullCusProduct,
|
||||
type FullCustomerEntitlement,
|
||||
type Rollover,
|
||||
import type {
|
||||
CustomerEntitlement,
|
||||
EntitlementWithFeature,
|
||||
FullCusProduct,
|
||||
FullCustomerEntitlement,
|
||||
Rollover,
|
||||
} from "@autumn/shared";
|
||||
import type { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { generateId } from "@/utils/genUtils.js";
|
||||
|
||||
@@ -52,9 +52,11 @@ export const setCachedApiCustomer = async ({
|
||||
});
|
||||
|
||||
// Build entity api customers (entity-level features only)
|
||||
const filteredFullCus = filterEntityLevelCustomerEntitlementsFromFullCustomer({
|
||||
const filteredFullCus = filterEntityLevelCustomerEntitlementsFromFullCustomer(
|
||||
{
|
||||
fullCustomer: fullCus,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
// Build entities first
|
||||
const entityBatch: {
|
||||
|
||||
@@ -75,7 +75,8 @@ export const setCachedGrantedBalance = async ({
|
||||
// ============================================================================
|
||||
// 2. Build entity balances batch (entity-level products only)
|
||||
// ============================================================================
|
||||
const entityLevelCusProducts = filterEntityLevelCustomerEntitlementsFromFullCustomer({
|
||||
const entityLevelCusProducts =
|
||||
filterEntityLevelCustomerEntitlementsFromFullCustomer({
|
||||
fullCustomer: fullCus,
|
||||
}).customer_products;
|
||||
|
||||
|
||||
@@ -522,7 +522,8 @@ export const getPaginatedFullCusQuery = ({
|
||||
FROM customers c
|
||||
WHERE c.org_id = ${orgId}
|
||||
AND c.env = ${env}
|
||||
${internalCustomerIds && internalCustomerIds.length > 0
|
||||
${
|
||||
internalCustomerIds && internalCustomerIds.length > 0
|
||||
? sql`AND c.internal_id IN (${sql.join(
|
||||
internalCustomerIds.map((id) => sql`${id}`),
|
||||
sql`, `,
|
||||
@@ -607,7 +608,8 @@ export const getPaginatedFullCusQuery = ({
|
||||
GROUP BY cpwp.internal_customer_id
|
||||
)
|
||||
|
||||
${withSubs
|
||||
${
|
||||
withSubs
|
||||
? sql`, customer_subscriptions AS (
|
||||
SELECT
|
||||
cpwp.internal_customer_id,
|
||||
@@ -622,7 +624,8 @@ export const getPaginatedFullCusQuery = ({
|
||||
: sql``
|
||||
}
|
||||
|
||||
${withEntities
|
||||
${
|
||||
withEntities
|
||||
? sql`, customer_entities AS (
|
||||
SELECT
|
||||
e.internal_customer_id,
|
||||
@@ -637,7 +640,8 @@ export const getPaginatedFullCusQuery = ({
|
||||
: sql``
|
||||
}
|
||||
|
||||
${includeInvoices
|
||||
${
|
||||
includeInvoices
|
||||
? sql`, customer_invoices AS (
|
||||
SELECT
|
||||
i.internal_customer_id,
|
||||
@@ -652,7 +656,8 @@ export const getPaginatedFullCusQuery = ({
|
||||
: sql``
|
||||
}
|
||||
|
||||
${withTrialsUsed
|
||||
${
|
||||
withTrialsUsed
|
||||
? sql`, customer_trials_used AS (
|
||||
SELECT
|
||||
cp.internal_customer_id,
|
||||
|
||||
@@ -90,7 +90,9 @@ export const handleDecreaseAndTransfer = async ({
|
||||
replaceables: [],
|
||||
entities: fullCus.entities,
|
||||
features,
|
||||
internalEntityId: toEntity?.internal_id ? toEntity.internal_id : undefined,
|
||||
internalEntityId: toEntity?.internal_id
|
||||
? toEntity.internal_id
|
||||
: undefined,
|
||||
entityId: toEntity?.id ? toEntity.id : undefined,
|
||||
},
|
||||
product,
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
import type {
|
||||
Feature,
|
||||
Organization,
|
||||
ProductItem,
|
||||
ProductV2,
|
||||
} from "@autumn/shared";
|
||||
import { getFeatureNameWithCapital } from "@/internal/features/utils/displayUtils.js";
|
||||
import {
|
||||
featurePricetoPricecnItem,
|
||||
getPriceText,
|
||||
} from "@/internal/products/pricecn/pricecnUtils.js";
|
||||
import {
|
||||
isFeatureItem,
|
||||
isFeaturePriceItem,
|
||||
isPriceItem,
|
||||
} from "@/internal/products/product-items/productItemUtils/getItemType.js";
|
||||
|
||||
import { Feature, Organization, ProductItem, ProductV2 } from "@autumn/shared";
|
||||
import { formatCurrency, formatTiers } from "./previewUtils.js";
|
||||
import { isFeaturePriceItem } from "@/internal/products/product-items/productItemUtils/getItemType.js";
|
||||
import { notNullish } from "@/utils/genUtils.js";
|
||||
import { getFeatureNameWithCapital } from "@/internal/features/utils/displayUtils.js";
|
||||
import { formatCurrency, formatTiers } from "./previewUtils.js";
|
||||
|
||||
export const getProductChargeText = ({
|
||||
product,
|
||||
@@ -22,10 +26,10 @@ export const getProductChargeText = ({
|
||||
org: Organization;
|
||||
features: Feature[];
|
||||
}) => {
|
||||
let basePrices = product.items.filter((i) => isPriceItem(i));
|
||||
let total = basePrices.reduce((acc, curr) => acc + curr.price!, 0);
|
||||
const basePrices = product.items.filter((i) => isPriceItem(i));
|
||||
const total = basePrices.reduce((acc, curr) => acc + curr.price!, 0);
|
||||
|
||||
let itemStrs = [];
|
||||
const itemStrs = [];
|
||||
if (total > 0) {
|
||||
itemStrs.push(
|
||||
formatCurrency({
|
||||
@@ -35,18 +39,18 @@ export const getProductChargeText = ({
|
||||
);
|
||||
}
|
||||
|
||||
let prepaidPrices = product.items.filter(
|
||||
const prepaidPrices = product.items.filter(
|
||||
(i) => isFeaturePriceItem(i) && i.usage_model == "prepaid",
|
||||
);
|
||||
|
||||
let prepaidStrings = prepaidPrices.map((i) => {
|
||||
let feature = features.find((f) => f.id === i.feature_id);
|
||||
let priceStr = formatTiers({
|
||||
const prepaidStrings = prepaidPrices.map((i) => {
|
||||
const feature = features.find((f) => f.id === i.feature_id);
|
||||
const priceStr = formatTiers({
|
||||
tiers: i.tiers!,
|
||||
org,
|
||||
});
|
||||
|
||||
let featureStr =
|
||||
const featureStr =
|
||||
i.billing_units && i.billing_units > 1
|
||||
? `${i.billing_units} ${feature?.name}`
|
||||
: feature?.name;
|
||||
@@ -67,15 +71,15 @@ export const getItemDescription = ({
|
||||
product: ProductV2;
|
||||
org: Organization;
|
||||
}) => {
|
||||
let prices = product.items.filter((i) => !isFeatureItem(i));
|
||||
const prices = product.items.filter((i) => !isFeatureItem(i));
|
||||
|
||||
let priceStr = getPriceText({
|
||||
const priceStr = getPriceText({
|
||||
item,
|
||||
org,
|
||||
});
|
||||
|
||||
if (isPriceItem(item)) {
|
||||
let baseName =
|
||||
const baseName =
|
||||
prices.length == 1
|
||||
? product.name
|
||||
: notNullish(item.interval)
|
||||
@@ -84,7 +88,7 @@ export const getItemDescription = ({
|
||||
|
||||
return baseName;
|
||||
} else {
|
||||
let feature = features.find((f) => f.id === item.feature_id);
|
||||
const feature = features.find((f) => f.id === item.feature_id);
|
||||
// let pricecnItem = featurePricetoPricecnItem({
|
||||
// feature,
|
||||
// item,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Organization, PriceTier } from "@autumn/shared";
|
||||
import type { Organization, PriceTier } from "@autumn/shared";
|
||||
|
||||
export const formatCurrency = ({
|
||||
amount,
|
||||
@@ -30,11 +30,11 @@ export const formatTiers = ({
|
||||
});
|
||||
}
|
||||
|
||||
let tiersStart = formatCurrency({
|
||||
const tiersStart = formatCurrency({
|
||||
amount: tiers[0].amount,
|
||||
defaultCurrency: org.default_currency!,
|
||||
});
|
||||
let tiersEnd = formatCurrency({
|
||||
const tiersEnd = formatCurrency({
|
||||
amount: tiers[tiers.length - 1].amount,
|
||||
defaultCurrency: org.default_currency!,
|
||||
});
|
||||
@@ -50,8 +50,8 @@ export const getItemsHtml = ({
|
||||
org: Organization;
|
||||
}) => {
|
||||
let html = "";
|
||||
let pricedItems = items.filter((item) => item.amount != 0);
|
||||
let totalAmount = pricedItems.reduce((acc: number, item: any) => {
|
||||
const pricedItems = items.filter((item) => item.amount != 0);
|
||||
const totalAmount = pricedItems.reduce((acc: number, item: any) => {
|
||||
return acc + item.amount;
|
||||
}, 0);
|
||||
|
||||
@@ -74,7 +74,7 @@ export const getItemsHtml = ({
|
||||
export const itemsToHtml = ({ items }: { items: any[] }) => {
|
||||
let html = "";
|
||||
|
||||
for (let item of items) {
|
||||
for (const item of items) {
|
||||
if (item.amount == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { MigrationService } from "../migrations/MigrationService.js";
|
||||
import { MigrationJobStep, type Organization } from "@autumn/shared";
|
||||
import type { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { sendTextEmail } from "@/external/resend/resendUtils.js";
|
||||
import { MigrationJobStep, Organization } from "@autumn/shared";
|
||||
import { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { safeResend } from "@/external/resend/safeResend.js";
|
||||
import { MigrationService } from "../migrations/MigrationService.js";
|
||||
import { FROM_AUTUMN } from "./constants.js";
|
||||
|
||||
export const sendMigrationEmail = safeResend({
|
||||
@@ -15,15 +15,15 @@ export const sendMigrationEmail = safeResend({
|
||||
migrationJobId: string;
|
||||
org: Organization;
|
||||
}) => {
|
||||
let migrationJob = await MigrationService.getJob({
|
||||
const migrationJob = await MigrationService.getJob({
|
||||
db,
|
||||
id: migrationJobId,
|
||||
});
|
||||
|
||||
// Send email
|
||||
let getCustomersStep =
|
||||
const getCustomersStep =
|
||||
migrationJob.step_details[MigrationJobStep.GetCustomers];
|
||||
let migrateStep =
|
||||
const migrateStep =
|
||||
migrationJob.step_details[MigrationJobStep.MigrateCustomers];
|
||||
|
||||
console.log("Sending migration email");
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import OTPEmail from "@emails/OTPEmail.js";
|
||||
import { logger } from "@/external/logtail/logtailUtils.js";
|
||||
import { createResendCli } from "@/external/resend/resendUtils.js";
|
||||
import OTPEmail from "@emails/OTPEmail.js";
|
||||
import { FROM_AUTUMN } from "./constants.js";
|
||||
|
||||
const sendOTPEmail = async ({ email, otp }: { email: string; otp: string }) => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { EntityService } from "@/internal/api/entities/EntityService.js";
|
||||
import { Feature, getFeatureName } from "@autumn/shared";
|
||||
import { type Feature, getFeatureName } from "@autumn/shared";
|
||||
import { AppEnv, Entity } from "autumn-js";
|
||||
import type { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { EntityService } from "@/internal/api/entities/EntityService.js";
|
||||
|
||||
export const getEntityInvoiceDescription = async ({
|
||||
db,
|
||||
@@ -15,12 +15,12 @@ export const getEntityInvoiceDescription = async ({
|
||||
logger: any;
|
||||
}) => {
|
||||
try {
|
||||
let entity = await EntityService.getByInternalId({
|
||||
const entity = await EntityService.getByInternalId({
|
||||
db,
|
||||
internalId: internalEntityId,
|
||||
});
|
||||
|
||||
let feature = features.find(
|
||||
const feature = features.find(
|
||||
(f) => f.internal_id == entity?.internal_feature_id,
|
||||
);
|
||||
|
||||
@@ -32,7 +32,7 @@ export const getEntityInvoiceDescription = async ({
|
||||
}
|
||||
|
||||
if (feature && entDetails) {
|
||||
let featureName = getFeatureName({
|
||||
const featureName = getFeatureName({
|
||||
feature,
|
||||
plural: false,
|
||||
capitalize: true,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { generateId, notNullish, nullish } from "@/utils/genUtils.js";
|
||||
import {
|
||||
AppEnv,
|
||||
Entity,
|
||||
type AppEnv,
|
||||
type Entity,
|
||||
FeatureType,
|
||||
FullCusEntWithFullCusProduct,
|
||||
} from "@autumn/shared";
|
||||
import { generateId, notNullish, nullish } from "@/utils/genUtils.js";
|
||||
|
||||
export const constructEntity = ({
|
||||
inputEntity,
|
||||
@@ -21,7 +21,7 @@ export const constructEntity = ({
|
||||
env: AppEnv;
|
||||
deleted?: boolean;
|
||||
}) => {
|
||||
let entity: Entity = {
|
||||
const entity: Entity = {
|
||||
internal_id: generateId("ety"),
|
||||
id: inputEntity.id,
|
||||
name: inputEntity.name,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { notNullish } from "@/utils/genUtils.js";
|
||||
import { nullish } from "@/utils/genUtils.js";
|
||||
import { Entity } from "@autumn/shared";
|
||||
import type { Entity } from "@autumn/shared";
|
||||
import { notNullish, nullish } from "@/utils/genUtils.js";
|
||||
|
||||
export const logEntityToAction = ({
|
||||
entityToAction,
|
||||
@@ -35,11 +34,13 @@ export const getEntityToAction = ({
|
||||
feature: any;
|
||||
logger: any;
|
||||
}) => {
|
||||
let entityToAction: any = {};
|
||||
const entityToAction: any = {};
|
||||
let createCount = 0;
|
||||
let replacedEntities: string[] = [];
|
||||
const replacedEntities: string[] = [];
|
||||
for (const inputEntity of inputEntities) {
|
||||
let curEntity = existingEntities.find((e: any) => e.id === inputEntity.id);
|
||||
const curEntity = existingEntities.find(
|
||||
(e: any) => e.id === inputEntity.id,
|
||||
);
|
||||
|
||||
if (curEntity && curEntity.deleted) {
|
||||
entityToAction[inputEntity.id] = {
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { Feature } from "@autumn/shared";
|
||||
|
||||
import { Organization } from "@autumn/shared";
|
||||
import { type Feature, Organization } from "@autumn/shared";
|
||||
|
||||
export const getFeatureName = ({
|
||||
feature,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { createRoute } from "@/honoMiddlewares/routeHandler.js";
|
||||
import { createStripeCli } from "@/external/connect/createStripeCli.js";
|
||||
import { createRoute } from "@/honoMiddlewares/routeHandler.js";
|
||||
|
||||
/**
|
||||
* Get Stripe invoice by Stripe invoice ID
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import { Organization, Price, Product, UsagePriceConfig } from "@autumn/shared";
|
||||
import type {
|
||||
Organization,
|
||||
Price,
|
||||
Product,
|
||||
UsagePriceConfig,
|
||||
} from "@autumn/shared";
|
||||
import { Decimal } from "decimal.js";
|
||||
import Stripe from "stripe";
|
||||
import type Stripe from "stripe";
|
||||
|
||||
export const constructStripeInvoiceItem = ({
|
||||
product,
|
||||
@@ -29,7 +34,7 @@ export const constructStripeInvoiceItem = ({
|
||||
new Decimal(amount).mul(100).round().toNumber(),
|
||||
);
|
||||
|
||||
let priceData =
|
||||
const priceData =
|
||||
amountInCents > 0
|
||||
? {
|
||||
price_data: {
|
||||
@@ -43,7 +48,7 @@ export const constructStripeInvoiceItem = ({
|
||||
currency: org.default_currency || "usd",
|
||||
};
|
||||
|
||||
let invoiceItem: Stripe.InvoiceItemCreateParams = {
|
||||
const invoiceItem: Stripe.InvoiceItemCreateParams = {
|
||||
subscription: stripeSubId,
|
||||
...priceData,
|
||||
|
||||
|
||||
@@ -11,7 +11,8 @@ const invoiceRedirectLimiter = rateLimiter<HonoEnv>({
|
||||
windowMs: 60 * 1000, // 1 minute
|
||||
limit: 10,
|
||||
standardHeaders: "draft-6",
|
||||
keyGenerator: (c) => c.req.header("x-forwarded-for") ?? c.req.header("x-real-ip") ?? "unknown",
|
||||
keyGenerator: (c) =>
|
||||
c.req.header("x-forwarded-for") ?? c.req.header("x-real-ip") ?? "unknown",
|
||||
});
|
||||
|
||||
publicInvoiceRouter.get(
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { generateId } from "@/utils/genUtils.js";
|
||||
import {
|
||||
AppEnv,
|
||||
MigrationError,
|
||||
MigrationJob,
|
||||
type AppEnv,
|
||||
type MigrationError,
|
||||
type MigrationJob,
|
||||
MigrationJobStep,
|
||||
Product,
|
||||
type Product,
|
||||
} from "@autumn/shared";
|
||||
import { generateId } from "@/utils/genUtils.js";
|
||||
|
||||
export const constructMigrationError = ({
|
||||
migrationJobId,
|
||||
@@ -20,7 +20,7 @@ export const constructMigrationError = ({
|
||||
code: string;
|
||||
message: string;
|
||||
}) => {
|
||||
let migrationError: MigrationError = {
|
||||
const migrationError: MigrationError = {
|
||||
migration_job_id: migrationJobId,
|
||||
internal_customer_id: internalCustomerId,
|
||||
data,
|
||||
@@ -40,7 +40,7 @@ export const constructMigrationJob = ({
|
||||
fromProduct: Product;
|
||||
toProduct: Product;
|
||||
}) => {
|
||||
let migrationJob: MigrationJob = {
|
||||
const migrationJob: MigrationJob = {
|
||||
id: generateId("mig_job"),
|
||||
created_at: Date.now(),
|
||||
updated_at: Date.now(),
|
||||
|
||||
@@ -18,8 +18,7 @@ export const handleDeleteView = createRoute({
|
||||
|
||||
// Remove from list
|
||||
const listKey = `saved_views_list:${org.id}:${env}`;
|
||||
const existingViews =
|
||||
(await CacheManager.getJson<string[]>(listKey)) || [];
|
||||
const existingViews = (await CacheManager.getJson<string[]>(listKey)) || [];
|
||||
const updatedViews = existingViews.filter((id: string) => id !== viewId);
|
||||
await CacheManager.setJson(listKey, updatedViews, "forever");
|
||||
|
||||
|
||||
@@ -39,7 +39,11 @@ export const parseChatProducts = async ({
|
||||
env: AppEnv.Sandbox,
|
||||
});
|
||||
|
||||
const { prices, entitlements, features: updatedFeatures } = await handleNewProductItems({
|
||||
const {
|
||||
prices,
|
||||
entitlements,
|
||||
features: updatedFeatures,
|
||||
} = await handleNewProductItems({
|
||||
db,
|
||||
curPrices: [],
|
||||
curEnts: [],
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { AppEnv, type Organization } from "@autumn/shared";
|
||||
import type { Logger } from "@/external/logtail/logtailUtils.js";
|
||||
import {
|
||||
deauthorizeAccount,
|
||||
deleteConnectedAccount,
|
||||
} from "@/external/connect/connectUtils.js";
|
||||
import type { Logger } from "@/external/logtail/logtailUtils.js";
|
||||
import { deleteSvixApp } from "@/external/svix/svixHelpers.js";
|
||||
import { deleteStripeWebhook } from "../orgUtils.js";
|
||||
|
||||
|
||||
@@ -95,7 +95,10 @@ export const createProduct = async ({
|
||||
const newFullProduct: FullProduct = {
|
||||
...product,
|
||||
prices,
|
||||
entitlements: getEntsWithFeature({ ents: entitlements, features: updatedFeatures }),
|
||||
entitlements: getEntsWithFeature({
|
||||
ents: entitlements,
|
||||
features: updatedFeatures,
|
||||
}),
|
||||
free_trial: newFreeTrial,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Entitlement, Price, UsagePriceConfig } from "@autumn/shared";
|
||||
import type { Entitlement, Price, UsagePriceConfig } from "@autumn/shared";
|
||||
import { Decimal } from "decimal.js";
|
||||
|
||||
export const getUsageFromBalance = ({
|
||||
@@ -10,17 +10,17 @@ export const getUsageFromBalance = ({
|
||||
price: Price;
|
||||
balance: number;
|
||||
}) => {
|
||||
let config = price.config as UsagePriceConfig;
|
||||
let billingUnits = config.billing_units || 1;
|
||||
const config = price.config as UsagePriceConfig;
|
||||
const billingUnits = config.billing_units || 1;
|
||||
|
||||
let overage = -Math.min(0, balance);
|
||||
let roundedOverage = new Decimal(overage)
|
||||
const overage = -Math.min(0, balance);
|
||||
const roundedOverage = new Decimal(overage)
|
||||
.div(billingUnits)
|
||||
.ceil()
|
||||
.mul(billingUnits)
|
||||
.toNumber();
|
||||
|
||||
let usage = new Decimal(ent.allowance!).sub(balance).toNumber();
|
||||
const usage = new Decimal(ent.allowance!).sub(balance).toNumber();
|
||||
|
||||
let roundedUsage = usage;
|
||||
if (overage > 0) {
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
import { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { PriceService } from "../PriceService.js";
|
||||
import { FixedPriceConfig, prices, PriceType } from "@autumn/shared";
|
||||
import {
|
||||
type FixedPriceConfig,
|
||||
type Price,
|
||||
PriceType,
|
||||
prices,
|
||||
type UsagePriceConfig,
|
||||
} from "@autumn/shared";
|
||||
import { eq } from "drizzle-orm";
|
||||
import type { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { generateId } from "@/utils/genUtils.js";
|
||||
import { Price, UsagePriceConfig } from "@autumn/shared";
|
||||
import { PriceService } from "../PriceService.js";
|
||||
|
||||
export const copyPrice = async ({
|
||||
db,
|
||||
@@ -20,7 +25,7 @@ export const copyPrice = async ({
|
||||
isCustom?: boolean;
|
||||
withPrevConfig?: boolean;
|
||||
}) => {
|
||||
let price = (await db.query.prices.findFirst({
|
||||
const price = (await db.query.prices.findFirst({
|
||||
where: eq(prices.id, priceId),
|
||||
})) as Price;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { BillingType, Price } from "@autumn/shared";
|
||||
import { BillingType, type Price } from "@autumn/shared";
|
||||
import { getBillingType } from "../priceUtils.js";
|
||||
|
||||
const BillingTypeOrder = [
|
||||
@@ -11,8 +11,8 @@ const BillingTypeOrder = [
|
||||
|
||||
export const sortPricesByType = (prices: Price[]) => {
|
||||
return prices.sort((a, b) => {
|
||||
let aType = getBillingType(a.config);
|
||||
let bType = getBillingType(b.config);
|
||||
const aType = getBillingType(a.config);
|
||||
const bType = getBillingType(b.config);
|
||||
return BillingTypeOrder.indexOf(aType) - BillingTypeOrder.indexOf(bType);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {
|
||||
Feature,
|
||||
type Feature,
|
||||
FeatureType,
|
||||
ProductItem,
|
||||
type ProductItem,
|
||||
ProductItemFeatureType,
|
||||
UsageModel,
|
||||
} from "@autumn/shared";
|
||||
|
||||
@@ -36,7 +36,10 @@ honoProductRouter.delete("/:product_id", ...handleDeleteProductHono);
|
||||
honoProductRouter.post("/:product_id/copy", ...handleCopyProductV2);
|
||||
|
||||
// Info before deleting plan
|
||||
honoProductRouter.get("/:product_id/has_customers", ...handlePlanHasCustomersV2);
|
||||
honoProductRouter.get(
|
||||
"/:product_id/has_customers",
|
||||
...handlePlanHasCustomersV2,
|
||||
);
|
||||
honoProductRouter.post(
|
||||
"/:product_id/has_customers",
|
||||
...handlePlanHasCustomersV2,
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import { FeatureId, sendProductEvent } from "@/external/autumn/autumnUtils.js";
|
||||
import { isEntitled } from "@/external/autumn/autumnUtils.js";
|
||||
import {
|
||||
FeatureId,
|
||||
isEntitled,
|
||||
sendProductEvent,
|
||||
} from "@/external/autumn/autumnUtils.js";
|
||||
import { handleRequestError } from "@/utils/errorUtils.js";
|
||||
|
||||
export const pricingMiddleware = async (req: any, res: any, next: any) => {
|
||||
let path = req.url;
|
||||
let method = req.method;
|
||||
const path = req.url;
|
||||
const method = req.method;
|
||||
|
||||
let host = req.headers.host;
|
||||
const host = req.headers.host;
|
||||
if (host.includes("localhost")) {
|
||||
next();
|
||||
return;
|
||||
@@ -33,7 +36,7 @@ export const pricingMiddleware = async (req: any, res: any, next: any) => {
|
||||
});
|
||||
}
|
||||
|
||||
if (path.match(/^\/products\/[^\/]+$/) && method === "DELETE") {
|
||||
if (path.match(/^\/products\/[^/]+$/) && method === "DELETE") {
|
||||
console.log("sending product delete event");
|
||||
await sendProductEvent({
|
||||
org: req.org,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { AppEnv, AuthType, ErrCode } from "@autumn/shared";
|
||||
import { verifyPublicKey } from "@/internal/dev/api-keys/publicKeyUtils.js";
|
||||
import RecaseError from "@/utils/errorUtils.js";
|
||||
import { AppEnv, AuthType, ErrCode } from "@autumn/shared";
|
||||
|
||||
const allowedEndpoints = [
|
||||
{
|
||||
@@ -82,7 +82,7 @@ export const verifyBearerPublishableKey = async (
|
||||
});
|
||||
}
|
||||
|
||||
let env: AppEnv = pkey.startsWith("am_pk_test")
|
||||
const env: AppEnv = pkey.startsWith("am_pk_test")
|
||||
? AppEnv.Sandbox
|
||||
: AppEnv.Live;
|
||||
|
||||
@@ -100,7 +100,7 @@ export const verifyBearerPublishableKey = async (
|
||||
});
|
||||
}
|
||||
|
||||
let { org, features } = data;
|
||||
const { org, features } = data;
|
||||
|
||||
req.minOrg = {
|
||||
id: org.id,
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
export const parseAuthHeader = (req: any) => {
|
||||
let authHeader = req.headers["Authorization"] || req.headers["authorization"];
|
||||
const authHeader =
|
||||
req.headers["Authorization"] || req.headers["authorization"];
|
||||
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
||||
return null;
|
||||
}
|
||||
let bearerToken = authHeader.split(" ")[1];
|
||||
const bearerToken = authHeader.split(" ")[1];
|
||||
return bearerToken;
|
||||
};
|
||||
|
||||
@@ -45,9 +45,6 @@ export const checkSubCountMatch = async ({
|
||||
.from(metadata)
|
||||
.where(inArray(metadata.stripe_invoice_id, invoiceIds as string[]));
|
||||
|
||||
|
||||
|
||||
|
||||
if (
|
||||
stripeSubs.length - (metadataCount?.[0]?.count || 0) !==
|
||||
subIds.length
|
||||
|
||||
@@ -17,7 +17,9 @@ export const saveCheckState = async ({
|
||||
result: StateCheckResult;
|
||||
}): Promise<void> => {
|
||||
const newFailedChecks = result.checks
|
||||
.filter((c): c is typeof c & { type: CheckType } => c.type !== "overall_status")
|
||||
.filter(
|
||||
(c): c is typeof c & { type: CheckType } => c.type !== "overall_status",
|
||||
)
|
||||
.filter((c) => !c.passed);
|
||||
|
||||
// Skip Redis entirely if all checks pass
|
||||
@@ -25,14 +27,18 @@ export const saveCheckState = async ({
|
||||
|
||||
const stateKey = `state:${org.id}:${env}:${fullCus.internal_id}`;
|
||||
|
||||
const existingState = (await upstash.get(stateKey)) as RedisChecksState | null;
|
||||
const existingState = (await upstash.get(
|
||||
stateKey,
|
||||
)) as RedisChecksState | null;
|
||||
|
||||
if (existingState) {
|
||||
// Merge with existing state
|
||||
const existingFailedTypes = new Set<CheckType>(existingState.checks.map((c) => c.type));
|
||||
const newFailedTypes = new Set<CheckType>(newFailedChecks.map((c) => c.type));
|
||||
|
||||
|
||||
const existingFailedTypes = new Set<CheckType>(
|
||||
existingState.checks.map((c) => c.type),
|
||||
);
|
||||
const newFailedTypes = new Set<CheckType>(
|
||||
newFailedChecks.map((c) => c.type),
|
||||
);
|
||||
|
||||
// Checks that were fixed (existed before but not now)
|
||||
const checksToRemove = new Set<CheckType>(
|
||||
@@ -44,7 +50,9 @@ export const saveCheckState = async ({
|
||||
);
|
||||
|
||||
// Keep checks that still fail, remove ones that are fixed
|
||||
const updatedChecks = existingState.checks.filter((c) => !checksToRemove.has(c.type));
|
||||
const updatedChecks = existingState.checks.filter(
|
||||
(c) => !checksToRemove.has(c.type),
|
||||
);
|
||||
|
||||
// Add new failing checks
|
||||
for (const check of newFailedChecks) {
|
||||
@@ -65,7 +73,6 @@ export const saveCheckState = async ({
|
||||
checks: updatedChecks,
|
||||
};
|
||||
await upstash.set(stateKey, JSON.stringify(updatedState));
|
||||
|
||||
} else {
|
||||
// Create new state
|
||||
const newState: RedisChecksState = {
|
||||
@@ -87,7 +94,5 @@ export const saveCheckState = async ({
|
||||
})),
|
||||
};
|
||||
await upstash.set(stateKey, JSON.stringify(newState));
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -50,6 +50,6 @@ export const generatePublishableKey = (env: string) => {
|
||||
// .replace(/[+/=]/g, "") // Remove non-URL safe characters
|
||||
// .slice(0, 100); // Ensure exactly 100 characters
|
||||
|
||||
let envString = env === AppEnv.Sandbox ? "test_" : "live_";
|
||||
const envString = env === AppEnv.Sandbox ? "test_" : "live_";
|
||||
return `am_pk_${envString}${KSUID.randomSync().string}`;
|
||||
};
|
||||
|
||||
@@ -19,8 +19,6 @@ export const checkEnvVars = () => {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!process.env.BETTER_AUTH_SECRET || !process.env.BETTER_AUTH_URL) {
|
||||
console.error(`BETTER_AUTH_SECRET or BETTER_AUTH_URL is not set`);
|
||||
process.exit(1);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { type Price } from "@autumn/shared";
|
||||
import type { Price } from "@autumn/shared";
|
||||
import type Stripe from "stripe";
|
||||
|
||||
// export const ItemSetSchema = z.object({
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import {
|
||||
AppEnv,
|
||||
customers,
|
||||
features,
|
||||
Organization,
|
||||
type Organization,
|
||||
products,
|
||||
} from "@autumn/shared";
|
||||
import { and, eq, inArray } from "drizzle-orm";
|
||||
import type { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
|
||||
export const clearCustomersInBatches = async ({
|
||||
db,
|
||||
|
||||
@@ -11,7 +11,7 @@ export const parseCsv = ({
|
||||
return new Promise((resolve, reject) => {
|
||||
const stream = fs.createReadStream(path);
|
||||
const results: any[] = [];
|
||||
let headers: string[] = [];
|
||||
const headers: string[] = [];
|
||||
stream
|
||||
.pipe(csv({ separator: delimiter }))
|
||||
.on("data", (data) => {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { AppEnv, FullCusProduct } from "@autumn/shared";
|
||||
import { AppEnv, type FullCusProduct } from "@autumn/shared";
|
||||
import { sql } from "drizzle-orm";
|
||||
import type { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
|
||||
let cusProductsQuery = ({
|
||||
const cusProductsQuery = ({
|
||||
lastProductId,
|
||||
internalProductId,
|
||||
pageSize = 250,
|
||||
@@ -87,8 +87,8 @@ export const getAllFullCusProducts = async ({
|
||||
internalProductId: string;
|
||||
}) => {
|
||||
let lastProductId = "";
|
||||
let allData: any[] = [];
|
||||
let pageSize = 500;
|
||||
const allData: any[] = [];
|
||||
const pageSize = 500;
|
||||
|
||||
while (true) {
|
||||
const data = await db.execute(
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { user } from "@autumn/shared";
|
||||
|
||||
import { desc } from "drizzle-orm";
|
||||
import type { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
|
||||
export const getAllUsers = async (db: DrizzleCli) => {
|
||||
const users = [];
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Organization, AppEnv } from "@autumn/shared";
|
||||
import { AppEnv, type Organization } from "@autumn/shared";
|
||||
import { deleteAllStripeCustomers } from "@/external/stripe/stripeCusUtils.js";
|
||||
import {
|
||||
deactivateStripeMeters,
|
||||
deleteAllStripeProducts,
|
||||
} from "@/external/stripe/stripeProductUtils.js";
|
||||
import { deleteAllStripeCustomers } from "@/external/stripe/stripeCusUtils.js";
|
||||
|
||||
export const resetOrgStripe = async ({ org }: { org: Organization }) => {
|
||||
const env = AppEnv.Sandbox;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { Duration, EntInterval } from "@autumn/shared";
|
||||
|
||||
import { Entitlement } from "@autumn/shared";
|
||||
import { add } from "date-fns";
|
||||
import { Duration, EntInterval, Entitlement } from "@autumn/shared";
|
||||
import { UTCDate } from "@date-fns/utc";
|
||||
import { add } from "date-fns";
|
||||
import { formatUnixToDate } from "./genUtils.js";
|
||||
|
||||
// Time conversion constants
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { beforeAll, describe, expect, test } from "bun:test";
|
||||
import { LegacyVersion } from "@autumn/shared";
|
||||
import chalk from "chalk";
|
||||
import { addHours, addMonths } from "date-fns";
|
||||
import type Stripe from "stripe";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import { hoursToFinalizeInvoice } from "@tests/utils/constants.js";
|
||||
import { attachAndExpectCorrect } from "@tests/utils/expectUtils/expectAttach.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import { getBasePrice } from "@tests/utils/testProductUtils/testProductUtils.js";
|
||||
import chalk from "chalk";
|
||||
import { addHours, addMonths } from "date-fns";
|
||||
import type Stripe from "stripe";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { constructFeatureItem } from "@/utils/scriptUtils/constructItem.js";
|
||||
import { constructProduct } from "@/utils/scriptUtils/createTestProducts.js";
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { beforeAll, describe, expect, test } from "bun:test";
|
||||
import { LegacyVersion } from "@autumn/shared";
|
||||
import chalk from "chalk";
|
||||
import { addDays, addMonths } from "date-fns";
|
||||
import type Stripe from "stripe";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import { attachAndExpectCorrect } from "@tests/utils/expectUtils/expectAttach.js";
|
||||
import { expectProductAttached } from "@tests/utils/expectUtils/expectProductAttached.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import chalk from "chalk";
|
||||
import { addDays, addMonths } from "date-fns";
|
||||
import type Stripe from "stripe";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { calculateProrationAmount } from "@/internal/invoices/prorationUtils.js";
|
||||
import {
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import { beforeAll, describe, expect, test } from "bun:test";
|
||||
import { LegacyVersion } from "@autumn/shared";
|
||||
import chalk from "chalk";
|
||||
import { addMonths } from "date-fns";
|
||||
import type Stripe from "stripe";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import { attachAndExpectCorrect } from "@tests/utils/expectUtils/expectAttach.js";
|
||||
import {
|
||||
@@ -11,6 +8,9 @@ import {
|
||||
} from "@tests/utils/expectUtils/expectScheduleUtils.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import { getBasePrice } from "@tests/utils/testProductUtils/testProductUtils.js";
|
||||
import chalk from "chalk";
|
||||
import { addMonths } from "date-fns";
|
||||
import type Stripe from "stripe";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { constructFeatureItem } from "@/utils/scriptUtils/constructItem.js";
|
||||
import { constructProduct } from "@/utils/scriptUtils/createTestProducts.js";
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { beforeAll, describe, expect, test } from "bun:test";
|
||||
import { ApiVersion, type AppEnv, LegacyVersion } from "@autumn/shared";
|
||||
import chalk from "chalk";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import {
|
||||
getPrepaidCusEnt,
|
||||
@@ -8,6 +7,7 @@ import {
|
||||
} from "@tests/utils/cusProductUtils/cusEntSearchUtils.js";
|
||||
import { getMainCusProduct } from "@tests/utils/cusProductUtils/cusProductUtils.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import chalk from "chalk";
|
||||
import type { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { timeout } from "@/utils/genUtils.js";
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { beforeAll, describe, expect, test } from "bun:test";
|
||||
import { ApiVersion, type AppEnv, LegacyVersion } from "@autumn/shared";
|
||||
import chalk from "chalk";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import {
|
||||
getLifetimeFreeCusEnt,
|
||||
@@ -8,6 +7,7 @@ import {
|
||||
} from "@tests/utils/cusProductUtils/cusEntSearchUtils.js";
|
||||
import { getMainCusProduct } from "@tests/utils/cusProductUtils/cusProductUtils.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import chalk from "chalk";
|
||||
import type { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { timeout } from "@/utils/genUtils.js";
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
import { beforeAll, describe, expect, test } from "bun:test";
|
||||
import { ApiVersion, type AppEnv } from "@autumn/shared";
|
||||
import chalk from "chalk";
|
||||
import { addMonths } from "date-fns";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import {
|
||||
getLifetimeFreeCusEnt,
|
||||
@@ -11,6 +9,8 @@ import {
|
||||
} from "@tests/utils/cusProductUtils/cusEntSearchUtils.js";
|
||||
import { getMainCusProduct } from "@tests/utils/cusProductUtils/cusProductUtils.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import chalk from "chalk";
|
||||
import { addMonths } from "date-fns";
|
||||
import type { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { timeout } from "@/utils/genUtils.js";
|
||||
|
||||
@@ -3,8 +3,8 @@ import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import { constructPriceItem } from "@/internal/products/product-items/productItemUtils.js";
|
||||
import {
|
||||
constructFeatureItem,
|
||||
constructArrearItem,
|
||||
constructFeatureItem,
|
||||
} from "@/utils/scriptUtils/constructItem.js";
|
||||
import { constructProduct } from "@/utils/scriptUtils/createTestProducts.js";
|
||||
import { createSharedProducts } from "@/utils/scriptUtils/testUtils/createSharedProduct.js";
|
||||
|
||||
@@ -5,12 +5,12 @@ import {
|
||||
ProductItemInterval,
|
||||
UsageModel,
|
||||
} from "@autumn/shared";
|
||||
import chalk from "chalk";
|
||||
import type Stripe from "stripe";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import { expectCustomerV0Correct } from "@tests/utils/expectUtils/expectCustomerV0Correct.js";
|
||||
import { getExpectedInvoiceTotal } from "@tests/utils/expectUtils/expectInvoiceUtils.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import chalk from "chalk";
|
||||
import type Stripe from "stripe";
|
||||
import { constructPriceItem } from "@/internal/products/product-items/productItemUtils.js";
|
||||
import { convertProductV2ToV1 } from "@/internal/products/productUtils/productV2Utils/convertProductV2ToV1.js";
|
||||
import { constructRawProduct } from "@/utils/scriptUtils/createTestProducts.js";
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { beforeAll, describe, expect, test } from "bun:test";
|
||||
import { ErrCode, LegacyVersion, type LimitedItem } from "@autumn/shared";
|
||||
import chalk from "chalk";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import { attachAndExpectCorrect } from "@tests/utils/expectUtils/expectAttach.js";
|
||||
import { expectAutumnError } from "@tests/utils/expectUtils/expectErrUtils.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import chalk from "chalk";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { constructArrearProratedItem } from "@/utils/scriptUtils/constructItem.js";
|
||||
import { constructProduct } from "@/utils/scriptUtils/createTestProducts.js";
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { beforeAll, describe, expect, test } from "bun:test";
|
||||
import { LegacyVersion, type LimitedItem } from "@autumn/shared";
|
||||
import chalk from "chalk";
|
||||
import type Stripe from "stripe";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import { attachAndExpectCorrect } from "@tests/utils/expectUtils/expectAttach.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import chalk from "chalk";
|
||||
import type Stripe from "stripe";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { timeout } from "@/utils/genUtils.js";
|
||||
import {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { beforeAll, describe, test } from "bun:test";
|
||||
import { ErrCode, LegacyVersion, type LimitedItem } from "@autumn/shared";
|
||||
import chalk from "chalk";
|
||||
import type Stripe from "stripe";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import { attachAndExpectCorrect } from "@tests/utils/expectUtils/expectAttach.js";
|
||||
import { expectAutumnError } from "@tests/utils/expectUtils/expectErrUtils.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import chalk from "chalk";
|
||||
import type Stripe from "stripe";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { constructPrepaidItem } from "@/utils/scriptUtils/constructItem.js";
|
||||
import { constructProduct } from "@/utils/scriptUtils/createTestProducts.js";
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { LegacyVersion, OnDecrease, OnIncrease } from "@autumn/shared";
|
||||
import { beforeAll, describe, expect, test } from "bun:test";
|
||||
import chalk from "chalk";
|
||||
import { addWeeks } from "date-fns";
|
||||
import type Stripe from "stripe";
|
||||
import { LegacyVersion, OnDecrease, OnIncrease } from "@autumn/shared";
|
||||
import { replaceItems } from "@tests/attach/utils.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import { attachAndExpectCorrect } from "@tests/utils/expectUtils/expectAttach.js";
|
||||
import { expectSubQuantityCorrect } from "@tests/utils/expectUtils/expectContUseUtils.js";
|
||||
import { advanceTestClock } from "@tests/utils/stripeUtils.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import chalk from "chalk";
|
||||
import { addWeeks } from "date-fns";
|
||||
import type Stripe from "stripe";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { constructArrearProratedItem } from "@/utils/scriptUtils/constructItem.js";
|
||||
import { constructProduct } from "@/utils/scriptUtils/createTestProducts.js";
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { LegacyVersion, OnDecrease, OnIncrease } from "@autumn/shared";
|
||||
import { beforeAll, describe, test } from "bun:test";
|
||||
import chalk from "chalk";
|
||||
import { LegacyVersion, OnDecrease, OnIncrease } from "@autumn/shared";
|
||||
import { replaceItems } from "@tests/attach/utils.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import { attachAndExpectCorrect } from "@tests/utils/expectUtils/expectAttach.js";
|
||||
import { attachNewContUseAndExpectCorrect } from "@tests/utils/expectUtils/expectContUse/expectUpdateContUse.js";
|
||||
import { expectSubQuantityCorrect } from "@tests/utils/expectUtils/expectContUseUtils.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import chalk from "chalk";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { constructArrearProratedItem } from "@/utils/scriptUtils/constructItem.js";
|
||||
import { constructProduct } from "@/utils/scriptUtils/createTestProducts.js";
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { LegacyVersion, OnDecrease, OnIncrease } from "@autumn/shared";
|
||||
import { beforeAll, describe, expect, test } from "bun:test";
|
||||
import chalk from "chalk";
|
||||
import { addWeeks } from "date-fns";
|
||||
import { LegacyVersion, OnDecrease, OnIncrease } from "@autumn/shared";
|
||||
import { replaceItems } from "@tests/attach/utils.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import { attachAndExpectCorrect } from "@tests/utils/expectUtils/expectAttach.js";
|
||||
import { attachNewContUseAndExpectCorrect } from "@tests/utils/expectUtils/expectContUse/expectUpdateContUse.js";
|
||||
import { expectSubQuantityCorrect } from "@tests/utils/expectUtils/expectContUseUtils.js";
|
||||
import { advanceTestClock } from "@tests/utils/stripeUtils.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import chalk from "chalk";
|
||||
import { addWeeks } from "date-fns";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { subToPeriodStartEnd } from "@/external/stripe/stripeSubUtils/convertSubUtils.js";
|
||||
import { calculateProrationAmount } from "@/internal/invoices/prorationUtils.js";
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { LegacyVersion, OnDecrease, OnIncrease } from "@autumn/shared";
|
||||
import { beforeAll, describe, test } from "bun:test";
|
||||
import chalk from "chalk";
|
||||
import { addWeeks } from "date-fns";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import { LegacyVersion, OnDecrease, OnIncrease } from "@autumn/shared";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import { attachAndExpectCorrect } from "@tests/utils/expectUtils/expectAttach.js";
|
||||
import { advanceTestClock } from "@tests/utils/stripeUtils.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import chalk from "chalk";
|
||||
import { addWeeks } from "date-fns";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { constructArrearProratedItem } from "@/utils/scriptUtils/constructItem.js";
|
||||
import { constructProduct } from "@/utils/scriptUtils/createTestProducts.js";
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { beforeAll, describe, test } from "bun:test";
|
||||
import { type AppEnv, LegacyVersion, type Organization } from "@autumn/shared";
|
||||
import chalk from "chalk";
|
||||
import type Stripe from "stripe";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import { attachAndExpectCorrect } from "@tests/utils/expectUtils/expectAttach.js";
|
||||
import { expectFeaturesCorrect } from "@tests/utils/expectUtils/expectFeaturesCorrect.js";
|
||||
import { expectProductAttached } from "@tests/utils/expectUtils/expectProductAttached.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import chalk from "chalk";
|
||||
import type Stripe from "stripe";
|
||||
import type { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { constructFeatureItem } from "@/utils/scriptUtils/constructItem.js";
|
||||
|
||||
@@ -5,13 +5,13 @@ import {
|
||||
type Entitlement,
|
||||
ProductItemInterval,
|
||||
} from "@autumn/shared";
|
||||
import chalk from "chalk";
|
||||
import { AutumnCli } from "@tests/cli/AutumnCli.js";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import { expectCustomerV0Correct } from "@tests/utils/expectUtils/expectCustomerV0Correct.js";
|
||||
import { timeout } from "@tests/utils/genUtils.js";
|
||||
import { completeCheckoutForm } from "@tests/utils/stripeUtils.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import chalk from "chalk";
|
||||
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { convertProductV2ToV1 } from "@/internal/products/productUtils/productV2Utils/convertProductV2ToV1.js";
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { beforeAll, describe, test } from "bun:test";
|
||||
import { ApiVersion } from "@autumn/shared";
|
||||
import chalk from "chalk";
|
||||
import { AutumnCli } from "@tests/cli/AutumnCli.js";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import { expectCustomerV0Correct } from "@tests/utils/expectUtils/expectCustomerV0Correct.js";
|
||||
import { timeout } from "@tests/utils/genUtils.js";
|
||||
import { completeCheckoutForm } from "@tests/utils/stripeUtils.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import chalk from "chalk";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { constructPrepaidItem } from "@/utils/scriptUtils/constructItem.js";
|
||||
import { constructProduct } from "@/utils/scriptUtils/createTestProducts.js";
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { beforeAll, describe, test } from "bun:test";
|
||||
import { type AppEnv, LegacyVersion, type Organization } from "@autumn/shared";
|
||||
import chalk from "chalk";
|
||||
import type Stripe from "stripe";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import { attachAndExpectCorrect } from "@tests/utils/expectUtils/expectAttach.js";
|
||||
import {
|
||||
@@ -9,6 +7,8 @@ import {
|
||||
expectNextCycleCorrect,
|
||||
} from "@tests/utils/expectUtils/expectScheduleUtils.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import chalk from "chalk";
|
||||
import type Stripe from "stripe";
|
||||
import type { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { constructFeatureItem } from "@/internal/products/product-items/productItemUtils.js";
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
import { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { ProductV2, Organization } from "@autumn/shared";
|
||||
import { AppEnv } from "autumn-js";
|
||||
import { expect } from "bun:test";
|
||||
import type { Organization, ProductV2 } from "@autumn/shared";
|
||||
import { expectSubToBeCorrect } from "@tests/merged/mergeUtils/expectSubCorrect.js";
|
||||
import { expectResetAtCorrect } from "@tests/utils/expectUtils/expectAttach/expectResetAtCorrect.js";
|
||||
import { expectTrialEndsAtCorrect } from "@tests/utils/expectUtils/expectAttach/expectTrialEndsAt.js";
|
||||
import { expectFeaturesCorrect } from "@tests/utils/expectUtils/expectFeaturesCorrect.js";
|
||||
import {
|
||||
expectSubItemsCorrect,
|
||||
getSubsFromCusId,
|
||||
} from "@tests/utils/expectUtils/expectSubUtils.js";
|
||||
import Stripe from "stripe";
|
||||
import { expect } from "bun:test";
|
||||
import { expectFeaturesCorrect } from "@tests/utils/expectUtils/expectFeaturesCorrect.js";
|
||||
import { expectResetAtCorrect } from "@tests/utils/expectUtils/expectAttach/expectResetAtCorrect.js";
|
||||
import { isFreeProductV2 } from "@/internal/products/productUtils/classifyProduct.js";
|
||||
import { expectTrialEndsAtCorrect } from "@tests/utils/expectUtils/expectAttach/expectTrialEndsAt.js";
|
||||
import { timeout } from "@/utils/genUtils.js";
|
||||
import type { AppEnv } from "autumn-js";
|
||||
import type Stripe from "stripe";
|
||||
import type { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import type { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { subToPeriodStartEnd } from "@/external/stripe/stripeSubUtils/convertSubUtils.js";
|
||||
import { expectSubToBeCorrect } from "@tests/merged/mergeUtils/expectSubCorrect.js";
|
||||
import { isFreeProductV2 } from "@/internal/products/productUtils/classifyProduct.js";
|
||||
import { timeout } from "@/utils/genUtils.js";
|
||||
|
||||
export const expectSubsSame = ({
|
||||
subsBefore,
|
||||
@@ -25,8 +25,8 @@ export const expectSubsSame = ({
|
||||
}) => {
|
||||
// let invoicesBefore = subsBefore.map((sub) => sub.latest_invoice);
|
||||
// let invoicesAfter = subsAfter.map((sub) => sub.latest_invoice);
|
||||
let subIdsBefore = subsBefore.map((sub) => sub.id);
|
||||
let subIdsAfter = subsAfter.map((sub) => sub.id);
|
||||
const subIdsBefore = subsBefore.map((sub) => sub.id);
|
||||
const subIdsAfter = subsAfter.map((sub) => sub.id);
|
||||
const periodsBefore = subsBefore.map((sub) => subToPeriodStartEnd({ sub }));
|
||||
const periodsAfter = subsAfter.map((sub) => subToPeriodStartEnd({ sub }));
|
||||
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
import {
|
||||
BillingInterval,
|
||||
LegacyVersion,
|
||||
type ProductV2,
|
||||
} from "@autumn/shared";
|
||||
import { beforeAll, describe, test } from "bun:test";
|
||||
import chalk from "chalk";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import { BillingInterval, LegacyVersion, type ProductV2 } from "@autumn/shared";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import { attachAndExpectCorrect } from "@tests/utils/expectUtils/expectAttach.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import chalk from "chalk";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { constructPriceItem } from "@/internal/products/product-items/productItemUtils.js";
|
||||
import { constructArrearItem } from "@/utils/scriptUtils/constructItem.js";
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import { type AppEnv, LegacyVersion, type Organization } from "@autumn/shared";
|
||||
import { beforeAll, describe, expect, test } from "bun:test";
|
||||
import chalk from "chalk";
|
||||
import type Stripe from "stripe";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import { type AppEnv, LegacyVersion, type Organization } from "@autumn/shared";
|
||||
import { attachAndExpectCorrect } from "@tests/utils/expectUtils/expectAttach.js";
|
||||
import {
|
||||
expectDowngradeCorrect,
|
||||
expectNextCycleCorrect,
|
||||
} from "@tests/utils/expectUtils/expectScheduleUtils.js";
|
||||
import { initProductsV0 } from "@/utils/scriptUtils/testUtils/initProductsV0.js";
|
||||
import { initCustomerV3 } from "@/utils/scriptUtils/testUtils/initCustomerV3.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import chalk from "chalk";
|
||||
import type Stripe from "stripe";
|
||||
import type { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { constructProduct } from "@/utils/scriptUtils/createTestProducts.js";
|
||||
import { initCustomerV3 } from "@/utils/scriptUtils/testUtils/initCustomerV3.js";
|
||||
import { initProductsV0 } from "@/utils/scriptUtils/testUtils/initProductsV0.js";
|
||||
|
||||
const testCase = "others1";
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { beforeAll, describe, expect, test } from "bun:test";
|
||||
import { LegacyVersion } from "@autumn/shared";
|
||||
import chalk from "chalk";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import { attachAndExpectCorrect } from "@tests/utils/expectUtils/expectAttach.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import chalk from "chalk";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { attachFailedPaymentMethod } from "@/external/stripe/stripeCusUtils.js";
|
||||
import { CusService } from "@/internal/customers/CusService.js";
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { type AppEnv, LegacyVersion, type Organization } from "@autumn/shared";
|
||||
import { beforeAll, describe, expect, test } from "bun:test";
|
||||
import { type AppEnv, LegacyVersion, type Organization } from "@autumn/shared";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import chalk from "chalk";
|
||||
import type Stripe from "stripe";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import { initProductsV0 } from "@/utils/scriptUtils/testUtils/initProductsV0.js";
|
||||
import { initCustomerV3 } from "@/utils/scriptUtils/testUtils/initCustomerV3.js";
|
||||
import type { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { attachFailedPaymentMethod } from "@/external/stripe/stripeCusUtils.js";
|
||||
import { CusService } from "@/internal/customers/CusService.js";
|
||||
import { constructProduct } from "@/utils/scriptUtils/createTestProducts.js";
|
||||
import { initCustomerV3 } from "@/utils/scriptUtils/testUtils/initCustomerV3.js";
|
||||
import { initProductsV0 } from "@/utils/scriptUtils/testUtils/initProductsV0.js";
|
||||
|
||||
const testCase = "others3";
|
||||
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { type AppEnv, LegacyVersion, type Organization } from "@autumn/shared";
|
||||
import { beforeAll, describe, expect, test } from "bun:test";
|
||||
import chalk from "chalk";
|
||||
import type Stripe from "stripe";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import { type AppEnv, LegacyVersion, type Organization } from "@autumn/shared";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import { expectAttachCorrect } from "@tests/utils/expectUtils/expectAttach.js";
|
||||
import { initProductsV0 } from "@/utils/scriptUtils/testUtils/initProductsV0.js";
|
||||
import { initCustomerV3 } from "@/utils/scriptUtils/testUtils/initCustomerV3.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import { getBasePrice } from "@tests/utils/testProductUtils/testProductUtils.js";
|
||||
import chalk from "chalk";
|
||||
import type Stripe from "stripe";
|
||||
import type { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { constructArrearItem } from "@/utils/scriptUtils/constructItem.js";
|
||||
import { constructProduct } from "@/utils/scriptUtils/createTestProducts.js";
|
||||
import { initCustomerV3 } from "@/utils/scriptUtils/testUtils/initCustomerV3.js";
|
||||
import { initProductsV0 } from "@/utils/scriptUtils/testUtils/initProductsV0.js";
|
||||
|
||||
export const pro = constructProduct({
|
||||
items: [constructArrearItem({ featureId: TestFeature.Words })],
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import { type AppEnv, LegacyVersion, type Organization } from "@autumn/shared";
|
||||
import { beforeAll, describe, expect, test } from "bun:test";
|
||||
import { type AppEnv, LegacyVersion, type Organization } from "@autumn/shared";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import { getBasePrice } from "@tests/utils/testProductUtils/testProductUtils.js";
|
||||
import chalk from "chalk";
|
||||
import type Stripe from "stripe";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import { initProductsV0 } from "@/utils/scriptUtils/testUtils/initProductsV0.js";
|
||||
import { initCustomerV3 } from "@/utils/scriptUtils/testUtils/initCustomerV3.js";
|
||||
import { getBasePrice } from "@tests/utils/testProductUtils/testProductUtils.js";
|
||||
import type { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import {
|
||||
@@ -14,6 +12,8 @@ import {
|
||||
constructPrepaidItem,
|
||||
} from "@/utils/scriptUtils/constructItem.js";
|
||||
import { constructProduct } from "@/utils/scriptUtils/createTestProducts.js";
|
||||
import { initCustomerV3 } from "@/utils/scriptUtils/testUtils/initCustomerV3.js";
|
||||
import { initProductsV0 } from "@/utils/scriptUtils/testUtils/initProductsV0.js";
|
||||
|
||||
export const pro = constructProduct({
|
||||
items: [
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { type AppEnv, LegacyVersion, type Organization } from "@autumn/shared";
|
||||
import { beforeAll, describe, expect, test } from "bun:test";
|
||||
import chalk from "chalk";
|
||||
import type Stripe from "stripe";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import { type AppEnv, LegacyVersion, type Organization } from "@autumn/shared";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import { attachAndExpectCorrect } from "@tests/utils/expectUtils/expectAttach.js";
|
||||
import { expectAutumnError } from "@tests/utils/expectUtils/expectErrUtils.js";
|
||||
import { initProductsV0 } from "@/utils/scriptUtils/testUtils/initProductsV0.js";
|
||||
import { initCustomerV3 } from "@/utils/scriptUtils/testUtils/initCustomerV3.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import chalk from "chalk";
|
||||
import type Stripe from "stripe";
|
||||
import type { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { constructFeatureItem } from "@/utils/scriptUtils/constructItem.js";
|
||||
import { constructProduct } from "@/utils/scriptUtils/createTestProducts.js";
|
||||
import { initCustomerV3 } from "@/utils/scriptUtils/testUtils/initCustomerV3.js";
|
||||
import { initProductsV0 } from "@/utils/scriptUtils/testUtils/initProductsV0.js";
|
||||
|
||||
export const free = constructProduct({
|
||||
items: [
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
import {
|
||||
AttachBranch,
|
||||
BillingInterval,
|
||||
LegacyVersion,
|
||||
} from "@autumn/shared";
|
||||
import { beforeAll, describe, expect, test } from "bun:test";
|
||||
import chalk from "chalk";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import { AttachBranch, BillingInterval, LegacyVersion } from "@autumn/shared";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import { attachAndExpectCorrect } from "@tests/utils/expectUtils/expectAttach.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import chalk from "chalk";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { constructPriceItem } from "@/internal/products/product-items/productItemUtils.js";
|
||||
import { nullish } from "@/utils/genUtils.js";
|
||||
|
||||
@@ -5,9 +5,6 @@ import {
|
||||
LegacyVersion,
|
||||
type Organization,
|
||||
} from "@autumn/shared";
|
||||
import chalk from "chalk";
|
||||
import { addWeeks } from "date-fns";
|
||||
import type Stripe from "stripe";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import { attachAndExpectCorrect } from "@tests/utils/expectUtils/expectAttach.js";
|
||||
import { expectAutumnError } from "@tests/utils/expectUtils/expectErrUtils.js";
|
||||
@@ -15,6 +12,9 @@ import { createProducts } from "@tests/utils/productUtils.js";
|
||||
import { advanceTestClock } from "@tests/utils/stripeUtils.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import { addPrefixToProducts } from "@tests/utils/testProductUtils/testProductUtils.js";
|
||||
import chalk from "chalk";
|
||||
import { addWeeks } from "date-fns";
|
||||
import type Stripe from "stripe";
|
||||
import type { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { timeout } from "@/utils/genUtils.js";
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { beforeAll, describe, test } from "bun:test";
|
||||
import { type AppEnv, LegacyVersion, type Organization } from "@autumn/shared";
|
||||
import chalk from "chalk";
|
||||
import { addWeeks } from "date-fns";
|
||||
import type Stripe from "stripe";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import { attachAndExpectCorrect } from "@tests/utils/expectUtils/expectAttach.js";
|
||||
import { advanceTestClock } from "@tests/utils/stripeUtils.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import chalk from "chalk";
|
||||
import { addWeeks } from "date-fns";
|
||||
import type Stripe from "stripe";
|
||||
import type { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { constructPrepaidItem } from "@/utils/scriptUtils/constructItem.js";
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { beforeAll, describe, test } from "bun:test";
|
||||
import { type AppEnv, LegacyVersion, type Organization } from "@autumn/shared";
|
||||
import chalk from "chalk";
|
||||
import { addWeeks } from "date-fns";
|
||||
import type Stripe from "stripe";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import { attachAndExpectCorrect } from "@tests/utils/expectUtils/expectAttach.js";
|
||||
import { advanceTestClock } from "@tests/utils/stripeUtils.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import chalk from "chalk";
|
||||
import { addWeeks } from "date-fns";
|
||||
import type Stripe from "stripe";
|
||||
import type { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { constructPrepaidItem } from "@/utils/scriptUtils/constructItem.js";
|
||||
|
||||
@@ -5,12 +5,12 @@ import {
|
||||
FreeTrialDuration,
|
||||
ProductItemInterval,
|
||||
} from "@autumn/shared";
|
||||
import chalk from "chalk";
|
||||
import { addDays } from "date-fns";
|
||||
import type Stripe from "stripe";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import { expectCustomerV0Correct } from "@tests/utils/expectUtils/expectCustomerV0Correct.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import chalk from "chalk";
|
||||
import { addDays } from "date-fns";
|
||||
import type Stripe from "stripe";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { constructPriceItem } from "@/internal/products/product-items/productItemUtils.js";
|
||||
import { constructFeatureItem } from "@/utils/scriptUtils/constructItem.js";
|
||||
|
||||
@@ -6,13 +6,13 @@ import {
|
||||
type Customer,
|
||||
ProductItemInterval,
|
||||
} from "@autumn/shared";
|
||||
import chalk from "chalk";
|
||||
import type Stripe from "stripe";
|
||||
import { AutumnCli } from "@tests/cli/AutumnCli.js";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import { expectCustomerV0Correct } from "@tests/utils/expectUtils/expectCustomerV0Correct.js";
|
||||
import { expectAutumnError } from "@tests/utils/expectUtils/expectErrUtils.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import chalk from "chalk";
|
||||
import type Stripe from "stripe";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import {
|
||||
attachFailedPaymentMethod,
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { beforeAll, describe, expect, test } from "bun:test";
|
||||
import { ApiVersion, type CheckResponseV2, ResetInterval } from "@autumn/shared";
|
||||
import {
|
||||
ApiVersion,
|
||||
type CheckResponseV2,
|
||||
ResetInterval,
|
||||
} from "@autumn/shared";
|
||||
import { TestFeature } from "@tests/setup/v2Features.js";
|
||||
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
||||
import chalk from "chalk";
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user