fix: lua scripts loading for trigger.dev

This commit is contained in:
John Yeo
2026-04-10 16:17:46 +01:00
parent e32e9e0be5
commit 0b5b151a3e
10 changed files with 84 additions and 325 deletions

View File

@@ -356,7 +356,7 @@
"pg": "^8.13.1",
"pino": "^9.6.0",
"pino-pretty": "^13.0.0",
"postgres": "^3.4.7",
"postgres": "catalog:",
"posthog-node": "^5.20.0",
"puppeteer-core": "^24.14.0",
"qs": "^6.14.0",
@@ -548,6 +548,7 @@
"decimal.js": "10.5.0",
"drizzle-kit": "^0.31.1",
"drizzle-orm": "0.43.1",
"postgres": "3.4.7",
"stripe": "19.3.0-beta.1",
"vite": "7.3.2",
"vite-tsconfig-paths": "6.1.1",
@@ -4437,7 +4438,11 @@
"postcss-values-parser": ["postcss-values-parser@6.0.2", "", { "dependencies": { "color-name": "^1.1.4", "is-url-superb": "^4.0.0", "quote-unquote": "^1.0.0" }, "peerDependencies": { "postcss": "^8.2.9" } }, "sha512-YLJpK0N1brcNJrs9WatuJFtHaV9q5aAOj+S4DI5S7jgHlRfm0PIbDCAFRYMQD5SHq7Fy6xsDhyutgS0QOAs0qw=="],
<<<<<<< Updated upstream
"postgres": ["postgres@3.4.9", "", {}, "sha512-GD3qdB0x1z9xgFI6cdRD6xu2Sp2WCOEoe3mtnyB5Ee0XrrL5Pe+e4CCnJrRMnL1zYtRDZmQQVbvOttLnKDLnaw=="],
=======
"postgres": ["postgres@3.4.7", "", {}, "sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw=="],
>>>>>>> Stashed changes
"postgres-array": ["postgres-array@2.0.0", "", {}, "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="],

View File

@@ -1,6 +1,9 @@
# Preload env override for all bun runs (from workspace root)
preload = ["./scripts/preload-env.ts"]
[loader]
".lua" = "text"
[test]
preload = ["./scripts/preload-env.ts", "./server/tests/setup-integration-tests.ts"]
timeout = 0

View File

@@ -33,6 +33,7 @@
"@orpc/openapi-client": "^1.0.0",
"@tanstack/react-query": "5.85.6",
"decimal.js": "10.5.0",
"postgres": "3.4.7",
"vite": "7.3.2",
"vite-tsconfig-paths": "6.1.1"
}

View File

@@ -1,6 +1,9 @@
# Server-specific config (for run.sh which executes from server/)
preload = ["../scripts/preload-env.ts"]
[loader]
".lua" = "text"
[test]
preload = ["../scripts/preload-env.ts", "./tests/setup-integration-tests.ts"]
timeout = 0

View File

@@ -120,7 +120,7 @@
"pg": "^8.13.1",
"pino": "^9.6.0",
"pino-pretty": "^13.0.0",
"postgres": "^3.4.7",
"postgres": "catalog:",
"posthog-node": "^5.20.0",
"puppeteer-core": "^24.14.0",
"qs": "^6.14.0",

4
server/src/_luaScripts/lua.d.ts vendored Normal file
View File

@@ -0,0 +1,4 @@
declare module "*.lua" {
const content: string;
export default content;
}

View File

@@ -1,26 +1,21 @@
import { readFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import {
CACHE_CUSTOMER_VERSION,
CACHE_GUARD_TTL_MS,
CACHE_TTL_SECONDS,
} from "./cacheConfig.js";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// ============================================================================
// SHARED LUA FUNCTIONS
// SHARED LUA FUNCTIONS (imported as text — works with both Bun and esbuild)
// ============================================================================
// Load cache key utilities and inject version constants
const CACHE_KEY_UTILS_RAW = readFileSync(
join(__dirname, "luaUtils/cacheKeyUtils.lua"),
"utf-8",
);
import CACHE_KEY_UTILS_RAW from "./luaUtils/cacheKeyUtils.lua";
import CACHE_BALANCE_UTILS from "./luaUtils/storeBalances.lua";
import LOAD_BALANCES from "./luaUtils/loadBalances.lua";
import FILTER_BALANCE_UTILS from "./luaUtils/filterBalanceUtils.lua";
import ACCUMULATOR_UTILS from "./luaUtils/accumulatorUtils.lua";
import SUBSCRIPTION_UTILS from "./luaUtils/apiSubscriptionUtils.lua";
import GET_CUSTOMER_ENTITY_UTILS from "./luaUtils/getCustomerEntityUtils.lua";
// Inject cache version and TTL constants into cache key utils
const CACHE_KEY_UTILS = CACHE_KEY_UTILS_RAW.replace(
"{CUSTOMER_VERSION}",
CACHE_CUSTOMER_VERSION,
@@ -28,158 +23,49 @@ const CACHE_KEY_UTILS = CACHE_KEY_UTILS_RAW.replace(
.replace("{TTL_SECONDS}", CACHE_TTL_SECONDS.toString())
.replace("{GUARD_TTL_MS}", CACHE_GUARD_TTL_MS.toString());
// Load balance storage utilities
const CACHE_BALANCE_UTILS = readFileSync(
join(__dirname, "luaUtils/storeBalances.lua"),
"utf-8",
);
// Load shared balance loading function (used by customer, entity, and deduction scripts)
const LOAD_BALANCES = readFileSync(
join(__dirname, "luaUtils/loadBalances.lua"),
"utf-8",
);
// Load balance filter utilities (used by deduction scripts for filtered balance operations)
const FILTER_BALANCE_UTILS = readFileSync(
join(__dirname, "luaUtils/filterBalanceUtils.lua"),
"utf-8",
);
// Load accumulator utilities (used by deduction scripts for collecting deltas/state changes)
const ACCUMULATOR_UTILS = readFileSync(
join(__dirname, "luaUtils/accumulatorUtils.lua"),
"utf-8",
);
// Load shared subscription utilities (used by customer and entity scripts)
const SUBSCRIPTION_UTILS = readFileSync(
join(__dirname, "luaUtils/apiSubscriptionUtils.lua"),
"utf-8",
);
// Load shared customer/entity getter utilities
const GET_CUSTOMER_ENTITY_UTILS = readFileSync(
join(__dirname, "luaUtils/getCustomerEntityUtils.lua"),
"utf-8",
);
// ============================================================================
// CUSTOMER SCRIPTS
// ============================================================================
// Load shared validation function
const CHECK_CACHE_EXISTS = readFileSync(
join(__dirname, "cusLuaScripts/checkCacheExists.lua"),
"utf-8",
);
import CHECK_CACHE_EXISTS from "./cusLuaScripts/checkCacheExists.lua";
import getCustomerScript from "./cusLuaScripts/getCustomer.lua";
import setCustomerScript from "./cusLuaScripts/setCustomer.lua";
import setSubscriptionsScript from "./cusLuaScripts/setSubscriptions.lua";
import setCustomerDetailsScript from "./cusLuaScripts/setCustomerDetails.lua";
import setInvoicesScript from "./cusLuaScripts/setInvoices.lua";
import setGrantedBalanceScript from "./cusLuaScripts/setGrantedBalance.lua";
import deleteCustomerScript from "./cusLuaScripts/deleteCustomer.lua";
import batchDeleteCustomersScript from "./cusLuaScripts/batchDeleteCustomers.lua";
// Prepend cache key utils, loadBalances, subscription utils, and getter utils to GET_CUSTOMER_SCRIPT
const getCustomerScript = readFileSync(
join(__dirname, "cusLuaScripts/getCustomer.lua"),
"utf-8",
);
export const GET_CUSTOMER_SCRIPT = `${CACHE_KEY_UTILS}\n${LOAD_BALANCES}\n${SUBSCRIPTION_UTILS}\n${GET_CUSTOMER_ENTITY_UTILS}\n${getCustomerScript}`;
// Prepend cache key utils and validation function to SET_CUSTOMER_SCRIPT
const setCustomerScript = readFileSync(
join(__dirname, "cusLuaScripts/setCustomer.lua"),
"utf-8",
);
export const SET_CUSTOMER_SCRIPT = `${CACHE_KEY_UTILS}\n${CACHE_BALANCE_UTILS}\n${CHECK_CACHE_EXISTS}\n${setCustomerScript}`;
// Prepend cache key utils to SET_SUBSCRIPTIONS_SCRIPT
const setSubscriptionsScript = readFileSync(
join(__dirname, "cusLuaScripts/setSubscriptions.lua"),
"utf-8",
);
export const SET_SUBSCRIPTIONS_SCRIPT = `${CACHE_KEY_UTILS}\n${setSubscriptionsScript}`;
// Legacy export for backwards compatibility
const SET_CUSTOMER_PRODUCTS_SCRIPT = SET_SUBSCRIPTIONS_SCRIPT;
// Prepend cache key utils to SET_CUSTOMER_DETAILS_SCRIPT
const setCustomerDetailsScript = readFileSync(
join(__dirname, "cusLuaScripts/setCustomerDetails.lua"),
"utf-8",
);
export const SET_CUSTOMER_DETAILS_SCRIPT = `${CACHE_KEY_UTILS}\n${setCustomerDetailsScript}`;
// Prepend cache key utils to SET_INVOICES_SCRIPT
const setInvoicesScript = readFileSync(
join(__dirname, "cusLuaScripts/setInvoices.lua"),
"utf-8",
);
export const SET_INVOICES_SCRIPT = `${CACHE_KEY_UTILS}\n${setInvoicesScript}`;
// Prepend cache key utils to SET_GRANTED_BALANCE_SCRIPT
const setGrantedBalanceScript = readFileSync(
join(__dirname, "cusLuaScripts/setGrantedBalance.lua"),
"utf-8",
);
export const SET_GRANTED_BALANCE_SCRIPT = `${CACHE_KEY_UTILS}\n${setGrantedBalanceScript}`;
// Prepend cache key utils to DELETE_CUSTOMER_SCRIPT
const deleteCustomerScript = readFileSync(
join(__dirname, "cusLuaScripts/deleteCustomer.lua"),
"utf-8",
);
export const DELETE_CUSTOMER_SCRIPT = `${CACHE_KEY_UTILS}\n${deleteCustomerScript}`;
// Prepend cache key utils to BATCH_DELETE_CUSTOMERS_SCRIPT
const batchDeleteCustomersScript = readFileSync(
join(__dirname, "cusLuaScripts/batchDeleteCustomers.lua"),
"utf-8",
);
export const BATCH_DELETE_CUSTOMERS_SCRIPT = `${CACHE_KEY_UTILS}\n${batchDeleteCustomersScript}`;
// ============================================================================
// ENTITY SCRIPTS
// ============================================================================
// Load shared validation function
const CHECK_ENTITY_CACHE_EXISTS = readFileSync(
join(__dirname, "entityLuaScripts/checkEntityCacheExists.lua"),
"utf-8",
);
import CHECK_ENTITY_CACHE_EXISTS from "./entityLuaScripts/checkEntityCacheExists.lua";
import getEntityScript from "./entityLuaScripts/getEntity.lua";
import setEntityScript from "./entityLuaScripts/setEntity.lua";
import setEntitiesBatchScript from "./entityLuaScripts/setEntitiesBatch.lua";
import setEntityProductsScript from "./entityLuaScripts/setEntityProducts.lua";
// Prepend cache key utils, loadBalances, subscription utils, and getter utils to GET_ENTITY_SCRIPT
const getEntityScript = readFileSync(
join(__dirname, "entityLuaScripts/getEntity.lua"),
"utf-8",
);
export const GET_ENTITY_SCRIPT = `${CACHE_KEY_UTILS}\n${LOAD_BALANCES}\n${SUBSCRIPTION_UTILS}\n${GET_CUSTOMER_ENTITY_UTILS}\n${getEntityScript}`;
// Prepend cache key utils and validation function to SET_ENTITY_SCRIPT
const setEntityScript = readFileSync(
join(__dirname, "entityLuaScripts/setEntity.lua"),
"utf-8",
);
const SET_ENTITY_SCRIPT = `${CACHE_KEY_UTILS}\n${CACHE_BALANCE_UTILS}\n${CHECK_ENTITY_CACHE_EXISTS}\n${setEntityScript}`;
// Prepend cache key utils and balance utils to SET_ENTITIES_BATCH_SCRIPT
const setEntitiesBatchScript = readFileSync(
join(__dirname, "entityLuaScripts/setEntitiesBatch.lua"),
"utf-8",
);
export const SET_ENTITIES_BATCH_SCRIPT = `${CACHE_KEY_UTILS}\n${CACHE_BALANCE_UTILS}\n${setEntitiesBatchScript}`;
// Prepend cache key utils to SET_ENTITY_PRODUCTS_SCRIPT
const setEntityProductsScript = readFileSync(
join(__dirname, "entityLuaScripts/setEntityProducts.lua"),
"utf-8",
);
export const SET_ENTITY_PRODUCTS_SCRIPT = `${CACHE_KEY_UTILS}\n${setEntityProductsScript}`;
// ============================================================================
// DEDUCTION SCRIPTS
// ============================================================================
// Load batchDeduction script
const batchDeduction = readFileSync(
join(__dirname, "deductionLuaScripts/batchDeduction.lua"),
"utf-8",
);
import batchDeduction from "./deductionLuaScripts/batchDeduction.lua";
export function getBatchDeductionScript(): string {
return `${CACHE_KEY_UTILS}\n${LOAD_BALANCES}\n${FILTER_BALANCE_UTILS}\n${ACCUMULATOR_UTILS}\n${SUBSCRIPTION_UTILS}\n${GET_CUSTOMER_ENTITY_UTILS}\n${batchDeduction}`;

View File

@@ -1,111 +1,40 @@
import { readFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { FULL_CUSTOMER_CACHE_VERSION } from "@/internal/customers/cusUtils/fullCustomerCacheUtils/fullCustomerCacheConfig.js";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Path to script folders
const DEDUCT_DIR = join(__dirname, "deductFromCustomerEntitlements");
const DEDUCTION_DIR = join(__dirname, "deduction");
const LOCK_DIR = join(DEDUCTION_DIR, "lock");
const DELETE_CACHE_DIR = join(__dirname, "deleteFullCustomerCache");
const RESET_DIR = join(__dirname, "resetCustomerEntitlements");
const UPDATE_DIR = join(__dirname, "updateCustomerEntitlements");
// ============================================================================
// HELPER MODULES
// HELPER MODULES (imported as text — works with both Bun and esbuild)
// ============================================================================
const FULL_CUSTOMER_DIR = join(__dirname, "fullCustomer");
const LUA_UTILS = readFileSync(join(DEDUCT_DIR, "luaUtils.lua"), "utf-8");
const FULL_CUSTOMER_UTILS = readFileSync(
join(FULL_CUSTOMER_DIR, "fullCustomerUtils.lua"),
"utf-8",
);
const READ_BALANCES = readFileSync(
join(DEDUCT_DIR, "readBalances.lua"),
"utf-8",
);
const CONTEXT_UTILS = readFileSync(
join(DEDUCT_DIR, "contextUtils.lua"),
"utf-8",
);
const GET_TOTAL_BALANCE = readFileSync(
join(DEDUCT_DIR, "getTotalBalance.lua"),
"utf-8",
);
const DEDUCT_FROM_ROLLOVERS = readFileSync(
join(DEDUCT_DIR, "deductFromRollovers.lua"),
"utf-8",
);
const DEDUCT_FROM_MAIN_BALANCE = readFileSync(
join(DEDUCT_DIR, "deductFromMainBalance.lua"),
"utf-8",
);
const RUN_DEDUCTION_ON_CONTEXT = readFileSync(
join(DEDUCT_DIR, "runDeductionOnContext.lua"),
"utf-8",
);
const SPEND_LIMIT_UTILS = readFileSync(
join(DEDUCT_DIR, "spendLimitUtils.lua"),
"utf-8",
);
const MUTATION_ITEM_UTILS = readFileSync(
join(DEDUCTION_DIR, "mutationItemUtils.lua"),
"utf-8",
);
const LOCK_RECEIPT_UTILS = readFileSync(
join(LOCK_DIR, "lockReceipt.lua"),
"utf-8",
);
const LOCK_STATE_UTILS = readFileSync(
join(LOCK_DIR, "lockStateUtils.lua"),
"utf-8",
);
const LOCK_UNWIND_UTILS = readFileSync(
join(LOCK_DIR, "unwindLockUtils.lua"),
"utf-8",
);
import LUA_UTILS from "./deductFromCustomerEntitlements/luaUtils.lua";
import FULL_CUSTOMER_UTILS from "./fullCustomer/fullCustomerUtils.lua";
import READ_BALANCES from "./deductFromCustomerEntitlements/readBalances.lua";
import CONTEXT_UTILS from "./deductFromCustomerEntitlements/contextUtils.lua";
import GET_TOTAL_BALANCE from "./deductFromCustomerEntitlements/getTotalBalance.lua";
import DEDUCT_FROM_ROLLOVERS from "./deductFromCustomerEntitlements/deductFromRollovers.lua";
import DEDUCT_FROM_MAIN_BALANCE from "./deductFromCustomerEntitlements/deductFromMainBalance.lua";
import RUN_DEDUCTION_ON_CONTEXT from "./deductFromCustomerEntitlements/runDeductionOnContext.lua";
import SPEND_LIMIT_UTILS from "./deductFromCustomerEntitlements/spendLimitUtils.lua";
import MUTATION_ITEM_UTILS from "./deduction/mutationItemUtils.lua";
import LOCK_RECEIPT_UTILS from "./deduction/lock/lockReceipt.lua";
import LOCK_STATE_UTILS from "./deduction/lock/lockStateUtils.lua";
import LOCK_UNWIND_UTILS from "./deduction/lock/unwindLockUtils.lua";
// ============================================================================
// FULL CUSTOMER KEY BUILDER LUA (version interpolated from TS config)
// ============================================================================
const FULL_CUSTOMER_KEY_BUILDERS = readFileSync(
join(__dirname, "fullCustomerKeyBuilders.lua"),
"utf-8",
).replaceAll("__FULL_CUSTOMER_CACHE_VERSION__", FULL_CUSTOMER_CACHE_VERSION);
import FULL_CUSTOMER_KEY_BUILDERS_RAW from "./fullCustomerKeyBuilders.lua";
const FULL_CUSTOMER_KEY_BUILDERS = FULL_CUSTOMER_KEY_BUILDERS_RAW.replaceAll(
"__FULL_CUSTOMER_CACHE_VERSION__",
FULL_CUSTOMER_CACHE_VERSION,
);
// ============================================================================
// MAIN SCRIPT
// ============================================================================
const mainScript = readFileSync(
join(DEDUCT_DIR, "deductFromCustomerEntitlements.lua"),
"utf-8",
);
import mainScript from "./deductFromCustomerEntitlements/deductFromCustomerEntitlements.lua";
/**
* Lua script for deducting from customer entitlements in Redis.
* Uses JSON.NUMINCRBY for atomic incremental updates to prevent race conditions.
* Composed from helper modules via string interpolation.
* Supports both positive deductions and negative refunds.
*/
export const DEDUCT_FROM_CUSTOMER_ENTITLEMENTS_SCRIPT = `${FULL_CUSTOMER_KEY_BUILDERS}
${LUA_UTILS}
${FULL_CUSTOMER_UTILS}
@@ -122,16 +51,8 @@ ${LOCK_STATE_UTILS}
${LOCK_UNWIND_UTILS}
${mainScript}`;
const claimLockReceiptMainScript = readFileSync(
join(LOCK_DIR, "claimLockReceipt.lua"),
"utf-8",
);
import claimLockReceiptMainScript from "./deduction/lock/claimLockReceipt.lua";
/**
* Atomically claims a lock receipt by transitioning status: pending → processing.
* KEYS[1]: lock_receipt_key
* Returns nil on success, or an error code string if not claimable.
*/
export const CLAIM_LOCK_RECEIPT_SCRIPT = `${LUA_UTILS}
${LOCK_RECEIPT_UTILS}
${LOCK_STATE_UTILS}
@@ -141,27 +62,13 @@ ${claimLockReceiptMainScript}`;
// DELETE FULL CUSTOMER CACHE SCRIPTS
// ============================================================================
const deleteFullCustomerCacheScript = readFileSync(
join(DELETE_CACHE_DIR, "deleteFullCustomerCache.lua"),
"utf-8",
);
import deleteFullCustomerCacheScript from "./deleteFullCustomerCache/deleteFullCustomerCache.lua";
/**
* Lua script for deleting a single FullCustomer cache from Redis.
* Builds all keys internally from orgId/env/customerId.
*/
export const DELETE_FULL_CUSTOMER_CACHE_SCRIPT = `${FULL_CUSTOMER_KEY_BUILDERS}
${deleteFullCustomerCacheScript}`;
const setFullCustomerCacheScript = readFileSync(
join(DELETE_CACHE_DIR, "setFullCustomerCache.lua"),
"utf-8",
);
import setFullCustomerCacheScript from "./deleteFullCustomerCache/setFullCustomerCache.lua";
/**
* Lua script for setting a FullCustomer cache in Redis.
* Builds all keys internally from orgId/env/customerId.
*/
export const SET_FULL_CUSTOMER_CACHE_SCRIPT = `${FULL_CUSTOMER_KEY_BUILDERS}
${setFullCustomerCacheScript}`;
@@ -169,14 +76,9 @@ ${setFullCustomerCacheScript}`;
// RESET CUSTOMER ENTITLEMENTS SCRIPT (deprecated — kept for backward compat)
// ============================================================================
const resetMainScript = readFileSync(
join(RESET_DIR, "resetCustomerEntitlements.lua"),
"utf-8",
);
import resetMainScript from "./resetCustomerEntitlements/resetCustomerEntitlements.lua";
/**
* @deprecated Use UPDATE_CUSTOMER_ENTITLEMENTS_SCRIPT instead.
*/
/** @deprecated Use UPDATE_CUSTOMER_ENTITLEMENTS_SCRIPT instead. */
export const RESET_CUSTOMER_ENTITLEMENTS_SCRIPT = `${LUA_UTILS}
${FULL_CUSTOMER_UTILS}
${resetMainScript}`;
@@ -185,16 +87,8 @@ ${resetMainScript}`;
// UPDATE CUSTOMER ENTITLEMENTS SCRIPT (unified reset + deduction cache update)
// ============================================================================
const updateMainScript = readFileSync(
join(UPDATE_DIR, "updateCustomerEntitlements.lua"),
"utf-8",
);
import updateMainScript from "./updateCustomerEntitlements/updateCustomerEntitlements.lua";
/**
* Unified Lua script for atomically updating cusEnt fields in the cached
* FullCustomer. Handles both reset and deduction cache updates — both are
* "apply absolute values to customer entitlements in the Redis cache."
*/
export const UPDATE_CUSTOMER_ENTITLEMENTS_SCRIPT = `${LUA_UTILS}
${FULL_CUSTOMER_UTILS}
${updateMainScript}`;
@@ -203,17 +97,8 @@ ${updateMainScript}`;
// ADJUST CUSTOMER ENTITLEMENT BALANCE SCRIPT
// ============================================================================
const CUS_ENT_DIR = join(__dirname, "customerEntitlements");
import adjustBalanceMainScript from "./customerEntitlements/adjustCustomerEntitlementBalance.lua";
const adjustBalanceMainScript = readFileSync(
join(CUS_ENT_DIR, "adjustCustomerEntitlementBalance.lua"),
"utf-8",
);
/**
* Lua script for atomically incrementing a cusEnt balance in the cached
* FullCustomer via JSON.NUMINCRBY. Safe with concurrent deductions.
*/
export const ADJUST_CUSTOMER_ENTITLEMENT_BALANCE_SCRIPT = `${LUA_UTILS}
${FULL_CUSTOMER_UTILS}
${adjustBalanceMainScript}`;
@@ -222,55 +107,23 @@ ${adjustBalanceMainScript}`;
// CUSTOMER SCRIPTS (top-level customer fields, entities, invoices)
// ============================================================================
const CUSTOMER_DIR = join(__dirname, "customers");
import updateCustomerDataMainScript from "./customers/updateCustomerData.lua";
const updateCustomerDataMainScript = readFileSync(
join(CUSTOMER_DIR, "updateCustomerData.lua"),
"utf-8",
);
/** Atomically update top-level customer fields (name, email, metadata, etc.). */
export const UPDATE_CUSTOMER_DATA_SCRIPT = `${LUA_UTILS}
${updateCustomerDataMainScript}`;
/**
* Atomically append an entity to the customer's entities array.
* CRDT-safe: JSON.ARRAPPEND uses merge conflict resolution in Active-Active.
*/
export const APPEND_ENTITY_TO_CUSTOMER_SCRIPT = readFileSync(
join(CUSTOMER_DIR, "appendEntityToCustomer.lua"),
"utf-8",
);
import APPEND_ENTITY_TO_CUSTOMER_SCRIPT_RAW from "./customers/appendEntityToCustomer.lua";
export const APPEND_ENTITY_TO_CUSTOMER_SCRIPT = APPEND_ENTITY_TO_CUSTOMER_SCRIPT_RAW;
/**
* Atomically update specific fields on an entity inside the cached FullCustomer.
*/
export const UPDATE_ENTITY_IN_CUSTOMER_SCRIPT = readFileSync(
join(CUSTOMER_DIR, "updateEntityInCustomer.lua"),
"utf-8",
);
import UPDATE_ENTITY_IN_CUSTOMER_SCRIPT_RAW from "./customers/updateEntityInCustomer.lua";
export const UPDATE_ENTITY_IN_CUSTOMER_SCRIPT = UPDATE_ENTITY_IN_CUSTOMER_SCRIPT_RAW;
/**
* Atomically upsert an invoice in the customer's invoices array.
* Matches by stripe_id — replaces if found, appends if not.
* CRDT-safe: JSON.ARRAPPEND uses merge, JSON.SET uses update-vs-update.
*/
export const UPSERT_INVOICE_IN_CUSTOMER_SCRIPT = readFileSync(
join(CUSTOMER_DIR, "upsertInvoice.lua"),
"utf-8",
);
import UPSERT_INVOICE_IN_CUSTOMER_SCRIPT_RAW from "./customers/upsertInvoice.lua";
export const UPSERT_INVOICE_IN_CUSTOMER_SCRIPT = UPSERT_INVOICE_IN_CUSTOMER_SCRIPT_RAW;
// ============================================================================
// CUSTOMER PRODUCT SCRIPTS
// ============================================================================
const CUS_PRODUCT_DIR = join(__dirname, "customerProducts");
/**
* Atomically update specific fields on a cusProduct in the cached FullCustomer.
* CRDT-safe: JSON.SET on specific paths uses "update vs update" resolution.
*/
export const UPDATE_CUSTOMER_PRODUCT_SCRIPT = readFileSync(
join(CUS_PRODUCT_DIR, "updateCustomerProduct.lua"),
"utf-8",
);
import UPDATE_CUSTOMER_PRODUCT_SCRIPT_RAW from "./customerProducts/updateCustomerProduct.lua";
export const UPDATE_CUSTOMER_PRODUCT_SCRIPT = UPDATE_CUSTOMER_PRODUCT_SCRIPT_RAW;

View File

@@ -1,7 +1,9 @@
import { createHash } from "node:crypto";
import type { AppEnv } from "@autumn/shared";
const getSecretFingerprint = ({ secret }: { secret: string }) => {
return Bun.hash(secret).toString();
if (typeof globalThis.Bun !== "undefined") return Bun.hash(secret).toString();
return createHash("sha256").update(secret).digest("hex").slice(0, 16);
};
/** Builds cache key for Stripe clients created via org secret key. */

View File

@@ -63,7 +63,9 @@ export const entToOptions = ({
options: FeatureOptions[];
}) => {
return options.find(
(option) => option.internal_feature_id === ent.internal_feature_id,
(option) =>
option.internal_feature_id === ent.internal_feature_id ||
(ent.feature_id && option.feature_id === ent.feature_id),
);
};