@donotdev/functions 0.0.3 → 0.0.5

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.
@@ -31217,14 +31217,11 @@ async function WR(e, t) {
31217
31217
  let c = { success: !0, customClaims: s };
31218
31218
  return (
31219
31219
  n &&
31220
- (await oe()
31221
- .collection('idempotency')
31222
- .doc(`claims_${n}`)
31223
- .set({
31224
- result: c,
31225
- processedAt: new Date().toISOString(),
31226
- processedBy: t.uid,
31227
- })),
31220
+ (await oe().collection('idempotency').doc(`claims_${n}`).set({
31221
+ result: c,
31222
+ processedAt: new Date().toISOString(),
31223
+ processedBy: t.uid,
31224
+ })),
31228
31225
  c
31229
31226
  );
31230
31227
  }
@@ -32504,14 +32501,11 @@ function yI(e, t) {
32504
32501
  w = Dt({ id: m.id, ...m.data() });
32505
32502
  return (
32506
32503
  s &&
32507
- (await u
32508
- .collection('idempotency')
32509
- .doc(`create_${s}`)
32510
- .set({
32511
- result: w,
32512
- processedAt: new Date().toISOString(),
32513
- processedBy: c,
32514
- })),
32504
+ (await u.collection('idempotency').doc(`create_${s}`).set({
32505
+ result: w,
32506
+ processedAt: new Date().toISOString(),
32507
+ processedBy: c,
32508
+ })),
32515
32509
  w
32516
32510
  );
32517
32511
  }, 'createEntityLogic');
@@ -32632,14 +32626,11 @@ function wI(e, t) {
32632
32626
  k = Dt({ id: C.id, ...C.data() });
32633
32627
  return (
32634
32628
  c &&
32635
- (await u
32636
- .collection('idempotency')
32637
- .doc(`update_${c}`)
32638
- .set({
32639
- result: k,
32640
- processedAt: new Date().toISOString(),
32641
- processedBy: h,
32642
- })),
32629
+ (await u.collection('idempotency').doc(`update_${c}`).set({
32630
+ result: k,
32631
+ processedAt: new Date().toISOString(),
32632
+ processedBy: h,
32633
+ })),
32643
32634
  k
32644
32635
  );
32645
32636
  }, 'updateEntityLogic');
@@ -32682,19 +32673,16 @@ async function Cue(e, t, r, n = 'pull', i) {
32682
32673
  });
32683
32674
  }
32684
32675
  (process.env.SAVE_GITHUB_ACCESS_TO_FIRESTORE === 'true' &&
32685
- (await oe()
32686
- .collection('githubAccess')
32687
- .doc(e)
32688
- .set(
32689
- {
32690
- githubUsername: t,
32691
- repoConfig: r,
32692
- permission: n,
32693
- accessGranted: !0,
32694
- grantedAt: Date.now(),
32695
- },
32696
- { merge: !0 }
32697
- )),
32676
+ (await oe().collection('githubAccess').doc(e).set(
32677
+ {
32678
+ githubUsername: t,
32679
+ repoConfig: r,
32680
+ permission: n,
32681
+ accessGranted: !0,
32682
+ grantedAt: Date.now(),
32683
+ },
32684
+ { merge: !0 }
32685
+ )),
32698
32686
  kc.info('GitHub repository access granted', {
32699
32687
  userId: e,
32700
32688
  githubUsername: t,
@@ -32964,14 +32952,11 @@ var Jue = TI(async (e) => {
32964
32952
  let C = { success: !0, credentials: S, profile: z };
32965
32953
  return (
32966
32954
  c &&
32967
- (await oe()
32968
- .collection('idempotency')
32969
- .doc(`oauth_${c}`)
32970
- .set({
32971
- result: C,
32972
- processedAt: new Date().toISOString(),
32973
- processedBy: t,
32974
- })),
32955
+ (await oe().collection('idempotency').doc(`oauth_${c}`).set({
32956
+ result: C,
32957
+ processedAt: new Date().toISOString(),
32958
+ processedBy: t,
32959
+ })),
32975
32960
  C
32976
32961
  );
32977
32962
  } catch (h) {
@@ -31308,14 +31308,11 @@ async function c5e(e, t) {
31308
31308
  o(c5e, 'checkIdempotency');
31309
31309
  async function h5e(e, t, r, n) {
31310
31310
  try {
31311
- (await Ue()
31312
- .collection('idempotency')
31313
- .doc(`${t}_${e}`)
31314
- .set({
31315
- result: r,
31316
- processedAt: new Date().toISOString(),
31317
- processedBy: n,
31318
- }),
31311
+ (await Ue().collection('idempotency').doc(`${t}_${e}`).set({
31312
+ result: r,
31313
+ processedAt: new Date().toISOString(),
31314
+ processedBy: n,
31315
+ }),
31319
31316
  B1.info('Idempotency result stored', {
31320
31317
  key: e,
31321
31318
  operation: t,
@@ -30612,23 +30612,19 @@ function Nr(e, t, r, o) {
30612
30612
  return a.status(405).json({ error: 'Method not allowed' });
30613
30613
  let l = Ft(t, i.body);
30614
30614
  if (!l.success)
30615
- return a
30616
- .status(400)
30617
- .json({
30618
- error: `Validation failed: ${l.issues.map((S) => S.message).join(', ')}`,
30619
- });
30615
+ return a.status(400).json({
30616
+ error: `Validation failed: ${l.issues.map((S) => S.message).join(', ')}`,
30617
+ });
30620
30618
  let h = l.output,
30621
30619
  d = P8(i.headers.authorization),
30622
30620
  m = `${r}_${d}`,
30623
30621
  p = O0[r] || O0.api,
30624
30622
  f = await A8(m, p);
30625
30623
  if (!f.allowed)
30626
- return a
30627
- .status(429)
30628
- .json({
30629
- error: `Rate limit exceeded. Try again in ${f.blockRemainingSeconds} seconds.`,
30630
- retryAfter: f.blockRemainingSeconds,
30631
- });
30624
+ return a.status(429).json({
30625
+ error: `Rate limit exceeded. Try again in ${f.blockRemainingSeconds} seconds.`,
30626
+ retryAfter: f.blockRemainingSeconds,
30627
+ });
30632
30628
  let z = await o(i, a, h, { uid: d });
30633
30629
  return (
30634
30630
  await D0({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@donotdev/functions",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "private": false,
5
5
  "description": "Backend functions for DoNotDev Framework - Firebase, Vercel, and platform-agnostic implementations for auth, billing, CRUD, and OAuth",
6
6
  "main": "./lib/firebase/index.js",
@@ -42,14 +42,14 @@
42
42
  "serve": "firebase emulators:start --only functions"
43
43
  },
44
44
  "dependencies": {
45
- "@donotdev/core": "0.0.3",
46
- "@donotdev/firebase": "0.0.3"
45
+ "@donotdev/core": "^0.0.12",
46
+ "@donotdev/firebase": "^0.0.5"
47
47
  },
48
48
  "peerDependencies": {
49
- "@sentry/node": "^10.25.0",
49
+ "@sentry/node": "^10.33.0",
50
50
  "firebase-admin": "^13.6.0",
51
51
  "firebase-functions": "^7.0.1",
52
- "next": "^16.0.7",
52
+ "next": "^16.1.4",
53
53
  "stripe": "^20.1.0",
54
54
  "valibot": "^1.2.0"
55
55
  },
@@ -15,10 +15,16 @@ import * as v from 'valibot';
15
15
  import { createBaseFunction } from '../baseFunction.js';
16
16
  import { AUTH_CONFIG } from '../config/constants.js';
17
17
 
18
- import type { CallableRequest } from 'firebase-functions/v2/https';
18
+ import type {
19
+ CallableFunction,
20
+ CallableRequest,
21
+ } from 'firebase-functions/v2/https';
19
22
 
20
23
  const getCustomClaimsSchema = v.object({});
21
24
 
25
+ type GetCustomClaimsRequest = v.InferOutput<typeof getCustomClaimsSchema>;
26
+ type GetCustomClaimsResponse = { customClaims: Record<string, any> };
27
+
22
28
  /**
23
29
  * Business logic for getting custom claims
24
30
  * Base function handles: validation, auth, rate limiting, monitoring
@@ -28,10 +34,10 @@ const getCustomClaimsSchema = v.object({});
28
34
  * @author AMBROISE PARK Consulting
29
35
  */
30
36
  async function getCustomClaimsLogic(
31
- data: v.InferOutput<typeof getCustomClaimsSchema>,
37
+ data: GetCustomClaimsRequest,
32
38
  context: {
33
39
  uid: string;
34
- request: CallableRequest<v.InferOutput<typeof getCustomClaimsSchema>>;
40
+ request: CallableRequest<GetCustomClaimsRequest>;
35
41
  }
36
42
  ) {
37
43
  const user = await getFirebaseAdminAuth().getUser(context.uid);
@@ -48,7 +54,10 @@ async function getCustomClaimsLogic(
48
54
  */
49
55
  export const getCustomClaims = (
50
56
  customSchema?: v.BaseSchema<unknown, any, v.BaseIssue<unknown>>
51
- ) => {
57
+ ): CallableFunction<
58
+ GetCustomClaimsRequest,
59
+ Promise<GetCustomClaimsResponse>
60
+ > => {
52
61
  const schema = customSchema || getCustomClaimsSchema;
53
62
  return createBaseFunction(
54
63
  AUTH_CONFIG,
@@ -15,10 +15,24 @@ import * as v from 'valibot';
15
15
  import { createBaseFunction } from '../baseFunction.js';
16
16
  import { AUTH_CONFIG } from '../config/constants.js';
17
17
 
18
- import type { CallableRequest } from 'firebase-functions/v2/https';
18
+ import type {
19
+ CallableFunction,
20
+ CallableRequest,
21
+ } from 'firebase-functions/v2/https';
19
22
 
20
23
  const getUserAuthStatusSchema = v.object({});
21
24
 
25
+ export type GetUserAuthStatusRequest = v.InferOutput<
26
+ typeof getUserAuthStatusSchema
27
+ >;
28
+ export type GetUserAuthStatusResponse = {
29
+ uid: string;
30
+ email?: string;
31
+ emailVerified: boolean;
32
+ customClaims: Record<string, any>;
33
+ disabled: boolean;
34
+ };
35
+
22
36
  /**
23
37
  * Business logic for getting user auth status
24
38
  * Base function handles: validation, auth, rate limiting, monitoring
@@ -28,10 +42,10 @@ const getUserAuthStatusSchema = v.object({});
28
42
  * @author AMBROISE PARK Consulting
29
43
  */
30
44
  async function getUserAuthStatusLogic(
31
- data: v.InferOutput<typeof getUserAuthStatusSchema>,
45
+ data: GetUserAuthStatusRequest,
32
46
  context: {
33
47
  uid: string;
34
- request: CallableRequest<v.InferOutput<typeof getUserAuthStatusSchema>>;
48
+ request: CallableRequest<GetUserAuthStatusRequest>;
35
49
  }
36
50
  ) {
37
51
  const user = await getFirebaseAdminAuth().getUser(context.uid);
@@ -55,7 +69,10 @@ async function getUserAuthStatusLogic(
55
69
  */
56
70
  export const getUserAuthStatus = (
57
71
  customSchema?: v.BaseSchema<unknown, any, v.BaseIssue<unknown>>
58
- ) => {
72
+ ): CallableFunction<
73
+ GetUserAuthStatusRequest,
74
+ Promise<GetUserAuthStatusResponse>
75
+ > => {
59
76
  const schema = customSchema || getUserAuthStatusSchema;
60
77
  return createBaseFunction(
61
78
  AUTH_CONFIG,
@@ -15,7 +15,10 @@ import * as v from 'valibot';
15
15
  import { createBaseFunction } from '../baseFunction.js';
16
16
  import { AUTH_CONFIG } from '../config/constants.js';
17
17
 
18
- import type { CallableRequest } from 'firebase-functions/v2/https';
18
+ import type {
19
+ CallableFunction,
20
+ CallableRequest,
21
+ } from 'firebase-functions/v2/https';
19
22
 
20
23
  const removeCustomClaimsSchema = v.object({
21
24
  claimsToRemove: v.pipe(
@@ -24,6 +27,14 @@ const removeCustomClaimsSchema = v.object({
24
27
  ),
25
28
  });
26
29
 
30
+ export type RemoveCustomClaimsRequest = v.InferOutput<
31
+ typeof removeCustomClaimsSchema
32
+ >;
33
+ export type RemoveCustomClaimsResponse = {
34
+ success: boolean;
35
+ customClaims: Record<string, any>;
36
+ };
37
+
27
38
  /**
28
39
  * Business logic for removing custom claims
29
40
  * Base function handles: validation, auth, rate limiting, monitoring
@@ -33,10 +44,10 @@ const removeCustomClaimsSchema = v.object({
33
44
  * @author AMBROISE PARK Consulting
34
45
  */
35
46
  async function removeCustomClaimsLogic(
36
- data: v.InferOutput<typeof removeCustomClaimsSchema>,
47
+ data: RemoveCustomClaimsRequest,
37
48
  context: {
38
49
  uid: string;
39
- request: CallableRequest<v.InferOutput<typeof removeCustomClaimsSchema>>;
50
+ request: CallableRequest<RemoveCustomClaimsRequest>;
40
51
  }
41
52
  ) {
42
53
  const { claimsToRemove } = data;
@@ -65,7 +76,10 @@ async function removeCustomClaimsLogic(
65
76
  */
66
77
  export const removeCustomClaims = (
67
78
  customSchema?: v.BaseSchema<unknown, any, v.BaseIssue<unknown>>
68
- ) => {
79
+ ): CallableFunction<
80
+ RemoveCustomClaimsRequest,
81
+ Promise<RemoveCustomClaimsResponse>
82
+ > => {
69
83
  const schema = customSchema || removeCustomClaimsSchema;
70
84
  return createBaseFunction(
71
85
  AUTH_CONFIG,
@@ -17,13 +17,24 @@ import * as v from 'valibot';
17
17
  import { createBaseFunction } from '../baseFunction.js';
18
18
  import { AUTH_CONFIG } from '../config/constants.js';
19
19
 
20
- import type { CallableRequest } from 'firebase-functions/v2/https';
20
+ import type {
21
+ CallableFunction,
22
+ CallableRequest,
23
+ } from 'firebase-functions/v2/https';
21
24
 
22
25
  const setCustomClaimsSchema = v.object({
23
26
  customClaims: v.record(v.string(), v.any()),
24
27
  idempotencyKey: v.optional(v.string()),
25
28
  });
26
29
 
30
+ export type SetCustomClaimsRequest = v.InferOutput<
31
+ typeof setCustomClaimsSchema
32
+ >;
33
+ export type SetCustomClaimsResponse = {
34
+ success: boolean;
35
+ customClaims: Record<string, any>;
36
+ };
37
+
27
38
  /**
28
39
  * Business logic for setting custom claims
29
40
  * Base function handles: validation, auth, rate limiting, monitoring
@@ -33,10 +44,10 @@ const setCustomClaimsSchema = v.object({
33
44
  * @author AMBROISE PARK Consulting
34
45
  */
35
46
  async function setCustomClaimsLogic(
36
- data: v.InferOutput<typeof setCustomClaimsSchema>,
47
+ data: SetCustomClaimsRequest,
37
48
  context: {
38
49
  uid: string;
39
- request: CallableRequest<v.InferOutput<typeof setCustomClaimsSchema>>;
50
+ request: CallableRequest<SetCustomClaimsRequest>;
40
51
  }
41
52
  ) {
42
53
  const { customClaims, idempotencyKey } = data;
@@ -94,7 +105,10 @@ async function setCustomClaimsLogic(
94
105
  */
95
106
  export const setCustomClaims = (
96
107
  customSchema?: v.BaseSchema<unknown, any, v.BaseIssue<unknown>>
97
- ) => {
108
+ ): CallableFunction<
109
+ SetCustomClaimsRequest,
110
+ Promise<SetCustomClaimsResponse>
111
+ > => {
98
112
  const schema = customSchema || setCustomClaimsSchema;
99
113
  return createBaseFunction(
100
114
  AUTH_CONFIG,
@@ -27,8 +27,13 @@ import {
27
27
  import { stripe, validateStripeEnvironment } from '../../shared/utils.js';
28
28
  import { createBaseFunction } from '../baseFunction.js';
29
29
  import { STRIPE_CONFIG } from '../config/constants.js';
30
+ import { stripeSecretKey } from '../config/secrets.js'; // ✅ IMPORT SECRET
31
+ import { initStripe } from '../../shared/utils.js'; // ✅ IMPORT INIT
30
32
 
31
- import type { CallableRequest } from 'firebase-functions/v2/https';
33
+ import type {
34
+ CallableFunction,
35
+ CallableRequest,
36
+ } from 'firebase-functions/v2/https';
32
37
 
33
38
  /**
34
39
  * Business logic for creating Stripe checkout session
@@ -41,6 +46,9 @@ async function createCheckoutSessionLogic(
41
46
  },
42
47
  billingConfig: StripeBackConfig
43
48
  ) {
49
+ // ✅ LATEST BEST PRACTICE: Initialize with secret value explicitly
50
+ initStripe(stripeSecretKey.value());
51
+
44
52
  try {
45
53
  validateStripeEnvironment();
46
54
  } catch (error) {
@@ -217,7 +225,12 @@ async function createCheckoutSessionLogic(
217
225
  * });
218
226
  * window.location.href = result.data.sessionUrl;
219
227
  */
220
- export function createCheckoutSession(billingConfig: StripeBackConfig) {
228
+ export function createCheckoutSession(
229
+ billingConfig: StripeBackConfig
230
+ ): CallableFunction<
231
+ CreateCheckoutSessionRequest,
232
+ Promise<{ sessionId: string; sessionUrl: string }>
233
+ > {
221
234
  return createBaseFunction<
222
235
  CreateCheckoutSessionRequest,
223
236
  { sessionId: string; sessionUrl: string }
@@ -13,38 +13,58 @@ import { getFirebaseAdminAuth } from '@donotdev/firebase/server';
13
13
  import * as v from 'valibot';
14
14
 
15
15
  import { handleError } from '../../shared/errorHandling.js';
16
- import { stripe, validateStripeEnvironment } from '../../shared/utils.js';
16
+ import {
17
+ stripe,
18
+ validateStripeEnvironment,
19
+ initStripe,
20
+ } from '../../shared/utils.js'; // ✅ IMPORT INIT
17
21
  import { createBaseFunction } from '../baseFunction.js';
18
22
  import { STRIPE_CONFIG } from '../config/constants.js';
23
+ import { stripeSecretKey } from '../config/secrets.js'; // ✅ IMPORT SECRET
19
24
 
20
- import type { CallableRequest } from 'firebase-functions/v2/https';
25
+ import type {
26
+ CallableFunction,
27
+ CallableRequest,
28
+ } from 'firebase-functions/v2/https';
21
29
 
22
30
  const customerPortalSchema = v.object({
23
31
  userId: v.string(),
24
32
  returnUrl: v.optional(v.pipe(v.string(), v.url())),
25
33
  });
26
34
 
35
+ type CustomerPortalRequest = v.InferOutput<typeof customerPortalSchema>;
36
+
27
37
  async function createCustomerPortalLogic(
28
- data: { userId: string; returnUrl?: string },
29
- context: { uid: string; request: CallableRequest }
38
+ data: CustomerPortalRequest,
39
+ context: { uid: string; request: CallableRequest<CustomerPortalRequest> }
30
40
  ) {
31
- validateStripeEnvironment();
41
+ // ✅ LATEST BEST PRACTICE: Init with secret value
42
+ initStripe(stripeSecretKey.value());
43
+
44
+ try {
45
+ validateStripeEnvironment();
46
+ } catch (error) {
47
+ throw handleError(error);
48
+ }
32
49
 
33
50
  const { userId, returnUrl } = data;
34
51
 
35
52
  // Get customer ID from user claims
36
53
  const user = await getFirebaseAdminAuth().getUser(userId);
37
- const currentClaims = user.customClaims || {};
38
- const customerId = currentClaims.subscription?.customerId;
54
+ // ... (rest of logic)
55
+ const currentClaims = (user.customClaims || {}) as any;
56
+ const customerId =
57
+ currentClaims.subscription?.customerId ||
58
+ user.customClaims?.stripeCustomerId;
39
59
 
40
60
  if (!customerId) {
41
- throw handleError(new Error('No customer found'));
61
+ throw handleError(new Error('No Stripe customer ID found for user'));
42
62
  }
43
63
 
44
64
  // Create portal session
45
65
  const session = await stripe.billingPortal.sessions.create({
46
66
  customer: customerId,
47
- return_url: returnUrl || `${process.env.FRONTEND_URL}/billing`,
67
+ return_url: returnUrl || 'https://donotdev.com/dashboard', // Fallback
48
68
  });
49
69
 
50
70
  return {
@@ -52,8 +72,11 @@ async function createCustomerPortalLogic(
52
72
  };
53
73
  }
54
74
 
55
- export function createCustomerPortal() {
56
- return createBaseFunction(
75
+ export function createCustomerPortal(): CallableFunction<
76
+ CustomerPortalRequest,
77
+ Promise<{ url: string }>
78
+ > {
79
+ return createBaseFunction<CustomerPortalRequest, { url: string }>(
57
80
  STRIPE_CONFIG,
58
81
  customerPortalSchema,
59
82
  'create_customer_portal',
@@ -10,15 +10,20 @@
10
10
  */
11
11
 
12
12
  import { logger } from 'firebase-functions/v2';
13
- import { onRequest } from 'firebase-functions/v2/https';
13
+ import { onRequest, type HttpsFunction } from 'firebase-functions/v2/https';
14
14
 
15
15
  import type { StripeBackConfig } from '@donotdev/core/server';
16
16
 
17
17
  import { updateUserSubscription } from '../../shared/billing/helpers/updateUserSubscription.js';
18
18
  import { processWebhook } from '../../shared/billing/webhookHandler.js';
19
19
  import { handleError } from '../../shared/errorHandling.js';
20
- import { stripe, validateStripeEnvironment } from '../../shared/utils.js';
20
+ import {
21
+ stripe,
22
+ validateStripeEnvironment,
23
+ initStripe,
24
+ } from '../../shared/utils.js'; // ✅ IMPORT INIT
21
25
  import { STRIPE_CONFIG } from '../config/constants.js';
26
+ import { stripeSecretKey, stripeWebhookSecret } from '../config/secrets.js'; // ✅ IMPORT SECRETS
22
27
 
23
28
  /**
24
29
  * Read raw body from request stream
@@ -42,10 +47,15 @@ async function getRawBody(req: any): Promise<Buffer> {
42
47
  /**
43
48
  * Create Firebase webhook handler from billing config
44
49
  */
45
- export function createStripeWebhook(billingConfig: StripeBackConfig) {
50
+ export function createStripeWebhook(
51
+ billingConfig: StripeBackConfig
52
+ ): HttpsFunction {
46
53
  return onRequest(STRIPE_CONFIG, async (req, res) => {
54
+ // ✅ LATEST BEST PRACTICE: Init with secret value
55
+ initStripe(stripeSecretKey.value());
56
+
47
57
  try {
48
- validateStripeEnvironment();
58
+ // validateStripeEnvironment(); // initStripe handles this now
49
59
 
50
60
  const sig = req.headers['stripe-signature'];
51
61
  if (!sig || Array.isArray(sig)) {
@@ -58,7 +68,9 @@ export function createStripeWebhook(billingConfig: StripeBackConfig) {
58
68
  throw handleError(error);
59
69
  }
60
70
 
61
- const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET;
71
+ // LATEST BEST PRACTICE: Use defineSecret value
72
+ const webhookSecret = stripeWebhookSecret.value();
73
+
62
74
  if (!webhookSecret) {
63
75
  const error = new Error('STRIPE_WEBHOOK_SECRET not configured');
64
76
  logger.error('[Webhook] Missing webhook secret', {
@@ -27,14 +27,19 @@ export const FUNCTION_CONFIG = {
27
27
  ...BASE_CONFIG,
28
28
  memory: '1GiB' as const,
29
29
  timeoutSeconds: 60,
30
+ cors: true, // Enable CORS by default for all functions (required for web apps)
30
31
  } as const;
31
32
 
33
+ import { stripeSecretKey, stripeWebhookSecret } from './secrets.js';
34
+
32
35
  /** Stripe/billing functions */
33
36
  export const STRIPE_CONFIG = {
34
37
  ...BASE_CONFIG,
35
38
  memory: '512MiB' as const,
36
39
  timeoutSeconds: 30,
37
- } as const;
40
+ cors: true,
41
+ secrets: [stripeSecretKey, stripeWebhookSecret],
42
+ };
38
43
 
39
44
  /** Auth functions */
40
45
  export const AUTH_CONFIG = {
@@ -48,6 +53,7 @@ export const CRUD_CONFIG = {
48
53
  ...BASE_CONFIG,
49
54
  memory: '256MiB' as const,
50
55
  timeoutSeconds: 15,
56
+ cors: true, // Enable CORS for cross-origin requests (required for web apps)
51
57
  } as const;
52
58
 
53
59
  /**
@@ -0,0 +1,32 @@
1
+ // packages/functions/src/firebase/config/secrets.ts
2
+
3
+ /**
4
+ * @fileoverview Firebase Functions V2 Secrets
5
+ * @description Definition of secrets using the modern defineSecret API
6
+ *
7
+ * @version 0.0.1
8
+ * @since 0.0.1
9
+ * @author AMBROISE PARK Consulting
10
+ */
11
+
12
+ import { defineSecret } from 'firebase-functions/params';
13
+
14
+ /**
15
+ * Stripe Secret Key
16
+ * Used for server-side Stripe API operations
17
+ */
18
+ export const stripeSecretKey = defineSecret('STRIPE_SECRET_KEY');
19
+
20
+ /**
21
+ * Stripe Webhook Secret
22
+ * Used to verify signatures of incoming Stripe webhooks
23
+ */
24
+ export const stripeWebhookSecret = defineSecret('STRIPE_WEBHOOK_SECRET');
25
+
26
+ /**
27
+ * GitHub Personal Access Token
28
+ * Used for GitHub API operations (repo access, etc.)
29
+ */
30
+ export const githubPersonalAccessToken = defineSecret(
31
+ 'GITHUB_PERSONAL_ACCESS_TOKEN'
32
+ );