@chaaskit/server 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/LICENSE +21 -0
  2. package/dist/api/admin.js +211 -0
  3. package/dist/api/admin.js.map +1 -1
  4. package/dist/api/auth.js +91 -6
  5. package/dist/api/auth.js.map +1 -1
  6. package/dist/api/chat.js +51 -3
  7. package/dist/api/chat.js.map +1 -1
  8. package/dist/api/config.js +25 -14
  9. package/dist/api/config.js.map +1 -1
  10. package/dist/api/credits.js +122 -0
  11. package/dist/api/credits.js.map +1 -0
  12. package/dist/api/payments.js +94 -11
  13. package/dist/api/payments.js.map +1 -1
  14. package/dist/api/user.js +3 -4
  15. package/dist/api/user.js.map +1 -1
  16. package/dist/app.js +15 -6
  17. package/dist/app.js.map +1 -1
  18. package/dist/config/loader.js +62 -2
  19. package/dist/config/loader.js.map +1 -1
  20. package/dist/extensions/loader.js +1 -0
  21. package/dist/extensions/loader.js.map +1 -1
  22. package/dist/index.js +2 -0
  23. package/dist/index.js.map +1 -1
  24. package/dist/middleware/apiKeyAuth.js +2 -1
  25. package/dist/middleware/apiKeyAuth.js.map +1 -1
  26. package/dist/middleware/auth.js +29 -5
  27. package/dist/middleware/auth.js.map +1 -1
  28. package/dist/queue/cli.js +0 -0
  29. package/dist/secrets/index.js +147 -0
  30. package/dist/secrets/index.js.map +1 -0
  31. package/dist/services/credits.js +206 -0
  32. package/dist/services/credits.js.map +1 -0
  33. package/dist/services/email/templates.js +116 -0
  34. package/dist/services/email/templates.js.map +1 -1
  35. package/dist/services/metering.js +24 -0
  36. package/dist/services/metering.js.map +1 -0
  37. package/dist/services/referrals.js +133 -0
  38. package/dist/services/referrals.js.map +1 -0
  39. package/dist/services/usage.js +42 -29
  40. package/dist/services/usage.js.map +1 -1
  41. package/dist/services/waitlist.js +142 -0
  42. package/dist/services/waitlist.js.map +1 -0
  43. package/package.json +26 -12
  44. package/dist/api/upload.js +0 -57
  45. package/dist/api/upload.js.map +0 -1
  46. package/dist/ssr/build.js +0 -90
  47. package/dist/ssr/build.js.map +0 -1
  48. package/dist/ssr/components/SSRMessageList.js +0 -120
  49. package/dist/ssr/components/SSRMessageList.js.map +0 -1
  50. package/dist/ssr/entry.client.js +0 -8
  51. package/dist/ssr/entry.client.js.map +0 -1
  52. package/dist/ssr/entry.server.js +0 -71
  53. package/dist/ssr/entry.server.js.map +0 -1
  54. package/dist/ssr/handler.js +0 -51
  55. package/dist/ssr/handler.js.map +0 -1
  56. package/dist/ssr/root.js +0 -184
  57. package/dist/ssr/root.js.map +0 -1
  58. package/dist/ssr/routes/login.js +0 -140
  59. package/dist/ssr/routes/login.js.map +0 -1
  60. package/dist/ssr/routes/pricing.js +0 -195
  61. package/dist/ssr/routes/pricing.js.map +0 -1
  62. package/dist/ssr/routes/privacy.js +0 -39
  63. package/dist/ssr/routes/privacy.js.map +0 -1
  64. package/dist/ssr/routes/register.js +0 -148
  65. package/dist/ssr/routes/register.js.map +0 -1
  66. package/dist/ssr/routes/shared.$shareId.js +0 -153
  67. package/dist/ssr/routes/shared.$shareId.js.map +0 -1
  68. package/dist/ssr/routes/terms.js +0 -39
  69. package/dist/ssr/routes/terms.js.map +0 -1
@@ -3,12 +3,23 @@ import { db } from '@chaaskit/db';
3
3
  import { AppError } from './errorHandler.js';
4
4
  import { HTTP_STATUS } from '@chaaskit/shared';
5
5
  import { getConfig } from '../config/loader.js';
6
- const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key';
6
+ const JWT_SECRET = process.env.JWT_SECRET;
7
+ const DEV_FALLBACK_SECRET = 'dev-insecure-secret';
8
+ function getJwtSecret() {
9
+ if (JWT_SECRET) {
10
+ return JWT_SECRET;
11
+ }
12
+ if (process.env.NODE_ENV === 'production') {
13
+ throw new Error('JWT_SECRET is required in production');
14
+ }
15
+ console.warn('[Auth] JWT_SECRET is not set; using insecure dev fallback');
16
+ return DEV_FALLBACK_SECRET;
17
+ }
7
18
  export function generateToken(userId, email) {
8
- return jwt.sign({ userId, email }, JWT_SECRET, { expiresIn: '7d' });
19
+ return jwt.sign({ userId, email }, getJwtSecret(), { expiresIn: '7d' });
9
20
  }
10
21
  export function verifyToken(token) {
11
- return jwt.verify(token, JWT_SECRET);
22
+ return jwt.verify(token, getJwtSecret());
12
23
  }
13
24
  export async function requireAuth(req, res, next) {
14
25
  try {
@@ -51,7 +62,13 @@ export async function requireAuth(req, res, next) {
51
62
  if (!user) {
52
63
  throw new AppError(HTTP_STATUS.UNAUTHORIZED, 'User not found');
53
64
  }
54
- req.user = user;
65
+ // Compute isAdmin from both database flag and config email list
66
+ const adminEmails = config.admin?.emails || [];
67
+ const isConfigAdmin = adminEmails.some((email) => email.toLowerCase() === user.email.toLowerCase());
68
+ req.user = {
69
+ ...user,
70
+ isAdmin: user.isAdmin || isConfigAdmin,
71
+ };
55
72
  next();
56
73
  }
57
74
  catch (error) {
@@ -95,7 +112,14 @@ export async function optionalAuth(req, res, next) {
95
112
  },
96
113
  });
97
114
  if (user) {
98
- req.user = user;
115
+ // Compute isAdmin from both database flag and config email list
116
+ const config = getConfig();
117
+ const adminEmails = config.admin?.emails || [];
118
+ const isConfigAdmin = adminEmails.some((email) => email.toLowerCase() === user.email.toLowerCase());
119
+ req.user = {
120
+ ...user,
121
+ isAdmin: user.isAdmin || isConfigAdmin,
122
+ };
99
123
  }
100
124
  next();
101
125
  }
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"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"}
package/dist/queue/cli.js CHANGED
File without changes
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Secrets Provider System
3
+ *
4
+ * Loads secrets from various backends and sets them as environment variables.
5
+ * Must be called BEFORE any modules that need these secrets are imported.
6
+ *
7
+ * Provider selection via environment variables:
8
+ * SECRETS_PROVIDER=env (default) - secrets already in env vars
9
+ * SECRETS_PROVIDER=aws-secrets-manager - load from AWS Secrets Manager
10
+ *
11
+ * Provider-specific configuration:
12
+ * AWS Secrets Manager:
13
+ * AWS_SECRET_ARN - ARN of the secret to load
14
+ * AWS_REGION - Region (optional, defaults to 'us-west-2')
15
+ */
16
+ /**
17
+ * Environment variable provider - no-op since secrets are already in env
18
+ */
19
+ class EnvSecretProvider {
20
+ name = 'env';
21
+ async loadSecrets() {
22
+ console.log('[Secrets] Using environment variables (no secret provider configured)');
23
+ }
24
+ }
25
+ /**
26
+ * AWS Secrets Manager provider
27
+ * Loads secrets from AWS Secrets Manager and sets them as environment variables
28
+ */
29
+ class AwsSecretsManagerProvider {
30
+ name = 'aws-secrets-manager';
31
+ secretArn;
32
+ region;
33
+ constructor() {
34
+ const secretArn = process.env.AWS_SECRET_ARN;
35
+ if (!secretArn) {
36
+ throw new Error('AWS_SECRET_ARN environment variable is required for aws-secrets-manager provider');
37
+ }
38
+ this.secretArn = secretArn;
39
+ this.region = process.env.AWS_REGION || 'us-west-2';
40
+ }
41
+ async loadSecrets() {
42
+ console.log(`[Secrets] Loading secrets from AWS Secrets Manager...`);
43
+ console.log(`[Secrets] Secret ARN: ${this.secretArn}`);
44
+ console.log(`[Secrets] Region: ${this.region}`);
45
+ // Dynamic import to avoid loading AWS SDK if not needed
46
+ const { SecretsManagerClient, GetSecretValueCommand } = await import('@aws-sdk/client-secrets-manager');
47
+ const client = new SecretsManagerClient({ region: this.region });
48
+ try {
49
+ const response = await client.send(new GetSecretValueCommand({ SecretId: this.secretArn }));
50
+ if (!response.SecretString) {
51
+ throw new Error('Secret value is empty');
52
+ }
53
+ const secret = JSON.parse(response.SecretString);
54
+ const secretKeys = Object.keys(secret);
55
+ console.log(`[Secrets] Found ${secretKeys.length} keys: ${secretKeys.join(', ')}`);
56
+ // Set DATABASE_URL from individual DB fields if not already set
57
+ if (!process.env.DATABASE_URL) {
58
+ const host = secret.host || secret.DB_HOST;
59
+ const port = secret.port || secret.DB_PORT || 5432;
60
+ const database = secret.dbname || secret.DB_NAME;
61
+ const username = secret.username || secret.DB_USER;
62
+ const password = secret.password || secret.DB_USER_PASSWORD;
63
+ if (host && username && password && database) {
64
+ process.env.DATABASE_URL = `postgresql://${encodeURIComponent(username)}:${encodeURIComponent(password)}@${host}:${port}/${database}`;
65
+ console.log(`[Secrets] DATABASE_URL constructed from secret fields`);
66
+ }
67
+ }
68
+ // Map common secret fields to environment variables
69
+ const envMappings = {
70
+ // API Keys
71
+ OPENAI_API_KEY: 'OPENAI_API_KEY',
72
+ ANTHROPIC_API_KEY: 'ANTHROPIC_API_KEY',
73
+ // Session
74
+ SESSION_SECRET: 'SESSION_SECRET',
75
+ // Stripe
76
+ STRIPE_SECRET_KEY: 'STRIPE_SECRET_KEY',
77
+ STRIPE_WEBHOOK_SECRET: 'STRIPE_WEBHOOK_SECRET',
78
+ // Slack
79
+ SLACK_CLIENT_ID: 'SLACK_CLIENT_ID',
80
+ SLACK_CLIENT_SECRET: 'SLACK_CLIENT_SECRET',
81
+ SLACK_SIGNING_SECRET: 'SLACK_SIGNING_SECRET',
82
+ // OAuth
83
+ GOOGLE_CLIENT_ID: 'GOOGLE_CLIENT_ID',
84
+ GOOGLE_CLIENT_SECRET: 'GOOGLE_CLIENT_SECRET',
85
+ GITHUB_CLIENT_ID: 'GITHUB_CLIENT_ID',
86
+ GITHUB_CLIENT_SECRET: 'GITHUB_CLIENT_SECRET',
87
+ };
88
+ for (const [secretKey, envKey] of Object.entries(envMappings)) {
89
+ if (secret[secretKey] && !process.env[envKey]) {
90
+ process.env[envKey] = secret[secretKey];
91
+ console.log(`[Secrets] ${envKey} set from Secrets Manager`);
92
+ }
93
+ }
94
+ console.log('[Secrets] Secrets loaded successfully');
95
+ }
96
+ catch (error) {
97
+ console.error('[Secrets] Failed to load secrets:', error);
98
+ throw error;
99
+ }
100
+ }
101
+ }
102
+ /**
103
+ * Get the appropriate secret provider based on environment configuration
104
+ */
105
+ function getSecretProvider() {
106
+ // Explicit provider selection
107
+ const providerName = process.env.SECRETS_PROVIDER;
108
+ if (providerName) {
109
+ switch (providerName) {
110
+ case 'env':
111
+ return new EnvSecretProvider();
112
+ case 'aws-secrets-manager':
113
+ return new AwsSecretsManagerProvider();
114
+ default:
115
+ throw new Error(`Unknown secrets provider: ${providerName}`);
116
+ }
117
+ }
118
+ // Auto-detect based on available env vars
119
+ if (process.env.AWS_SECRET_ARN) {
120
+ return new AwsSecretsManagerProvider();
121
+ }
122
+ // Default to env provider
123
+ return new EnvSecretProvider();
124
+ }
125
+ /**
126
+ * Load secrets from the configured provider.
127
+ *
128
+ * Call this at the very start of your application, before importing
129
+ * any modules that depend on environment variables like DATABASE_URL.
130
+ *
131
+ * @example
132
+ * ```typescript
133
+ * // server.js
134
+ * import { loadSecrets } from '@chaaskit/server';
135
+ *
136
+ * await loadSecrets();
137
+ *
138
+ * // Now safe to import modules that need DATABASE_URL, OPENAI_API_KEY, etc.
139
+ * const { createApp } = await import('@chaaskit/server');
140
+ * ```
141
+ */
142
+ export async function loadSecrets() {
143
+ const provider = getSecretProvider();
144
+ console.log(`[Secrets] Using provider: ${provider.name}`);
145
+ await provider.loadSecrets();
146
+ }
147
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/secrets/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAOH;;GAEG;AACH,MAAM,iBAAiB;IACrB,IAAI,GAAG,KAAK,CAAC;IAEb,KAAK,CAAC,WAAW;QACf,OAAO,CAAC,GAAG,CAAC,uEAAuE,CAAC,CAAC;IACvF,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,yBAAyB;IAC7B,IAAI,GAAG,qBAAqB,CAAC;IAErB,SAAS,CAAS;IAClB,MAAM,CAAS;IAEvB;QACE,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;QAC7C,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CACb,kFAAkF,CACnF,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,WAAW,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,WAAW;QACf,OAAO,CAAC,GAAG,CAAC,uDAAuD,CAAC,CAAC;QACrE,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;QACvD,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QAEhD,wDAAwD;QACxD,MAAM,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,GAAG,MAAM,MAAM,CAClE,iCAAiC,CAClC,CAAC;QAEF,MAAM,MAAM,GAAG,IAAI,oBAAoB,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QAEjE,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAChC,IAAI,qBAAqB,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CACxD,CAAC;YAEF,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC;gBAC3B,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;YAC3C,CAAC;YAED,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;YACjD,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACvC,OAAO,CAAC,GAAG,CAAC,mBAAmB,UAAU,CAAC,MAAM,UAAU,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEnF,gEAAgE;YAChE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;gBAC9B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,OAAO,CAAC;gBAC3C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,OAAO,IAAI,IAAI,CAAC;gBACnD,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,OAAO,CAAC;gBACjD,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,OAAO,CAAC;gBACnD,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,gBAAgB,CAAC;gBAE5D,IAAI,IAAI,IAAI,QAAQ,IAAI,QAAQ,IAAI,QAAQ,EAAE,CAAC;oBAC7C,OAAO,CAAC,GAAG,CAAC,YAAY,GAAG,gBAAgB,kBAAkB,CAAC,QAAQ,CAAC,IAAI,kBAAkB,CAAC,QAAQ,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,QAAQ,EAAE,CAAC;oBACtI,OAAO,CAAC,GAAG,CAAC,uDAAuD,CAAC,CAAC;gBACvE,CAAC;YACH,CAAC;YAED,oDAAoD;YACpD,MAAM,WAAW,GAA2B;gBAC1C,WAAW;gBACX,cAAc,EAAE,gBAAgB;gBAChC,iBAAiB,EAAE,mBAAmB;gBACtC,UAAU;gBACV,cAAc,EAAE,gBAAgB;gBAChC,SAAS;gBACT,iBAAiB,EAAE,mBAAmB;gBACtC,qBAAqB,EAAE,uBAAuB;gBAC9C,QAAQ;gBACR,eAAe,EAAE,iBAAiB;gBAClC,mBAAmB,EAAE,qBAAqB;gBAC1C,oBAAoB,EAAE,sBAAsB;gBAC5C,QAAQ;gBACR,gBAAgB,EAAE,kBAAkB;gBACpC,oBAAoB,EAAE,sBAAsB;gBAC5C,gBAAgB,EAAE,kBAAkB;gBACpC,oBAAoB,EAAE,sBAAsB;aAC7C,CAAC;YAEF,KAAK,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC9D,IAAI,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC9C,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;oBACxC,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,2BAA2B,CAAC,CAAC;gBAC9D,CAAC;YACH,CAAC;YAED,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;QACvD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAC;YAC1D,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;CACF;AAED;;GAEG;AACH,SAAS,iBAAiB;IACxB,8BAA8B;IAC9B,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IAElD,IAAI,YAAY,EAAE,CAAC;QACjB,QAAQ,YAAY,EAAE,CAAC;YACrB,KAAK,KAAK;gBACR,OAAO,IAAI,iBAAiB,EAAE,CAAC;YACjC,KAAK,qBAAqB;gBACxB,OAAO,IAAI,yBAAyB,EAAE,CAAC;YACzC;gBACE,MAAM,IAAI,KAAK,CAAC,6BAA6B,YAAY,EAAE,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IAED,0CAA0C;IAC1C,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC;QAC/B,OAAO,IAAI,yBAAyB,EAAE,CAAC;IACzC,CAAC;IAED,0BAA0B;IAC1B,OAAO,IAAI,iBAAiB,EAAE,CAAC;AACjC,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,QAAQ,GAAG,iBAAiB,EAAE,CAAC;IACrC,OAAO,CAAC,GAAG,CAAC,6BAA6B,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAC1D,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,206 @@
1
+ import { db } from '@chaaskit/db';
2
+ import { getConfig } from '../config/loader.js';
3
+ const DEFAULT_TOKENS_PER_CREDIT = 1000;
4
+ function getTokensPerCredit() {
5
+ const config = getConfig();
6
+ return config.credits?.tokensPerCredit ?? DEFAULT_TOKENS_PER_CREDIT;
7
+ }
8
+ function getDefaultExpiryDays() {
9
+ const config = getConfig();
10
+ if (!config.credits?.expiryEnabled) {
11
+ return undefined;
12
+ }
13
+ return config.credits.defaultExpiryDays ?? undefined;
14
+ }
15
+ async function setOwnerCreditsCache(tx, ownerType, ownerId, balance) {
16
+ if (ownerType === 'team') {
17
+ await tx.team.update({
18
+ where: { id: ownerId },
19
+ data: { credits: balance },
20
+ });
21
+ return;
22
+ }
23
+ await tx.user.update({
24
+ where: { id: ownerId },
25
+ data: { credits: balance },
26
+ });
27
+ }
28
+ async function adjustCreditsBalance(tx, ownerType, ownerId, delta) {
29
+ const existing = await tx.creditsBalance.findUnique({
30
+ where: { ownerType_ownerId: { ownerType, ownerId } },
31
+ });
32
+ const nextBalance = Math.max(0, (existing?.balance ?? 0) + delta);
33
+ await tx.creditsBalance.upsert({
34
+ where: { ownerType_ownerId: { ownerType, ownerId } },
35
+ update: { balance: nextBalance },
36
+ create: { ownerType, ownerId, balance: nextBalance },
37
+ });
38
+ await setOwnerCreditsCache(tx, ownerType, ownerId, nextBalance);
39
+ return nextBalance;
40
+ }
41
+ async function expireCreditsIfNeeded(tx, ownerType, ownerId) {
42
+ const now = new Date();
43
+ const expiredGrants = await tx.creditsGrant.findMany({
44
+ where: {
45
+ ownerType,
46
+ ownerId,
47
+ remaining: { gt: 0 },
48
+ expiresAt: { lt: now },
49
+ },
50
+ });
51
+ if (expiredGrants.length === 0) {
52
+ return;
53
+ }
54
+ let totalExpired = 0;
55
+ for (const grant of expiredGrants) {
56
+ totalExpired += grant.remaining;
57
+ }
58
+ await tx.creditsGrant.updateMany({
59
+ where: { id: { in: expiredGrants.map(({ id }) => id) } },
60
+ data: { remaining: 0 },
61
+ });
62
+ for (const grant of expiredGrants) {
63
+ await tx.creditsLedger.create({
64
+ data: {
65
+ ownerType,
66
+ ownerId,
67
+ delta: -grant.remaining,
68
+ reason: 'expired',
69
+ sourceType: 'expiry',
70
+ expiresAt: grant.expiresAt ?? undefined,
71
+ metadata: {
72
+ grantId: grant.id,
73
+ expiredAt: now.toISOString(),
74
+ },
75
+ },
76
+ });
77
+ }
78
+ await adjustCreditsBalance(tx, ownerType, ownerId, -totalExpired);
79
+ }
80
+ export async function getCreditsBalance(ownerType, ownerId) {
81
+ const [balance, soonestExpiry] = await db.$transaction(async (tx) => {
82
+ await expireCreditsIfNeeded(tx, ownerType, ownerId);
83
+ const current = await tx.creditsBalance.findUnique({
84
+ where: { ownerType_ownerId: { ownerType, ownerId } },
85
+ });
86
+ const nextExpiry = await tx.creditsGrant.findFirst({
87
+ where: {
88
+ ownerType,
89
+ ownerId,
90
+ remaining: { gt: 0 },
91
+ expiresAt: { not: null },
92
+ },
93
+ orderBy: { expiresAt: 'asc' },
94
+ select: { expiresAt: true },
95
+ });
96
+ return [current?.balance ?? 0, nextExpiry?.expiresAt ?? null];
97
+ });
98
+ return {
99
+ balance,
100
+ expiresSoonestAt: soonestExpiry,
101
+ };
102
+ }
103
+ export async function grantCredits(params) {
104
+ const { ownerType, ownerId, amount, reason, sourceType, metadata } = params;
105
+ const expiresAt = params.expiresAt ?? undefined;
106
+ if (amount <= 0) {
107
+ return getCreditsBalance(ownerType, ownerId).then((b) => b.balance);
108
+ }
109
+ const defaultExpiryDays = getDefaultExpiryDays();
110
+ const resolvedExpiresAt = expiresAt ?? (defaultExpiryDays ? new Date(Date.now() + defaultExpiryDays * 24 * 60 * 60 * 1000) : undefined);
111
+ const run = async (tx) => {
112
+ const ledger = await tx.creditsLedger.create({
113
+ data: {
114
+ ownerType,
115
+ ownerId,
116
+ delta: amount,
117
+ reason,
118
+ sourceType,
119
+ expiresAt: resolvedExpiresAt,
120
+ metadata: metadata ?? undefined,
121
+ },
122
+ });
123
+ await tx.creditsGrant.create({
124
+ data: {
125
+ ownerType,
126
+ ownerId,
127
+ total: amount,
128
+ remaining: amount,
129
+ expiresAt: resolvedExpiresAt,
130
+ ledgerId: ledger.id,
131
+ },
132
+ });
133
+ return adjustCreditsBalance(tx, ownerType, ownerId, amount);
134
+ };
135
+ const balance = params.tx ? await run(params.tx) : await db.$transaction(run);
136
+ return balance;
137
+ }
138
+ export async function consumeCredits(params) {
139
+ const { ownerType, ownerId, amount, reason, sourceType, metadata } = params;
140
+ if (amount <= 0) {
141
+ const current = await getCreditsBalance(ownerType, ownerId);
142
+ return { consumed: 0, shortfall: 0, balance: current.balance };
143
+ }
144
+ const result = await db.$transaction(async (tx) => {
145
+ await expireCreditsIfNeeded(tx, ownerType, ownerId);
146
+ const expiring = await tx.creditsGrant.findMany({
147
+ where: {
148
+ ownerType,
149
+ ownerId,
150
+ remaining: { gt: 0 },
151
+ expiresAt: { not: null },
152
+ },
153
+ orderBy: [{ expiresAt: 'asc' }, { createdAt: 'asc' }],
154
+ });
155
+ const nonExpiring = await tx.creditsGrant.findMany({
156
+ where: {
157
+ ownerType,
158
+ ownerId,
159
+ remaining: { gt: 0 },
160
+ expiresAt: null,
161
+ },
162
+ orderBy: { createdAt: 'asc' },
163
+ });
164
+ const grants = [...expiring, ...nonExpiring];
165
+ let remainingToConsume = amount;
166
+ let consumed = 0;
167
+ for (const grant of grants) {
168
+ if (remainingToConsume <= 0) {
169
+ break;
170
+ }
171
+ const useAmount = Math.min(grant.remaining, remainingToConsume);
172
+ if (useAmount <= 0) {
173
+ continue;
174
+ }
175
+ await tx.creditsGrant.update({
176
+ where: { id: grant.id },
177
+ data: { remaining: grant.remaining - useAmount },
178
+ });
179
+ remainingToConsume -= useAmount;
180
+ consumed += useAmount;
181
+ }
182
+ if (consumed > 0) {
183
+ await tx.creditsLedger.create({
184
+ data: {
185
+ ownerType,
186
+ ownerId,
187
+ delta: -consumed,
188
+ reason,
189
+ sourceType,
190
+ metadata: metadata ?? undefined,
191
+ },
192
+ });
193
+ }
194
+ const balance = await adjustCreditsBalance(tx, ownerType, ownerId, -consumed);
195
+ return { consumed, shortfall: remainingToConsume, balance };
196
+ });
197
+ return result;
198
+ }
199
+ export function calculateCreditsCost(totalTokens) {
200
+ const tokensPerCredit = getTokensPerCredit();
201
+ if (totalTokens <= 0) {
202
+ return 1;
203
+ }
204
+ return Math.max(1, Math.ceil(totalTokens / tokensPerCredit));
205
+ }
206
+ //# sourceMappingURL=credits.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credits.js","sourceRoot":"","sources":["../../src/services/credits.ts"],"names":[],"mappings":"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"}
@@ -143,6 +143,43 @@ This code will expire in 15 minutes.
143
143
  If you didn't create an account with ${config.app.name}, you can safely ignore this email.
144
144
  `.trim();
145
145
  }
146
+ /**
147
+ * Generate magic link email HTML
148
+ */
149
+ export function generateMagicLinkEmailHtml(magicLinkUrl, config) {
150
+ const content = `
151
+ <div class="header">
152
+ <h1>Sign in with magic link</h1>
153
+ </div>
154
+ <div class="content">
155
+ <p>Click the button below to sign in to ${config.app.name}:</p>
156
+ <div class="button-container">
157
+ <a href="${magicLinkUrl}" class="button">Sign In</a>
158
+ </div>
159
+ <div class="divider"></div>
160
+ <p class="muted">This link will expire soon. If you didn't request this email, you can safely ignore it.</p>
161
+ <p class="muted">If you can't click the button, copy and paste this link into your browser:</p>
162
+ <p class="muted" style="word-break: break-all;">${magicLinkUrl}</p>
163
+ </div>
164
+ `;
165
+ return wrapInEmailTemplate(content, {
166
+ appName: config.app.name,
167
+ appUrl: config.app.url,
168
+ });
169
+ }
170
+ /**
171
+ * Generate magic link email plain text
172
+ */
173
+ export function generateMagicLinkEmailText(magicLinkUrl, config) {
174
+ return `
175
+ Sign in with magic link
176
+
177
+ Click the link below to sign in to ${config.app.name}:
178
+ ${magicLinkUrl}
179
+
180
+ This link will expire soon. If you didn't request this email, you can safely ignore it.
181
+ `.trim();
182
+ }
146
183
  /**
147
184
  * Generate team invitation email HTML
148
185
  */
@@ -191,4 +228,83 @@ This invitation will expire in 7 days.
191
228
  If you don't have an account yet, you'll be able to create one when you accept the invitation.
192
229
  `.trim();
193
230
  }
231
+ /**
232
+ * Generate app invitation email HTML
233
+ */
234
+ export function generateAppInviteEmailHtml(inviteUrl, expiresInDays, config) {
235
+ const content = `
236
+ <div class="header">
237
+ <h1>You're invited</h1>
238
+ </div>
239
+ <div class="content">
240
+ <p>You’ve been invited to join ${config.app.name}.</p>
241
+ <p>Click the button below to create your account:</p>
242
+ <div class="button-container">
243
+ <a href="${inviteUrl}" class="button">Accept Invitation</a>
244
+ </div>
245
+ <div class="divider"></div>
246
+ <p class="muted">This invitation will expire in ${expiresInDays} days.</p>
247
+ <p class="muted">If you can't click the button, copy and paste this link into your browser:</p>
248
+ <p class="muted" style="word-break: break-all;">${inviteUrl}</p>
249
+ </div>
250
+ `;
251
+ return wrapInEmailTemplate(content, {
252
+ appName: config.app.name,
253
+ appUrl: config.app.url,
254
+ });
255
+ }
256
+ /**
257
+ * Generate app invitation email plain text
258
+ */
259
+ export function generateAppInviteEmailText(inviteUrl, expiresInDays, config) {
260
+ return `
261
+ You're invited
262
+
263
+ You've been invited to join ${config.app.name}.
264
+
265
+ Accept the invitation by visiting this link:
266
+ ${inviteUrl}
267
+
268
+ This invitation will expire in ${expiresInDays} days.
269
+ `.trim();
270
+ }
271
+ /**
272
+ * Generate payment failed email HTML
273
+ */
274
+ export function generatePaymentFailedEmailHtml(params, config) {
275
+ const amountLine = params.amountDue ? `<p><strong>Amount due:</strong> ${params.amountDue}</p>` : '';
276
+ const invoiceLine = params.invoiceUrl
277
+ ? `<p class="muted">View invoice: <a href="${params.invoiceUrl}">${params.invoiceUrl}</a></p>`
278
+ : '';
279
+ const content = `
280
+ <div class="header">
281
+ <h1>Payment failed</h1>
282
+ </div>
283
+ <div class="content">
284
+ <p>We were unable to process the payment for ${params.subjectName} on ${config.app.name}.</p>
285
+ ${amountLine}
286
+ <p>Please update your payment method to avoid service interruption.</p>
287
+ ${invoiceLine}
288
+ </div>
289
+ `;
290
+ return wrapInEmailTemplate(content, {
291
+ appName: config.app.name,
292
+ appUrl: config.app.url,
293
+ });
294
+ }
295
+ /**
296
+ * Generate payment failed email plain text
297
+ */
298
+ export function generatePaymentFailedEmailText(params, config) {
299
+ const amountLine = params.amountDue ? `Amount due: ${params.amountDue}\n` : '';
300
+ const invoiceLine = params.invoiceUrl ? `View invoice: ${params.invoiceUrl}\n` : '';
301
+ return `
302
+ Payment failed
303
+
304
+ We were unable to process the payment for ${params.subjectName} on ${config.app.name}.
305
+ ${amountLine}
306
+ Please update your payment method to avoid service interruption.
307
+ ${invoiceLine}
308
+ `.trim();
309
+ }
194
310
  //# sourceMappingURL=templates.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../../src/services/email/templates.ts"],"names":[],"mappings":"AAAA;;GAEG;AASH;;GAEG;AACH,SAAS,mBAAmB,CAAC,OAAe,EAAE,MAA0B;IACtE,OAAO;;;;;;WAME,MAAM,CAAC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAqFjB,OAAO;;;kBAGG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,IAAI,MAAM,CAAC,OAAO;;;;;CAK3D,CAAC,IAAI,EAAE,CAAC;AACT,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,6BAA6B,CAC3C,IAAY,EACZ,MAAiB;IAEjB,MAAM,OAAO,GAAG;;;;;sBAKI,MAAM,CAAC,GAAG,CAAC,IAAI;;6BAER,IAAI;;mGAEkE,MAAM,CAAC,GAAG,CAAC,IAAI;;GAE/G,CAAC;IAEF,OAAO,mBAAmB,CAAC,OAAO,EAAE;QAClC,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI;QACxB,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG;KACvB,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,6BAA6B,CAC3C,IAAY,EACZ,MAAiB;IAEjB,OAAO;;;aAGI,MAAM,CAAC,GAAG,CAAC,IAAI;;EAE1B,IAAI;;;;uCAIiC,MAAM,CAAC,GAAG,CAAC,IAAI;CACrD,CAAC,IAAI,EAAE,CAAC;AACT,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,2BAA2B,CACzC,QAAgB,EAChB,SAAiB,EACjB,WAA0B,EAC1B,MAAiB;IAEjB,MAAM,WAAW,GAAG,WAAW;QAC7B,CAAC,CAAC,GAAG,WAAW,kBAAkB;QAClC,CAAC,CAAC,uBAAuB,CAAC;IAE5B,MAAM,OAAO,GAAG;;;;;WAKP,WAAW,oBAAoB,QAAQ,gBAAgB,MAAM,CAAC,GAAG,CAAC,IAAI;;;mBAG9D,SAAS;;;;;wDAK4B,SAAS;;GAE9D,CAAC;IAEF,OAAO,mBAAmB,CAAC,OAAO,EAAE;QAClC,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI;QACxB,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG;KACvB,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,2BAA2B,CACzC,QAAgB,EAChB,SAAiB,EACjB,WAA0B,EAC1B,MAAiB;IAEjB,MAAM,WAAW,GAAG,WAAW;QAC7B,CAAC,CAAC,GAAG,WAAW,kBAAkB;QAClC,CAAC,CAAC,uBAAuB,CAAC;IAE5B,OAAO;;;EAGP,WAAW,aAAa,QAAQ,QAAQ,MAAM,CAAC,GAAG,CAAC,IAAI;;;EAGvD,SAAS;;;;;CAKV,CAAC,IAAI,EAAE,CAAC;AACT,CAAC"}
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../../src/services/email/templates.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import { db } from '@chaaskit/db';
2
+ import { getConfig } from '../config/loader.js';
3
+ export async function recordUsage(params) {
4
+ const config = getConfig();
5
+ if (!config.metering?.enabled) {
6
+ return;
7
+ }
8
+ const promptTokens = config.metering.recordPromptCompletion === false ? 0 : params.promptTokens;
9
+ const completionTokens = config.metering.recordPromptCompletion === false ? 0 : params.completionTokens;
10
+ const totalTokens = (promptTokens ?? 0) + (completionTokens ?? 0);
11
+ await db.usageMeter.create({
12
+ data: {
13
+ provider: params.provider,
14
+ model: params.model,
15
+ promptTokens,
16
+ completionTokens,
17
+ totalTokens,
18
+ userId: params.userId,
19
+ teamId: params.teamId ?? undefined,
20
+ messageId: params.messageId ?? undefined,
21
+ },
22
+ });
23
+ }
24
+ //# sourceMappingURL=metering.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metering.js","sourceRoot":"","sources":["../../src/services/metering.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAQjC;IACC,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC;QAC9B,OAAO;IACT,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,CAAC,QAAQ,CAAC,sBAAsB,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC;IAChG,MAAM,gBAAgB,GAAG,MAAM,CAAC,QAAQ,CAAC,sBAAsB,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC;IACxG,MAAM,WAAW,GAAG,CAAC,YAAY,IAAI,CAAC,CAAC,GAAG,CAAC,gBAAgB,IAAI,CAAC,CAAC,CAAC;IAElE,MAAM,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC;QACzB,IAAI,EAAE;YACJ,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,YAAY;YACZ,gBAAgB;YAChB,WAAW;YACX,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,SAAS;YAClC,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,SAAS;SACzC;KACF,CAAC,CAAC;AACL,CAAC"}