@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.
- package/README.md +199 -0
- package/build/core/containerPool.d.ts +129 -26
- package/build/core/containerPool.js +213 -68
- package/build/core/handler.d.ts +2 -2
- package/build/core/handler.js +6 -12
- package/build/core/index.d.ts +1 -0
- package/build/core/index.js +1 -0
- package/build/core/logger.d.ts +89 -1
- package/build/core/logger.js +136 -5
- package/build/core/telemetry/config.d.ts +331 -0
- package/build/core/telemetry/config.js +153 -0
- package/build/core/telemetry/index.d.ts +22 -0
- package/build/core/telemetry/index.js +45 -0
- package/build/core/telemetry/provider.d.ts +203 -0
- package/build/core/telemetry/provider.js +3 -0
- package/build/core/telemetry/providers/console-provider.d.ts +54 -0
- package/build/core/telemetry/providers/console-provider.js +124 -0
- package/build/core/telemetry/providers/index.d.ts +10 -0
- package/build/core/telemetry/providers/index.js +19 -0
- package/build/core/telemetry/providers/noop-provider.d.ts +51 -0
- package/build/core/telemetry/providers/noop-provider.js +67 -0
- package/build/core/telemetry/providers/opentelemetry-provider.d.ts +102 -0
- package/build/core/telemetry/providers/opentelemetry-provider.js +342 -0
- package/build/middlewares/bodyValidationMiddleware.js +1 -1
- package/build/middlewares/dependencyInjectionMiddleware.d.ts +16 -8
- package/build/middlewares/dependencyInjectionMiddleware.js +31 -11
- package/build/middlewares/guards/adapters/CustomTokenVerificationPortAdapter.d.ts +1 -1
- package/build/middlewares/guards/guards/FastAuthGuard.d.ts +5 -5
- package/build/middlewares/guards/guards/FastAuthGuard.js +3 -2
- package/build/middlewares/guards/guards/PermissionGuardFactory.d.ts +7 -9
- package/build/middlewares/guards/resolvers/ExpressionPermissionResolver.d.ts +1 -1
- package/build/middlewares/guards/resolvers/ExpressionPermissionResolver.js +1 -1
- package/build/middlewares/guards/resolvers/PermissionResolver.d.ts +1 -1
- package/build/middlewares/guards/resolvers/PlainPermissionResolver.d.ts +1 -1
- package/build/middlewares/guards/resolvers/WildcardPermissionResolver.d.ts +1 -1
- package/build/middlewares/guards/services/FastUserContextService.d.ts +11 -32
- package/build/middlewares/index.d.ts +1 -0
- package/build/middlewares/index.js +1 -0
- package/build/middlewares/openTelemetryMiddleware.d.ts +162 -0
- package/build/middlewares/openTelemetryMiddleware.js +359 -0
- package/build/middlewares/rateLimitingMiddleware.js +16 -5
- package/build/utils/container.utils.js +4 -1
- package/build/utils/fastify-wrapper.d.ts +74 -0
- package/build/utils/fastify-wrapper.js +175 -0
- package/build/utils/index.d.ts +4 -0
- package/build/utils/index.js +23 -1
- package/build/utils/otel.helper.d.ts +122 -0
- package/build/utils/otel.helper.js +258 -0
- package/build/utils/pubsub-trace.utils.d.ts +102 -0
- package/build/utils/pubsub-trace.utils.js +155 -0
- package/build/utils/wrapper-utils.d.ts +177 -0
- package/build/utils/wrapper-utils.js +236 -0
- 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
|
-
*
|
|
4
|
-
* This reduces object creation overhead and improves memory efficiency
|
|
3
|
+
* Service definition for container registration
|
|
5
4
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
*
|
|
14
|
+
* Enable hybrid proxy container (default: true)
|
|
15
|
+
* Set to false to use legacy pooling behavior
|
|
13
16
|
*/
|
|
14
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
82
|
+
static initializeGlobal(services?: ServiceDefinition[], options?: ContainerPoolOptions): void;
|
|
19
83
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
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
|
-
|
|
108
|
+
static createProxyContainer(): ContainerInstance;
|
|
25
109
|
/**
|
|
26
|
-
*
|
|
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
|
-
|
|
29
|
-
available: number;
|
|
30
|
-
created: number;
|
|
31
|
-
maxSize: number;
|
|
32
|
-
};
|
|
126
|
+
static asMiddleware(services?: ServiceDefinition[]): (container?: ContainerInstance) => ContainerInstance;
|
|
33
127
|
/**
|
|
34
|
-
*
|
|
128
|
+
* Get statistics about the container pool
|
|
129
|
+
* (Maintained for backward compatibility)
|
|
35
130
|
*/
|
|
36
|
-
|
|
131
|
+
static getStats(): {
|
|
132
|
+
useProxy: boolean;
|
|
133
|
+
globalInitialized: boolean;
|
|
134
|
+
};
|
|
37
135
|
/**
|
|
38
|
-
* Clear
|
|
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
|
-
|
|
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
|