joopjs 2.0.5 → 2.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.
Files changed (146) hide show
  1. package/.claude/skills/auth.md +235 -0
  2. package/.claude/skills/banking.md +377 -0
  3. package/.claude/skills/encryption.md +265 -0
  4. package/.claude/skills/finance.md +248 -0
  5. package/.claude/skills/observables.md +270 -0
  6. package/.claude/skills/security.md +240 -0
  7. package/.claude/skills/setup.md +196 -0
  8. package/.cursor/rules/joopjs.mdc +150 -0
  9. package/.github/copilot-instructions.md +143 -0
  10. package/.windsurf/rules/joopjs.md +226 -0
  11. package/CHANGELOG.md +81 -0
  12. package/README.md +47 -7
  13. package/ai-rules/AGENTS.md +241 -0
  14. package/ai-rules/GEMINI.md +183 -0
  15. package/dist/ai/index.js +15 -3
  16. package/dist/ai/index.js.map +1 -1
  17. package/dist/ai/index.mjs +15 -3
  18. package/dist/ai/index.mjs.map +1 -1
  19. package/dist/analytics/index.js +10 -2
  20. package/dist/analytics/index.js.map +1 -1
  21. package/dist/analytics/index.mjs +10 -2
  22. package/dist/analytics/index.mjs.map +1 -1
  23. package/dist/angular/index.d.mts +98 -27
  24. package/dist/angular/index.d.ts +98 -27
  25. package/dist/angular/index.js +44 -0
  26. package/dist/angular/index.js.map +1 -1
  27. package/dist/angular/index.mjs +39 -1
  28. package/dist/angular/index.mjs.map +1 -1
  29. package/dist/api/index.js +15 -3
  30. package/dist/api/index.js.map +1 -1
  31. package/dist/api/index.mjs +15 -3
  32. package/dist/api/index.mjs.map +1 -1
  33. package/dist/auth/index.js +15 -3
  34. package/dist/auth/index.js.map +1 -1
  35. package/dist/auth/index.mjs +15 -3
  36. package/dist/auth/index.mjs.map +1 -1
  37. package/dist/banking/index.js +15 -3
  38. package/dist/banking/index.js.map +1 -1
  39. package/dist/banking/index.mjs +15 -3
  40. package/dist/banking/index.mjs.map +1 -1
  41. package/dist/cache/index.js +15 -3
  42. package/dist/cache/index.js.map +1 -1
  43. package/dist/cache/index.mjs +15 -3
  44. package/dist/cache/index.mjs.map +1 -1
  45. package/dist/{index-DFqEoX_l.d.ts → consent.service-CIHNtx9h.d.ts} +1 -2
  46. package/dist/{index-B_ksKpS1.d.mts → consent.service-DQ-JAEJx.d.mts} +1 -2
  47. package/dist/core/index.d.mts +34 -1
  48. package/dist/core/index.d.ts +34 -1
  49. package/dist/core/index.js +56 -5
  50. package/dist/core/index.js.map +1 -1
  51. package/dist/core/index.mjs +54 -6
  52. package/dist/core/index.mjs.map +1 -1
  53. package/dist/deeplink/index.js +15 -3
  54. package/dist/deeplink/index.js.map +1 -1
  55. package/dist/deeplink/index.mjs +15 -3
  56. package/dist/deeplink/index.mjs.map +1 -1
  57. package/dist/device/index.js +15 -3
  58. package/dist/device/index.js.map +1 -1
  59. package/dist/device/index.mjs +15 -3
  60. package/dist/device/index.mjs.map +1 -1
  61. package/dist/forms/index.js +15 -3
  62. package/dist/forms/index.js.map +1 -1
  63. package/dist/forms/index.mjs +15 -3
  64. package/dist/forms/index.mjs.map +1 -1
  65. package/dist/i18n/index.js +15 -3
  66. package/dist/i18n/index.js.map +1 -1
  67. package/dist/i18n/index.mjs +15 -3
  68. package/dist/i18n/index.mjs.map +1 -1
  69. package/dist/index.d.mts +2 -2
  70. package/dist/index.d.ts +2 -2
  71. package/dist/index.js +50 -8
  72. package/dist/index.js.map +1 -1
  73. package/dist/index.mjs +50 -8
  74. package/dist/index.mjs.map +1 -1
  75. package/dist/{joop-CA3DMeOO.d.ts → joop-Dim2yEKG.d.ts} +1 -1
  76. package/dist/{joop-Bx7Iwj5p.d.mts → joop-GkQw13f9.d.mts} +1 -1
  77. package/dist/native-bridge/index.js +10 -2
  78. package/dist/native-bridge/index.js.map +1 -1
  79. package/dist/native-bridge/index.mjs +10 -2
  80. package/dist/native-bridge/index.mjs.map +1 -1
  81. package/dist/network/index.js +15 -3
  82. package/dist/network/index.js.map +1 -1
  83. package/dist/network/index.mjs +15 -3
  84. package/dist/network/index.mjs.map +1 -1
  85. package/dist/observability/index.js +15 -3
  86. package/dist/observability/index.js.map +1 -1
  87. package/dist/observability/index.mjs +15 -3
  88. package/dist/observability/index.mjs.map +1 -1
  89. package/dist/pwa/index.js +15 -3
  90. package/dist/pwa/index.js.map +1 -1
  91. package/dist/pwa/index.mjs +15 -3
  92. package/dist/pwa/index.mjs.map +1 -1
  93. package/dist/react/index.d.mts +2 -2
  94. package/dist/react/index.d.ts +2 -2
  95. package/dist/react/index.js +15 -3
  96. package/dist/react/index.js.map +1 -1
  97. package/dist/react/index.mjs +15 -3
  98. package/dist/react/index.mjs.map +1 -1
  99. package/dist/router/index.js +15 -3
  100. package/dist/router/index.js.map +1 -1
  101. package/dist/router/index.mjs +15 -3
  102. package/dist/router/index.mjs.map +1 -1
  103. package/dist/security/index.js +15 -3
  104. package/dist/security/index.js.map +1 -1
  105. package/dist/security/index.mjs +15 -3
  106. package/dist/security/index.mjs.map +1 -1
  107. package/dist/session/index.js +15 -3
  108. package/dist/session/index.js.map +1 -1
  109. package/dist/session/index.mjs +15 -3
  110. package/dist/session/index.mjs.map +1 -1
  111. package/dist/state/index.js +15 -3
  112. package/dist/state/index.js.map +1 -1
  113. package/dist/state/index.mjs +15 -3
  114. package/dist/state/index.mjs.map +1 -1
  115. package/dist/storage/index.js +15 -3
  116. package/dist/storage/index.js.map +1 -1
  117. package/dist/storage/index.mjs +15 -3
  118. package/dist/storage/index.mjs.map +1 -1
  119. package/dist/sync/index.js +15 -3
  120. package/dist/sync/index.js.map +1 -1
  121. package/dist/sync/index.mjs +15 -3
  122. package/dist/sync/index.mjs.map +1 -1
  123. package/dist/theme/index.js +15 -3
  124. package/dist/theme/index.js.map +1 -1
  125. package/dist/theme/index.mjs +15 -3
  126. package/dist/theme/index.mjs.map +1 -1
  127. package/dist/ui/index.js +15 -3
  128. package/dist/ui/index.js.map +1 -1
  129. package/dist/ui/index.mjs +15 -3
  130. package/dist/ui/index.mjs.map +1 -1
  131. package/dist/utilities/index.js +46 -4
  132. package/dist/utilities/index.js.map +1 -1
  133. package/dist/utilities/index.mjs +46 -4
  134. package/dist/utilities/index.mjs.map +1 -1
  135. package/dist/vue/index.d.mts +2 -2
  136. package/dist/vue/index.d.ts +2 -2
  137. package/dist/vue/index.js +15 -3
  138. package/dist/vue/index.js.map +1 -1
  139. package/dist/vue/index.mjs +15 -3
  140. package/dist/vue/index.mjs.map +1 -1
  141. package/dist/workflow/index.js +15 -3
  142. package/dist/workflow/index.js.map +1 -1
  143. package/dist/workflow/index.mjs +15 -3
  144. package/dist/workflow/index.mjs.map +1 -1
  145. package/package.json +96 -32
  146. package/scripts/setup-ai.mjs +133 -0
@@ -0,0 +1,150 @@
1
+ ---
2
+ description: Rules for using joopjs — enterprise financial SDK
3
+ globs: ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx"]
4
+ alwaysApply: true
5
+ ---
6
+
7
+ # JoopJS SDK Rules for Cursor
8
+
9
+ **Author:** Kundan Singh
10
+
11
+ This project uses **joopjs** — a framework-agnostic TypeScript SDK for enterprise financial apps. Apply these rules whenever you generate or suggest code that involves joopjs.
12
+
13
+ ## Import Rules
14
+
15
+ Always import from the package root or named sub-paths:
16
+ ```ts
17
+ // Correct
18
+ import { JoopDigitalWalletService, JoopAuthService } from 'joopjs';
19
+ import { JoopGcmService } from 'joopjs/encryption';
20
+
21
+ // Wrong — never import from internal paths
22
+ import { JoopDigitalWalletService } from 'joopjs/src/banking/digital-wallet.service';
23
+ ```
24
+
25
+ Available sub-paths: `auth`, `encryption`, `banking`, `security`, `api`, `core`, `session`, `device`, `observability`, `theme`, `i18n`, `ui`, `forms`, `router`, `state`, `workers`, `workflow`, `sync`, `platform`, `cache`, `network`, `analytics`, `validation`, `utilities`, `pwa`, `native-bridge`, `deeplink`, `react`, `angular`, `vue`, `india`.
26
+
27
+ ## Service Instantiation
28
+
29
+ All services are plain classes with no dependencies:
30
+ ```ts
31
+ const wallet = new JoopDigitalWalletService();
32
+ const auth = new JoopAuthService();
33
+ const loans = new JoopLoanServicingService();
34
+ const gcm = new JoopGcmService();
35
+ ```
36
+
37
+ Create them once at module/app level and share as singletons. No `@Injectable`, no DI container needed.
38
+
39
+ ## Observables — Critical Rules
40
+
41
+ ```ts
42
+ // Subscribe
43
+ const unsub = service.someEvent$().subscribe(value => { /* handler */ });
44
+
45
+ // Emit (from inside a service or your own subject)
46
+ mySubject.next(value); // CORRECT
47
+ mySubject.emit(value); // WRONG — will throw
48
+
49
+ // Read current value (BehaviorSubject only)
50
+ const current = myBehaviorSubject.getValue();
51
+
52
+ // Unsubscribe
53
+ unsub(); // call the returned function — not .unsubscribe()
54
+
55
+ // Do NOT use RxJS operators
56
+ service.alert$().pipe(map(x => x)) // WRONG — not RxJS
57
+ ```
58
+
59
+ ## Data Types
60
+
61
+ - Amounts: `number` (no Money class or BigDecimal)
62
+ - Currencies: ISO-4217 string literal — `'USD'`, `'EUR'`, `'AED'`, `'INR'`
63
+ - Timestamps: Unix epoch milliseconds as `number` — `Date.now()`, never `new Date()`
64
+ - All IDs: `string`
65
+
66
+ ## Error Handling
67
+
68
+ Services throw `Error` objects on invalid operations. Always use try/catch:
69
+ ```ts
70
+ try {
71
+ const result = await service.doSomething();
72
+ } catch (error) {
73
+ console.error(error.message);
74
+ }
75
+ ```
76
+
77
+ ## Reference Formats
78
+
79
+ Auto-generated reference numbers follow predictable patterns:
80
+ - Loans: `LN-YYYY-000001`
81
+ - FX Forwards: `FWD-YYYY-000001`
82
+ - Journal Entries: `JE-YYYY-000001`
83
+ - Standing Orders: `SO-YYYY-000001`
84
+ - Remittances: `RMT-YYYY-000001`
85
+
86
+ ## Framework Integration
87
+
88
+ ### React
89
+ ```tsx
90
+ useEffect(() => {
91
+ const unsub = service.event$().subscribe(handleEvent);
92
+ return unsub; // cleanup on unmount
93
+ }, []);
94
+ ```
95
+
96
+ ### Angular
97
+ `joopjs/angular` ships real Angular 17+ DI. Bootstrap with `provideJoopAngular(instance)`, then inject and bridge observables to signals (auto-teardown via `DestroyRef`):
98
+ ```ts
99
+ const joop = injectJoop();
100
+ balance = joopSignal(joop.wallet.balance$()); // Angular signal
101
+ ```
102
+ Also available: `joopAuthGuard()` (CanActivateFn), `joopAuthInterceptor()` (HttpInterceptorFn). Legacy `provideJoop`, `JoopModule`, `fromJoop` are deprecated but still work.
103
+
104
+ ### Vue
105
+ ```ts
106
+ onMounted(() => { unsub = service.event$().subscribe(handleEvent); });
107
+ onUnmounted(() => unsub?.());
108
+ ```
109
+
110
+ ## Key Services Quick Reference
111
+
112
+ | Use Case | Service | Key Methods |
113
+ |----------|---------|-------------|
114
+ | Digital wallet | `JoopDigitalWalletService` | `createWallet`, `topUp`, `pay`, `transfer`, `getBalance`, `balance$` |
115
+ | Loan management | `JoopLoanServicingService` | `createLoan`, `recordPayment`, `getSchedule`, `getOutstandingBalance` |
116
+ | FX forwards | `JoopFxForwardService` | `setSpotRate`, `createForward`, `settleForward`, `getMarkToMarket` |
117
+ | Mutual funds | `JoopMutualFundService` | `registerFund`, `invest`, `redeem`, `updateNav`, `createSip`, `executeSip` |
118
+ | Sanctions | `JoopSanctionsScreeningService` | `loadList`, `screen`, `hit$` |
119
+ | AML | `JoopAmlService` | `addRule`, `checkTransaction`, `alert$` |
120
+ | Auth | `JoopAuthService` | `login`, `logout`, `refresh`, `getCurrentUser`, `session$` |
121
+ | JWT | `JoopJwtService` | `sign`, `verify`, `decode`, `revoke` |
122
+ | Encryption | `JoopGcmService` | `generateKey`, `encrypt`, `decrypt` |
123
+ | Key exchange | `JoopX25519Service` | `generateKeyPair`, `deriveSharedSecret`, `deriveAesKey` |
124
+ | Double-entry | `JoopLedgerService` | `addAccount`, `postEntry`, `getBalance`, `getTrialBalance` |
125
+ | Reconciliation | `JoopReconciliationService` | `createSession`, `autoMatch`, `manualMatch`, `getSummary` |
126
+
127
+ ---
128
+
129
+ ## What Gets Published to npm
130
+
131
+ Controlled by `"files"` in `package.json` — acts as an allowlist. Only these two are included:
132
+
133
+ | Published to npm | Never published |
134
+ |-----------------|----------------|
135
+ | `dist/` — ESM + CJS + `.d.ts` for all 34 sub-paths | `src/` — TypeScript source |
136
+ | `CHANGELOG.md` — release history | `tests/` — test suite |
137
+ | | `scripts/` — release automation |
138
+ | | `playground/` — Vite demo app |
139
+ | | `.claude/` — Claude skills |
140
+ | | `.cursor/` — these Cursor rules |
141
+ | | `.windsurf/` — Windsurf rules |
142
+ | | `GEMINI.md`, `AGENTS.md` — AI tool instructions |
143
+ | | `tsup.config.ts`, `vitest.config.ts`, `tsconfig.json` |
144
+
145
+ Source code, AI rules, and dev tooling are **never** published to npm.
146
+
147
+ Verify the tarball contents before any publish:
148
+ ```bash
149
+ npm pack --dry-run
150
+ ```
@@ -0,0 +1,143 @@
1
+ # GitHub Copilot Instructions — JoopJS SDK
2
+
3
+ **Author:** Kundan Singh
4
+
5
+ This workspace uses **joopjs** (`npm install joopjs`), a framework-agnostic TypeScript SDK for enterprise financial applications.
6
+
7
+ ## Always Follow These Rules
8
+
9
+ ### Imports
10
+ - Import everything from `'joopjs'` (single entry point), or from sub-paths like `'joopjs/auth'`, `'joopjs/encryption'`
11
+ - Never import from internal paths like `'joopjs/src/...'` or `'joopjs/dist/...'`
12
+
13
+ ### Service instantiation
14
+ - All services are plain classes: `const svc = new JoopXxxService();`
15
+ - No dependency injection or Angular `@Injectable` needed for the core SDK
16
+ - For Angular 17+ apps, `joopjs/angular` offers real DI: `provideJoopAngular`, `injectJoop`, `joopSignal`, `joopAuthGuard`, `joopAuthInterceptor`
17
+ - Create one instance per module/app (treat as singletons)
18
+
19
+ ### Reactive observables
20
+ - Use `.subscribe(callback)` — returns an unsubscribe function, call it to stop listening
21
+ - Emit values with `.next(value)` — **never** `.emit(value)`
22
+ - Read current value with `.getValue()` on JoopBehaviorSubject
23
+ - Do NOT use RxJS operators (`.pipe()`, `.map()`, etc.) — these are not RxJS Observables
24
+ - Emission is error-isolated — one throwing subscriber does not block the others
25
+
26
+ ### Data conventions
27
+ - Amounts: plain `number`, never a Money class
28
+ - Currencies: ISO-4217 string (`'USD'`, `'EUR'`, `'AED'`)
29
+ - Timestamps: Unix epoch milliseconds (`number`), never `Date` objects
30
+ - IDs: pass as `string`
31
+
32
+ ### Error handling
33
+ - All services throw standard `Error` on invalid input
34
+ - Wrap service calls in `try/catch`
35
+
36
+ ---
37
+
38
+ ## Common Completions to Suggest
39
+
40
+ ### Digital Wallet
41
+ ```ts
42
+ import { JoopDigitalWalletService } from 'joopjs';
43
+ const wallet = new JoopDigitalWalletService();
44
+ const w = wallet.createWallet('user-001', { currency: 'USD', label: 'Primary' });
45
+ wallet.topUp(w.id, 500);
46
+ wallet.pay(w.id, 50, 'merchant-id', 'description');
47
+ const bal = wallet.getBalance(w.id);
48
+ wallet.balance$().subscribe(({ walletId, balance }) => { /* update UI */ });
49
+ ```
50
+
51
+ ### Auth + JWT
52
+ ```ts
53
+ import { JoopAuthService, JoopJwtService } from 'joopjs';
54
+ const auth = new JoopAuthService();
55
+ const jwt = new JoopJwtService({ secret: process.env.JWT_SECRET!, expiryMs: 3600_000 });
56
+ const session = await auth.login(email, password);
57
+ const token = jwt.sign({ userId: session.userId, role: 'user' });
58
+ ```
59
+
60
+ ### AES-GCM Encryption
61
+ ```ts
62
+ import { JoopGcmService } from 'joopjs';
63
+ const gcm = new JoopGcmService();
64
+ const key = await gcm.generateKey();
65
+ const enc = await gcm.encrypt(sensitiveData, key);
66
+ const dec = await gcm.decrypt(enc.ciphertext, key, enc.iv);
67
+ ```
68
+
69
+ ### Loan Servicing
70
+ ```ts
71
+ import { JoopLoanServicingService } from 'joopjs';
72
+ const loans = new JoopLoanServicingService();
73
+ const loan = loans.createLoan({ borrowerName, borrowerId, principalAmount, annualInterestRatePercent, tenureMonths, currency: 'USD' });
74
+ loans.recordPayment(loan.id, loan.emiAmount);
75
+ const schedule = loans.getSchedule(loan.id);
76
+ ```
77
+
78
+ ### Sanctions Screening
79
+ ```ts
80
+ import { JoopSanctionsScreeningService } from 'joopjs';
81
+ const sanctions = new JoopSanctionsScreeningService();
82
+ sanctions.loadList('ofac', entities);
83
+ const result = sanctions.screen({ name: customerName, country: customerCountry });
84
+ if (result.status !== 'clear') { /* block or escalate */ }
85
+ ```
86
+
87
+ ### Mutual Fund SIP
88
+ ```ts
89
+ import { JoopMutualFundService } from 'joopjs';
90
+ const mf = new JoopMutualFundService();
91
+ const sip = mf.createSip(fundId, investorId, monthlyAmount, 'monthly', Date.now());
92
+ mf.executeSip(sip.id);
93
+ ```
94
+
95
+ ---
96
+
97
+ ## TypeScript Types (prefix `Joop*`)
98
+
99
+ ```ts
100
+ // Auth
101
+ JoopAuthUser, JoopAuthSession, JoopAuthToken
102
+
103
+ // Banking
104
+ JoopWallet, JoopWalletTransaction, JoopWalletTxnType
105
+ JoopLoanAccount, JoopInstallment, JoopLoanAccountStatus
106
+ JoopFxForward, JoopForwardType, JoopForwardStatus
107
+ JoopLedgerAccount, JoopJournalEntry, JoopTrialBalance
108
+
109
+ // Finance
110
+ JoopMutualFund, JoopFundHolding, JoopSip, JoopSipStatus, JoopFundCategory
111
+
112
+ // Security
113
+ JoopSanctionsEntity, JoopScreeningResult, JoopSanctionMatchType
114
+ JoopAmlAlert, JoopCompliancePolicy
115
+ ```
116
+
117
+ All types are exported from `'joopjs'`.
118
+
119
+ ---
120
+
121
+ ## What Gets Published to npm
122
+
123
+ Controlled by `"files"` in `package.json` — acts as an allowlist. Only these two are included:
124
+
125
+ | Published to npm | Never published |
126
+ |-----------------|----------------|
127
+ | `dist/` — ESM + CJS + `.d.ts` for all 34 sub-paths | `src/` — TypeScript source |
128
+ | `CHANGELOG.md` — release history | `tests/` — test suite |
129
+ | | `scripts/` — release automation |
130
+ | | `playground/` — Vite demo app |
131
+ | | `.claude/` — Claude skills |
132
+ | | `.cursor/` — Cursor rules |
133
+ | | `.windsurf/` — Windsurf rules |
134
+ | | `GEMINI.md`, `AGENTS.md` — AI tool instructions |
135
+ | | `.github/copilot-instructions.md` — this file |
136
+ | | `tsup.config.ts`, `vitest.config.ts`, `tsconfig.json` |
137
+
138
+ Source code, AI rules, and dev tooling are **never** published to npm.
139
+
140
+ Verify the tarball contents before any publish:
141
+ ```bash
142
+ npm pack --dry-run
143
+ ```
@@ -0,0 +1,226 @@
1
+ # JoopJS SDK Rules for Windsurf Cascade
2
+
3
+ **Author:** Kundan Singh
4
+
5
+ This project uses **joopjs** — a framework-agnostic TypeScript SDK for building enterprise financial applications.
6
+
7
+ ## Package Information
8
+
9
+ - **Package name:** `joopjs`
10
+ - **Install:** `npm install joopjs`
11
+ - **Version:** 2.0.0
12
+ - **Compatibility:** Any TypeScript/JavaScript project — React, Angular, Vue, Node.js, plain TS
13
+
14
+ ---
15
+
16
+ ## Core Conventions
17
+
18
+ ### All imports come from `'joopjs'`
19
+
20
+ ```ts
21
+ import {
22
+ JoopAuthService,
23
+ JoopDigitalWalletService,
24
+ JoopLoanServicingService,
25
+ JoopMutualFundService,
26
+ JoopSanctionsScreeningService,
27
+ JoopGcmService,
28
+ JoopX25519Service,
29
+ JoopSubject,
30
+ JoopBehaviorSubject,
31
+ } from 'joopjs';
32
+ ```
33
+
34
+ Or use sub-path imports for tree-shaking: `'joopjs/auth'`, `'joopjs/encryption'`, `'joopjs/banking'`, etc.
35
+
36
+ ### Services are plain class instances
37
+
38
+ ```ts
39
+ // Good
40
+ const wallet = new JoopDigitalWalletService();
41
+
42
+ // Bad — no DI framework needed
43
+ @Injectable() class MyService { constructor(private wallet: JoopDigitalWalletService) {} }
44
+ ```
45
+
46
+ For Angular 17+ apps, `joopjs/angular` provides real DI: bootstrap with `provideJoopAngular(instance)`, then `const joop = injectJoop(); balance = joopSignal(joop.wallet.balance$());` (signal with auto-teardown). The core SDK itself still imports no framework.
47
+
48
+ ---
49
+
50
+ ## Reactive Pattern (Non-RxJS)
51
+
52
+ ```ts
53
+ // Subscribe — returns unsubscribe function
54
+ const stop = service.change$().subscribe(value => handleChange(value));
55
+
56
+ // Emit
57
+ subject.next(newValue); // CORRECT
58
+ subject.emit(newValue); // WILL THROW — wrong method name
59
+
60
+ // Cleanup
61
+ stop();
62
+
63
+ // BehaviorSubject current value
64
+ const val = behaviorSubject.getValue();
65
+ ```
66
+
67
+ Emission is error-isolated: a throwing subscriber no longer blocks delivery to the others. Route subscriber errors with `setSubjectErrorHandler(fn)` (defaults to `console.error`). Still not RxJS.
68
+
69
+ ---
70
+
71
+ ## Data Types
72
+
73
+ | Concept | Type | Example |
74
+ |---------|------|---------|
75
+ | Money amount | `number` | `5000.00` |
76
+ | Currency | `string` (ISO-4217) | `'USD'`, `'AED'` |
77
+ | Timestamp | `number` (epoch ms) | `Date.now()` |
78
+ | Duration | `number` (ms) | `7 * 86_400_000` |
79
+ | ID | `string` | `'u-001'` |
80
+
81
+ ---
82
+
83
+ ## Domain Services Reference
84
+
85
+ ### Banking
86
+
87
+ ```ts
88
+ // Digital Wallet
89
+ const w = wallet.createWallet(userId, { currency: 'USD' });
90
+ wallet.topUp(w.id, amount);
91
+ wallet.pay(w.id, amount, merchantId, description);
92
+ wallet.transfer(w.id, toWalletId, amount);
93
+ wallet.freeze(w.id) / wallet.unfreeze(w.id) / wallet.close(w.id);
94
+ wallet.balance$().subscribe(({ walletId, balance }) => { });
95
+
96
+ // Loans
97
+ const loan = loans.createLoan({ borrowerName, borrowerId, principalAmount, annualInterestRatePercent, tenureMonths, currency });
98
+ loans.recordPayment(loan.id, amount); // interest-first allocation
99
+ const schedule = loans.getSchedule(loan.id); // JoopInstallment[]
100
+
101
+ // FX Forwards
102
+ fx.setSpotRate('USD', 'EUR', 0.92);
103
+ const fwd = fx.createForward({ type: 'sell', baseCurrency, quoteCurrency, notionalAmount, contractRate, maturityDate });
104
+ fx.settleForward(fwd.id, spotRateAtSettlement); // returns { pnl }
105
+
106
+ // Ledger
107
+ ledger.addAccount(code, name, 'asset' | 'liability' | 'equity' | 'revenue' | 'expense');
108
+ ledger.postEntry(description, [{ accountCode, debit, credit }, ...]);
109
+ ledger.getTrialBalance(); // { isBalanced, totalDebits, totalCredits }
110
+ ```
111
+
112
+ ### Finance
113
+
114
+ ```ts
115
+ // Mutual Funds
116
+ mf.registerFund({ id, name, category: 'equity'|'debt'|'hybrid'|'index'|'etf', currentNav, currency });
117
+ mf.invest(fundId, investorId, amount);
118
+ mf.redeem(fundId, investorId, units);
119
+ const sip = mf.createSip(fundId, investorId, amount, 'monthly'|'weekly'|'quarterly', startDate);
120
+ mf.executeSip(sip.id);
121
+
122
+ // Budget
123
+ budget.createBudget({ name, period: 'monthly', currency, startDate });
124
+ budget.addCategory(budgetId, { name, limit });
125
+ budget.recordSpend(budgetId, categoryId, amount, description);
126
+
127
+ // Portfolio
128
+ portfolio.createPortfolio({ name, currency, userId });
129
+ portfolio.addHolding(portfolioId, { symbol, name, quantity, avgCostPrice, currentPrice, assetClass });
130
+ portfolio.updatePrice(portfolioId, symbol, newPrice);
131
+ ```
132
+
133
+ ### Security
134
+
135
+ ```ts
136
+ // Sanctions Screening
137
+ sanctions.loadList('ofac' | 'un' | 'eu' | 'uk' | 'custom', entities);
138
+ const result = sanctions.screen({ name, country? });
139
+ // result.status: 'clear' | 'hit' | 'review'
140
+ // result.matches[]: [{ entity, matchType: 'exact'|'alias'|'fuzzy', score }]
141
+ sanctions.hit$().subscribe(hit => { }); // only fires on non-clear results
142
+
143
+ // AML
144
+ aml.addRule({ id, name, type, threshold, currency, action: 'flag'|'block', enabled });
145
+ const alert = aml.checkTransaction({ id, amount, currency, type, userId, timestamp });
146
+ // null = passes; JoopAmlAlert = flagged/blocked
147
+
148
+ // Risk Engine
149
+ risk.addFactor({ key, weight, transform? });
150
+ const score = risk.evaluate(signals); // { total: [0-1], level: 'low'|'medium'|'high'|'critical' }
151
+ ```
152
+
153
+ ### Auth & Encryption
154
+
155
+ ```ts
156
+ // Auth
157
+ const session = await auth.login(email, password);
158
+ await auth.logout(session.sessionId);
159
+ auth.session$().subscribe(session => { /* null = logged out */ });
160
+
161
+ // JWT
162
+ const token = jwt.sign({ userId, role }, secret);
163
+ const claims = jwt.verify(token, secret); // null if invalid/expired
164
+
165
+ // AES-GCM
166
+ const key = await gcm.generateKey();
167
+ const { ciphertext, iv } = await gcm.encrypt(plaintext, key);
168
+ const decrypted = await gcm.decrypt(ciphertext, key, iv);
169
+
170
+ // X25519 Key Exchange
171
+ const keys = x25519.generateKeyPair();
172
+ const shared = x25519.deriveSharedSecret(myPrivKey, theirPubKey);
173
+ const aesKey = await x25519.deriveAesKey(shared); // use with gcm.encrypt()
174
+ ```
175
+
176
+ ---
177
+
178
+ ## Error Handling Pattern
179
+
180
+ ```ts
181
+ try {
182
+ const result = loans.createLoan({ ... });
183
+ } catch (err) {
184
+ if (err instanceof Error) {
185
+ // All joopjs errors are standard Error with descriptive messages
186
+ console.error(err.message);
187
+ }
188
+ }
189
+ ```
190
+
191
+ ---
192
+
193
+ ## When Cascade Generates JoopJS Code
194
+
195
+ Always:
196
+ 1. Use `new JoopXxxService()` — no DI
197
+ 2. Call `.next(value)` to emit — never `.emit(value)`
198
+ 3. Use `number` for amounts and timestamps
199
+ 4. Wrap service calls in `try/catch`
200
+ 5. Store the unsubscribe function from `.subscribe()` and call it to clean up
201
+ 6. Use ISO-4217 strings for currency — `'USD'`, not `USD` (no enum)
202
+
203
+ ---
204
+
205
+ ## What Gets Published to npm
206
+
207
+ Controlled by `"files"` in `package.json` — acts as an allowlist. Only these two are included:
208
+
209
+ | Published to npm | Never published |
210
+ |-----------------|----------------|
211
+ | `dist/` — ESM + CJS + `.d.ts` for all 34 sub-paths | `src/` — TypeScript source |
212
+ | `CHANGELOG.md` — release history | `tests/` — test suite |
213
+ | | `scripts/` — release automation |
214
+ | | `playground/` — Vite demo app |
215
+ | | `.claude/` — Claude skills |
216
+ | | `.cursor/` — Cursor rules |
217
+ | | `.windsurf/` — these Windsurf rules |
218
+ | | `GEMINI.md`, `AGENTS.md` — AI tool instructions |
219
+ | | `tsup.config.ts`, `vitest.config.ts`, `tsconfig.json` |
220
+
221
+ Source code, AI rules, and dev tooling are **never** published to npm.
222
+
223
+ Verify the tarball contents before any publish:
224
+ ```bash
225
+ npm pack --dry-run
226
+ ```
package/CHANGELOG.md CHANGED
@@ -8,10 +8,45 @@ Versioning follows [Semantic Versioning](https://semver.org/).
8
8
 
9
9
  ---
10
10
 
11
+ ## [2.1.0] — 2026-06-25 — Angular DI & Federation-Safe Core
12
+
13
+ **0 new services · 21 new tests · 2189 tests total**
14
+
15
+ ### Added
16
+ - **`joopjs/angular` — real Angular 17+ DI.** Alongside the existing string tokens (kept for back-compat):
17
+ - `JOOP_INSTANCE` — typed `InjectionToken<JoopInstance>`, plus `provideJoopAngular()` and `injectJoop()`.
18
+ - `joopSignal(obs, opts?)` — bridges a `JoopObservable` to an Angular `Signal`, seeded from the current value and torn down automatically via `DestroyRef`.
19
+ - `joopAuthGuard(opts?)` — functional `CanActivateFn` backed by `JoopAuthService`, returning a redirect `UrlTree` when unauthenticated.
20
+ - `joopAuthInterceptor(opts?)` — `HttpInterceptorFn` that attaches the access token from `JoopTokenService` (configurable header/scheme).
21
+ - **`joopjs/core` — federation-safe singletons.** `globalSingleton()`, `joopCopyCount()`, and `silenceDuplicateCopyWarning()`. Module-level singletons (`logger`, `configService`, `joopEventBus`, `clipboard`, `clientProfile`) now resolve through a version-keyed `globalThis` registry, so duplicate bundled copies in a micro-frontend converge on one instance instead of fragmenting state. A one-time console warning fires when more than one copy is detected.
22
+ - **`setSubjectErrorHandler()`** in the events module to route subscriber errors.
23
+ - **`scripts/check-core-boundary.mjs`** + `npm run check:boundary` — CI guard enforcing that core never imports a framework (framework imports allowed only in `angular`/`react`/`vue` sub-paths).
24
+
25
+ ### Changed
26
+ - **`JoopSubject` / `JoopBehaviorSubject` emission is now error-isolated.** `next()` snapshots its listeners and wraps each in try/catch, so one throwing subscriber no longer aborts delivery to the rest, and a subscribe/unsubscribe triggered mid-emission can't disturb the in-flight notification.
27
+ - `@angular/common` and `@angular/router` added as **optional** peer dependencies (for `joopAuthGuard` / `joopAuthInterceptor`); `tsup` externalizes them so they are never bundled.
28
+
29
+ ### Deprecated
30
+ - `joopjs/angular`: the string tokens (`JOOP`, `JOOP_AUTH`, …), `provideJoop()`, `JoopModule`, and `fromJoop()` are superseded by `JOOP_INSTANCE` + `provideJoopAngular()` + `joopSignal()`. They remain functional but will be removed in a future major. (`toJoop()` is **not** deprecated — it has no signal equivalent for bringing existing RxJS streams into JoopJS.)
31
+
32
+ ## [2.0.6] — 2026-06-22 — Patch Release
33
+
34
+ **0 new services · 0 new tests · 2168 tests total**
35
+
36
+ ### Fixed
37
+ - README version badge updated from `v2.0.5` → `v2.0.6`
38
+
39
+ ### Notes
40
+ - Patch bump to correctly reflect the published npm version after the 2.0.5 AI Rules Setup release.
41
+ - All 21 smoke tests pass against the npm-published package (wallet, loans, AML, sanctions, mutual funds, GCM encryption, setup-ai files).
42
+
11
43
  ## Version History
12
44
 
13
45
  | Version | Codename | New Services | Tests | Total Tests | Sub-paths Added |
14
46
  |---|---|---|---|---|---|
47
+ | [2.1.0](#210--angular-di--federation-safe-core) | Angular DI & Federation-Safe Core | — | +21 | **2189** | — |
48
+ | [2.0.6](#206--patch-release) | Patch Release | — | — | **2168** | — |
49
+ | [2.0.5](#205--ai-rules-setup) | AI Rules Setup | — | — | **2168** | — |
15
50
  | [2.0.0](#200--vue-composables) | Vue Composables | — | +39 | **1080** | `vue` |
16
51
  | [1.9.0](#190--banking-depth) | Banking Depth | 4 | +100 | **1041** | — |
17
52
  | [1.8.0](#180--framework-bindings) | Framework Bindings | — | +25 | 941 | `react`, `angular` |
@@ -67,6 +102,52 @@ Versioning follows [Semantic Versioning](https://semver.org/).
67
102
 
68
103
  ---
69
104
 
105
+ ## [2.0.5] — AI Rules Setup
106
+
107
+ **0 new services · 0 new tests · 2168 tests total · DX release**
108
+
109
+ ### Added
110
+
111
+ - **`npx joopjs setup-ai`** — one-command AI assistant setup for consumers. Copies joopjs-aware rules into the user's project so that Claude Code, Cursor, Windsurf, GitHub Copilot, Gemini CLI, and Codex all understand the joopjs API out of the box.
112
+
113
+ - **`scripts/setup-ai.mjs`** — the setup script, published as the `joopjs` bin entry. Copies consumer-facing rules from `node_modules/joopjs/` to the correct locations in the user's project. Skips existing files by default; `--force` flag overwrites. Prints a post-install summary with the exact CLAUDE.md skill lines to add.
114
+
115
+ - **`ai-rules/`** — new directory included in the npm package. Contains consumer-only versions of `GEMINI.md` and `AGENTS.md` (usage guide only, no library-dev content).
116
+
117
+ - **Consumer AI rules** included in the npm package for the first time:
118
+ - `.claude/skills/` — 7 consumer skills: `setup`, `banking`, `finance`, `security`, `auth`, `encryption`, `observables`
119
+ - `.cursor/rules/joopjs.mdc` — Cursor rule (auto-applied to all `.ts` / `.tsx` / `.js` files)
120
+ - `.windsurf/rules/joopjs.md` — Windsurf Cascade rule
121
+ - `.github/copilot-instructions.md` — GitHub Copilot instructions
122
+ - `ai-rules/GEMINI.md` — Gemini CLI consumer guide
123
+ - `ai-rules/AGENTS.md` — Codex / OpenAI Agents consumer guide
124
+
125
+ - **Library-dev skills** (not published to npm) — 4 new Claude Code skills for library contributors:
126
+ - `/dev-build` — dev environment, build commands, tsup config, dist structure
127
+ - `/dev-testing` — Vitest commands, test conventions, writing tests for new services
128
+ - `/dev-contributing` — full checklist for adding a service or sub-path, code conventions
129
+ - `/dev-release` — local and CI release flow, preflight checks, CHANGELOG format
130
+
131
+ - **Cursor dev rules** (`.cursor/rules/dev-contributing.mdc`) and **Windsurf dev rules** (`.windsurf/rules/dev-contributing.md`) — development-focused rule files for library contributors using Cursor or Windsurf.
132
+
133
+ - **`GEMINI.md`** and **`AGENTS.md`** at project root — library-dev guides for Gemini CLI and Codex contributors.
134
+
135
+ ### Changed
136
+
137
+ - `package.json` `"files"` — extended to include `ai-rules/`, `scripts/setup-ai.mjs`, the 7 consumer Claude skills, `.cursor/rules/joopjs.mdc`, `.windsurf/rules/joopjs.md`, and `.github/copilot-instructions.md`.
138
+ - `package.json` `"bin"` — added `"joopjs": "scripts/setup-ai.mjs"` enabling `npx joopjs setup-ai`.
139
+ - `README.md` — added **AI Assistant Setup** section immediately after Install; npm badge updated to v2.0.5.
140
+
141
+ ### User workflow
142
+
143
+ ```bash
144
+ npm install joopjs
145
+ npx joopjs setup-ai # first time
146
+ npx joopjs setup-ai --force # after upgrading joopjs
147
+ ```
148
+
149
+ ---
150
+
70
151
  ## [2.0.0] — Vue Composables
71
152
 
72
153
  **0 new core services · 39 new tests · 1080 tests total · 90 test files · 1 new sub-path**