@noony-serverless/core 0.3.4 → 0.4.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 (53) hide show
  1. package/README.md +199 -0
  2. package/build/core/containerPool.d.ts +129 -26
  3. package/build/core/containerPool.js +213 -68
  4. package/build/core/handler.d.ts +2 -2
  5. package/build/core/handler.js +6 -12
  6. package/build/core/index.d.ts +1 -0
  7. package/build/core/index.js +1 -0
  8. package/build/core/logger.d.ts +89 -1
  9. package/build/core/logger.js +136 -5
  10. package/build/core/telemetry/config.d.ts +331 -0
  11. package/build/core/telemetry/config.js +153 -0
  12. package/build/core/telemetry/index.d.ts +22 -0
  13. package/build/core/telemetry/index.js +45 -0
  14. package/build/core/telemetry/provider.d.ts +203 -0
  15. package/build/core/telemetry/provider.js +3 -0
  16. package/build/core/telemetry/providers/console-provider.d.ts +54 -0
  17. package/build/core/telemetry/providers/console-provider.js +124 -0
  18. package/build/core/telemetry/providers/index.d.ts +10 -0
  19. package/build/core/telemetry/providers/index.js +19 -0
  20. package/build/core/telemetry/providers/noop-provider.d.ts +51 -0
  21. package/build/core/telemetry/providers/noop-provider.js +67 -0
  22. package/build/core/telemetry/providers/opentelemetry-provider.d.ts +102 -0
  23. package/build/core/telemetry/providers/opentelemetry-provider.js +342 -0
  24. package/build/middlewares/bodyValidationMiddleware.js +1 -1
  25. package/build/middlewares/dependencyInjectionMiddleware.d.ts +16 -8
  26. package/build/middlewares/dependencyInjectionMiddleware.js +31 -11
  27. package/build/middlewares/guards/adapters/CustomTokenVerificationPortAdapter.d.ts +1 -1
  28. package/build/middlewares/guards/guards/FastAuthGuard.d.ts +5 -5
  29. package/build/middlewares/guards/guards/FastAuthGuard.js +3 -2
  30. package/build/middlewares/guards/guards/PermissionGuardFactory.d.ts +7 -9
  31. package/build/middlewares/guards/resolvers/ExpressionPermissionResolver.d.ts +1 -1
  32. package/build/middlewares/guards/resolvers/ExpressionPermissionResolver.js +1 -1
  33. package/build/middlewares/guards/resolvers/PermissionResolver.d.ts +1 -1
  34. package/build/middlewares/guards/resolvers/PlainPermissionResolver.d.ts +1 -1
  35. package/build/middlewares/guards/resolvers/WildcardPermissionResolver.d.ts +1 -1
  36. package/build/middlewares/guards/services/FastUserContextService.d.ts +11 -32
  37. package/build/middlewares/index.d.ts +1 -0
  38. package/build/middlewares/index.js +1 -0
  39. package/build/middlewares/openTelemetryMiddleware.d.ts +162 -0
  40. package/build/middlewares/openTelemetryMiddleware.js +359 -0
  41. package/build/middlewares/rateLimitingMiddleware.js +16 -5
  42. package/build/utils/container.utils.js +4 -1
  43. package/build/utils/fastify-wrapper.d.ts +74 -0
  44. package/build/utils/fastify-wrapper.js +175 -0
  45. package/build/utils/index.d.ts +4 -0
  46. package/build/utils/index.js +23 -1
  47. package/build/utils/otel.helper.d.ts +122 -0
  48. package/build/utils/otel.helper.js +258 -0
  49. package/build/utils/pubsub-trace.utils.d.ts +102 -0
  50. package/build/utils/pubsub-trace.utils.js +155 -0
  51. package/build/utils/wrapper-utils.d.ts +177 -0
  52. package/build/utils/wrapper-utils.js +236 -0
  53. package/package.json +61 -2
package/README.md CHANGED
@@ -432,11 +432,210 @@ EXPOSE 8080
432
432
  CMD ["npm", "start"]
433
433
  ```
434
434
 
435
+ ## Publishing to npm
436
+
437
+ This package is published as `@noony-serverless/core` on npm. Follow these steps to publish a new version:
438
+
439
+ ### Prerequisites
440
+
441
+ 1. **npm Account**: You need an npm account. Create one at [npmjs.com/signup](https://www.npmjs.com/signup)
442
+ 2. **Organization Access**: You must have access to the `@noony-serverless` organization on npm
443
+ - If you own the organization, you're all set
444
+ - If not, you need to [create the organization](https://www.npmjs.com/org/create) first
445
+ 3. **Two-Factor Authentication**: Highly recommended for security
446
+
447
+ ### Publishing Steps
448
+
449
+ #### 1. Login to npm
450
+
451
+ ```bash
452
+ npm login
453
+ ```
454
+
455
+ You'll be prompted for:
456
+
457
+ - Username
458
+ - Password
459
+ - Email
460
+ - One-time password (if 2FA is enabled)
461
+
462
+ Verify you're logged in:
463
+
464
+ ```bash
465
+ npm whoami
466
+ ```
467
+
468
+ #### 2. Prepare the Package
469
+
470
+ Ensure all changes are committed and tests pass:
471
+
472
+ ```bash
473
+ # Run tests
474
+ npm test
475
+
476
+ # Run linter
477
+ npm run lint
478
+
479
+ # Build the package
480
+ npm run build
481
+ ```
482
+
483
+ #### 3. Update Version
484
+
485
+ Update the version in `package.json` following [Semantic Versioning](https://semver.org/):
486
+
487
+ ```bash
488
+ # For bug fixes (0.4.0 -> 0.4.1)
489
+ npm version patch
490
+
491
+ # For new features (0.4.0 -> 0.5.0)
492
+ npm version minor
493
+
494
+ # For breaking changes (0.4.0 -> 1.0.0)
495
+ npm version major
496
+ ```
497
+
498
+ This will:
499
+
500
+ - Update `package.json` version
501
+ - Create a git commit
502
+ - Create a git tag
503
+
504
+ #### 4. Publish to npm
505
+
506
+ For scoped packages (like `@noony-serverless/core`), you must specify public access:
507
+
508
+ ```bash
509
+ npm publish --access public
510
+ ```
511
+
512
+ **For the first publish only**, you need the `--access public` flag. Subsequent publishes can use:
513
+
514
+ ```bash
515
+ npm publish
516
+ ```
517
+
518
+ #### 5. Push to Git
519
+
520
+ Don't forget to push the version commit and tags:
521
+
522
+ ```bash
523
+ git push && git push --tags
524
+ ```
525
+
526
+ ### Publishing Checklist
527
+
528
+ Before publishing, verify:
529
+
530
+ - [ ] All tests pass (`npm test`)
531
+ - [ ] No linting errors (`npm run lint`)
532
+ - [ ] Build succeeds (`npm run build`)
533
+ - [ ] Version number updated in `package.json`
534
+ - [ ] CHANGELOG.md updated (if applicable)
535
+ - [ ] README.md is up to date
536
+ - [ ] All changes committed to git
537
+ - [ ] Logged into npm (`npm whoami`)
538
+
539
+ ### Troubleshooting
540
+
541
+ #### Error: "Access token expired or revoked"
542
+
543
+ **Solution**: Run `npm login` to re-authenticate
544
+
545
+ #### Error: "404 Not Found - Not in this registry"
546
+
547
+ **Solution**: For first publish of a scoped package, use:
548
+
549
+ ```bash
550
+ npm publish --access public
551
+ ```
552
+
553
+ #### Error: "You do not have permission to publish"
554
+
555
+ **Solution**:
556
+
557
+ - Verify you're logged in as the correct user
558
+ - Check you have publish access to the `@noony-serverless` organization
559
+ - Create the organization if it doesn't exist
560
+
561
+ #### Error: "Cannot publish over existing version"
562
+
563
+ **Solution**: Update the version number in `package.json` or use:
564
+
565
+ ```bash
566
+ npm version patch # or minor/major
567
+ ```
568
+
569
+ #### Error: "403 Forbidden"
570
+
571
+ **Solutions**:
572
+
573
+ - Ensure you're logged in: `npm whoami`
574
+ - Verify you own the package or have collaborator access
575
+ - If this is a new scoped package, verify the organization exists
576
+
577
+ ### Automated Publishing with GitHub Actions
578
+
579
+ For automated publishing, create `.github/workflows/publish.yml`:
580
+
581
+ ```yaml
582
+ name: Publish to npm
583
+
584
+ on:
585
+ release:
586
+ types: [created]
587
+
588
+ jobs:
589
+ publish:
590
+ runs-on: ubuntu-latest
591
+ steps:
592
+ - uses: actions/checkout@v3
593
+ - uses: actions/setup-node@v3
594
+ with:
595
+ node-version: '20'
596
+ registry-url: 'https://registry.npmjs.org'
597
+ - run: npm ci
598
+ - run: npm test
599
+ - run: npm run build
600
+ - run: npm publish --access public
601
+ env:
602
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
603
+ ```
604
+
605
+ To use this:
606
+
607
+ 1. Create an npm access token at [npmjs.com/settings/tokens](https://www.npmjs.com/settings/tokens)
608
+ 2. Add it as a GitHub secret named `NPM_TOKEN`
609
+ 3. Create a GitHub release to trigger publishing
610
+
611
+ ### Version Management
612
+
613
+ This package follows [Semantic Versioning](https://semver.org/):
614
+
615
+ - **MAJOR** version (1.0.0 → 2.0.0): Breaking changes
616
+ - **MINOR** version (1.0.0 → 1.1.0): New features, backwards compatible
617
+ - **PATCH** version (1.0.0 → 1.0.1): Bug fixes, backwards compatible
618
+
619
+ Current version: **0.4.0**
620
+
621
+ ### Package Distribution
622
+
623
+ When published, the package includes only the `build/` directory contents:
624
+
625
+ - `build/core/**/*.js` and `*.d.ts`
626
+ - `build/middlewares/**/*.js` and `*.d.ts`
627
+ - `build/utils/**/*.js` and `*.d.ts`
628
+ - `build/index.js` and `index.d.ts`
629
+ - `README.md`
630
+
631
+ Source TypeScript files are not included in the npm package.
632
+
435
633
  ## Community & Support
436
634
 
437
635
  - 📖 [Documentation](https://github.com/noony-org/noony-serverless)
438
636
  - 🐛 [Issue Tracker](https://github.com/noony-org/noony-serverless/issues)
439
637
  - 💬 [Discussions](https://github.com/noony-org/noony-serverless/discussions)
638
+ - 📦 [npm Package](https://www.npmjs.com/package/@noony-serverless/core)
440
639
 
441
640
  ## License
442
641
 
@@ -1,44 +1,147 @@
1
1
  import { ContainerInstance } from 'typedi';
2
2
  /**
3
- * Performance optimization: Container Pool for reusing TypeDI containers
4
- * This reduces object creation overhead and improves memory efficiency
3
+ * Service definition for container registration
5
4
  */
6
- declare class ContainerPool {
7
- private availableContainers;
8
- private maxPoolSize;
9
- private createdContainers;
10
- constructor(maxPoolSize?: number);
5
+ export interface ServiceDefinition {
6
+ id: any;
7
+ value: any;
8
+ }
9
+ /**
10
+ * Options for container pool initialization
11
+ */
12
+ export interface ContainerPoolOptions {
11
13
  /**
12
- * Get a container from the pool or create a new one
14
+ * Enable hybrid proxy container (default: true)
15
+ * Set to false to use legacy pooling behavior
13
16
  */
14
- acquire(): ContainerInstance;
17
+ useProxy?: boolean;
18
+ }
19
+ /**
20
+ * Hybrid Proxy Container Pool for serverless environments
21
+ *
22
+ * This implementation uses a zero-copy proxy pattern that provides:
23
+ * - Process Lifetime (Global): Services initialized once and shared across requests
24
+ * - Request Lifetime (Local): Services isolated per request with zero overhead
25
+ *
26
+ * Architecture:
27
+ * - Global Container: Singleton with process-lifetime services (DB, Logger, etc.)
28
+ * - Proxy Container: Lightweight wrapper per-request that shadows local overrides
29
+ * - Memory: O(1) per request (just the proxy + local overrides Map)
30
+ * - Performance: ~99% memory reduction vs traditional container pooling
31
+ *
32
+ * @example
33
+ * Basic usage with global services:
34
+ * ```typescript
35
+ * // Initialize global services once at startup
36
+ * containerPool.initializeGlobal([
37
+ * { id: 'Database', value: new DatabaseService() },
38
+ * { id: 'Logger', value: new LoggerService() }
39
+ * ]);
40
+ *
41
+ * // Per-request: Create lightweight proxy
42
+ * const container = containerPool.createProxyContainer();
43
+ * const db = container.get('Database'); // From global
44
+ * ```
45
+ *
46
+ * @example
47
+ * Request-scoped services with local overrides:
48
+ * ```typescript
49
+ * // Global services
50
+ * containerPool.initializeGlobal([
51
+ * { id: UserService, value: new UserService() }
52
+ * ]);
53
+ *
54
+ * // Per-request: Add request-scoped data
55
+ * const container = containerPool.createProxyContainer();
56
+ * container.set('RequestId', 'req-123'); // Local scope only
57
+ * container.set('CurrentUser', currentUser); // Local scope only
58
+ *
59
+ * const userService = container.get(UserService); // From global
60
+ * const requestId = container.get('RequestId'); // From local
61
+ * ```
62
+ */
63
+ declare class ContainerPool {
64
+ private static globalContainer;
65
+ private static useProxy;
15
66
  /**
16
- * Return a container to the pool for reuse
67
+ * Initialize the global container with process-lifetime services
68
+ * This should be called once at application startup
69
+ *
70
+ * @param services - Array of service definitions to register globally
71
+ * @param options - Configuration options
72
+ *
73
+ * @example
74
+ * ```typescript
75
+ * containerPool.initializeGlobal([
76
+ * { id: 'config', value: { apiUrl: 'https://api.example.com' } },
77
+ * { id: DatabaseService, value: new DatabaseService() },
78
+ * { id: LoggerService, value: new LoggerService() }
79
+ * ]);
80
+ * ```
17
81
  */
18
- release(container: ContainerInstance): void;
82
+ static initializeGlobal(services?: ServiceDefinition[], options?: ContainerPoolOptions): void;
19
83
  /**
20
- * Reset container state to prevent cross-request contamination
21
- * Note: TypeDI containers are isolated by default, so we mainly need
22
- * to clear any manually set values
84
+ * Create a lightweight proxy container for a single request
85
+ *
86
+ * The proxy provides:
87
+ * - Read access to global services (zero-copy)
88
+ * - Local overrides for request-scoped data
89
+ * - Automatic garbage collection (no manual cleanup needed)
90
+ *
91
+ * @returns A proxy container instance with request-local scope
92
+ *
93
+ * @example
94
+ * ```typescript
95
+ * async function handleRequest(req, res) {
96
+ * const container = containerPool.createProxyContainer();
97
+ *
98
+ * // Add request-specific data
99
+ * container.set('TraceId', req.headers['x-trace-id']);
100
+ *
101
+ * // Access global services
102
+ * const db = container.get(DatabaseService);
103
+ *
104
+ * // No cleanup needed - auto GC'd
105
+ * }
106
+ * ```
23
107
  */
24
- private resetContainer;
108
+ static createProxyContainer(): ContainerInstance;
25
109
  /**
26
- * Get pool statistics for monitoring
110
+ * Create a middleware-compatible container factory
111
+ *
112
+ * @param services - Optional services to set as local overrides per-request
113
+ * @returns Function that creates proxy container with optional local services
114
+ *
115
+ * @example
116
+ * ```typescript
117
+ * const handler = new Handler()
118
+ * .use(containerPool.asMiddleware([
119
+ * { id: 'RequestId', value: 'req-123' }
120
+ * ]))
121
+ * .handle(async (context) => {
122
+ * const requestId = context.container.get('RequestId');
123
+ * });
124
+ * ```
27
125
  */
28
- getStats(): {
29
- available: number;
30
- created: number;
31
- maxSize: number;
32
- };
126
+ static asMiddleware(services?: ServiceDefinition[]): (container?: ContainerInstance) => ContainerInstance;
33
127
  /**
34
- * Warm up the pool by pre-creating containers
128
+ * Get statistics about the container pool
129
+ * (Maintained for backward compatibility)
35
130
  */
36
- warmUp(count?: number): void;
131
+ static getStats(): {
132
+ useProxy: boolean;
133
+ globalInitialized: boolean;
134
+ };
37
135
  /**
38
- * Clear all containers from the pool
136
+ * Clear the global container (useful for testing)
137
+ * ⚠️ WARNING: This resets ALL global services
39
138
  */
40
- clear(): void;
139
+ static clear(): void;
41
140
  }
42
- declare const containerPool: ContainerPool;
141
+ /**
142
+ * Global container pool instance
143
+ * Pre-initialized for immediate use in serverless environments
144
+ */
145
+ declare const containerPool: typeof ContainerPool;
43
146
  export { ContainerPool, containerPool };
44
147
  //# sourceMappingURL=containerPool.d.ts.map