backend-manager 5.0.39 → 5.0.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.codeclimate.yml +32 -0
- package/CHANGELOG.md +25 -0
- package/CLAUDE.md +3 -2
- package/README.md +1 -0
- package/REFACTOR-BEM-API.md +6 -2
- package/TODO.md +149 -0
- package/bin/bem +1 -1
- package/package.json +2 -1
- package/src/cli/commands/base-command.js +59 -32
- package/src/cli/commands/emulators.js +39 -18
- package/src/cli/commands/setup-tests/emulators-config.js +2 -0
- package/src/cli/commands/setup-tests/hosting-rewrites.js +1 -0
- package/src/cli/commands/test.js +14 -19
- package/src/manager/cron/daily/ghostii-auto-publisher.js +278 -0
- package/src/manager/cron/daily/reset-usage.js +140 -0
- package/src/manager/cron/daily.js +54 -0
- package/src/manager/events/auth/before-create.js +52 -0
- package/src/manager/events/auth/before-signin.js +42 -0
- package/src/manager/events/auth/on-create.js +270 -0
- package/src/manager/events/auth/on-delete.js +94 -0
- package/src/manager/events/firestore/notifications/on-write.js +77 -0
- package/src/manager/functions/{core → _legacy}/actions/create-post-handler.js +10 -9
- package/src/manager/functions/core/actions/api/admin/edit-post.js +1 -1
- package/src/manager/functions/core/actions/api/admin/send-email.js +3 -3
- package/src/manager/functions/core/actions/api/general/add-marketing-contact.js +604 -0
- package/src/manager/functions/core/actions/api/general/remove-marketing-contact.js +234 -0
- package/src/manager/functions/core/actions/api/general/send-email.js +7 -3
- package/src/manager/functions/core/actions/api/user/delete.js +1 -1
- package/src/manager/functions/core/actions/api/user/oauth2.js +1 -1
- package/src/manager/functions/core/actions/api.js +40 -0
- package/src/manager/helpers/assistant.js +0 -1
- package/src/manager/helpers/event-middleware.js +94 -0
- package/src/manager/helpers/middleware.js +26 -23
- package/src/manager/helpers/settings.js +17 -13
- package/src/manager/index.js +35 -19
- package/src/manager/libraries/disposable-domains.json +839 -0
- package/src/manager/routes/admin/backup/post.js +105 -0
- package/src/manager/routes/admin/cron/post.js +37 -0
- package/src/manager/routes/admin/database/get.js +33 -0
- package/src/manager/routes/admin/database/post.js +32 -0
- package/src/manager/routes/admin/email/post.js +451 -0
- package/src/manager/routes/admin/firestore/get.js +33 -0
- package/src/manager/routes/admin/firestore/post.js +54 -0
- package/src/manager/routes/admin/firestore/query/post.js +126 -0
- package/src/manager/routes/admin/hook/post.js +83 -0
- package/src/manager/routes/admin/notification/post.js +260 -0
- package/src/manager/routes/admin/payment/post.js +56 -0
- package/src/manager/routes/admin/post/post.js +301 -0
- package/src/manager/routes/admin/post/put.js +136 -0
- package/src/manager/routes/admin/post/templates/post.html +15 -0
- package/src/manager/routes/admin/repo/content/post.js +102 -0
- package/src/manager/routes/admin/stats/get.js +213 -0
- package/src/manager/routes/admin/users/sync/post.js +119 -0
- package/src/manager/routes/content/post/get.js +104 -0
- package/src/manager/routes/firebase/providers/get.js +80 -0
- package/src/manager/routes/general/email/post.js +99 -0
- package/src/manager/routes/general/email/templates/download-app-link.js +25 -0
- package/src/manager/routes/general/uuid/post.js +34 -0
- package/src/manager/routes/handler/post/post.js +131 -0
- package/src/manager/routes/index.js +4 -20
- package/src/manager/routes/marketing/contact/delete.js +207 -0
- package/src/manager/routes/marketing/contact/post.js +504 -0
- package/src/manager/routes/restart/index.js +10 -22
- package/src/manager/routes/special/electron-client/post.js +72 -0
- package/src/manager/routes/test/authenticate/get.js +8 -0
- package/src/manager/routes/test/health/get.js +13 -0
- package/src/manager/routes/test/index.js +2 -26
- package/src/manager/routes/test/lab/post.js +17 -0
- package/src/manager/routes/test/redirect/get.js +9 -0
- package/src/manager/routes/test/schema/post.js +20 -0
- package/src/manager/routes/test/usage/post.js +50 -0
- package/src/manager/routes/test/webhook/post.js +21 -0
- package/src/manager/routes/user/api-keys/post.js +49 -0
- package/src/manager/routes/user/delete.js +71 -0
- package/src/manager/routes/user/feedback/post.js +85 -0
- package/src/manager/routes/user/get.js +14 -0
- package/src/manager/routes/user/oauth2/post.js +326 -0
- package/src/manager/routes/user/oauth2/providers/discord.js +47 -0
- package/src/manager/routes/user/oauth2/providers/google.js +38 -0
- package/src/manager/routes/user/sessions/delete.js +93 -0
- package/src/manager/routes/user/sessions/get.js +38 -0
- package/src/manager/routes/user/settings/validate/post.js +85 -0
- package/src/manager/routes/user/signup/post.js +185 -0
- package/src/manager/routes/user/subscription/get.js +61 -0
- package/src/manager/routes/user/token/post.js +28 -0
- package/src/manager/schemas/admin/backup/post.js +6 -0
- package/src/manager/schemas/admin/cron/post.js +6 -0
- package/src/manager/schemas/admin/database/get.js +7 -0
- package/src/manager/schemas/admin/database/post.js +12 -0
- package/src/manager/schemas/admin/email/post.js +20 -0
- package/src/manager/schemas/admin/firestore/get.js +7 -0
- package/src/manager/schemas/admin/firestore/post.js +22 -0
- package/src/manager/schemas/admin/firestore/query/post.js +7 -0
- package/src/manager/schemas/admin/hook/post.js +6 -0
- package/src/manager/schemas/admin/notification/post.js +21 -0
- package/src/manager/schemas/admin/payment/post.js +6 -0
- package/src/manager/schemas/admin/post/post.js +20 -0
- package/src/manager/schemas/admin/post/put.js +11 -0
- package/src/manager/schemas/admin/repo/content/post.js +10 -0
- package/src/manager/schemas/admin/stats/get.js +7 -0
- package/src/manager/schemas/admin/users/sync/post.js +6 -0
- package/src/manager/schemas/content/post/get.js +6 -0
- package/src/manager/schemas/firebase/providers/get.js +6 -0
- package/src/manager/schemas/general/email/post.js +8 -0
- package/src/manager/schemas/general/uuid/post.js +22 -0
- package/src/manager/schemas/handler/post/post.js +11 -0
- package/src/manager/schemas/marketing/contact/delete.js +7 -0
- package/src/manager/schemas/marketing/contact/post.js +13 -0
- package/src/manager/schemas/restart/index.js +6 -13
- package/src/manager/schemas/special/electron-client/post.js +9 -0
- package/src/manager/schemas/test/authenticate/get.js +1 -0
- package/src/manager/schemas/test/health/get.js +1 -0
- package/src/manager/schemas/test/index.js +6 -13
- package/src/manager/schemas/test/lab/post.js +1 -0
- package/src/manager/schemas/test/redirect/get.js +7 -0
- package/src/manager/schemas/test/schema/post.js +145 -0
- package/src/manager/schemas/test/usage/post.js +7 -0
- package/src/manager/schemas/test/webhook/post.js +17 -0
- package/src/manager/schemas/user/api-keys/post.js +12 -0
- package/src/manager/schemas/user/delete.js +7 -0
- package/src/manager/schemas/user/feedback/post.js +22 -0
- package/src/manager/schemas/user/get.js +1 -0
- package/src/manager/schemas/user/oauth2/post.js +77 -0
- package/src/manager/schemas/user/sessions/delete.js +12 -0
- package/src/manager/schemas/user/sessions/get.js +12 -0
- package/src/manager/schemas/user/settings/validate/post.js +22 -0
- package/src/manager/schemas/user/signup/post.js +22 -0
- package/src/manager/schemas/user/subscription/get.js +7 -0
- package/src/manager/schemas/user/token/post.js +7 -0
- package/src/test/run-tests.js +5 -2
- package/src/test/runner.js +123 -8
- package/src/test/test-accounts.js +113 -53
- package/src/test/utils/http-client.js +116 -131
- package/templates/_.env +11 -7
- package/test/_init/accounts-validation.js +58 -0
- package/test/_legacy/ai/index.js +231 -0
- package/test/_legacy/ai/test.jpg +0 -0
- package/test/_legacy/ai/test.pdf +0 -0
- package/test/_legacy/cli-commands.test.js +224 -0
- package/test/_legacy/index.js +31 -0
- package/test/_legacy/payment-resolver/chargebee/orders/refunded.json +0 -0
- package/test/_legacy/payment-resolver/chargebee/orders/unpaid.json +98 -0
- package/test/_legacy/payment-resolver/chargebee/subscriptions/active.json +578 -0
- package/test/_legacy/payment-resolver/chargebee/subscriptions/trial-in-trial.json +38 -0
- package/test/_legacy/payment-resolver/chargebee/subscriptions/trial-skipped-to-active.json +135 -0
- package/test/_legacy/payment-resolver/chargebee/subscriptions/trial-to-active-to-cancelled.json +42 -0
- package/test/_legacy/payment-resolver/chargebee/subscriptions/trial-to-active.json +44 -0
- package/test/_legacy/payment-resolver/chargebee/subscriptions/trial-to-cancelled.json +39 -0
- package/test/_legacy/payment-resolver/chargebee/subscriptions/trial-to-refund.json +143 -0
- package/test/_legacy/payment-resolver/chargebee/subscriptions/trial-to-suspended.json +48 -0
- package/test/_legacy/payment-resolver/coinbase/orders/regular.json +204 -0
- package/test/_legacy/payment-resolver/coinbase/subscriptions/cancelled.json +204 -0
- package/test/_legacy/payment-resolver/coinbase/subscriptions/paid-2.json +125 -0
- package/test/_legacy/payment-resolver/index.js +1558 -0
- package/test/_legacy/payment-resolver/paypal/orders/refunded.json +0 -0
- package/test/_legacy/payment-resolver/paypal/orders/regular.json +120 -0
- package/test/_legacy/payment-resolver/paypal/subscriptions/active-refund-previous-stmnt.json +323 -0
- package/test/_legacy/payment-resolver/paypal/subscriptions/active.json +192 -0
- package/test/_legacy/payment-resolver/paypal/subscriptions/trial-in-trial.json +125 -0
- package/test/_legacy/payment-resolver/paypal/subscriptions/trial-payment-not-complete.json +76 -0
- package/test/_legacy/payment-resolver/paypal/subscriptions/trial-payment-overdue-2.json +114 -0
- package/test/_legacy/payment-resolver/paypal/subscriptions/trial-payment-overdue.json +114 -0
- package/test/_legacy/payment-resolver/paypal/subscriptions/trial-to-active-to-cancelled.json +111 -0
- package/test/_legacy/payment-resolver/paypal/subscriptions/trial-to-active.json +132 -0
- package/test/_legacy/payment-resolver/paypal/subscriptions/trial-to-cancelled.json +107 -0
- package/test/_legacy/payment-resolver/paypal/subscriptions/trial-to-expired.json +91 -0
- package/test/_legacy/payment-resolver/paypal/subscriptions/trial-to-refund.json +147 -0
- package/test/_legacy/payment-resolver/paypal/subscriptions/trial-to-suspended.json +120 -0
- package/test/_legacy/payment-resolver/stripe/orders/refunded.json +0 -0
- package/test/_legacy/payment-resolver/stripe/orders/regular.json +91 -0
- package/test/_legacy/payment-resolver/stripe/subscriptions/active.json +421 -0
- package/test/_legacy/payment-resolver/stripe/subscriptions/trial-in-trial.json +349 -0
- package/test/_legacy/payment-resolver/stripe/subscriptions/trial-to-active-failed-authorization.json +430 -0
- package/test/_legacy/payment-resolver/stripe/subscriptions/trial-to-active.json +319 -0
- package/test/_legacy/payment-resolver/stripe/subscriptions/trial-to-cancelled.json +319 -0
- package/test/_legacy/payment-resolver/stripe/subscriptions/trial-to-refund.json +414 -0
- package/test/_legacy/payment-resolver/stripe/subscriptions/trial-to-suspended.json +319 -0
- package/test/_legacy/payment-resolver/stripe/subscriptions/unsure.json +339 -0
- package/test/_legacy/test-new +1178 -0
- package/test/_legacy/test.md +89 -0
- package/test/_legacy/usage.js +170 -0
- package/test/_legacy/user.js +31 -0
- package/test/functions/admin/database-read.js +148 -0
- package/test/functions/admin/database-write.js +173 -0
- package/test/functions/admin/edit-post.js +366 -0
- package/test/functions/admin/firestore-query.js +221 -0
- package/test/functions/admin/firestore-read.js +144 -0
- package/test/functions/admin/firestore-write.js +116 -0
- package/test/functions/admin/get-stats.js +115 -0
- package/test/functions/admin/send-email.js +206 -0
- package/test/functions/admin/send-notification.js +208 -0
- package/test/functions/admin/write-repo-content.js +223 -0
- package/test/functions/general/add-marketing-contact.js +373 -0
- package/test/functions/general/fetch-post.js +54 -0
- package/test/functions/general/generate-uuid.js +114 -0
- package/test/functions/test/authenticate.js +64 -0
- package/test/functions/user/create-custom-token.js +73 -0
- package/test/functions/user/delete.js +135 -0
- package/test/functions/user/get-active-sessions.js +111 -0
- package/test/functions/user/get-subscription-info.js +105 -0
- package/test/functions/user/regenerate-api-keys.js +156 -0
- package/test/functions/user/resolve.js +52 -0
- package/test/functions/user/sign-out-all-sessions.js +94 -0
- package/test/functions/user/sign-up.js +214 -0
- package/test/functions/user/submit-feedback.js +104 -0
- package/test/functions/user/validate-settings.js +82 -0
- package/test/routes/admin/database.js +144 -0
- package/test/routes/admin/email.js +163 -0
- package/test/routes/admin/firestore-query.js +217 -0
- package/test/routes/admin/firestore.js +141 -0
- package/test/routes/admin/notification.js +198 -0
- package/test/routes/admin/post.js +366 -0
- package/test/routes/admin/repo-content.js +223 -0
- package/test/routes/admin/stats.js +112 -0
- package/test/routes/content/post.js +54 -0
- package/test/routes/general/uuid.js +115 -0
- package/test/routes/marketing/contact.js +375 -0
- package/test/routes/test/authenticate.js +59 -0
- package/test/routes/test/schema.js +554 -0
- package/test/routes/test/usage.js +228 -0
- package/test/routes/user/api-keys.js +156 -0
- package/test/routes/user/delete.js +136 -0
- package/test/routes/user/feedback.js +104 -0
- package/test/routes/user/sessions.js +199 -0
- package/test/routes/user/settings-validate.js +82 -0
- package/test/routes/user/signup.js +214 -0
- package/test/routes/user/subscription.js +105 -0
- package/test/routes/user/token.js +73 -0
- package/test/routes/user/user.js +153 -0
- package/test/rules/notifications.js +410 -0
- package/test/rules/user.js +366 -0
- package/.gitignore FROM BEM TEMPALTE +0 -74
- package/_backup/analytics copy.js +0 -217
- package/_backup/assistant-old-auth.js +0 -116
- package/_backup/cli.js +0 -1435
- package/_backup/create-post-old.js +0 -215
- package/_backup/get-providers copy.js +0 -154
- package/firebase-debug.log +0 -444
- package/src/manager/functions/core/actions/api/handler/create-post.js +0 -145
- package/src/manager/functions/core/cron/daily/ghostii-auto-publisher.js +0 -376
- package/src/manager/functions/core/cron/daily/reset-usage.js +0 -173
- package/src/manager/functions/core/cron/daily.js +0 -114
- package/src/manager/functions/core/events/auth/before-create.js +0 -79
- package/src/manager/functions/core/events/auth/before-signin.js +0 -69
- package/src/manager/functions/core/events/auth/on-create.js +0 -360
- package/src/manager/functions/core/events/auth/on-delete.js +0 -135
- package/src/manager/functions/core/events/firestore/notifications/on-write.js +0 -118
- /package/src/cli/{cli-refactored.js → index.js} +0 -0
- /package/src/manager/functions/{core → _legacy}/actions/generate-uuid.js +0 -0
- /package/src/manager/functions/{core → _legacy}/actions/sign-up-handler.js +0 -0
- /package/src/manager/functions/{core → _legacy}/admin/create-post.js +0 -0
- /package/src/manager/functions/{core → _legacy}/admin/firestore-write.js +0 -0
- /package/src/manager/functions/{core → _legacy}/admin/get-stats.js +0 -0
- /package/src/manager/functions/{core → _legacy}/admin/query.js +0 -0
- /package/src/manager/functions/{core → _legacy}/admin/send-notification.js +0 -0
- /package/src/manager/functions/{core/actions/api → _legacy}/template.js +0 -0
- /package/src/manager/functions/{test → _legacy/test}/authenticate.js +0 -0
- /package/src/manager/functions/{test → _legacy/test}/webhook.js +0 -0
package/.codeclimate.yml
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
version: "2" # required to adjust maintainability checks
|
|
2
|
+
checks:
|
|
3
|
+
# argument-count:
|
|
4
|
+
# config:
|
|
5
|
+
# threshold: 4
|
|
6
|
+
# complex-logic:
|
|
7
|
+
# config:
|
|
8
|
+
# threshold: 4
|
|
9
|
+
# file-lines:
|
|
10
|
+
# config:
|
|
11
|
+
# threshold: 250
|
|
12
|
+
# method-complexity:
|
|
13
|
+
# config:
|
|
14
|
+
# threshold: 5
|
|
15
|
+
# method-count:
|
|
16
|
+
# config:
|
|
17
|
+
# threshold: 20
|
|
18
|
+
method-lines:
|
|
19
|
+
config:
|
|
20
|
+
threshold: 200
|
|
21
|
+
# nested-control-flow:
|
|
22
|
+
# config:
|
|
23
|
+
# threshold: 4
|
|
24
|
+
# return-statements:
|
|
25
|
+
# config:
|
|
26
|
+
# threshold: 4
|
|
27
|
+
# similar-code:
|
|
28
|
+
# config:
|
|
29
|
+
# threshold: # language-specific defaults. an override will affect all languages.
|
|
30
|
+
identical-code:
|
|
31
|
+
config:
|
|
32
|
+
threshold: 10
|
package/CHANGELOG.md
CHANGED
|
@@ -14,6 +14,31 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
|
14
14
|
- `Fixed` for any bug fixes.
|
|
15
15
|
- `Security` in case of vulnerabilities.
|
|
16
16
|
|
|
17
|
+
# [5.0.39] - 2025-01-12
|
|
18
|
+
### Added
|
|
19
|
+
- New test infrastructure with Firebase emulator support for reliable, isolated testing.
|
|
20
|
+
- Test runner with emulator auto-detection and startup.
|
|
21
|
+
- Test types: standalone, suite (sequential with shared state), group (independent).
|
|
22
|
+
- Built-in test accounts with SSOT configuration (basic, admin, premium-active, etc.).
|
|
23
|
+
- Firestore security rules testing support.
|
|
24
|
+
- HTTP client with auth helpers (`http.as('admin').command()`).
|
|
25
|
+
- Rich assertion library (`isSuccess`, `isError`, `hasProperty`, etc.).
|
|
26
|
+
- New `bm emulators` command for standalone emulator management.
|
|
27
|
+
- Enhanced `bm test` with path filtering and parallel test support.
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
- Reorganized test files to `test/functions/` with `admin/`, `user/`, `general/` categories.
|
|
31
|
+
- Standardized auth test naming to `unauthenticated-rejected`.
|
|
32
|
+
- Auth rejection tests moved to end of test files (before cleanup).
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
- Changed unauthenticated API error from 500 to 401 with proper "Authentication required" message.
|
|
36
|
+
|
|
37
|
+
### Removed
|
|
38
|
+
- Removed legacy test files (moved to `test/_legacy/`).
|
|
39
|
+
- Removed deprecated CLI files and templates.
|
|
40
|
+
- Consolidated test account creation from API endpoint to test runner.
|
|
41
|
+
|
|
17
42
|
# [5.0.31] - 2025-01-17
|
|
18
43
|
### Changed
|
|
19
44
|
- Refactored CLI to modular command architecture with individual command classes and test files for better maintainability.
|
package/CLAUDE.md
CHANGED
|
@@ -71,7 +71,7 @@ src/
|
|
|
71
71
|
routes/ # Built-in routes
|
|
72
72
|
schemas/ # Built-in schemas
|
|
73
73
|
cli/
|
|
74
|
-
|
|
74
|
+
index.js # CLI entry point
|
|
75
75
|
commands/ # CLI commands
|
|
76
76
|
templates/
|
|
77
77
|
backend-manager-config.json # Config template
|
|
@@ -521,13 +521,14 @@ assert.fail(message) // Explicit fail
|
|
|
521
521
|
| Batch utilities | `src/manager/helpers/utilities.js` |
|
|
522
522
|
| Main API handler | `src/manager/functions/core/actions/api.js` |
|
|
523
523
|
| Config template | `templates/backend-manager-config.json` |
|
|
524
|
-
| CLI entry | `src/cli/
|
|
524
|
+
| CLI entry | `src/cli/index.js` |
|
|
525
525
|
|
|
526
526
|
## Environment Detection
|
|
527
527
|
|
|
528
528
|
```javascript
|
|
529
529
|
assistant.isDevelopment() // true when ENVIRONMENT !== 'production' or in emulator
|
|
530
530
|
assistant.isProduction() // true when ENVIRONMENT === 'production'
|
|
531
|
+
assistant.isTesting() // true when running tests (via npx bm test)
|
|
531
532
|
```
|
|
532
533
|
|
|
533
534
|
## Response Headers
|
package/README.md
CHANGED
|
@@ -447,6 +447,7 @@ assistant.debug('Debug message');
|
|
|
447
447
|
// Environment
|
|
448
448
|
assistant.isDevelopment(); // true in emulator
|
|
449
449
|
assistant.isProduction(); // true in production
|
|
450
|
+
assistant.isTesting(); // true when running tests
|
|
450
451
|
|
|
451
452
|
// File uploads
|
|
452
453
|
const { fields, files } = await assistant.parseMultipartFormData();
|
package/REFACTOR-BEM-API.md
CHANGED
|
@@ -65,8 +65,12 @@ I would like each new route to have a great name clearly indicating its purpose,
|
|
|
65
65
|
|
|
66
66
|
Since we can build this new API system however we want, i also expect you to rewrite and refactor the BEM api endppints to be kickass, modern, and well designed.
|
|
67
67
|
|
|
68
|
+
Also, certain VERBS should be removed from the actual file/function names since they are implied by the HTTP method. For example, instead of having a generate-uuid.js file, we could just have uuid.js since the POST method implies that we are generating/creating a new one, or insetad of add-marketing-contact we could just have marketing-contact.js since the POST method implies adding a new one and GET would imply fetching them.
|
|
68
69
|
|
|
70
|
+
Next, some fucntions have a lot crammed isnide them that could use some separation. For example, in add-marketing-contact.js we have code for handling multiple email providers (SendGrid, Beehiiv) all jammed into a single file. I think we should refactor this to have a separate file for each provider in subfolder that handles the specifics of that provider, and then the main route file just calls those provider-specific files as needed. This will make it much easier to maintain and extend in the future as we add more providers.
|
|
69
71
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
+
Also, sometimes there are two endpoints that should be combined,for example
|
|
73
|
+
* /Users/ian/Developer/Repositories/ITW-Creative-Works/backend-manager/src/manager/functions/core/actions/api/general/add-marketing-contact.js
|
|
74
|
+
* /Users/ian/Developer/Repositories/ITW-Creative-Works/backend-manager/src/manager/functions/core/actions/api/general/remove-marketing-contact.js
|
|
75
|
+
These could be combined into a single marketing-contact.js file that handles both adding and removing based on the HTTP method (POST for add, DELETE for remove). This will make the API more RESTful and easier to understand.
|
|
72
76
|
|
package/TODO.md
CHANGED
|
@@ -26,3 +26,152 @@ BEM
|
|
|
26
26
|
|
|
27
27
|
ADD HEALTHCHECK TO BEM!!!
|
|
28
28
|
✗ https://api.clockii.com/backend-manager?command=healthcheck → fetch failed
|
|
29
|
+
|
|
30
|
+
TODO
|
|
31
|
+
|
|
32
|
+
# TEST REWRRK
|
|
33
|
+
btw... the account.json needs to be removed. remove it from BEM and the consumong project. when we make our test system, we DO NOT NEED TO STORE THE ACCOUBT IN A JSON file. we just need a source of truth in BEM for what uid/emails to look for
|
|
34
|
+
|
|
35
|
+
need a "projectScripts" that creates the npm start, npm test, etc scripts in the consuming project.
|
|
36
|
+
|
|
37
|
+
during test run, we need to check that the test accounts exist. we also need to ALWAYS reset them at the begining of the run to ensure they are in the proper format, specifically by resetting their usage, roles, amd subscriptipn
|
|
38
|
+
|
|
39
|
+
needa new account type that we can change the subscription level of to test the sub events? maybe _test-upgrade that starts free and we test how it progresses from free to paid to canceled?
|
|
40
|
+
|
|
41
|
+
# Use gitignore from backend-manager-tempalte
|
|
42
|
+
|
|
43
|
+
# CLEAN
|
|
44
|
+
having different ID and UID is messy and annoying, just make it the same
|
|
45
|
+
admin: {
|
|
46
|
+
id: 'admin',
|
|
47
|
+
uid: '_test-admin',
|
|
48
|
+
email: '_test.admin@{domain}',
|
|
49
|
+
|
|
50
|
+
should be "admin" for ALL
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
# TODO
|
|
54
|
+
Update deps
|
|
55
|
+
Remove unused deps like
|
|
56
|
+
* node-fetch
|
|
57
|
+
|
|
58
|
+
# MOVE LEGACY BEM INDIVIDUAL FUNCTIONS TO AN _OLD FOLDER
|
|
59
|
+
/Users/ian/Developer/Repositories/ITW-Creative-Works/backend-manager/src/manager/functions/core/actions/create-post-handler.js
|
|
60
|
+
/Users/ian/Developer/Repositories/ITW-Creative-Works/backend-manager/src/manager/functions/core/actions/generate-uuid.js
|
|
61
|
+
/Users/ian/Developer/Repositories/ITW-Creative-Works/backend-manager/src/manager/functions/core/actions/sign-up-handler.js
|
|
62
|
+
/Users/ian/Developer/Repositories/ITW-Creative-Works/backend-manager/src/manager/functions/test
|
|
63
|
+
/Users/ian/Developer/Repositories/ITW-Creative-Works/backend-manager/src/manager/functions/core/admin
|
|
64
|
+
|
|
65
|
+
# Things to deprecate
|
|
66
|
+
* api manager
|
|
67
|
+
|
|
68
|
+
# Email
|
|
69
|
+
Move the sendEmail function to HERE instead of calling ITW
|
|
70
|
+
|
|
71
|
+
# BEM TESTS
|
|
72
|
+
# User Auth rules
|
|
73
|
+
* User can only access their own user doc
|
|
74
|
+
* fails when trying to access another user's doc
|
|
75
|
+
* succeeds when accessing their own,
|
|
76
|
+
* fails when NOT authed
|
|
77
|
+
* fails when trying to perform an admin action (can create/use the test:admin http event to test this)
|
|
78
|
+
* fails when a user tries to write to a restricted field/key like roles, subscription, usage, etc (SEE RULES)
|
|
79
|
+
* Any other rules: /Users/ian/Developer/Repositories/ITW-Creative-Works/backend-manager/templates/firestore.rules
|
|
80
|
+
* User can delete their own user doc (can use _test-delete via user:delete http event)
|
|
81
|
+
* fails when trying to delete another user's doc
|
|
82
|
+
* succeeds when deleting their own,
|
|
83
|
+
* fails when NOT authed
|
|
84
|
+
|
|
85
|
+
# Signup Flow
|
|
86
|
+
* Create a referrer user and a referred user then use user:signup http event on the referred user to test that
|
|
87
|
+
* the referral code works and the bonus is applied to the referrer
|
|
88
|
+
* something is added to the account to denote it received the signup event??? not sure
|
|
89
|
+
* context data is added to the referred user's account
|
|
90
|
+
* a second signup event
|
|
91
|
+
|
|
92
|
+
# Test
|
|
93
|
+
* test:authenticate http event
|
|
94
|
+
* success when valid uid
|
|
95
|
+
* fail when invalid uid
|
|
96
|
+
* fail when no uid
|
|
97
|
+
* test admin
|
|
98
|
+
* all admin functions fail when not authed as admin
|
|
99
|
+
* test each admin function
|
|
100
|
+
|
|
101
|
+
# Usage
|
|
102
|
+
* Using an account with a specific plan, test that the usage limits are enforced
|
|
103
|
+
* success if user has access to the plan
|
|
104
|
+
* success if the user is within the usage limits
|
|
105
|
+
* fail if the user exceeds the usage limits
|
|
106
|
+
* fail if the user is on a plan that does not allow usage (free plan)
|
|
107
|
+
* successful usage should increment the usage count
|
|
108
|
+
|
|
109
|
+
# Events
|
|
110
|
+
* trigger cron daily
|
|
111
|
+
* it should reset temp usage for all users
|
|
112
|
+
* reset userdocs to current usage = 0
|
|
113
|
+
|
|
114
|
+
# Payment
|
|
115
|
+
* test subscription upgrade flow via http event
|
|
116
|
+
* start with free plan
|
|
117
|
+
* upgrade to paid plan
|
|
118
|
+
* verify plan is updated
|
|
119
|
+
* verify usage limits are updated
|
|
120
|
+
* downgrade back to free plan
|
|
121
|
+
* verify plan is updated
|
|
122
|
+
* verify usage limits are updated
|
|
123
|
+
|
|
124
|
+
# BEM API
|
|
125
|
+
# Admin
|
|
126
|
+
* All functions need to fail when not authed as admin
|
|
127
|
+
* then test each one
|
|
128
|
+
|
|
129
|
+
# Advanced
|
|
130
|
+
* test sub accounts
|
|
131
|
+
|
|
132
|
+
# payment system
|
|
133
|
+
* dont store a "resolved" status, but make a universal library that frontend and backend use to determine whther a user has access to a plan currently
|
|
134
|
+
|
|
135
|
+
# New bem api and test to make
|
|
136
|
+
# test:usage
|
|
137
|
+
* the fnction itself just utilizes the usage API to increment an arbitrary usage item
|
|
138
|
+
|
|
139
|
+
the test should check the usage storage and ensure that it was incremented successfully
|
|
140
|
+
|
|
141
|
+
# test for bm_cronDaily
|
|
142
|
+
then, we need to test the bm_cronDaily function to ensure that it does its things like clearing the usage storage properly
|
|
143
|
+
|
|
144
|
+
# test for schema
|
|
145
|
+
* a comprehesive schema with fields that test EVERY possible field type including required, default, min, max, "value" etc (both static and FUNCTIONS)
|
|
146
|
+
* test multiple plan levels including unathenticated, basic, & premium
|
|
147
|
+
|
|
148
|
+
# quetsion
|
|
149
|
+
* how does usage get reset? does it reset daily? or monthly?
|
|
150
|
+
* how do we set usage limits?
|
|
151
|
+
* per plan? or when users prmeium is updated do we set it inside their doc?
|
|
152
|
+
* if we store it per plan, where should we store the plan data? firestore or in code?
|
|
153
|
+
* if its firestore we will use lots of reads, if we store in code we have to push new code to update plan limits (not a huge issue)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
change name from routes/content/post to maye routes/blog/post??? whatfdo you think??
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
# MIGRATIONS
|
|
160
|
+
## user
|
|
161
|
+
affiliate: {
|
|
162
|
+
referrer: affiliateCode,
|
|
163
|
+
},
|
|
164
|
+
-->
|
|
165
|
+
attribution.affiliate.code
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
## OLD TESTS
|
|
171
|
+
"_test": "npm run prepare && ./node_modules/mocha/bin/mocha test/ --recursive --timeout=10000",
|
|
172
|
+
"test": "./node_modules/mocha/bin/mocha test/ --recursive --timeout=10000",
|
|
173
|
+
"test:cli": "./node_modules/mocha/bin/mocha test/cli-commands.test.js --timeout=10000",
|
|
174
|
+
"test:usage": "./node_modules/mocha/bin/mocha test/usage.js --timeout=10000",
|
|
175
|
+
"test:payment-resolver": "./node_modules/mocha/bin/mocha test/payment-resolver/index.js --timeout=10000",
|
|
176
|
+
"test:user": "./node_modules/mocha/bin/mocha test/user.js --timeout=10000",
|
|
177
|
+
"test:ai": "./node_modules/mocha/bin/mocha test/ai/index.js --timeout=10000",
|
package/bin/bem
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "backend-manager",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.41",
|
|
4
4
|
"description": "Quick tools for developing Firebase functions",
|
|
5
5
|
"main": "src/manager/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@firebase/rules-unit-testing": "^5.0.0",
|
|
47
|
+
"@google-cloud/pubsub": "^5.2.2",
|
|
47
48
|
"@google-cloud/storage": "^7.16.0",
|
|
48
49
|
"@octokit/rest": "^19.0.13",
|
|
49
50
|
"@sendgrid/mail": "^7.7.0",
|
|
@@ -42,11 +42,12 @@ class BaseCommand {
|
|
|
42
42
|
.filter(([_, port]) => port)
|
|
43
43
|
.map(([name, port]) => ({ name, port }));
|
|
44
44
|
|
|
45
|
+
// Collect ALL processes on each blocked port
|
|
45
46
|
const blockedPorts = [];
|
|
46
47
|
for (const { name, port } of portsToCheck) {
|
|
47
|
-
const
|
|
48
|
-
if (
|
|
49
|
-
blockedPorts.push({ name, port,
|
|
48
|
+
const processes = this.getProcessesOnPort(port);
|
|
49
|
+
if (processes) {
|
|
50
|
+
blockedPorts.push({ name, port, processes });
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
53
|
|
|
@@ -55,9 +56,11 @@ class BaseCommand {
|
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
this.log(chalk.yellow('\n The following ports are in use:'));
|
|
58
|
-
for (const { name, port,
|
|
59
|
-
const
|
|
60
|
-
|
|
59
|
+
for (const { name, port, processes } of blockedPorts) {
|
|
60
|
+
for (const { pid, processName, command } of processes) {
|
|
61
|
+
const cmdInfo = command ? ` ${command}` : '';
|
|
62
|
+
this.log(chalk.gray(` - ${name} emulator (port ${port}) - PID ${pid} (${processName})${cmdInfo}`));
|
|
63
|
+
}
|
|
61
64
|
}
|
|
62
65
|
|
|
63
66
|
const { shouldKill } = await inquirer.prompt([{
|
|
@@ -72,13 +75,19 @@ class BaseCommand {
|
|
|
72
75
|
return false;
|
|
73
76
|
}
|
|
74
77
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
// Kill ALL processes on each blocked port
|
|
79
|
+
for (const { name, port, processes } of blockedPorts) {
|
|
80
|
+
for (const { pid } of processes) {
|
|
81
|
+
try {
|
|
82
|
+
process.kill(pid, 'SIGKILL');
|
|
83
|
+
this.log(chalk.green(` ✓ Killed process ${pid} on port ${port} (${name})`));
|
|
84
|
+
} catch (error) {
|
|
85
|
+
// ESRCH means process already dead - that's fine
|
|
86
|
+
if (error.code !== 'ESRCH') {
|
|
87
|
+
this.logError(` ✗ Failed to kill process ${pid}: ${error.message}`);
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
82
91
|
}
|
|
83
92
|
}
|
|
84
93
|
|
|
@@ -88,39 +97,57 @@ class BaseCommand {
|
|
|
88
97
|
}
|
|
89
98
|
|
|
90
99
|
/**
|
|
91
|
-
* Get info about
|
|
100
|
+
* Get info about ALL processes using a specific port
|
|
92
101
|
* @param {number} port - Port number to check
|
|
93
|
-
* @returns {object|null} -
|
|
102
|
+
* @returns {object[]|null} - Array of process info if port is in use, null otherwise
|
|
94
103
|
*/
|
|
95
|
-
|
|
104
|
+
getProcessesOnPort(port) {
|
|
96
105
|
try {
|
|
97
106
|
const result = execSync(`lsof -ti:${port} 2>/dev/null`, { encoding: 'utf8' });
|
|
98
|
-
const
|
|
99
|
-
|
|
107
|
+
const pids = result.trim().split('\n')
|
|
108
|
+
.map(line => parseInt(line.trim(), 10))
|
|
109
|
+
.filter(pid => !isNaN(pid));
|
|
110
|
+
|
|
111
|
+
if (pids.length === 0) {
|
|
100
112
|
return null;
|
|
101
113
|
}
|
|
102
114
|
|
|
103
|
-
// Get
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
115
|
+
// Get unique PIDs (lsof can return duplicates for multiple connections)
|
|
116
|
+
const uniquePids = [...new Set(pids)];
|
|
117
|
+
|
|
118
|
+
const processes = uniquePids.map(pid => {
|
|
119
|
+
let processName = 'unknown';
|
|
120
|
+
let command = '';
|
|
121
|
+
try {
|
|
122
|
+
const psResult = execSync(`ps -p ${pid} -o comm=,args= 2>/dev/null`, { encoding: 'utf8' });
|
|
123
|
+
const parts = psResult.trim().split(/\s+/);
|
|
124
|
+
processName = parts[0] || 'unknown';
|
|
125
|
+
command = parts.slice(1).join(' ').substring(0, 100);
|
|
126
|
+
if (command.length === 100) {
|
|
127
|
+
command += '...';
|
|
128
|
+
}
|
|
129
|
+
} catch (e) {
|
|
130
|
+
// Ignore - just use defaults
|
|
113
131
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
132
|
+
return { pid, processName, command };
|
|
133
|
+
});
|
|
117
134
|
|
|
118
|
-
return
|
|
135
|
+
return processes.length > 0 ? processes : null;
|
|
119
136
|
} catch (error) {
|
|
120
137
|
return null;
|
|
121
138
|
}
|
|
122
139
|
}
|
|
123
140
|
|
|
141
|
+
/**
|
|
142
|
+
* Get info about a process using a specific port (returns first process only for backwards compatibility)
|
|
143
|
+
* @param {number} port - Port number to check
|
|
144
|
+
* @returns {object|null} - Process info if port is in use, null otherwise
|
|
145
|
+
*/
|
|
146
|
+
getProcessOnPort(port) {
|
|
147
|
+
const processes = this.getProcessesOnPort(port);
|
|
148
|
+
return processes ? processes[0] : null;
|
|
149
|
+
}
|
|
150
|
+
|
|
124
151
|
/**
|
|
125
152
|
* Check if a port is in use
|
|
126
153
|
* @param {number} port - Port number to check
|
|
@@ -9,39 +9,60 @@ const { DEFAULT_EMULATOR_PORTS } = require('./setup-tests/emulators-config');
|
|
|
9
9
|
|
|
10
10
|
class EmulatorsCommand extends BaseCommand {
|
|
11
11
|
async execute() {
|
|
12
|
-
const projectDir = this.main.firebaseProjectPath;
|
|
13
|
-
|
|
14
|
-
// Load emulator ports from firebase.json
|
|
15
|
-
const emulatorPorts = this.loadEmulatorPorts(projectDir);
|
|
16
|
-
|
|
17
|
-
// Check for port conflicts before starting emulators
|
|
18
|
-
const canProceed = await this.checkAndKillBlockingProcesses(emulatorPorts);
|
|
19
|
-
if (!canProceed) {
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
12
|
this.log(chalk.cyan('\n Starting Firebase emulators (keep-alive mode)...\n'));
|
|
24
13
|
this.log(chalk.gray(' Emulators will stay running until you press Ctrl+C\n'));
|
|
25
14
|
|
|
15
|
+
// Warn if TEST_EXTENDED_MODE is enabled
|
|
16
|
+
if (process.env.TEST_EXTENDED_MODE) {
|
|
17
|
+
this.log(chalk.yellow.bold('\n ⚠️⚠️⚠️ WARNING: TEST_EXTENDED_MODE IS TRUE ⚠️⚠️⚠️'));
|
|
18
|
+
this.log(chalk.yellow(' External API calls (emails, SendGrid, etc.) are ENABLED!'));
|
|
19
|
+
this.log(chalk.yellow(' This will send real emails and make real API calls.\n'));
|
|
20
|
+
}
|
|
21
|
+
|
|
26
22
|
// Start BEM watcher in background
|
|
27
23
|
const watcher = new WatchCommand(this.main);
|
|
28
24
|
watcher.startBackground();
|
|
29
25
|
|
|
30
|
-
//
|
|
31
|
-
|
|
32
|
-
const emulatorsCommand = `BEM_TESTING=true firebase emulators:exec --only functions,firestore,auth,database --ui 'echo ""; echo "Emulators ready. Press Ctrl+C to shut down..."; sleep 86400'`;
|
|
26
|
+
// Run emulators with keep-alive command (use single quotes since runWithEmulators wraps in double quotes)
|
|
27
|
+
const keepAliveCommand = "echo ''; echo 'Emulators ready. Press Ctrl+C to shut down...'; sleep 86400";
|
|
33
28
|
|
|
34
29
|
try {
|
|
35
|
-
await
|
|
36
|
-
log: true,
|
|
37
|
-
cwd: projectDir,
|
|
38
|
-
});
|
|
30
|
+
await this.runWithEmulators(keepAliveCommand);
|
|
39
31
|
} catch (error) {
|
|
40
32
|
// User pressed Ctrl+C - this is expected
|
|
41
33
|
this.log(chalk.gray('\n Emulators stopped.\n'));
|
|
42
34
|
}
|
|
43
35
|
}
|
|
44
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Run a command with Firebase emulators
|
|
39
|
+
* @param {string} command - The command to execute inside emulators:exec
|
|
40
|
+
* @returns {Promise<void>}
|
|
41
|
+
*/
|
|
42
|
+
async runWithEmulators(command) {
|
|
43
|
+
const projectDir = this.main.firebaseProjectPath;
|
|
44
|
+
|
|
45
|
+
// Load emulator ports from firebase.json
|
|
46
|
+
const emulatorPorts = this.loadEmulatorPorts(projectDir);
|
|
47
|
+
|
|
48
|
+
// Check for port conflicts before starting emulators
|
|
49
|
+
const canProceed = await this.checkAndKillBlockingProcesses(emulatorPorts);
|
|
50
|
+
if (!canProceed) {
|
|
51
|
+
throw new Error('Port conflicts could not be resolved');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// BEM_TESTING=true is passed so Functions skip external API calls (emails, SendGrid)
|
|
55
|
+
// hosting is included so localhost:5002 rewrites work (e.g., /backend-manager -> bm_api)
|
|
56
|
+
// pubsub is included so scheduled functions (bm_cronDaily) can be triggered in tests
|
|
57
|
+
// Use double quotes for command wrapper since the command may contain single quotes (JSON strings)
|
|
58
|
+
const emulatorsCommand = `BEM_TESTING=true firebase emulators:exec --only functions,firestore,auth,database,hosting,pubsub --ui "${command}"`;
|
|
59
|
+
|
|
60
|
+
await powertools.execute(emulatorsCommand, {
|
|
61
|
+
log: true,
|
|
62
|
+
cwd: projectDir,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
45
66
|
/**
|
|
46
67
|
* Load emulator ports from firebase.json or use defaults
|
|
47
68
|
*/
|
|
@@ -10,6 +10,7 @@ const DEFAULT_EMULATOR_PORTS = {
|
|
|
10
10
|
database: 9000,
|
|
11
11
|
hosting: 5002,
|
|
12
12
|
storage: 9199,
|
|
13
|
+
pubsub: 8085,
|
|
13
14
|
ui: 4000,
|
|
14
15
|
};
|
|
15
16
|
|
|
@@ -20,6 +21,7 @@ const REQUIRED_EMULATORS = {
|
|
|
20
21
|
database: { port: DEFAULT_EMULATOR_PORTS.database },
|
|
21
22
|
hosting: { port: DEFAULT_EMULATOR_PORTS.hosting },
|
|
22
23
|
storage: { port: DEFAULT_EMULATOR_PORTS.storage },
|
|
24
|
+
pubsub: { port: DEFAULT_EMULATOR_PORTS.pubsub },
|
|
23
25
|
ui: { enabled: true },
|
|
24
26
|
};
|
|
25
27
|
|
package/src/cli/commands/test.js
CHANGED
|
@@ -5,6 +5,7 @@ const jetpack = require('fs-jetpack');
|
|
|
5
5
|
const JSON5 = require('json5');
|
|
6
6
|
const powertools = require('node-powertools');
|
|
7
7
|
const { DEFAULT_EMULATOR_PORTS } = require('./setup-tests/emulators-config');
|
|
8
|
+
const EmulatorsCommand = require('./emulators');
|
|
8
9
|
|
|
9
10
|
class TestCommand extends BaseCommand {
|
|
10
11
|
async execute() {
|
|
@@ -28,12 +29,14 @@ class TestCommand extends BaseCommand {
|
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
// Build unified test config object
|
|
32
|
+
// Use hosting URL for all API requests (rewrites to bm_api function)
|
|
31
33
|
const testConfig = {
|
|
32
34
|
...projectConfig,
|
|
33
|
-
|
|
35
|
+
hostingUrl: `http://127.0.0.1:${emulatorPorts.hosting}`,
|
|
34
36
|
projectDir,
|
|
35
37
|
testPaths,
|
|
36
38
|
emulatorPorts,
|
|
39
|
+
includeLegacy: argv.legacy || false, // Include legacy tests from test/functions/
|
|
37
40
|
};
|
|
38
41
|
|
|
39
42
|
// Build the test command
|
|
@@ -47,7 +50,7 @@ class TestCommand extends BaseCommand {
|
|
|
47
50
|
await this.runTestsDirectly(testCommand, functionsDir, emulatorPorts);
|
|
48
51
|
} else {
|
|
49
52
|
this.log(chalk.cyan('Starting emulators and running tests...'));
|
|
50
|
-
await this.runEmulatorTests(testCommand
|
|
53
|
+
await this.runEmulatorTests(testCommand);
|
|
51
54
|
}
|
|
52
55
|
}
|
|
53
56
|
|
|
@@ -103,6 +106,7 @@ class TestCommand extends BaseCommand {
|
|
|
103
106
|
const projectId = config.firebaseConfig?.projectId;
|
|
104
107
|
const backendManagerKey = argv.key || process.env.BACKEND_MANAGER_KEY;
|
|
105
108
|
const appId = config.brand?.id;
|
|
109
|
+
const brandName = config.brand?.name;
|
|
106
110
|
const githubRepoWebsite = config.github?.repo_website;
|
|
107
111
|
|
|
108
112
|
// Extract domain from brand.contact.email (e.g., 'support@example.com' -> 'example.com')
|
|
@@ -131,7 +135,7 @@ class TestCommand extends BaseCommand {
|
|
|
131
135
|
return null;
|
|
132
136
|
}
|
|
133
137
|
|
|
134
|
-
return { appId, projectId, backendManagerKey, domain, githubRepoWebsite };
|
|
138
|
+
return { appId, projectId, backendManagerKey, domain, brandName, githubRepoWebsite };
|
|
135
139
|
}
|
|
136
140
|
|
|
137
141
|
/**
|
|
@@ -140,9 +144,9 @@ class TestCommand extends BaseCommand {
|
|
|
140
144
|
buildTestCommand(testConfig) {
|
|
141
145
|
const testScriptPath = path.join(__dirname, '..', '..', 'test', 'run-tests.js');
|
|
142
146
|
|
|
143
|
-
// Pass entire config as JSON
|
|
147
|
+
// Pass entire config as base64-encoded JSON to avoid shell escaping issues
|
|
144
148
|
const testEnv = {
|
|
145
|
-
BEM_TEST_CONFIG: JSON.stringify(testConfig),
|
|
149
|
+
BEM_TEST_CONFIG: Buffer.from(JSON.stringify(testConfig)).toString('base64'),
|
|
146
150
|
FIRESTORE_EMULATOR_HOST: `127.0.0.1:${testConfig.emulatorPorts.firestore}`,
|
|
147
151
|
FIREBASE_AUTH_EMULATOR_HOST: `127.0.0.1:${testConfig.emulatorPorts.auth}`,
|
|
148
152
|
};
|
|
@@ -167,7 +171,7 @@ class TestCommand extends BaseCommand {
|
|
|
167
171
|
* Run tests directly (emulators already running)
|
|
168
172
|
*/
|
|
169
173
|
async runTestsDirectly(testCommand, functionsDir, emulatorPorts) {
|
|
170
|
-
this.log(chalk.gray(`
|
|
174
|
+
this.log(chalk.gray(` Hosting: http://127.0.0.1:${emulatorPorts.hosting}`));
|
|
171
175
|
this.log(chalk.gray(` Firestore: 127.0.0.1:${emulatorPorts.firestore}`));
|
|
172
176
|
this.log(chalk.gray(` Auth: 127.0.0.1:${emulatorPorts.auth}`));
|
|
173
177
|
this.log(chalk.gray(` UI: http://127.0.0.1:${emulatorPorts.ui}\n`));
|
|
@@ -185,23 +189,14 @@ class TestCommand extends BaseCommand {
|
|
|
185
189
|
/**
|
|
186
190
|
* Run tests with Firebase emulators (starts emulators, runs tests, shuts down)
|
|
187
191
|
*/
|
|
188
|
-
async runEmulatorTests(testCommand
|
|
189
|
-
// Check for port conflicts before starting emulators
|
|
190
|
-
const canProceed = await this.checkAndKillBlockingProcesses(emulatorPorts);
|
|
191
|
-
if (!canProceed) {
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
|
|
192
|
+
async runEmulatorTests(testCommand) {
|
|
195
193
|
this.log(chalk.gray(' Starting Firebase emulators...\n'));
|
|
196
194
|
|
|
197
|
-
//
|
|
198
|
-
const
|
|
195
|
+
// Use EmulatorsCommand to run tests with emulators
|
|
196
|
+
const emulatorsCmd = new EmulatorsCommand(this.main);
|
|
199
197
|
|
|
200
198
|
try {
|
|
201
|
-
await
|
|
202
|
-
log: true,
|
|
203
|
-
cwd: projectDir,
|
|
204
|
-
});
|
|
199
|
+
await emulatorsCmd.runWithEmulators(testCommand);
|
|
205
200
|
} catch (error) {
|
|
206
201
|
// Only exit with error if it wasn't a user-initiated exit
|
|
207
202
|
if (error.code !== 0) {
|