@broxium/apps-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,59 @@
1
+ import type { DynamicModule, Type } from "@nestjs/common";
2
+ export declare const BRODOX_SHARED = "BRODOX_SHARED";
3
+ export declare type BusHandler = (params: unknown, context: BusCallContext) => Promise<unknown>;
4
+ export interface BusCallContext {
5
+ callerSlug: string;
6
+ tenantId?: number;
7
+ }
8
+ export interface AppBusAdapter {
9
+ /**
10
+ * Register a named function that other apps can call.
11
+ * Call this inside onApplicationBootstrap so the service is fully initialized.
12
+ *
13
+ * @param event unique name within this app (e.g. 'send-sms')
14
+ * @param handler function to run when this event is called
15
+ */
16
+ defineEvent(event: string, handler: BusHandler): void;
17
+ /**
18
+ * Call a named function on another app.
19
+ * If the target app is idle (evicted), it will be automatically re-mounted first.
20
+ *
21
+ * @param targetSlug the slug of the app to call (e.g. 'quicksms')
22
+ * @param event the event name registered in that app
23
+ * @param params any data to pass to the handler
24
+ */
25
+ call(targetSlug: string, event: string, params?: unknown): Promise<unknown>;
26
+ }
27
+ export interface CacheHelper {
28
+ get<T>(key: string): Promise<T | null>;
29
+ set(key: string, value: unknown, ttl?: number): Promise<void>;
30
+ forget(key: string): Promise<void>;
31
+ remember<T>(key: string, ttl: number, fn: () => Promise<T>): Promise<T>;
32
+ }
33
+ export interface BrodoxSharedContainer {
34
+ /**
35
+ * Resolve any registered resource by key.
36
+ * Throws if the key is not registered.
37
+ *
38
+ * @example
39
+ * const redis = shared.resolve<Redis>('redis');
40
+ * const myDb = shared.resolve<PrismaClient>('prisma:brodox');
41
+ */
42
+ resolve<T>(key: string): T;
43
+ /**
44
+ * Check if a resource is registered before resolving.
45
+ */
46
+ has(key: string): boolean;
47
+ cache: CacheHelper;
48
+ bus: AppBusAdapter;
49
+ }
50
+ export interface BrodoxAppManifest {
51
+ slug: string;
52
+ name: string;
53
+ description: string;
54
+ version: string;
55
+ module: Type<unknown> | DynamicModule | ((shared: BrodoxSharedContainer) => Type<unknown> | DynamicModule);
56
+ requires?: string[];
57
+ }
58
+ /** Type-safe helper — just enables IDE autocomplete for the manifest. */
59
+ export declare function defineApp(m: BrodoxAppManifest): BrodoxAppManifest;
package/dist/index.js ADDED
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defineApp = exports.BRODOX_SHARED = void 0;
4
+ // ─────────────────────────────────────────────────────────────────────────────
5
+ // INJECT TOKEN
6
+ // Sub-apps use this to receive the shared container from the core.
7
+ // Usage inside a sub-app service:
8
+ // constructor(@Inject(BRODOX_SHARED) private readonly shared: BrodoxSharedContainer) {}
9
+ // ─────────────────────────────────────────────────────────────────────────────
10
+ exports.BRODOX_SHARED = "BRODOX_SHARED";
11
+ /** Type-safe helper — just enables IDE autocomplete for the manifest. */
12
+ function defineApp(m) {
13
+ return m;
14
+ }
15
+ exports.defineApp = defineApp;
package/package.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "@broxium/apps-sdk",
3
+ "version": "1.0.0",
4
+ "main": "dist/index.js",
5
+ "types": "dist/index.d.ts",
6
+ "scripts": {
7
+ "build": "tsc"
8
+ },
9
+ "devDependencies": {
10
+ "@nestjs/common": "^11.0.0",
11
+ "typescript": "^5.7.3"
12
+ },
13
+ "dependencies": {
14
+ "ioredis": "^5.10.1"
15
+ }
16
+ }
package/src/index.ts ADDED
@@ -0,0 +1,122 @@
1
+ import type { DynamicModule, Type } from "@nestjs/common";
2
+
3
+ // ─────────────────────────────────────────────────────────────────────────────
4
+ // INJECT TOKEN
5
+ // Sub-apps use this to receive the shared container from the core.
6
+ // Usage inside a sub-app service:
7
+ // constructor(@Inject(BRODOX_SHARED) private readonly shared: BrodoxSharedContainer) {}
8
+ // ─────────────────────────────────────────────────────────────────────────────
9
+ export const BRODOX_SHARED = "BRODOX_SHARED";
10
+
11
+ // ─────────────────────────────────────────────────────────────────────────────
12
+ // BUS SYSTEM
13
+ // Allows one sub-app to call another sub-app's named functions.
14
+ // The target app is automatically woken up (lazy-mounted) if it was sleeping.
15
+ //
16
+ // DEFINE (inside the target app's onApplicationBootstrap):
17
+ // shared.bus.defineEvent('send-sms', async (opts) => { return smsSvc.send(opts); });
18
+ //
19
+ // CALL (from any app or from the core):
20
+ // const result = await shared.bus.call('quicksms', 'send-sms', { phone: '...', msg: '...' });
21
+ // ─────────────────────────────────────────────────────────────────────────────
22
+ export type BusHandler = (
23
+ params: unknown,
24
+ context: BusCallContext,
25
+ ) => Promise<unknown>;
26
+
27
+ export interface BusCallContext {
28
+ callerSlug: string; // who is calling
29
+ tenantId?: number; // the current tenant (if any)
30
+ }
31
+
32
+ export interface AppBusAdapter {
33
+ /**
34
+ * Register a named function that other apps can call.
35
+ * Call this inside onApplicationBootstrap so the service is fully initialized.
36
+ *
37
+ * @param event unique name within this app (e.g. 'send-sms')
38
+ * @param handler function to run when this event is called
39
+ */
40
+ defineEvent(event: string, handler: BusHandler): void;
41
+
42
+ /**
43
+ * Call a named function on another app.
44
+ * If the target app is idle (evicted), it will be automatically re-mounted first.
45
+ *
46
+ * @param targetSlug the slug of the app to call (e.g. 'quicksms')
47
+ * @param event the event name registered in that app
48
+ * @param params any data to pass to the handler
49
+ */
50
+ call(targetSlug: string, event: string, params?: unknown): Promise<unknown>;
51
+ }
52
+
53
+ // ─────────────────────────────────────────────────────────────────────────────
54
+ // SHARED CONTAINER
55
+ // This is the single bag of shared resources every sub-app receives.
56
+ // The core registers resources here; sub-apps read them.
57
+ //
58
+ // Built-in keys the core always provides:
59
+ // resolve<Redis>('redis') → shared ioredis client
60
+ // resolve<CacheHelper>('cache') → cache wrapper (remember, get, set, forget)
61
+ // resolve<any>('prisma:brodox') → shared Prisma client (when you wire it)
62
+ // resolve<any>('prisma:substores')
63
+ //
64
+ // You can register ANYTHING: functions, class instances, Prisma clients, RabbitMQ...
65
+ // (from main.ts or SharedResourcesProvider.onModuleInit)
66
+ // shared.register('rabbitmq', rabbitMQClient);
67
+ // shared.register('stripe', stripeClient);
68
+ // ─────────────────────────────────────────────────────────────────────────────
69
+ export interface CacheHelper {
70
+ get<T>(key: string): Promise<T | null>;
71
+ set(key: string, value: unknown, ttl?: number): Promise<void>;
72
+ forget(key: string): Promise<void>;
73
+ remember<T>(key: string, ttl: number, fn: () => Promise<T>): Promise<T>;
74
+ }
75
+
76
+ export interface BrodoxSharedContainer {
77
+ /**
78
+ * Resolve any registered resource by key.
79
+ * Throws if the key is not registered.
80
+ *
81
+ * @example
82
+ * const redis = shared.resolve<Redis>('redis');
83
+ * const myDb = shared.resolve<PrismaClient>('prisma:brodox');
84
+ */
85
+ resolve<T>(key: string): T;
86
+
87
+ /**
88
+ * Check if a resource is registered before resolving.
89
+ */
90
+ has(key: string): boolean;
91
+
92
+ // Convenient direct references (most apps only need these two)
93
+ cache: CacheHelper;
94
+ bus: AppBusAdapter;
95
+ }
96
+
97
+ // ─────────────────────────────────────────────────────────────────────────────
98
+ // APP MANIFEST
99
+ // Every app's dist/index.js must export a manifest of this shape.
100
+ //
101
+ // The module field can be:
102
+ // - A static NestJS module class: module: PosProModule
103
+ // - A factory that receives shared resources: module: (s) => PosProModule.withShared(s)
104
+ //
105
+ // Use the factory form so your app gets DB/Redis/bus from the core.
106
+ // ─────────────────────────────────────────────────────────────────────────────
107
+ export interface BrodoxAppManifest {
108
+ slug: string;
109
+ name: string;
110
+ description: string;
111
+ version: string;
112
+ module:
113
+ | Type<unknown>
114
+ | DynamicModule
115
+ | ((shared: BrodoxSharedContainer) => Type<unknown> | DynamicModule);
116
+ requires?: string[]; // optional: list of resource keys this app needs from core
117
+ }
118
+
119
+ /** Type-safe helper — just enables IDE autocomplete for the manifest. */
120
+ export function defineApp(m: BrodoxAppManifest): BrodoxAppManifest {
121
+ return m;
122
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es2021",
4
+ "module": "commonjs",
5
+ "outDir": "./dist",
6
+ "declaration": true,
7
+ "strict": true,
8
+ "experimentalDecorators": true,
9
+ "emitDecoratorMetadata": true,
10
+ "skipLibCheck": true
11
+ },
12
+ "include": ["src/**/*"]
13
+ }