@soulbatical/tetra-core 0.1.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.
Potentially problematic release.
This version of @soulbatical/tetra-core might be problematic. Click here for more details.
- package/dist/core/SupabaseUserClient.d.ts +14 -0
- package/dist/core/SupabaseUserClient.d.ts.map +1 -0
- package/dist/core/SupabaseUserClient.js +49 -0
- package/dist/core/SupabaseUserClient.js.map +1 -0
- package/dist/core/adminDb.d.ts +21 -0
- package/dist/core/adminDb.d.ts.map +1 -0
- package/dist/core/adminDb.js +43 -0
- package/dist/core/adminDb.js.map +1 -0
- package/dist/core/publicDb.d.ts +19 -0
- package/dist/core/publicDb.d.ts.map +1 -0
- package/dist/core/publicDb.js +29 -0
- package/dist/core/publicDb.js.map +1 -0
- package/dist/core/superadminDb.d.ts +29 -0
- package/dist/core/superadminDb.d.ts.map +1 -0
- package/dist/core/superadminDb.js +53 -0
- package/dist/core/superadminDb.js.map +1 -0
- package/dist/core/systemDb.d.ts +34 -0
- package/dist/core/systemDb.d.ts.map +1 -0
- package/dist/core/systemDb.js +64 -0
- package/dist/core/systemDb.js.map +1 -0
- package/dist/core/userDb.d.ts +22 -0
- package/dist/core/userDb.d.ts.map +1 -0
- package/dist/core/userDb.js +36 -0
- package/dist/core/userDb.js.map +1 -0
- package/dist/core/webhookDb.d.ts +16 -0
- package/dist/core/webhookDb.d.ts.map +1 -0
- package/dist/core/webhookDb.js +26 -0
- package/dist/core/webhookDb.js.map +1 -0
- package/dist/frontend/components/FeatureFilters.d.ts +81 -0
- package/dist/frontend/components/FeatureFilters.d.ts.map +1 -0
- package/dist/frontend/components/FeatureFilters.js +257 -0
- package/dist/frontend/components/FeatureFilters.js.map +1 -0
- package/dist/frontend/components/FeatureTable.d.ts +96 -0
- package/dist/frontend/components/FeatureTable.d.ts.map +1 -0
- package/dist/frontend/components/FeatureTable.js +279 -0
- package/dist/frontend/components/FeatureTable.js.map +1 -0
- package/dist/frontend/hooks/useFeature.d.ts +108 -0
- package/dist/frontend/hooks/useFeature.d.ts.map +1 -0
- package/dist/frontend/hooks/useFeature.js +354 -0
- package/dist/frontend/hooks/useFeature.js.map +1 -0
- package/dist/frontend/index.d.ts +17 -0
- package/dist/frontend/index.d.ts.map +1 -0
- package/dist/frontend/index.js +14 -0
- package/dist/frontend/index.js.map +1 -0
- package/dist/index.d.ts +78 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +71 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/authMiddleware.d.ts +137 -0
- package/dist/middleware/authMiddleware.d.ts.map +1 -0
- package/dist/middleware/authMiddleware.js +292 -0
- package/dist/middleware/authMiddleware.js.map +1 -0
- package/dist/middleware/autoRegisterValidators.d.ts +31 -0
- package/dist/middleware/autoRegisterValidators.d.ts.map +1 -0
- package/dist/middleware/autoRegisterValidators.js +125 -0
- package/dist/middleware/autoRegisterValidators.js.map +1 -0
- package/dist/middleware/validateQueryParams.d.ts +62 -0
- package/dist/middleware/validateQueryParams.d.ts.map +1 -0
- package/dist/middleware/validateQueryParams.js +321 -0
- package/dist/middleware/validateQueryParams.js.map +1 -0
- package/dist/shared/controllers/BaseMutationController.d.ts +79 -0
- package/dist/shared/controllers/BaseMutationController.d.ts.map +1 -0
- package/dist/shared/controllers/BaseMutationController.js +241 -0
- package/dist/shared/controllers/BaseMutationController.js.map +1 -0
- package/dist/shared/controllers/BaseQueryController.d.ts +72 -0
- package/dist/shared/controllers/BaseQueryController.d.ts.map +1 -0
- package/dist/shared/controllers/BaseQueryController.js +375 -0
- package/dist/shared/controllers/BaseQueryController.js.map +1 -0
- package/dist/shared/controllers/FilterConfigController.d.ts +37 -0
- package/dist/shared/controllers/FilterConfigController.d.ts.map +1 -0
- package/dist/shared/controllers/FilterConfigController.js +94 -0
- package/dist/shared/controllers/FilterConfigController.js.map +1 -0
- package/dist/shared/controllers/index.d.ts +5 -0
- package/dist/shared/controllers/index.d.ts.map +1 -0
- package/dist/shared/controllers/index.js +4 -0
- package/dist/shared/controllers/index.js.map +1 -0
- package/dist/shared/controllers/types.d.ts +57 -0
- package/dist/shared/controllers/types.d.ts.map +1 -0
- package/dist/shared/controllers/types.js +2 -0
- package/dist/shared/controllers/types.js.map +1 -0
- package/dist/shared/factories/BatchRouteFactory.d.ts +33 -0
- package/dist/shared/factories/BatchRouteFactory.d.ts.map +1 -0
- package/dist/shared/factories/BatchRouteFactory.js +54 -0
- package/dist/shared/factories/BatchRouteFactory.js.map +1 -0
- package/dist/shared/factories/MutationRouteFactory.d.ts +27 -0
- package/dist/shared/factories/MutationRouteFactory.d.ts.map +1 -0
- package/dist/shared/factories/MutationRouteFactory.js +39 -0
- package/dist/shared/factories/MutationRouteFactory.js.map +1 -0
- package/dist/shared/factories/PhaseRouteFactory.d.ts +33 -0
- package/dist/shared/factories/PhaseRouteFactory.d.ts.map +1 -0
- package/dist/shared/factories/PhaseRouteFactory.js +67 -0
- package/dist/shared/factories/PhaseRouteFactory.js.map +1 -0
- package/dist/shared/factories/QueryRouteFactory.d.ts +37 -0
- package/dist/shared/factories/QueryRouteFactory.d.ts.map +1 -0
- package/dist/shared/factories/QueryRouteFactory.js +244 -0
- package/dist/shared/factories/QueryRouteFactory.js.map +1 -0
- package/dist/shared/factories/QueryServiceFactory.d.ts +282 -0
- package/dist/shared/factories/QueryServiceFactory.d.ts.map +1 -0
- package/dist/shared/factories/QueryServiceFactory.js +277 -0
- package/dist/shared/factories/QueryServiceFactory.js.map +1 -0
- package/dist/shared/factories/index.d.ts +8 -0
- package/dist/shared/factories/index.d.ts.map +1 -0
- package/dist/shared/factories/index.js +6 -0
- package/dist/shared/factories/index.js.map +1 -0
- package/dist/shared/factories/types.d.ts +98 -0
- package/dist/shared/factories/types.d.ts.map +1 -0
- package/dist/shared/factories/types.js +8 -0
- package/dist/shared/factories/types.js.map +1 -0
- package/dist/shared/ownership/types.d.ts +84 -0
- package/dist/shared/ownership/types.d.ts.map +1 -0
- package/dist/shared/ownership/types.js +8 -0
- package/dist/shared/ownership/types.js.map +1 -0
- package/dist/shared/rfc7807ErrorResponse.d.ts +54 -0
- package/dist/shared/rfc7807ErrorResponse.d.ts.map +1 -0
- package/dist/shared/rfc7807ErrorResponse.js +98 -0
- package/dist/shared/rfc7807ErrorResponse.js.map +1 -0
- package/dist/shared/services/BaseCronService.d.ts +171 -0
- package/dist/shared/services/BaseCronService.d.ts.map +1 -0
- package/dist/shared/services/BaseCronService.js +444 -0
- package/dist/shared/services/BaseCronService.js.map +1 -0
- package/dist/shared/services/BasePhaseService.d.ts +170 -0
- package/dist/shared/services/BasePhaseService.d.ts.map +1 -0
- package/dist/shared/services/BasePhaseService.js +409 -0
- package/dist/shared/services/BasePhaseService.js.map +1 -0
- package/dist/shared/services/CronRegistry.d.ts +67 -0
- package/dist/shared/services/CronRegistry.d.ts.map +1 -0
- package/dist/shared/services/CronRegistry.js +68 -0
- package/dist/shared/services/CronRegistry.js.map +1 -0
- package/dist/shared/services/SimpleRPCQueryService.d.ts +111 -0
- package/dist/shared/services/SimpleRPCQueryService.d.ts.map +1 -0
- package/dist/shared/services/SimpleRPCQueryService.js +265 -0
- package/dist/shared/services/SimpleRPCQueryService.js.map +1 -0
- package/dist/shared/types/feature-config.d.ts +611 -0
- package/dist/shared/types/feature-config.d.ts.map +1 -0
- package/dist/shared/types/feature-config.js +85 -0
- package/dist/shared/types/feature-config.js.map +1 -0
- package/dist/shared/types/query-config.d.ts +41 -0
- package/dist/shared/types/query-config.d.ts.map +1 -0
- package/dist/shared/types/query-config.js +6 -0
- package/dist/shared/types/query-config.js.map +1 -0
- package/dist/shared/utils/config-driven-filters.d.ts +215 -0
- package/dist/shared/utils/config-driven-filters.d.ts.map +1 -0
- package/dist/shared/utils/config-driven-filters.js +451 -0
- package/dist/shared/utils/config-driven-filters.js.map +1 -0
- package/dist/shared/utils/controllerErrorHandler.d.ts +44 -0
- package/dist/shared/utils/controllerErrorHandler.d.ts.map +1 -0
- package/dist/shared/utils/controllerErrorHandler.js +126 -0
- package/dist/shared/utils/controllerErrorHandler.js.map +1 -0
- package/dist/shared/utils/parseInclude.d.ts +14 -0
- package/dist/shared/utils/parseInclude.d.ts.map +1 -0
- package/dist/shared/utils/parseInclude.js +28 -0
- package/dist/shared/utils/parseInclude.js.map +1 -0
- package/dist/shared/utils/queryHelpers.d.ts +62 -0
- package/dist/shared/utils/queryHelpers.d.ts.map +1 -0
- package/dist/shared/utils/queryHelpers.js +61 -0
- package/dist/shared/utils/queryHelpers.js.map +1 -0
- package/dist/shared/utils/response-mapper.d.ts +42 -0
- package/dist/shared/utils/response-mapper.d.ts.map +1 -0
- package/dist/shared/utils/response-mapper.js +176 -0
- package/dist/shared/utils/response-mapper.js.map +1 -0
- package/dist/shared/utils/responseBuilder.d.ts +103 -0
- package/dist/shared/utils/responseBuilder.d.ts.map +1 -0
- package/dist/shared/utils/responseBuilder.js +131 -0
- package/dist/shared/utils/responseBuilder.js.map +1 -0
- package/dist/shared/validators/featureConfigValidator.d.ts +23 -0
- package/dist/shared/validators/featureConfigValidator.d.ts.map +1 -0
- package/dist/shared/validators/featureConfigValidator.js +143 -0
- package/dist/shared/validators/featureConfigValidator.js.map +1 -0
- package/dist/shared/validators/organizationValidator.d.ts +53 -0
- package/dist/shared/validators/organizationValidator.d.ts.map +1 -0
- package/dist/shared/validators/organizationValidator.js +69 -0
- package/dist/shared/validators/organizationValidator.js.map +1 -0
- package/dist/shared/validators/uuidValidator.d.ts +57 -0
- package/dist/shared/validators/uuidValidator.d.ts.map +1 -0
- package/dist/shared/validators/uuidValidator.js +77 -0
- package/dist/shared/validators/uuidValidator.js.map +1 -0
- package/dist/utils/logger.d.ts +40 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +47 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +80 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feature Config Validator
|
|
3
|
+
*
|
|
4
|
+
* Validates feature configurations at startup to catch common mistakes early.
|
|
5
|
+
* Runs during RouteManager initialization to fail fast with clear error messages.
|
|
6
|
+
*/
|
|
7
|
+
import { createLogger } from '../../utils/logger.js';
|
|
8
|
+
const logger = createLogger('config:validator');
|
|
9
|
+
/**
|
|
10
|
+
* Known wrong table names — projects register their own via addWrongTableNames().
|
|
11
|
+
*/
|
|
12
|
+
const wrongTableNames = {};
|
|
13
|
+
/**
|
|
14
|
+
* Register known wrong table name mappings for validation.
|
|
15
|
+
* @example addWrongTableNames({ 'userspublic': 'users_public' });
|
|
16
|
+
*/
|
|
17
|
+
export function addWrongTableNames(mappings) {
|
|
18
|
+
Object.assign(wrongTableNames, mappings);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Validate a feature configuration
|
|
22
|
+
* @throws Error if validation fails (fail-fast approach)
|
|
23
|
+
*/
|
|
24
|
+
export function validateFeatureConfig(config, featureName) {
|
|
25
|
+
const errors = [];
|
|
26
|
+
// ==========================================
|
|
27
|
+
// SECURITY: navigationPanels validation
|
|
28
|
+
// ==========================================
|
|
29
|
+
if (config.display?.card?.navigationPanels) {
|
|
30
|
+
const navigationPanels = config.display.card.navigationPanels;
|
|
31
|
+
// 🚨 CRITICAL: 'organization' and 'organizations' are FORBIDDEN in navigation panels
|
|
32
|
+
const forbiddenPanels = navigationPanels.filter(panel => panel === 'organization' || panel === 'organizations');
|
|
33
|
+
if (forbiddenPanels.length > 0) {
|
|
34
|
+
errors.push({
|
|
35
|
+
feature: featureName,
|
|
36
|
+
field: 'display.card.navigationPanels',
|
|
37
|
+
error: `Contains forbidden values: ${forbiddenPanels.join(', ')}`,
|
|
38
|
+
fix: `Remove '${forbiddenPanels.join("', '")}' from navigationPanels array. Organizations contain sensitive multi-tenant data and should NEVER be exposed in UI navigation.`
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// ==========================================
|
|
43
|
+
// DATABASE: Table name validation
|
|
44
|
+
// ==========================================
|
|
45
|
+
if (config.tableName) {
|
|
46
|
+
// Check for correct snake_case format
|
|
47
|
+
if (config.tableName.includes('-')) {
|
|
48
|
+
errors.push({
|
|
49
|
+
feature: featureName,
|
|
50
|
+
field: 'tableName',
|
|
51
|
+
error: `Uses hyphens instead of underscores: '${config.tableName}'`,
|
|
52
|
+
fix: `Use snake_case: '${config.tableName.replace(/-/g, '_')}'`
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
// Check for plural form (best practice)
|
|
56
|
+
if (!config.tableName.endsWith('s') && !config.tableName.includes('_')) {
|
|
57
|
+
logger.warn(`[${featureName}] Table name '${config.tableName}' should be plural (e.g., 'orders', 'users')`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// ==========================================
|
|
61
|
+
// INCLUDE MAPPING: Table name validation
|
|
62
|
+
// ==========================================
|
|
63
|
+
if (config.includeMapping) {
|
|
64
|
+
Object.entries(config.includeMapping).forEach(([key, mapping]) => {
|
|
65
|
+
// Check for correct snake_case in table names
|
|
66
|
+
if (mapping.tableName.includes('-')) {
|
|
67
|
+
errors.push({
|
|
68
|
+
feature: featureName,
|
|
69
|
+
field: `includeMapping.${key}.tableName`,
|
|
70
|
+
error: `Uses hyphens instead of underscores: '${mapping.tableName}'`,
|
|
71
|
+
fix: `Use snake_case: '${mapping.tableName.replace(/-/g, '_')}'`
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
// Check for common typos — projects can register their own via addWrongTableNames()
|
|
75
|
+
const correctName = wrongTableNames[mapping.tableName];
|
|
76
|
+
if (correctName) {
|
|
77
|
+
errors.push({
|
|
78
|
+
feature: featureName,
|
|
79
|
+
field: `includeMapping.${key}.tableName`,
|
|
80
|
+
error: `Incorrect table name: '${mapping.tableName}'`,
|
|
81
|
+
fix: `Should be: '${correctName}'`
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
// ==========================================
|
|
87
|
+
// DISPLAY CONFIG: Required fields validation
|
|
88
|
+
// ==========================================
|
|
89
|
+
if (config.display) {
|
|
90
|
+
// Check page config
|
|
91
|
+
if (!config.display.page) {
|
|
92
|
+
logger.warn(`[${featureName}] Missing display.page config - GeneratedPage may not work correctly`);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
if (!config.display.page.title) {
|
|
96
|
+
logger.warn(`[${featureName}] Missing display.page.title`);
|
|
97
|
+
}
|
|
98
|
+
if (!config.display.page.entityName) {
|
|
99
|
+
logger.warn(`[${featureName}] Missing display.page.entityName`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// Check card config
|
|
103
|
+
if (!config.display.card) {
|
|
104
|
+
logger.warn(`[${featureName}] Missing display.card config - cards may not render correctly`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// ==========================================
|
|
108
|
+
// THROW ERRORS IF ANY FOUND
|
|
109
|
+
// ==========================================
|
|
110
|
+
if (errors.length > 0) {
|
|
111
|
+
const errorMessage = errors.map(err => `\n🚨 [${err.feature}] ${err.field}:\n` +
|
|
112
|
+
` Error: ${err.error}\n` +
|
|
113
|
+
` Fix: ${err.fix}`).join('\n');
|
|
114
|
+
throw new Error(`\n${'='.repeat(80)}\n` +
|
|
115
|
+
`❌ FEATURE CONFIG VALIDATION FAILED\n` +
|
|
116
|
+
`${'='.repeat(80)}` +
|
|
117
|
+
errorMessage +
|
|
118
|
+
`\n${'='.repeat(80)}\n`);
|
|
119
|
+
}
|
|
120
|
+
logger.debug(`✅ [${featureName}] Feature config validation passed`);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Validate all feature configs
|
|
124
|
+
* Call this during application startup
|
|
125
|
+
*/
|
|
126
|
+
export function validateAllFeatureConfigs(configs) {
|
|
127
|
+
logger.info(`🔍 Validating ${Object.keys(configs).length} feature configs...`);
|
|
128
|
+
let totalErrors = 0;
|
|
129
|
+
for (const [featureName, config] of Object.entries(configs)) {
|
|
130
|
+
try {
|
|
131
|
+
validateFeatureConfig(config, featureName);
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
totalErrors++;
|
|
135
|
+
// Re-throw to fail startup
|
|
136
|
+
throw error;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (totalErrors === 0) {
|
|
140
|
+
logger.info(`✅ All feature configs validated successfully`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=featureConfigValidator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"featureConfigValidator.js","sourceRoot":"","sources":["../../../src/shared/validators/featureConfigValidator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Response } from 'express';
|
|
2
|
+
import { AuthenticatedRequest } from '../../middleware/authMiddleware.js';
|
|
3
|
+
/**
|
|
4
|
+
* Organization Validation Utilities
|
|
5
|
+
*
|
|
6
|
+
* Prevents multi-tenancy security gaps:
|
|
7
|
+
* - Users accessing data from other organizations
|
|
8
|
+
* - Missing organization filtering in queries
|
|
9
|
+
* - Inconsistent organization validation
|
|
10
|
+
*
|
|
11
|
+
* CRITICAL: All Admin controllers MUST validate organization ID
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Validate organization ID exists on request
|
|
15
|
+
*
|
|
16
|
+
* @param req - Authenticated request
|
|
17
|
+
* @returns Organization ID if valid
|
|
18
|
+
* @throws Error if missing
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* const organizationId = validateOrganization(req);
|
|
22
|
+
* // Throws if req.user?.organizationId is missing
|
|
23
|
+
*/
|
|
24
|
+
export declare function validateOrganization(req: AuthenticatedRequest): string;
|
|
25
|
+
/**
|
|
26
|
+
* Validate organization ID and send 403 response if missing
|
|
27
|
+
*
|
|
28
|
+
* Use this for early return pattern in controllers
|
|
29
|
+
*
|
|
30
|
+
* @param req - Authenticated request
|
|
31
|
+
* @param res - Express response
|
|
32
|
+
* @returns Organization ID if valid, undefined if response was sent
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* const organizationId = validateOrganizationOrRespond(req, res);
|
|
36
|
+
* if (!organizationId) return; // Response already sent
|
|
37
|
+
*
|
|
38
|
+
* // Continue with valid organizationId
|
|
39
|
+
*/
|
|
40
|
+
export declare function validateOrganizationOrRespond(req: AuthenticatedRequest, res: Response): string | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* Check if user has organization ID
|
|
43
|
+
*
|
|
44
|
+
* @param req - Authenticated request
|
|
45
|
+
* @returns true if organization ID exists, false otherwise
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* if (!hasOrganization(req)) {
|
|
49
|
+
* // Handle missing organization
|
|
50
|
+
* }
|
|
51
|
+
*/
|
|
52
|
+
export declare function hasOrganization(req: AuthenticatedRequest): boolean;
|
|
53
|
+
//# sourceMappingURL=organizationValidator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"organizationValidator.d.ts","sourceRoot":"","sources":["../../../src/shared/validators/organizationValidator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAE1E;;;;;;;;;GASG;AAEH;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,oBAAoB,GAAG,MAAM,CAQtE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,6BAA6B,CAC3C,GAAG,EAAE,oBAAoB,EACzB,GAAG,EAAE,QAAQ,GACZ,MAAM,GAAG,SAAS,CAYpB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,oBAAoB,GAAG,OAAO,CAElE"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Organization Validation Utilities
|
|
3
|
+
*
|
|
4
|
+
* Prevents multi-tenancy security gaps:
|
|
5
|
+
* - Users accessing data from other organizations
|
|
6
|
+
* - Missing organization filtering in queries
|
|
7
|
+
* - Inconsistent organization validation
|
|
8
|
+
*
|
|
9
|
+
* CRITICAL: All Admin controllers MUST validate organization ID
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Validate organization ID exists on request
|
|
13
|
+
*
|
|
14
|
+
* @param req - Authenticated request
|
|
15
|
+
* @returns Organization ID if valid
|
|
16
|
+
* @throws Error if missing
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* const organizationId = validateOrganization(req);
|
|
20
|
+
* // Throws if req.user?.organizationId is missing
|
|
21
|
+
*/
|
|
22
|
+
export function validateOrganization(req) {
|
|
23
|
+
const organizationId = req.user?.organizationId;
|
|
24
|
+
if (!organizationId) {
|
|
25
|
+
throw new Error('Organization ID is required');
|
|
26
|
+
}
|
|
27
|
+
return organizationId;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Validate organization ID and send 403 response if missing
|
|
31
|
+
*
|
|
32
|
+
* Use this for early return pattern in controllers
|
|
33
|
+
*
|
|
34
|
+
* @param req - Authenticated request
|
|
35
|
+
* @param res - Express response
|
|
36
|
+
* @returns Organization ID if valid, undefined if response was sent
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* const organizationId = validateOrganizationOrRespond(req, res);
|
|
40
|
+
* if (!organizationId) return; // Response already sent
|
|
41
|
+
*
|
|
42
|
+
* // Continue with valid organizationId
|
|
43
|
+
*/
|
|
44
|
+
export function validateOrganizationOrRespond(req, res) {
|
|
45
|
+
const organizationId = req.user?.organizationId;
|
|
46
|
+
if (!organizationId) {
|
|
47
|
+
res.status(403).json({
|
|
48
|
+
success: false,
|
|
49
|
+
message: 'Organization ID is required'
|
|
50
|
+
});
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
return organizationId;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Check if user has organization ID
|
|
57
|
+
*
|
|
58
|
+
* @param req - Authenticated request
|
|
59
|
+
* @returns true if organization ID exists, false otherwise
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* if (!hasOrganization(req)) {
|
|
63
|
+
* // Handle missing organization
|
|
64
|
+
* }
|
|
65
|
+
*/
|
|
66
|
+
export function hasOrganization(req) {
|
|
67
|
+
return !!req.user?.organizationId;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=organizationValidator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"organizationValidator.js","sourceRoot":"","sources":["../../../src/shared/validators/organizationValidator.ts"],"names":[],"mappings":"AAGA;;;;;;;;;GASG;AAEH;;;;;;;;;;GAUG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAyB;IAC5D,MAAM,cAAc,GAAG,GAAG,CAAC,IAAI,EAAE,cAAc,CAAC;IAEhD,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACjD,CAAC;IAED,OAAO,cAAc,CAAC;AACxB,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,6BAA6B,CAC3C,GAAyB,EACzB,GAAa;IAEb,MAAM,cAAc,GAAG,GAAG,CAAC,IAAI,EAAE,cAAc,CAAC;IAEhD,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACnB,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,6BAA6B;SACvC,CAAC,CAAC;QACH,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,cAAc,CAAC;AACxB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,eAAe,CAAC,GAAyB;IACvD,OAAO,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,cAAc,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UUID Validation Utilities
|
|
3
|
+
*
|
|
4
|
+
* Centralized UUID validation to prevent:
|
|
5
|
+
* - Code duplication across controllers
|
|
6
|
+
* - SQL injection attempts
|
|
7
|
+
* - Performance issues from invalid IDs
|
|
8
|
+
* - Inconsistent error messages
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Validate UUID format
|
|
12
|
+
*
|
|
13
|
+
* @param id - The ID to validate
|
|
14
|
+
* @returns true if valid UUID, false otherwise
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* validateUUID('550e8400-e29b-41d4-a716-446655440000') // true
|
|
18
|
+
* validateUUID('invalid-id') // false
|
|
19
|
+
* validateUUID('') // false
|
|
20
|
+
*/
|
|
21
|
+
export declare function validateUUID(id: string): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Validate UUID and throw error if invalid
|
|
24
|
+
*
|
|
25
|
+
* Useful for early validation in controller methods
|
|
26
|
+
*
|
|
27
|
+
* @param id - The ID to validate
|
|
28
|
+
* @param resourceName - Name of resource for error message (default: 'Resource')
|
|
29
|
+
* @throws Error if ID is invalid
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* validateUUIDOrThrow(req.params.id, 'Order');
|
|
33
|
+
* // Throws: "Invalid Order ID format"
|
|
34
|
+
*/
|
|
35
|
+
export declare function validateUUIDOrThrow(id: string, resourceName?: string): void;
|
|
36
|
+
/**
|
|
37
|
+
* Validate multiple UUIDs at once
|
|
38
|
+
*
|
|
39
|
+
* @param ids - Array of IDs to validate
|
|
40
|
+
* @returns true if all are valid UUIDs, false otherwise
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* validateUUIDs(['uuid1', 'uuid2']) // true/false
|
|
44
|
+
*/
|
|
45
|
+
export declare function validateUUIDs(ids: string[]): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Filter out invalid UUIDs from array
|
|
48
|
+
*
|
|
49
|
+
* @param ids - Array of IDs to filter
|
|
50
|
+
* @returns Array containing only valid UUIDs
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* filterValidUUIDs(['valid-uuid', 'invalid', 'another-valid-uuid'])
|
|
54
|
+
* // Returns: ['valid-uuid', 'another-valid-uuid']
|
|
55
|
+
*/
|
|
56
|
+
export declare function filterValidUUIDs(ids: string[]): string[];
|
|
57
|
+
//# sourceMappingURL=uuidValidator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uuidValidator.d.ts","sourceRoot":"","sources":["../../../src/shared/validators/uuidValidator.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAKhD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,EAAE,YAAY,GAAE,MAAmB,GAAG,IAAI,CAIvF;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAKpD;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAKxD"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UUID Validation Utilities
|
|
3
|
+
*
|
|
4
|
+
* Centralized UUID validation to prevent:
|
|
5
|
+
* - Code duplication across controllers
|
|
6
|
+
* - SQL injection attempts
|
|
7
|
+
* - Performance issues from invalid IDs
|
|
8
|
+
* - Inconsistent error messages
|
|
9
|
+
*/
|
|
10
|
+
const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
11
|
+
/**
|
|
12
|
+
* Validate UUID format
|
|
13
|
+
*
|
|
14
|
+
* @param id - The ID to validate
|
|
15
|
+
* @returns true if valid UUID, false otherwise
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* validateUUID('550e8400-e29b-41d4-a716-446655440000') // true
|
|
19
|
+
* validateUUID('invalid-id') // false
|
|
20
|
+
* validateUUID('') // false
|
|
21
|
+
*/
|
|
22
|
+
export function validateUUID(id) {
|
|
23
|
+
if (!id || typeof id !== 'string') {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
return UUID_REGEX.test(id);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Validate UUID and throw error if invalid
|
|
30
|
+
*
|
|
31
|
+
* Useful for early validation in controller methods
|
|
32
|
+
*
|
|
33
|
+
* @param id - The ID to validate
|
|
34
|
+
* @param resourceName - Name of resource for error message (default: 'Resource')
|
|
35
|
+
* @throws Error if ID is invalid
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* validateUUIDOrThrow(req.params.id, 'Order');
|
|
39
|
+
* // Throws: "Invalid Order ID format"
|
|
40
|
+
*/
|
|
41
|
+
export function validateUUIDOrThrow(id, resourceName = 'Resource') {
|
|
42
|
+
if (!validateUUID(id)) {
|
|
43
|
+
throw new Error(`Invalid ${resourceName} ID format`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Validate multiple UUIDs at once
|
|
48
|
+
*
|
|
49
|
+
* @param ids - Array of IDs to validate
|
|
50
|
+
* @returns true if all are valid UUIDs, false otherwise
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* validateUUIDs(['uuid1', 'uuid2']) // true/false
|
|
54
|
+
*/
|
|
55
|
+
export function validateUUIDs(ids) {
|
|
56
|
+
if (!Array.isArray(ids) || ids.length === 0) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
return ids.every(id => validateUUID(id));
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Filter out invalid UUIDs from array
|
|
63
|
+
*
|
|
64
|
+
* @param ids - Array of IDs to filter
|
|
65
|
+
* @returns Array containing only valid UUIDs
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* filterValidUUIDs(['valid-uuid', 'invalid', 'another-valid-uuid'])
|
|
69
|
+
* // Returns: ['valid-uuid', 'another-valid-uuid']
|
|
70
|
+
*/
|
|
71
|
+
export function filterValidUUIDs(ids) {
|
|
72
|
+
if (!Array.isArray(ids)) {
|
|
73
|
+
return [];
|
|
74
|
+
}
|
|
75
|
+
return ids.filter(id => validateUUID(id));
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=uuidValidator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uuidValidator.js","sourceRoot":"","sources":["../../../src/shared/validators/uuidValidator.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,UAAU,GAAG,iEAAiE,CAAC;AAErF;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY,CAAC,EAAU;IACrC,IAAI,CAAC,EAAE,IAAI,OAAO,EAAE,KAAK,QAAQ,EAAE,CAAC;QAClC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC7B,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAAU,EAAE,eAAuB,UAAU;IAC/E,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,WAAW,YAAY,YAAY,CAAC,CAAC;IACvD,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAAC,GAAa;IACzC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5C,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC;AAC3C,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAa;IAC5C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tetra Logging Utility - Pino Edition
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* ```typescript
|
|
6
|
+
* import { createLogger } from '@tetra/core';
|
|
7
|
+
*
|
|
8
|
+
* const logger = createLogger('workflow:executor');
|
|
9
|
+
* logger.info({ stepId: 'abc', duration: 123 }, 'Step completed');
|
|
10
|
+
* logger.error({ error: err }, 'Step failed');
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* Environment Variables:
|
|
14
|
+
* - LOG_LEVEL: Set minimum log level (default: info in prod, debug in dev)
|
|
15
|
+
* - NODE_ENV: development/staging/production
|
|
16
|
+
*/
|
|
17
|
+
import pino from 'pino';
|
|
18
|
+
export declare const rootLogger: pino.Logger<never, boolean>;
|
|
19
|
+
/**
|
|
20
|
+
* Logger interface that accepts both argument orders:
|
|
21
|
+
* - logger.info({ context }, 'message') (pino native)
|
|
22
|
+
* - logger.info('message', { context }) (legacy)
|
|
23
|
+
*/
|
|
24
|
+
export interface Logger {
|
|
25
|
+
trace(msg: string, ...args: any[]): void;
|
|
26
|
+
trace(obj: object, msg?: string, ...args: any[]): void;
|
|
27
|
+
debug(msg: string, ...args: any[]): void;
|
|
28
|
+
debug(obj: object, msg?: string, ...args: any[]): void;
|
|
29
|
+
info(msg: string, ...args: any[]): void;
|
|
30
|
+
info(obj: object, msg?: string, ...args: any[]): void;
|
|
31
|
+
warn(msg: string, ...args: any[]): void;
|
|
32
|
+
warn(obj: object, msg?: string, ...args: any[]): void;
|
|
33
|
+
error(msg: string, ...args: any[]): void;
|
|
34
|
+
error(obj: object, msg?: string, ...args: any[]): void;
|
|
35
|
+
fatal(msg: string, ...args: any[]): void;
|
|
36
|
+
fatal(obj: object, msg?: string, ...args: any[]): void;
|
|
37
|
+
child(bindings: Record<string, any>): Logger;
|
|
38
|
+
}
|
|
39
|
+
export declare function createLogger(namespace: string): Logger;
|
|
40
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,IAAI,MAAM,MAAM,CAAC;AAKxB,eAAO,MAAM,UAAU,6BAYrB,CAAC;AAEH;;;;GAIG;AACH,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IACzC,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IACvD,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IACzC,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IACvD,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IACxC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IACtD,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IACxC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IACtD,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IACzC,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IACvD,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IACzC,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IACvD,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC;CAC9C;AAiBD,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEtD"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tetra Logging Utility - Pino Edition
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* ```typescript
|
|
6
|
+
* import { createLogger } from '@tetra/core';
|
|
7
|
+
*
|
|
8
|
+
* const logger = createLogger('workflow:executor');
|
|
9
|
+
* logger.info({ stepId: 'abc', duration: 123 }, 'Step completed');
|
|
10
|
+
* logger.error({ error: err }, 'Step failed');
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* Environment Variables:
|
|
14
|
+
* - LOG_LEVEL: Set minimum log level (default: info in prod, debug in dev)
|
|
15
|
+
* - NODE_ENV: development/staging/production
|
|
16
|
+
*/
|
|
17
|
+
import pino from 'pino';
|
|
18
|
+
const isDevelopment = process.env.NODE_ENV !== 'production';
|
|
19
|
+
const logLevel = process.env.LOG_LEVEL || (isDevelopment ? 'debug' : 'info');
|
|
20
|
+
export const rootLogger = pino({
|
|
21
|
+
level: logLevel,
|
|
22
|
+
...(isDevelopment && {
|
|
23
|
+
transport: {
|
|
24
|
+
target: 'pino-pretty',
|
|
25
|
+
options: {
|
|
26
|
+
colorize: true,
|
|
27
|
+
translateTime: 'HH:MM:ss',
|
|
28
|
+
ignore: 'pid,hostname'
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
})
|
|
32
|
+
});
|
|
33
|
+
function wrapLogger(pinoLogger) {
|
|
34
|
+
const levels = ['trace', 'debug', 'info', 'warn', 'error', 'fatal'];
|
|
35
|
+
const wrapped = {};
|
|
36
|
+
for (const level of levels) {
|
|
37
|
+
wrapped[level] = (...args) => {
|
|
38
|
+
pinoLogger[level](...args);
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
wrapped.child = (bindings) => wrapLogger(pinoLogger.child(bindings));
|
|
42
|
+
return wrapped;
|
|
43
|
+
}
|
|
44
|
+
export function createLogger(namespace) {
|
|
45
|
+
return wrapLogger(rootLogger.child({ namespace }));
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC;AAC5D,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7E,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC;IAC7B,KAAK,EAAE,QAAQ;IACf,GAAG,CAAC,aAAa,IAAI;QACnB,SAAS,EAAE;YACT,MAAM,EAAE,aAAa;YACrB,OAAO,EAAE;gBACP,QAAQ,EAAE,IAAI;gBACd,aAAa,EAAE,UAAU;gBACzB,MAAM,EAAE,cAAc;aACvB;SACF;KACF,CAAC;CACH,CAAC,CAAC;AAuBH,SAAS,UAAU,CAAC,UAAuB;IACzC,MAAM,MAAM,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAU,CAAC;IAC7E,MAAM,OAAO,GAAQ,EAAE,CAAC;IAExB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAW,EAAE,EAAE;YACjC,UAAU,CAAC,KAAK,CAAS,CAAC,GAAG,IAAI,CAAC,CAAC;QACtC,CAAC,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,KAAK,GAAG,CAAC,QAA6B,EAAE,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;IAE1F,OAAO,OAAiB,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,SAAiB;IAC5C,OAAO,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;AACrD,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@soulbatical/tetra-core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "restricted"
|
|
6
|
+
},
|
|
7
|
+
"description": "The foundation framework for VCA platform projects — config-driven Express + Supabase + TypeScript",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"main": "dist/index.js",
|
|
10
|
+
"types": "dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js",
|
|
15
|
+
"require": "./dist/index.js",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./frontend": {
|
|
19
|
+
"types": "./dist/frontend/index.d.ts",
|
|
20
|
+
"import": "./dist/frontend/index.js",
|
|
21
|
+
"require": "./dist/frontend/index.js",
|
|
22
|
+
"default": "./dist/frontend/index.js"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist"
|
|
27
|
+
],
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "tsc",
|
|
30
|
+
"prepublishOnly": "npm run build",
|
|
31
|
+
"typecheck": "tsc --noEmit"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"express-rate-limit": "^8.2.1",
|
|
35
|
+
"helmet": "^8.1.0",
|
|
36
|
+
"node-cron": "^4.1.1",
|
|
37
|
+
"zod": "^3.22.4"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"@supabase/supabase-js": "2.93.3",
|
|
41
|
+
"@tanstack/react-table": "^8.0.0",
|
|
42
|
+
"express": "^5.0.0",
|
|
43
|
+
"pino": "^9.0.0",
|
|
44
|
+
"react": "^18.0.0 || ^19.0.0"
|
|
45
|
+
},
|
|
46
|
+
"peerDependenciesMeta": {
|
|
47
|
+
"pino": {
|
|
48
|
+
"optional": true
|
|
49
|
+
},
|
|
50
|
+
"react": {
|
|
51
|
+
"optional": true
|
|
52
|
+
},
|
|
53
|
+
"@tanstack/react-table": {
|
|
54
|
+
"optional": true
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@supabase/supabase-js": "2.93.3",
|
|
59
|
+
"@tanstack/react-table": "^8.21.3",
|
|
60
|
+
"@types/express": "^5.0.0",
|
|
61
|
+
"@types/node": "^20.11.0",
|
|
62
|
+
"@types/node-cron": "^3.0.11",
|
|
63
|
+
"@types/react": "^19.2.14",
|
|
64
|
+
"express": "^5.2.1",
|
|
65
|
+
"pino": "^9.12.0",
|
|
66
|
+
"react": "^19.2.4",
|
|
67
|
+
"typescript": "^5.7.3"
|
|
68
|
+
},
|
|
69
|
+
"keywords": [
|
|
70
|
+
"tetra",
|
|
71
|
+
"framework",
|
|
72
|
+
"express",
|
|
73
|
+
"supabase",
|
|
74
|
+
"config-driven",
|
|
75
|
+
"multi-tenant",
|
|
76
|
+
"rls"
|
|
77
|
+
],
|
|
78
|
+
"author": "Albert Barth",
|
|
79
|
+
"license": "MIT"
|
|
80
|
+
}
|