@xbg.solutions/create-backend 1.0.0
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/bin/create-backend.js +3 -0
- package/lib/cli.d.ts +12 -0
- package/lib/cli.js +55 -0
- package/lib/cli.js.map +1 -0
- package/lib/commands/add-util.d.ts +9 -0
- package/lib/commands/add-util.js +119 -0
- package/lib/commands/add-util.js.map +1 -0
- package/lib/commands/init.d.ts +11 -0
- package/lib/commands/init.js +372 -0
- package/lib/commands/init.js.map +1 -0
- package/lib/commands/sync.d.ts +10 -0
- package/lib/commands/sync.js +161 -0
- package/lib/commands/sync.js.map +1 -0
- package/lib/utils-registry.d.ts +25 -0
- package/lib/utils-registry.js +187 -0
- package/lib/utils-registry.js.map +1 -0
- package/package.json +38 -0
- package/src/project-template/__examples__/README.md +559 -0
- package/src/project-template/__examples__/blog-platform.model.ts +528 -0
- package/src/project-template/__examples__/communications-usage.ts +175 -0
- package/src/project-template/__examples__/ecommerce-store.model.ts +1200 -0
- package/src/project-template/__examples__/saas-multi-tenant.model.ts +798 -0
- package/src/project-template/__examples__/user.model.ts +221 -0
- package/src/project-template/__scripts__/deploy.js +115 -0
- package/src/project-template/__scripts__/generate.js +122 -0
- package/src/project-template/__scripts__/setup.js +425 -0
- package/src/project-template/__scripts__/validate.js +325 -0
- package/src/project-template/firebase.json +32 -0
- package/src/project-template/firestore.rules +12 -0
- package/src/project-template/functions/jest.config.js +49 -0
- package/src/project-template/functions/src/index.ts +46 -0
- package/src/project-template/functions/tsconfig.json +38 -0
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Configuration Validation Script
|
|
5
|
+
* Validates that the backend project is properly configured
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const { execSync } = require('child_process');
|
|
11
|
+
|
|
12
|
+
const colors = {
|
|
13
|
+
reset: '\x1b[0m',
|
|
14
|
+
bright: '\x1b[1m',
|
|
15
|
+
dim: '\x1b[2m',
|
|
16
|
+
green: '\x1b[32m',
|
|
17
|
+
blue: '\x1b[34m',
|
|
18
|
+
yellow: '\x1b[33m',
|
|
19
|
+
red: '\x1b[31m',
|
|
20
|
+
cyan: '\x1b[36m',
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const CHECK_MARK = '✓';
|
|
24
|
+
const CROSS_MARK = '✗';
|
|
25
|
+
const WARNING_MARK = '⚠';
|
|
26
|
+
|
|
27
|
+
let errors = 0;
|
|
28
|
+
let warnings = 0;
|
|
29
|
+
let checks = 0;
|
|
30
|
+
|
|
31
|
+
function printHeader(title) {
|
|
32
|
+
console.log(`\n${colors.bright}${colors.blue}${title}${colors.reset}`);
|
|
33
|
+
console.log(`${colors.dim}${'─'.repeat(60)}${colors.reset}`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function printSuccess(message) {
|
|
37
|
+
checks++;
|
|
38
|
+
console.log(`${colors.green}${CHECK_MARK}${colors.reset} ${message}`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function printWarning(message) {
|
|
42
|
+
checks++;
|
|
43
|
+
warnings++;
|
|
44
|
+
console.log(`${colors.yellow}${WARNING_MARK}${colors.reset} ${message}`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function printError(message) {
|
|
48
|
+
checks++;
|
|
49
|
+
errors++;
|
|
50
|
+
console.log(`${colors.red}${CROSS_MARK}${colors.reset} ${message}`);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function fileExists(filePath) {
|
|
54
|
+
return fs.existsSync(path.join(__dirname, '..', filePath));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function readEnvFile() {
|
|
58
|
+
const envPath = path.join(__dirname, '../functions/.env');
|
|
59
|
+
if (!fs.existsSync(envPath)) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const envContent = fs.readFileSync(envPath, 'utf8');
|
|
64
|
+
const env = {};
|
|
65
|
+
|
|
66
|
+
envContent.split('\n').forEach(line => {
|
|
67
|
+
const trimmed = line.trim();
|
|
68
|
+
if (trimmed && !trimmed.startsWith('#')) {
|
|
69
|
+
const [key, ...valueParts] = trimmed.split('=');
|
|
70
|
+
env[key.trim()] = valueParts.join('=').trim();
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
return env;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function checkCommand(command, name) {
|
|
78
|
+
try {
|
|
79
|
+
execSync(`which ${command}`, { stdio: 'ignore' });
|
|
80
|
+
return true;
|
|
81
|
+
} catch {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function runCommand(command, cwd) {
|
|
87
|
+
try {
|
|
88
|
+
execSync(command, {
|
|
89
|
+
cwd: cwd || path.join(__dirname, '../functions'),
|
|
90
|
+
stdio: 'pipe',
|
|
91
|
+
encoding: 'utf8',
|
|
92
|
+
});
|
|
93
|
+
return true;
|
|
94
|
+
} catch (error) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
console.log(`
|
|
100
|
+
${colors.bright}${colors.blue}╔════════════════════════════════════════════════════════════╗
|
|
101
|
+
║ ║
|
|
102
|
+
║ 🔍 Backend Boilerplate Validation ║
|
|
103
|
+
║ ║
|
|
104
|
+
╚════════════════════════════════════════════════════════════╝${colors.reset}
|
|
105
|
+
`);
|
|
106
|
+
|
|
107
|
+
// Check prerequisites
|
|
108
|
+
printHeader('Prerequisites');
|
|
109
|
+
|
|
110
|
+
if (checkCommand('node', 'Node.js')) {
|
|
111
|
+
const nodeVersion = execSync('node --version', { encoding: 'utf8' }).trim();
|
|
112
|
+
printSuccess(`Node.js installed (${nodeVersion})`);
|
|
113
|
+
|
|
114
|
+
// Check Node.js version
|
|
115
|
+
const majorVersion = parseInt(nodeVersion.slice(1).split('.')[0]);
|
|
116
|
+
if (majorVersion < 22) {
|
|
117
|
+
printWarning(`Node.js version ${nodeVersion} is below recommended 22+`);
|
|
118
|
+
}
|
|
119
|
+
} else {
|
|
120
|
+
printError('Node.js not found - install from https://nodejs.org');
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (checkCommand('npm', 'npm')) {
|
|
124
|
+
const npmVersion = execSync('npm --version', { encoding: 'utf8' }).trim();
|
|
125
|
+
printSuccess(`npm installed (v${npmVersion})`);
|
|
126
|
+
} else {
|
|
127
|
+
printError('npm not found');
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (checkCommand('firebase', 'Firebase CLI')) {
|
|
131
|
+
const firebaseVersion = execSync('firebase --version', { encoding: 'utf8' }).trim();
|
|
132
|
+
printSuccess(`Firebase CLI installed (${firebaseVersion})`);
|
|
133
|
+
} else {
|
|
134
|
+
printWarning('Firebase CLI not found - install with: npm install -g firebase-tools');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Check project structure
|
|
138
|
+
printHeader('Project Structure');
|
|
139
|
+
|
|
140
|
+
const requiredFiles = [
|
|
141
|
+
'functions/package.json',
|
|
142
|
+
'functions/tsconfig.json',
|
|
143
|
+
'functions/src/index.ts',
|
|
144
|
+
'firebase.json',
|
|
145
|
+
'.firebaserc',
|
|
146
|
+
];
|
|
147
|
+
|
|
148
|
+
requiredFiles.forEach(file => {
|
|
149
|
+
if (fileExists(file)) {
|
|
150
|
+
printSuccess(`Found ${file}`);
|
|
151
|
+
} else {
|
|
152
|
+
printError(`Missing required file: ${file}`);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
const requiredDirs = [
|
|
157
|
+
'functions/src/config',
|
|
158
|
+
'functions/src/base',
|
|
159
|
+
'functions/src/middleware',
|
|
160
|
+
'functions/src/utilities',
|
|
161
|
+
'__scripts__',
|
|
162
|
+
'__docs__',
|
|
163
|
+
'__examples__',
|
|
164
|
+
];
|
|
165
|
+
|
|
166
|
+
requiredDirs.forEach(dir => {
|
|
167
|
+
if (fileExists(dir)) {
|
|
168
|
+
printSuccess(`Found directory: ${dir}`);
|
|
169
|
+
} else {
|
|
170
|
+
printWarning(`Directory not found: ${dir}`);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
// Check environment configuration
|
|
175
|
+
printHeader('Environment Configuration');
|
|
176
|
+
|
|
177
|
+
const env = readEnvFile();
|
|
178
|
+
|
|
179
|
+
if (env) {
|
|
180
|
+
printSuccess('.env file exists');
|
|
181
|
+
|
|
182
|
+
// Check for required environment variables
|
|
183
|
+
const requiredVars = [
|
|
184
|
+
'APP_NAME',
|
|
185
|
+
'NODE_ENV',
|
|
186
|
+
'FIREBASE_PROJECT_ID',
|
|
187
|
+
'API_BASE_PATH',
|
|
188
|
+
];
|
|
189
|
+
|
|
190
|
+
const optionalVars = [
|
|
191
|
+
'CORS_ORIGINS',
|
|
192
|
+
'LOG_LEVEL',
|
|
193
|
+
'RATE_LIMIT_ENABLED',
|
|
194
|
+
];
|
|
195
|
+
|
|
196
|
+
requiredVars.forEach(varName => {
|
|
197
|
+
if (env[varName]) {
|
|
198
|
+
if (env[varName].includes('FIXME') || env[varName].includes('your-')) {
|
|
199
|
+
printWarning(`${varName} is set but contains placeholder value`);
|
|
200
|
+
} else {
|
|
201
|
+
printSuccess(`${varName} is configured`);
|
|
202
|
+
}
|
|
203
|
+
} else {
|
|
204
|
+
printError(`Missing required environment variable: ${varName}`);
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
optionalVars.forEach(varName => {
|
|
209
|
+
if (env[varName]) {
|
|
210
|
+
printSuccess(`${varName} is configured`);
|
|
211
|
+
} else {
|
|
212
|
+
printWarning(`Optional variable ${varName} not set`);
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
} else {
|
|
217
|
+
printError('.env file not found - run: npm run setup');
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Check dependencies
|
|
221
|
+
printHeader('Dependencies');
|
|
222
|
+
|
|
223
|
+
const packageJsonPath = path.join(__dirname, '../functions/package.json');
|
|
224
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
225
|
+
printSuccess('package.json found');
|
|
226
|
+
|
|
227
|
+
const nodeModulesPath = path.join(__dirname, '../functions/node_modules');
|
|
228
|
+
if (fs.existsSync(nodeModulesPath)) {
|
|
229
|
+
printSuccess('node_modules directory exists');
|
|
230
|
+
} else {
|
|
231
|
+
printError('node_modules not found - run: npm install');
|
|
232
|
+
}
|
|
233
|
+
} else {
|
|
234
|
+
printError('package.json not found');
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Check TypeScript compilation
|
|
238
|
+
printHeader('TypeScript Compilation');
|
|
239
|
+
|
|
240
|
+
console.log(`${colors.dim}Running TypeScript compiler check...${colors.reset}`);
|
|
241
|
+
if (runCommand('npx tsc --noEmit')) {
|
|
242
|
+
printSuccess('TypeScript compilation check passed');
|
|
243
|
+
} else {
|
|
244
|
+
printWarning('TypeScript compilation has errors - run: npm run build');
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Check linting (if requested)
|
|
248
|
+
const skipLint = process.argv.includes('--skip-lint');
|
|
249
|
+
if (!skipLint) {
|
|
250
|
+
printHeader('Code Quality');
|
|
251
|
+
|
|
252
|
+
console.log(`${colors.dim}Running ESLint...${colors.reset}`);
|
|
253
|
+
if (runCommand('npm run lint')) {
|
|
254
|
+
printSuccess('ESLint passed');
|
|
255
|
+
} else {
|
|
256
|
+
printWarning('ESLint found issues - run: npm run lint:fix');
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Check tests (if requested)
|
|
261
|
+
const skipTests = process.argv.includes('--skip-tests');
|
|
262
|
+
if (!skipTests) {
|
|
263
|
+
printHeader('Tests');
|
|
264
|
+
|
|
265
|
+
console.log(`${colors.dim}Running test suite...${colors.reset}`);
|
|
266
|
+
if (runCommand('npm test')) {
|
|
267
|
+
printSuccess('All tests passed');
|
|
268
|
+
} else {
|
|
269
|
+
printError('Some tests failed - run: npm test');
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Check build (if requested)
|
|
274
|
+
const skipBuild = process.argv.includes('--skip-build');
|
|
275
|
+
if (!skipBuild) {
|
|
276
|
+
printHeader('Build');
|
|
277
|
+
|
|
278
|
+
console.log(`${colors.dim}Running production build...${colors.reset}`);
|
|
279
|
+
if (runCommand('npm run build')) {
|
|
280
|
+
printSuccess('Production build succeeded');
|
|
281
|
+
} else {
|
|
282
|
+
printError('Build failed - check TypeScript errors');
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Firebase configuration
|
|
287
|
+
printHeader('Firebase Configuration');
|
|
288
|
+
|
|
289
|
+
const firebaseRcPath = path.join(__dirname, '../.firebaserc');
|
|
290
|
+
if (fs.existsSync(firebaseRcPath)) {
|
|
291
|
+
try {
|
|
292
|
+
const firebaseRc = JSON.parse(fs.readFileSync(firebaseRcPath, 'utf8'));
|
|
293
|
+
if (firebaseRc.projects && firebaseRc.projects.default) {
|
|
294
|
+
printSuccess(`Firebase project: ${firebaseRc.projects.default}`);
|
|
295
|
+
} else {
|
|
296
|
+
printWarning('Firebase project not configured in .firebaserc');
|
|
297
|
+
}
|
|
298
|
+
} catch {
|
|
299
|
+
printError('Could not parse .firebaserc file');
|
|
300
|
+
}
|
|
301
|
+
} else {
|
|
302
|
+
printError('.firebaserc not found - run: firebase init');
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Summary
|
|
306
|
+
printHeader('Summary');
|
|
307
|
+
|
|
308
|
+
console.log(`
|
|
309
|
+
${colors.bright}Validation Results:${colors.reset}
|
|
310
|
+
${colors.green}${CHECK_MARK} ${checks - errors - warnings} checks passed${colors.reset}
|
|
311
|
+
${warnings > 0 ? `${colors.yellow}${WARNING_MARK} ${warnings} warnings${colors.reset}` : ''}
|
|
312
|
+
${errors > 0 ? `${colors.red}${CROSS_MARK} ${errors} errors${colors.reset}` : ''}
|
|
313
|
+
`);
|
|
314
|
+
|
|
315
|
+
if (errors === 0 && warnings === 0) {
|
|
316
|
+
console.log(`${colors.green}${colors.bright}✨ All checks passed! Your project is properly configured.${colors.reset}\n`);
|
|
317
|
+
process.exit(0);
|
|
318
|
+
} else if (errors === 0) {
|
|
319
|
+
console.log(`${colors.yellow}${colors.bright}⚠️ Validation completed with warnings. Review warnings above.${colors.reset}\n`);
|
|
320
|
+
process.exit(0);
|
|
321
|
+
} else {
|
|
322
|
+
console.log(`${colors.red}${colors.bright}❌ Validation failed. Fix the errors above before proceeding.${colors.reset}\n`);
|
|
323
|
+
console.log(`${colors.dim}Tip: Run ${colors.bright}npm run setup${colors.reset}${colors.dim} to configure the project automatically.${colors.reset}\n`);
|
|
324
|
+
process.exit(1);
|
|
325
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"firestore": {
|
|
3
|
+
"rules": "firestore.rules"
|
|
4
|
+
},
|
|
5
|
+
"functions": {
|
|
6
|
+
"source": "functions",
|
|
7
|
+
"runtime": "nodejs22",
|
|
8
|
+
"ignore": [
|
|
9
|
+
"node_modules",
|
|
10
|
+
".git",
|
|
11
|
+
"firebase-debug.log",
|
|
12
|
+
"firebase-debug.*.log"
|
|
13
|
+
],
|
|
14
|
+
"predeploy": [
|
|
15
|
+
"npm --prefix \"$RESOURCE_DIR\" run lint",
|
|
16
|
+
"npm --prefix \"$RESOURCE_DIR\" run build"
|
|
17
|
+
]
|
|
18
|
+
},
|
|
19
|
+
"emulators": {
|
|
20
|
+
"functions": {
|
|
21
|
+
"port": 5001
|
|
22
|
+
},
|
|
23
|
+
"firestore": {
|
|
24
|
+
"port": 8080
|
|
25
|
+
},
|
|
26
|
+
"ui": {
|
|
27
|
+
"enabled": true,
|
|
28
|
+
"port": 4000
|
|
29
|
+
},
|
|
30
|
+
"singleProjectMode": true
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
rules_version = '2';
|
|
2
|
+
service cloud.firestore {
|
|
3
|
+
match /databases/{database}/documents {
|
|
4
|
+
// Deny all client SDK access by default.
|
|
5
|
+
// This backend uses the Admin SDK (which bypasses rules).
|
|
6
|
+
// These rules act as defense-in-depth against accidental
|
|
7
|
+
// client-side database exposure.
|
|
8
|
+
match /{document=**} {
|
|
9
|
+
allow read, write: if false;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
preset: 'ts-jest',
|
|
3
|
+
testEnvironment: 'node',
|
|
4
|
+
roots: ['<rootDir>/src'],
|
|
5
|
+
testMatch: [
|
|
6
|
+
'**/__tests__/**/*.test.ts',
|
|
7
|
+
'**/?(*.)+(spec|test).ts'
|
|
8
|
+
],
|
|
9
|
+
transform: {
|
|
10
|
+
'^.+\\.ts$': 'ts-jest',
|
|
11
|
+
},
|
|
12
|
+
collectCoverageFrom: [
|
|
13
|
+
'src/**/*.ts',
|
|
14
|
+
'!src/**/*.d.ts',
|
|
15
|
+
'!src/**/__tests__/**',
|
|
16
|
+
'!src/index.ts',
|
|
17
|
+
'!src/server.ts',
|
|
18
|
+
'!src/generated/**',
|
|
19
|
+
],
|
|
20
|
+
coverageDirectory: 'coverage',
|
|
21
|
+
coverageReporters: ['text', 'lcov', 'html'],
|
|
22
|
+
coverageThreshold: {
|
|
23
|
+
global: {
|
|
24
|
+
branches: 70,
|
|
25
|
+
functions: 70,
|
|
26
|
+
lines: 70,
|
|
27
|
+
statements: 70,
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
setupFilesAfterEnv: ['<rootDir>/src/__tests__/setup.ts'],
|
|
31
|
+
moduleNameMapper: {
|
|
32
|
+
'^@/(.*)$': '<rootDir>/src/$1',
|
|
33
|
+
'^@utilities/(.*)$': '<rootDir>/src/utilities/$1',
|
|
34
|
+
'^@base/(.*)$': '<rootDir>/src/base/$1',
|
|
35
|
+
'^@middleware/(.*)$': '<rootDir>/src/middleware/$1',
|
|
36
|
+
'^@config/(.*)$': '<rootDir>/src/config/$1',
|
|
37
|
+
'^@generated/(.*)$': '<rootDir>/src/generated/$1',
|
|
38
|
+
},
|
|
39
|
+
globals: {
|
|
40
|
+
'ts-jest': {
|
|
41
|
+
tsconfig: {
|
|
42
|
+
esModuleInterop: true,
|
|
43
|
+
allowSyntheticDefaultImports: true,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
testTimeout: 10000,
|
|
48
|
+
verbose: true,
|
|
49
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Firebase Functions Entry Point
|
|
3
|
+
* Exports HTTP functions for Firebase deployment
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as functions from 'firebase-functions';
|
|
7
|
+
import { createApp } from '@xbg/backend-core';
|
|
8
|
+
import { logger } from '@xbg/utils-logger';
|
|
9
|
+
|
|
10
|
+
// Import controllers here as they are created
|
|
11
|
+
// import { UserController } from './generated/controllers/UserController';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Initialize controllers
|
|
15
|
+
* Add your generated or custom controllers here
|
|
16
|
+
*/
|
|
17
|
+
function initializeControllers(): Array<{ getRouter: () => any; getBasePath: () => string }> {
|
|
18
|
+
const controllers: Array<{ getRouter: () => any; getBasePath: () => string }> = [];
|
|
19
|
+
|
|
20
|
+
// Example:
|
|
21
|
+
// const userController = new UserController(userService, '/users');
|
|
22
|
+
// controllers.push(userController);
|
|
23
|
+
|
|
24
|
+
return controllers;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Create Express app with controllers
|
|
29
|
+
*/
|
|
30
|
+
const expressApp = createApp({
|
|
31
|
+
controllers: initializeControllers(),
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Export as Firebase HTTPS Function
|
|
36
|
+
*/
|
|
37
|
+
export const api = functions.https.onRequest(expressApp);
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Export for local development
|
|
41
|
+
*/
|
|
42
|
+
export { expressApp };
|
|
43
|
+
|
|
44
|
+
logger.info('Firebase Functions initialized', {
|
|
45
|
+
environment: process.env.NODE_ENV || 'development',
|
|
46
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"module": "commonjs",
|
|
4
|
+
"moduleResolution": "node",
|
|
5
|
+
"noImplicitReturns": true,
|
|
6
|
+
"noUnusedLocals": true,
|
|
7
|
+
"outDir": "lib",
|
|
8
|
+
"sourceMap": true,
|
|
9
|
+
"strict": true,
|
|
10
|
+
"target": "es2017",
|
|
11
|
+
"esModuleInterop": true,
|
|
12
|
+
"skipLibCheck": true,
|
|
13
|
+
"resolveJsonModule": true,
|
|
14
|
+
"declaration": true,
|
|
15
|
+
"declarationMap": true,
|
|
16
|
+
"forceConsistentCasingInFileNames": true,
|
|
17
|
+
"noImplicitAny": true,
|
|
18
|
+
"strictNullChecks": true,
|
|
19
|
+
"strictFunctionTypes": true,
|
|
20
|
+
"strictBindCallApply": true,
|
|
21
|
+
"strictPropertyInitialization": true,
|
|
22
|
+
"noImplicitThis": true,
|
|
23
|
+
"alwaysStrict": true,
|
|
24
|
+
"noFallthroughCasesInSwitch": true,
|
|
25
|
+
"experimentalDecorators": true,
|
|
26
|
+
"emitDecoratorMetadata": true,
|
|
27
|
+
"baseUrl": "."
|
|
28
|
+
},
|
|
29
|
+
"compileOnSave": true,
|
|
30
|
+
"include": [
|
|
31
|
+
"src/**/*"
|
|
32
|
+
],
|
|
33
|
+
"exclude": [
|
|
34
|
+
"node_modules",
|
|
35
|
+
"**/*.spec.ts",
|
|
36
|
+
"**/*.test.ts"
|
|
37
|
+
]
|
|
38
|
+
}
|