@fnd-platform/api 1.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +204 -0
  3. package/lib/api-project.d.ts +99 -0
  4. package/lib/api-project.d.ts.map +1 -0
  5. package/lib/api-project.js +668 -0
  6. package/lib/api-project.js.map +1 -0
  7. package/lib/handlers/content.d.ts +52 -0
  8. package/lib/handlers/content.d.ts.map +1 -0
  9. package/lib/handlers/content.js +122 -0
  10. package/lib/handlers/content.js.map +1 -0
  11. package/lib/handlers/health.d.ts +43 -0
  12. package/lib/handlers/health.d.ts.map +1 -0
  13. package/lib/handlers/health.js +43 -0
  14. package/lib/handlers/health.js.map +1 -0
  15. package/lib/handlers/media.d.ts +86 -0
  16. package/lib/handlers/media.d.ts.map +1 -0
  17. package/lib/handlers/media.js +287 -0
  18. package/lib/handlers/media.js.map +1 -0
  19. package/lib/index.d.ts +22 -0
  20. package/lib/index.d.ts.map +1 -0
  21. package/lib/index.js +50 -0
  22. package/lib/index.js.map +1 -0
  23. package/lib/lib/errors.d.ts +114 -0
  24. package/lib/lib/errors.d.ts.map +1 -0
  25. package/lib/lib/errors.js +154 -0
  26. package/lib/lib/errors.js.map +1 -0
  27. package/lib/lib/middleware.d.ts +33 -0
  28. package/lib/lib/middleware.d.ts.map +1 -0
  29. package/lib/lib/middleware.js +36 -0
  30. package/lib/lib/middleware.js.map +1 -0
  31. package/lib/lib/request.d.ts +90 -0
  32. package/lib/lib/request.d.ts.map +1 -0
  33. package/lib/lib/request.js +115 -0
  34. package/lib/lib/request.js.map +1 -0
  35. package/lib/lib/response.d.ts +131 -0
  36. package/lib/lib/response.d.ts.map +1 -0
  37. package/lib/lib/response.js +163 -0
  38. package/lib/lib/response.js.map +1 -0
  39. package/lib/middleware/auth.d.ts +57 -0
  40. package/lib/middleware/auth.d.ts.map +1 -0
  41. package/lib/middleware/auth.js +62 -0
  42. package/lib/middleware/auth.js.map +1 -0
  43. package/lib/middleware/cors.d.ts +51 -0
  44. package/lib/middleware/cors.d.ts.map +1 -0
  45. package/lib/middleware/cors.js +62 -0
  46. package/lib/middleware/cors.js.map +1 -0
  47. package/lib/middleware/error-handler.d.ts +38 -0
  48. package/lib/middleware/error-handler.d.ts.map +1 -0
  49. package/lib/middleware/error-handler.js +49 -0
  50. package/lib/middleware/error-handler.js.map +1 -0
  51. package/lib/middleware/index.d.ts +15 -0
  52. package/lib/middleware/index.d.ts.map +1 -0
  53. package/lib/middleware/index.js +49 -0
  54. package/lib/middleware/index.js.map +1 -0
  55. package/lib/middleware/logging.d.ts +48 -0
  56. package/lib/middleware/logging.d.ts.map +1 -0
  57. package/lib/middleware/logging.js +58 -0
  58. package/lib/middleware/logging.js.map +1 -0
  59. package/lib/middleware/validation.d.ts +41 -0
  60. package/lib/middleware/validation.d.ts.map +1 -0
  61. package/lib/middleware/validation.js +76 -0
  62. package/lib/middleware/validation.js.map +1 -0
  63. package/lib/options.d.ts +48 -0
  64. package/lib/options.d.ts.map +1 -0
  65. package/lib/options.js +3 -0
  66. package/lib/options.js.map +1 -0
  67. package/lib/types/api.d.ts +108 -0
  68. package/lib/types/api.d.ts.map +1 -0
  69. package/lib/types/api.js +11 -0
  70. package/lib/types/api.js.map +1 -0
  71. package/lib/types/middleware.d.ts +59 -0
  72. package/lib/types/middleware.d.ts.map +1 -0
  73. package/lib/types/middleware.js +11 -0
  74. package/lib/types/middleware.js.map +1 -0
  75. package/package.json +54 -0
@@ -0,0 +1,668 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FndApiProject = void 0;
4
+ const projen_1 = require("projen");
5
+ const { TypeScriptModuleResolution } = projen_1.javascript;
6
+ /**
7
+ * Creates a Lambda API package within an fnd-platform monorepo.
8
+ *
9
+ * This class generates a complete API package scaffold with:
10
+ * - Lambda handler templates
11
+ * - Response helper utilities
12
+ * - Error handling classes
13
+ * - TypeScript types for API interactions
14
+ *
15
+ * Files are generated using Projen's SampleFile, allowing users to modify
16
+ * them after generation while still maintaining the project structure.
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * import { FndMonorepoProject } from '@fnd-platform/core';
21
+ * import { FndApiProject } from '@fnd-platform/api';
22
+ *
23
+ * const monorepo = new FndMonorepoProject({
24
+ * name: 'my-app',
25
+ * defaultReleaseBranch: 'main',
26
+ * });
27
+ *
28
+ * const api = new FndApiProject({
29
+ * parent: monorepo,
30
+ * name: 'api',
31
+ * });
32
+ *
33
+ * monorepo.synth();
34
+ * ```
35
+ */
36
+ class FndApiProject extends projen_1.typescript.TypeScriptProject {
37
+ /**
38
+ * Reference to the parent monorepo project.
39
+ */
40
+ parentProject;
41
+ /**
42
+ * Whether DynamoDB integration is enabled.
43
+ */
44
+ dynamodbEnabled;
45
+ /**
46
+ * Whether Cognito auth integration is enabled.
47
+ */
48
+ cognitoEnabled;
49
+ /**
50
+ * Whether CORS is enabled.
51
+ */
52
+ corsEnabled;
53
+ /**
54
+ * Creates a new FndApiProject.
55
+ *
56
+ * @param options - Configuration options for the API project
57
+ * @throws {Error} If required options are missing
58
+ */
59
+ constructor(options) {
60
+ // Validate required options
61
+ if (!options.parent) {
62
+ throw new Error('FndApiProject requires a parent option');
63
+ }
64
+ if (!options.name) {
65
+ throw new Error('FndApiProject requires a name option');
66
+ }
67
+ const outdir = options.outdir ?? `packages/${options.name}`;
68
+ const packageName = `@${options.parent.name}/${options.name}`;
69
+ super({
70
+ name: packageName,
71
+ parent: options.parent,
72
+ outdir,
73
+ defaultReleaseBranch: 'main',
74
+ // TypeScript configuration for Lambda
75
+ tsconfig: {
76
+ compilerOptions: {
77
+ target: 'ES2022',
78
+ module: 'NodeNext',
79
+ moduleResolution: TypeScriptModuleResolution.NODE_NEXT,
80
+ outDir: 'lib',
81
+ rootDir: 'src',
82
+ declaration: true,
83
+ declarationMap: true,
84
+ sourceMap: true,
85
+ strict: true,
86
+ esModuleInterop: true,
87
+ skipLibCheck: true,
88
+ forceConsistentCasingInFileNames: true,
89
+ },
90
+ },
91
+ // Disable Projen defaults - will inherit from monorepo or configure manually
92
+ sampleCode: false,
93
+ jest: false,
94
+ eslint: false,
95
+ prettier: false,
96
+ projenrcTs: false,
97
+ });
98
+ this.parentProject = options.parent;
99
+ this.dynamodbEnabled = options.dynamodb ?? true;
100
+ this.cognitoEnabled = options.cognito ?? true;
101
+ this.corsEnabled = options.cors ?? true;
102
+ // Add dependencies
103
+ this.addApiDependencies();
104
+ // Generate directory structure and files
105
+ this.generateHandlersDirectory();
106
+ this.generateLibDirectory();
107
+ this.generateTypesDirectory();
108
+ }
109
+ /**
110
+ * Adds API-specific dependencies to the project.
111
+ */
112
+ addApiDependencies() {
113
+ // Runtime dependencies
114
+ if (this.dynamodbEnabled) {
115
+ this.addDeps('@aws-sdk/client-dynamodb', '@aws-sdk/lib-dynamodb');
116
+ }
117
+ // Dev dependencies
118
+ this.addDevDeps('@types/aws-lambda', 'esbuild', 'vitest', '@vitest/coverage-v8');
119
+ }
120
+ /**
121
+ * Generates the handlers directory with Lambda handler templates.
122
+ */
123
+ generateHandlersDirectory() {
124
+ // Health check handler - always included
125
+ new projen_1.SampleFile(this, 'src/handlers/health.ts', {
126
+ contents: this.getHealthHandlerTemplate(),
127
+ });
128
+ }
129
+ /**
130
+ * Generates the lib directory with utility files.
131
+ */
132
+ generateLibDirectory() {
133
+ // Response helpers
134
+ new projen_1.SampleFile(this, 'src/lib/response.ts', {
135
+ contents: this.getResponseTemplate(),
136
+ });
137
+ // Error classes
138
+ new projen_1.SampleFile(this, 'src/lib/errors.ts', {
139
+ contents: this.getErrorsTemplate(),
140
+ });
141
+ // Middleware utilities (stub for Sprint 03)
142
+ new projen_1.SampleFile(this, 'src/lib/middleware.ts', {
143
+ contents: this.getMiddlewareTemplate(),
144
+ });
145
+ }
146
+ /**
147
+ * Generates the types directory with TypeScript type definitions.
148
+ */
149
+ generateTypesDirectory() {
150
+ // API types
151
+ new projen_1.SampleFile(this, 'src/types/api.ts', {
152
+ contents: this.getApiTypesTemplate(),
153
+ });
154
+ // Entity types stub
155
+ new projen_1.SampleFile(this, 'src/types/entities.ts', {
156
+ contents: this.getEntityTypesTemplate(),
157
+ });
158
+ }
159
+ /**
160
+ * Returns the health handler template content.
161
+ */
162
+ getHealthHandlerTemplate() {
163
+ return `import type { APIGatewayProxyHandler, APIGatewayProxyResult } from 'aws-lambda';
164
+ import { success } from '../lib/response';
165
+
166
+ /**
167
+ * Health check endpoint handler.
168
+ * Returns the current health status of the API.
169
+ *
170
+ * @returns Health status with timestamp
171
+ */
172
+ export const handler: APIGatewayProxyHandler = async (): Promise<APIGatewayProxyResult> => {
173
+ return success({
174
+ status: 'healthy',
175
+ timestamp: new Date().toISOString(),
176
+ version: process.env.API_VERSION ?? '0.0.0',
177
+ });
178
+ };
179
+ `;
180
+ }
181
+ /**
182
+ * Returns the response helpers template content.
183
+ */
184
+ getResponseTemplate() {
185
+ const corsHeaders = this.corsEnabled
186
+ ? `
187
+ 'Access-Control-Allow-Origin': '*',
188
+ 'Access-Control-Allow-Headers': 'Content-Type,Authorization',`
189
+ : '';
190
+ return `import type { APIGatewayProxyResult } from 'aws-lambda';
191
+ import {
192
+ ApiError,
193
+ NotFoundError,
194
+ UnauthorizedError,
195
+ ForbiddenError,
196
+ ValidationError,
197
+ } from './errors';
198
+
199
+ /**
200
+ * Success response envelope structure.
201
+ */
202
+ export interface SuccessResponse<T = unknown> {
203
+ success: true;
204
+ data: T;
205
+ }
206
+
207
+ /**
208
+ * Error response envelope structure.
209
+ */
210
+ export interface ErrorResponse {
211
+ success: false;
212
+ error: {
213
+ code: string;
214
+ message: string;
215
+ details?: unknown;
216
+ };
217
+ }
218
+
219
+ /**
220
+ * Default headers included in all responses.
221
+ */
222
+ function defaultHeaders(): Record<string, string> {
223
+ return {
224
+ 'Content-Type': 'application/json',${corsHeaders}
225
+ };
226
+ }
227
+
228
+ /**
229
+ * Creates a successful API response.
230
+ *
231
+ * @param data - Response body data
232
+ * @param statusCode - HTTP status code (default: 200)
233
+ * @returns API Gateway proxy result with success envelope
234
+ */
235
+ export function success<T>(data: T, statusCode = 200): APIGatewayProxyResult {
236
+ const body: SuccessResponse<T> = { success: true, data };
237
+ return {
238
+ statusCode,
239
+ headers: defaultHeaders(),
240
+ body: JSON.stringify(body),
241
+ };
242
+ }
243
+
244
+ /**
245
+ * Creates an error API response.
246
+ *
247
+ * @param err - Error object or message string
248
+ * @param statusCode - HTTP status code (default: 500)
249
+ * @returns API Gateway proxy result with error envelope
250
+ */
251
+ export function error(err: Error | string, statusCode = 500): APIGatewayProxyResult {
252
+ const message = typeof err === 'string' ? err : err.message;
253
+ const code = err instanceof ApiError ? err.code : 'INTERNAL_ERROR';
254
+ const details = err instanceof ApiError ? err.details : undefined;
255
+
256
+ const body: ErrorResponse = {
257
+ success: false,
258
+ error: { code, message, details },
259
+ };
260
+
261
+ return {
262
+ statusCode,
263
+ headers: defaultHeaders(),
264
+ body: JSON.stringify(body),
265
+ };
266
+ }
267
+
268
+ /**
269
+ * Creates a 404 Not Found response.
270
+ *
271
+ * @param message - Error message (default: 'Resource not found')
272
+ * @returns API Gateway proxy result with 404 status
273
+ */
274
+ export function notFound(message = 'Resource not found'): APIGatewayProxyResult {
275
+ return error(new NotFoundError(message), 404);
276
+ }
277
+
278
+ /**
279
+ * Creates a 401 Unauthorized response.
280
+ *
281
+ * @param message - Error message (default: 'Unauthorized')
282
+ * @returns API Gateway proxy result with 401 status
283
+ */
284
+ export function unauthorized(message = 'Unauthorized'): APIGatewayProxyResult {
285
+ return error(new UnauthorizedError(message), 401);
286
+ }
287
+
288
+ /**
289
+ * Creates a 403 Forbidden response.
290
+ *
291
+ * @param message - Error message (default: 'Forbidden')
292
+ * @returns API Gateway proxy result with 403 status
293
+ */
294
+ export function forbidden(message = 'Forbidden'): APIGatewayProxyResult {
295
+ return error(new ForbiddenError(message), 403);
296
+ }
297
+
298
+ /**
299
+ * Creates a 400 Bad Request response.
300
+ *
301
+ * @param message - Error message (default: 'Bad request')
302
+ * @param details - Optional validation error details
303
+ * @returns API Gateway proxy result with 400 status
304
+ */
305
+ export function badRequest(message = 'Bad request', details?: unknown): APIGatewayProxyResult {
306
+ return error(new ValidationError(message, details), 400);
307
+ }
308
+
309
+ /**
310
+ * Creates a 201 Created response.
311
+ *
312
+ * @param data - Created resource data
313
+ * @returns API Gateway proxy result with 201 status
314
+ */
315
+ export function created<T>(data: T): APIGatewayProxyResult {
316
+ return success(data, 201);
317
+ }
318
+ `;
319
+ }
320
+ /**
321
+ * Returns the error classes template content.
322
+ */
323
+ getErrorsTemplate() {
324
+ return `/**
325
+ * Custom error classes for API responses.
326
+ *
327
+ * All API errors extend ApiError and include an error code,
328
+ * HTTP status code, and optional details for structured error handling.
329
+ */
330
+
331
+ /**
332
+ * Base API error class.
333
+ * All API errors should extend this class.
334
+ */
335
+ export class ApiError extends Error {
336
+ /**
337
+ * Creates a new ApiError.
338
+ *
339
+ * @param message - Human-readable error message
340
+ * @param code - Machine-readable error code (UPPER_SNAKE_CASE)
341
+ * @param statusCode - HTTP status code (default: 500)
342
+ * @param details - Optional additional error details
343
+ */
344
+ constructor(
345
+ message: string,
346
+ public readonly code: string,
347
+ public readonly statusCode: number = 500,
348
+ public readonly details?: unknown
349
+ ) {
350
+ super(message);
351
+ this.name = 'ApiError';
352
+
353
+ // Maintains proper stack trace for where error was thrown
354
+ Error.captureStackTrace(this, this.constructor);
355
+ }
356
+
357
+ /**
358
+ * Converts the error to a JSON-serializable object.
359
+ */
360
+ toJSON(): { code: string; message: string; details?: unknown } {
361
+ return {
362
+ code: this.code,
363
+ message: this.message,
364
+ details: this.details,
365
+ };
366
+ }
367
+ }
368
+
369
+ /**
370
+ * 404 Not Found error.
371
+ */
372
+ export class NotFoundError extends ApiError {
373
+ constructor(message = 'Resource not found') {
374
+ super(message, 'NOT_FOUND', 404);
375
+ this.name = 'NotFoundError';
376
+ }
377
+ }
378
+
379
+ /**
380
+ * 400 Validation error.
381
+ */
382
+ export class ValidationError extends ApiError {
383
+ constructor(message = 'Validation failed', details?: unknown) {
384
+ super(message, 'VALIDATION_ERROR', 400, details);
385
+ this.name = 'ValidationError';
386
+ }
387
+ }
388
+
389
+ /**
390
+ * 401 Unauthorized error.
391
+ */
392
+ export class UnauthorizedError extends ApiError {
393
+ constructor(message = 'Unauthorized') {
394
+ super(message, 'UNAUTHORIZED', 401);
395
+ this.name = 'UnauthorizedError';
396
+ }
397
+ }
398
+
399
+ /**
400
+ * 403 Forbidden error.
401
+ */
402
+ export class ForbiddenError extends ApiError {
403
+ constructor(message = 'Forbidden') {
404
+ super(message, 'FORBIDDEN', 403);
405
+ this.name = 'ForbiddenError';
406
+ }
407
+ }
408
+
409
+ /**
410
+ * 409 Conflict error.
411
+ */
412
+ export class ConflictError extends ApiError {
413
+ constructor(message = 'Resource conflict') {
414
+ super(message, 'CONFLICT', 409);
415
+ this.name = 'ConflictError';
416
+ }
417
+ }
418
+ `;
419
+ }
420
+ /**
421
+ * Returns the middleware template content.
422
+ */
423
+ getMiddlewareTemplate() {
424
+ return `import type { APIGatewayProxyHandler, APIGatewayProxyResult } from 'aws-lambda';
425
+
426
+ /**
427
+ * Middleware function type.
428
+ * Takes a handler and returns a wrapped handler.
429
+ */
430
+ export type Middleware = (
431
+ handler: APIGatewayProxyHandler
432
+ ) => APIGatewayProxyHandler;
433
+
434
+ /**
435
+ * Composes multiple middleware functions into a single middleware.
436
+ * Middleware is applied from right to left (last middleware wraps first).
437
+ *
438
+ * @param middlewares - Middleware functions to compose
439
+ * @returns Composed middleware function
440
+ *
441
+ * @example
442
+ * \`\`\`typescript
443
+ * const handler = compose(
444
+ * withErrorHandler(),
445
+ * withAuth(),
446
+ * withValidation(schema)
447
+ * )(baseHandler);
448
+ * \`\`\`
449
+ *
450
+ * @note Full middleware implementation will be added in Sprint 03.
451
+ */
452
+ export function compose(...middlewares: Middleware[]): Middleware {
453
+ return (handler: APIGatewayProxyHandler): APIGatewayProxyHandler => {
454
+ return middlewares.reduceRight(
455
+ (wrapped, middleware) => middleware(wrapped),
456
+ handler
457
+ );
458
+ };
459
+ }
460
+
461
+ /**
462
+ * Error handler middleware.
463
+ * Catches errors thrown by the handler and converts them to API responses.
464
+ *
465
+ * @returns Middleware that wraps error handling
466
+ *
467
+ * @note Full implementation will be added in Sprint 03.
468
+ */
469
+ export function withErrorHandler(): Middleware {
470
+ return (handler: APIGatewayProxyHandler): APIGatewayProxyHandler => {
471
+ return async (event, context, callback): Promise<APIGatewayProxyResult> => {
472
+ try {
473
+ const result = await handler(event, context, callback);
474
+ return result as APIGatewayProxyResult;
475
+ } catch (err) {
476
+ const message = err instanceof Error ? err.message : 'Internal Server Error';
477
+ const statusCode = (err as { statusCode?: number }).statusCode ?? 500;
478
+ const code = (err as { code?: string }).code ?? 'INTERNAL_ERROR';
479
+
480
+ return {
481
+ statusCode,
482
+ headers: { 'Content-Type': 'application/json' },
483
+ body: JSON.stringify({
484
+ success: false,
485
+ error: { code, message },
486
+ }),
487
+ };
488
+ }
489
+ };
490
+ };
491
+ }
492
+
493
+ // Additional middleware will be implemented in Sprint 03:
494
+ // - withAuth()
495
+ // - withValidation()
496
+ // - withCors()
497
+ // - withRateLimit()
498
+ `;
499
+ }
500
+ /**
501
+ * Returns the API types template content.
502
+ */
503
+ getApiTypesTemplate() {
504
+ return `import type {
505
+ APIGatewayProxyEvent,
506
+ APIGatewayProxyResult,
507
+ Context,
508
+ } from 'aws-lambda';
509
+
510
+ /**
511
+ * Standard Lambda handler type.
512
+ */
513
+ export type Handler = (
514
+ event: APIGatewayProxyEvent,
515
+ context: Context
516
+ ) => Promise<APIGatewayProxyResult>;
517
+
518
+ /**
519
+ * Cognito JWT claims structure.
520
+ */
521
+ export interface CognitoClaims {
522
+ /** User's unique identifier (Cognito sub) */
523
+ sub: string;
524
+ /** User's email address */
525
+ email: string;
526
+ /** User's Cognito groups (roles) */
527
+ 'cognito:groups'?: string[];
528
+ }
529
+
530
+ /**
531
+ * API Gateway event with Cognito authorizer claims.
532
+ */
533
+ export interface AuthenticatedEvent extends APIGatewayProxyEvent {
534
+ requestContext: APIGatewayProxyEvent['requestContext'] & {
535
+ authorizer: {
536
+ claims: CognitoClaims;
537
+ };
538
+ };
539
+ }
540
+
541
+ /**
542
+ * Lambda handler type for authenticated requests.
543
+ */
544
+ export type AuthenticatedHandler = (
545
+ event: AuthenticatedEvent,
546
+ context: Context
547
+ ) => Promise<APIGatewayProxyResult>;
548
+
549
+ /**
550
+ * Pagination parameters for list endpoints.
551
+ */
552
+ export interface PaginatedRequest {
553
+ /** Maximum number of items to return */
554
+ limit?: number;
555
+ /** Cursor for pagination */
556
+ cursor?: string;
557
+ }
558
+
559
+ /**
560
+ * Paginated response structure.
561
+ */
562
+ export interface PaginatedResponse<T> {
563
+ /** Array of items for the current page */
564
+ items: T[];
565
+ /** Cursor for the next page, undefined if no more pages */
566
+ nextCursor?: string;
567
+ /** Total count of items (optional) */
568
+ total?: number;
569
+ }
570
+ `;
571
+ }
572
+ /**
573
+ * Returns the entity types template content.
574
+ */
575
+ getEntityTypesTemplate() {
576
+ return `/**
577
+ * Base entity interface with common fields.
578
+ */
579
+ export interface BaseEntity {
580
+ /**
581
+ * Unique identifier.
582
+ */
583
+ id: string;
584
+
585
+ /**
586
+ * ISO 8601 timestamp when the entity was created.
587
+ */
588
+ createdAt: string;
589
+
590
+ /**
591
+ * ISO 8601 timestamp when the entity was last updated.
592
+ */
593
+ updatedAt: string;
594
+ }
595
+
596
+ /**
597
+ * Content entity for CMS content items.
598
+ * This is a template - customize based on your content model.
599
+ */
600
+ export interface ContentEntity extends BaseEntity {
601
+ /**
602
+ * Content title.
603
+ */
604
+ title: string;
605
+
606
+ /**
607
+ * URL-friendly slug.
608
+ */
609
+ slug: string;
610
+
611
+ /**
612
+ * Content body (HTML or markdown).
613
+ */
614
+ content: string;
615
+
616
+ /**
617
+ * Content status.
618
+ */
619
+ status: 'draft' | 'published' | 'archived';
620
+
621
+ /**
622
+ * Author user ID.
623
+ */
624
+ authorId: string;
625
+
626
+ /**
627
+ * Content type identifier.
628
+ */
629
+ contentType: string;
630
+
631
+ /**
632
+ * Optional metadata.
633
+ */
634
+ metadata?: Record<string, unknown>;
635
+ }
636
+
637
+ /**
638
+ * User profile entity.
639
+ * This is a template - customize based on your user model.
640
+ */
641
+ export interface UserEntity extends BaseEntity {
642
+ /**
643
+ * User's email address.
644
+ */
645
+ email: string;
646
+
647
+ /**
648
+ * Display name.
649
+ */
650
+ displayName?: string;
651
+
652
+ /**
653
+ * User role.
654
+ */
655
+ role: 'admin' | 'editor' | 'viewer';
656
+
657
+ /**
658
+ * Profile image URL.
659
+ */
660
+ avatarUrl?: string;
661
+ }
662
+
663
+ // Add your custom entity types below
664
+ `;
665
+ }
666
+ }
667
+ exports.FndApiProject = FndApiProject;
668
+ //# sourceMappingURL=api-project.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-project.js","sourceRoot":"","sources":["../src/api-project.ts"],"names":[],"mappings":"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"}