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
@@ -1,6 +1,9 @@
1
1
  'use strict';
2
2
 
3
3
  // src/events/index.ts
4
+ var _onListenerError = (error) => {
5
+ console.error("[joopjs] a subject subscriber threw during emission:", error);
6
+ };
4
7
  var JoopSubject = class {
5
8
  _listeners = [];
6
9
  subscribe(listener) {
@@ -10,8 +13,13 @@ var JoopSubject = class {
10
13
  };
11
14
  }
12
15
  next(value) {
13
- for (const listener of this._listeners) {
14
- listener(value);
16
+ const listeners = this._listeners.slice();
17
+ for (const listener of listeners) {
18
+ try {
19
+ listener(value);
20
+ } catch (error) {
21
+ _onListenerError(error);
22
+ }
15
23
  }
16
24
  }
17
25
  asObservable() {
@@ -32,7 +40,11 @@ var JoopBehaviorSubject = class extends JoopSubject {
32
40
  super.next(value);
33
41
  }
34
42
  subscribe(listener) {
35
- listener(this._value);
43
+ try {
44
+ listener(this._value);
45
+ } catch (error) {
46
+ _onListenerError(error);
47
+ }
36
48
  return super.subscribe(listener);
37
49
  }
38
50
  asObservable() {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/events/index.ts","../../src/workflow/state-machine.ts","../../src/workflow/workflow-engine.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export type Unsubscribe = () => void;\nexport type Listener<T> = (value: T) => void;\n\n/**\n * Lightweight pub/sub subject — emits to all current subscribers.\n * Replaces RxJS Subject without pulling in the full RxJS dependency.\n */\nexport class JoopSubject<T> {\n private _listeners: Listener<T>[] = [];\n\n subscribe(listener: Listener<T>): Unsubscribe {\n this._listeners.push(listener);\n return () => {\n this._listeners = this._listeners.filter(l => l !== listener);\n };\n }\n\n next(value: T): void {\n for (const listener of this._listeners) {\n listener(value);\n }\n }\n\n asObservable(): JoopObservable<T> {\n return new JoopObservable<T>(listener => this.subscribe(listener));\n }\n}\n\n/**\n * Stateful subject — replays the current value to any new subscriber immediately.\n * Replaces RxJS BehaviorSubject.\n */\nexport class JoopBehaviorSubject<T> extends JoopSubject<T> {\n private _value: T;\n\n constructor(initialValue: T) {\n super();\n this._value = initialValue;\n }\n\n getValue(): T {\n return this._value;\n }\n\n override next(value: T): void {\n this._value = value;\n super.next(value);\n }\n\n override subscribe(listener: Listener<T>): Unsubscribe {\n listener(this._value);\n return super.subscribe(listener);\n }\n\n override asObservable(): JoopObservable<T> {\n return new JoopObservable<T>(listener => this.subscribe(listener));\n }\n}\n\n/**\n * Read-only observable handle returned from asObservable().\n */\nexport class JoopObservable<T> {\n constructor(private _subscribeFn: (listener: Listener<T>) => Unsubscribe) {}\n\n subscribe(listener: Listener<T>): Unsubscribe {\n return this._subscribeFn(listener);\n }\n\n /** Returns the current value without subscribing (only meaningful for BehaviorSubject-backed observables). */\n getOnce(): T | undefined {\n let result: T | undefined;\n const unsub = this.subscribe(v => { result = v; });\n unsub();\n return result;\n }\n}\n","import { JoopBehaviorSubject, JoopSubject } from '../events';\n\nexport interface JoopTransition<S extends string, E extends string> {\n target: S;\n guard?: (context?: unknown) => boolean;\n action?: (context?: unknown) => void;\n}\n\nexport interface JoopStateConfig<S extends string, E extends string> {\n on?: Partial<Record<E, JoopTransition<S, E> | S>>;\n onEnter?: (context?: unknown) => void;\n onExit?: (context?: unknown) => void;\n type?: 'final' | 'normal';\n}\n\nexport interface JoopMachineConfig<S extends string, E extends string> {\n id?: string;\n initial: S;\n context?: unknown;\n states: Record<S, JoopStateConfig<S, E>>;\n}\n\nexport interface JoopStateTransition<S extends string, E extends string> {\n from: S;\n event: E;\n to: S;\n timestamp: number;\n}\n\nexport class JoopStateMachine<S extends string, E extends string> {\n private _state$: JoopBehaviorSubject<S>;\n private _transition$ = new JoopSubject<JoopStateTransition<S, E>>();\n private _cfg: JoopMachineConfig<S, E>;\n private _history: JoopStateTransition<S, E>[] = [];\n private _context: unknown;\n\n constructor(config: JoopMachineConfig<S, E>) {\n this._cfg = config;\n this._context = config.context;\n this._state$ = new JoopBehaviorSubject<S>(config.initial);\n this._cfg.states[config.initial]?.onEnter?.(this._context);\n }\n\n getState(): S { return this._state$.getValue(); }\n getContext(): unknown { return this._context; }\n state$() { return this._state$.asObservable(); }\n transition$() { return this._transition$.asObservable(); }\n history(): JoopStateTransition<S, E>[] { return [...this._history]; }\n\n matches(state: S): boolean { return this._state$.getValue() === state; }\n isFinal(): boolean { return this._cfg.states[this.getState()]?.type === 'final'; }\n\n /** Returns true if the event can be sent from current state */\n can(event: E): boolean {\n const cfg = this._cfg.states[this.getState()]?.on;\n if (!cfg || !(event in cfg)) return false;\n const t = this._resolveTransition(this.getState(), event);\n return t !== null;\n }\n\n /** Send an event; returns true if a transition occurred */\n send(event: E, context?: unknown): boolean {\n const from = this.getState();\n const stateCfg = this._cfg.states[from];\n if (!stateCfg?.on || !(event in stateCfg.on)) return false;\n\n const t = this._resolveTransition(from, event, context);\n if (!t) return false;\n\n const to = t.target;\n stateCfg.onExit?.(this._context);\n t.action?.(this._context);\n if (context !== undefined) this._context = context;\n\n const record: JoopStateTransition<S, E> = { from, event, to, timestamp: Date.now() };\n this._history.push(record);\n this._state$.next(to);\n this._transition$.next(record);\n\n this._cfg.states[to]?.onEnter?.(this._context);\n return true;\n }\n\n /** Update context without triggering a transition */\n setContext(ctx: unknown): void { this._context = ctx; }\n\n reset(): void {\n const initial = this._cfg.initial;\n this._state$.next(initial);\n this._history = [];\n this._cfg.states[initial]?.onEnter?.(this._context);\n }\n\n /** Export as Mermaid state diagram */\n toMermaid(): string {\n const lines = ['stateDiagram-v2'];\n lines.push(` [*] --> ${this._cfg.initial}`);\n for (const [state, cfg] of Object.entries(this._cfg.states) as Array<[S, JoopStateConfig<S,E>]>) {\n if (cfg.type === 'final') lines.push(` ${state} --> [*]`);\n if (cfg.on) {\n for (const [event, trans] of Object.entries(cfg.on)) {\n const target = typeof trans === 'string' ? trans : (trans as JoopTransition<S,E>).target;\n lines.push(` ${state} --> ${target} : ${event}`);\n }\n }\n }\n return lines.join('\\n');\n }\n\n private _resolveTransition(from: S, event: E, context?: unknown): JoopTransition<S, E> | null {\n const rawTrans = this._cfg.states[from]?.on?.[event];\n if (!rawTrans) return null;\n const t: JoopTransition<S, E> = typeof rawTrans === 'string' ? { target: rawTrans as S } : rawTrans;\n if (t.guard && !t.guard(context ?? this._context)) return null;\n return t;\n }\n}\n","import { JoopBehaviorSubject, JoopSubject } from '../events';\n\nexport interface JoopWorkflowStep {\n id: string;\n name?: string;\n after?: string[]; // step IDs this depends on\n execute: (context: unknown) => Promise<unknown>;\n compensate?: (context: unknown) => Promise<void>; // saga rollback\n timeout?: number;\n retries?: number;\n}\n\nexport interface JoopWorkflowDefinition {\n id: string;\n steps: JoopWorkflowStep[];\n}\n\nexport type JoopWorkflowRunStatus = 'pending' | 'running' | 'completed' | 'failed' | 'cancelled' | 'compensating';\n\nexport interface JoopWorkflowRun {\n runId: string;\n workflowId: string;\n status: JoopWorkflowRunStatus;\n input: unknown;\n outputs: Record<string, unknown>;\n errors: Record<string, string>;\n startedAt: number;\n completedAt?: number;\n}\n\nexport interface JoopWorkflowResult {\n runId: string;\n status: 'completed' | 'failed';\n outputs: Record<string, unknown>;\n errors: Record<string, string>;\n durationMs: number;\n}\n\nexport class JoopWorkflowEngine {\n private _definitions = new Map<string, JoopWorkflowDefinition>();\n private _runs = new Map<string, JoopWorkflowRun>();\n private _runStatus$ = new JoopSubject<JoopWorkflowRun>();\n private _cancellations = new Set<string>();\n\n define(workflow: JoopWorkflowDefinition): void { this._definitions.set(workflow.id, workflow); }\n undefine(id: string): void { this._definitions.delete(id); }\n\n async run(workflowId: string, input: unknown = null): Promise<JoopWorkflowResult> {\n const def = this._definitions.get(workflowId);\n if (!def) throw new Error(`JoopWorkflowEngine: unknown workflow '${workflowId}'`);\n\n const runId = `${workflowId}_${Date.now()}_${Math.floor(Math.random() * 1000)}`;\n const run: JoopWorkflowRun = {\n runId, workflowId, status: 'running',\n input, outputs: {}, errors: {}, startedAt: Date.now(),\n };\n this._runs.set(runId, run);\n this._emit(run);\n\n const completed = new Set<string>();\n const context = { input, outputs: run.outputs };\n\n // Build execution order respecting `after` dependencies\n const remaining = [...def.steps];\n const executedSteps: JoopWorkflowStep[] = [];\n\n while (remaining.length > 0) {\n if (this._cancellations.has(runId)) {\n run.status = 'cancelled'; this._emit(run); break;\n }\n\n // Find steps whose dependencies are all satisfied\n const ready = remaining.filter(s => (s.after ?? []).every(dep => completed.has(dep)));\n if (ready.length === 0 && remaining.length > 0) throw new Error(`Workflow deadlock in '${workflowId}': circular/missing dependencies`);\n\n // Run ready steps in parallel\n const results = await Promise.allSettled(ready.map(s => this._runStep(s, context, runId)));\n for (let i = 0; i < ready.length; i++) {\n const step = ready[i];\n const result = results[i];\n remaining.splice(remaining.indexOf(step), 1);\n if (result.status === 'fulfilled') {\n run.outputs[step.id] = result.value;\n (context as Record<string, unknown>).outputs = run.outputs;\n completed.add(step.id);\n executedSteps.push(step);\n } else {\n run.errors[step.id] = String(result.reason);\n run.status = 'failed';\n break;\n }\n }\n if (run.status === 'failed') break;\n }\n\n if (run.status === 'failed') {\n // Saga: compensate in reverse order\n run.status = 'compensating'; this._emit(run);\n for (const step of [...executedSteps].reverse()) {\n if (step.compensate) { try { await step.compensate(context); } catch { /* best effort */ } }\n }\n } else if (run.status === 'running') {\n run.status = 'completed';\n }\n\n run.completedAt = Date.now();\n this._emit(run);\n this._cancellations.delete(runId);\n\n return {\n runId,\n status: run.status === 'completed' ? 'completed' : 'failed',\n outputs: run.outputs,\n errors: run.errors,\n durationMs: run.completedAt - run.startedAt,\n };\n }\n\n cancel(runId: string): void { this._cancellations.add(runId); }\n\n status(runId: string): JoopWorkflowRun | undefined { return this._runs.get(runId); }\n history(): JoopWorkflowRun[] { return Array.from(this._runs.values()); }\n runStatus$() { return this._runStatus$.asObservable(); }\n\n private async _runStep(step: JoopWorkflowStep, context: unknown, runId: string): Promise<unknown> {\n const maxAttempts = (step.retries ?? 0) + 1;\n let lastErr: unknown;\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n if (this._cancellations.has(runId)) throw new Error('Cancelled');\n try {\n const run = step.timeout\n ? await _withTimeout(step.execute(context), step.timeout, step.id)\n : await step.execute(context);\n return run;\n } catch (e) { lastErr = e; }\n }\n throw lastErr;\n }\n\n private _emit(run: JoopWorkflowRun): void { this._runStatus$.next({ ...run }); }\n}\n\nfunction _withTimeout<T>(promise: Promise<T>, ms: number, id: string): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => reject(new Error(`Step '${id}' timed out after ${ms}ms`)), ms);\n promise.then(v => { clearTimeout(timer); resolve(v); }, e => { clearTimeout(timer); reject(e); });\n });\n}\n"]}
1
+ {"version":3,"sources":["../../src/events/index.ts","../../src/workflow/state-machine.ts","../../src/workflow/workflow-engine.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export type Unsubscribe = () => void;\nexport type Listener<T> = (value: T) => void;\n\n/**\n * Reports a subscriber that threw during emission, without aborting delivery\n * to the remaining subscribers. Defaults to console.error; override to route\n * to your own logger (e.g. in a banking app where dropped events matter).\n */\nlet _onListenerError: (error: unknown) => void = (error) => {\n // eslint-disable-next-line no-console\n console.error('[joopjs] a subject subscriber threw during emission:', error);\n};\n\n/** Override how subscriber errors are reported during emission. */\nexport function setSubjectErrorHandler(handler: (error: unknown) => void): void {\n _onListenerError = handler;\n}\n\n/**\n * Lightweight pub/sub subject — emits to all current subscribers.\n * Replaces RxJS Subject without pulling in the full RxJS dependency.\n */\nexport class JoopSubject<T> {\n private _listeners: Listener<T>[] = [];\n\n subscribe(listener: Listener<T>): Unsubscribe {\n this._listeners.push(listener);\n return () => {\n this._listeners = this._listeners.filter(l => l !== listener);\n };\n }\n\n next(value: T): void {\n // Snapshot so a subscribe()/unsubscribe() triggered by a listener can't\n // disturb this emission, and isolate each listener so one that throws\n // doesn't deprive later subscribers of the value.\n const listeners = this._listeners.slice();\n for (const listener of listeners) {\n try {\n listener(value);\n } catch (error) {\n _onListenerError(error);\n }\n }\n }\n\n asObservable(): JoopObservable<T> {\n return new JoopObservable<T>(listener => this.subscribe(listener));\n }\n}\n\n/**\n * Stateful subject — replays the current value to any new subscriber immediately.\n * Replaces RxJS BehaviorSubject.\n */\nexport class JoopBehaviorSubject<T> extends JoopSubject<T> {\n private _value: T;\n\n constructor(initialValue: T) {\n super();\n this._value = initialValue;\n }\n\n getValue(): T {\n return this._value;\n }\n\n override next(value: T): void {\n this._value = value;\n super.next(value);\n }\n\n override subscribe(listener: Listener<T>): Unsubscribe {\n try {\n listener(this._value);\n } catch (error) {\n _onListenerError(error);\n }\n return super.subscribe(listener);\n }\n\n override asObservable(): JoopObservable<T> {\n return new JoopObservable<T>(listener => this.subscribe(listener));\n }\n}\n\n/**\n * Read-only observable handle returned from asObservable().\n */\nexport class JoopObservable<T> {\n constructor(private _subscribeFn: (listener: Listener<T>) => Unsubscribe) {}\n\n subscribe(listener: Listener<T>): Unsubscribe {\n return this._subscribeFn(listener);\n }\n\n /** Returns the current value without subscribing (only meaningful for BehaviorSubject-backed observables). */\n getOnce(): T | undefined {\n let result: T | undefined;\n const unsub = this.subscribe(v => { result = v; });\n unsub();\n return result;\n }\n}\n","import { JoopBehaviorSubject, JoopSubject } from '../events';\n\nexport interface JoopTransition<S extends string, E extends string> {\n target: S;\n guard?: (context?: unknown) => boolean;\n action?: (context?: unknown) => void;\n}\n\nexport interface JoopStateConfig<S extends string, E extends string> {\n on?: Partial<Record<E, JoopTransition<S, E> | S>>;\n onEnter?: (context?: unknown) => void;\n onExit?: (context?: unknown) => void;\n type?: 'final' | 'normal';\n}\n\nexport interface JoopMachineConfig<S extends string, E extends string> {\n id?: string;\n initial: S;\n context?: unknown;\n states: Record<S, JoopStateConfig<S, E>>;\n}\n\nexport interface JoopStateTransition<S extends string, E extends string> {\n from: S;\n event: E;\n to: S;\n timestamp: number;\n}\n\nexport class JoopStateMachine<S extends string, E extends string> {\n private _state$: JoopBehaviorSubject<S>;\n private _transition$ = new JoopSubject<JoopStateTransition<S, E>>();\n private _cfg: JoopMachineConfig<S, E>;\n private _history: JoopStateTransition<S, E>[] = [];\n private _context: unknown;\n\n constructor(config: JoopMachineConfig<S, E>) {\n this._cfg = config;\n this._context = config.context;\n this._state$ = new JoopBehaviorSubject<S>(config.initial);\n this._cfg.states[config.initial]?.onEnter?.(this._context);\n }\n\n getState(): S { return this._state$.getValue(); }\n getContext(): unknown { return this._context; }\n state$() { return this._state$.asObservable(); }\n transition$() { return this._transition$.asObservable(); }\n history(): JoopStateTransition<S, E>[] { return [...this._history]; }\n\n matches(state: S): boolean { return this._state$.getValue() === state; }\n isFinal(): boolean { return this._cfg.states[this.getState()]?.type === 'final'; }\n\n /** Returns true if the event can be sent from current state */\n can(event: E): boolean {\n const cfg = this._cfg.states[this.getState()]?.on;\n if (!cfg || !(event in cfg)) return false;\n const t = this._resolveTransition(this.getState(), event);\n return t !== null;\n }\n\n /** Send an event; returns true if a transition occurred */\n send(event: E, context?: unknown): boolean {\n const from = this.getState();\n const stateCfg = this._cfg.states[from];\n if (!stateCfg?.on || !(event in stateCfg.on)) return false;\n\n const t = this._resolveTransition(from, event, context);\n if (!t) return false;\n\n const to = t.target;\n stateCfg.onExit?.(this._context);\n t.action?.(this._context);\n if (context !== undefined) this._context = context;\n\n const record: JoopStateTransition<S, E> = { from, event, to, timestamp: Date.now() };\n this._history.push(record);\n this._state$.next(to);\n this._transition$.next(record);\n\n this._cfg.states[to]?.onEnter?.(this._context);\n return true;\n }\n\n /** Update context without triggering a transition */\n setContext(ctx: unknown): void { this._context = ctx; }\n\n reset(): void {\n const initial = this._cfg.initial;\n this._state$.next(initial);\n this._history = [];\n this._cfg.states[initial]?.onEnter?.(this._context);\n }\n\n /** Export as Mermaid state diagram */\n toMermaid(): string {\n const lines = ['stateDiagram-v2'];\n lines.push(` [*] --> ${this._cfg.initial}`);\n for (const [state, cfg] of Object.entries(this._cfg.states) as Array<[S, JoopStateConfig<S,E>]>) {\n if (cfg.type === 'final') lines.push(` ${state} --> [*]`);\n if (cfg.on) {\n for (const [event, trans] of Object.entries(cfg.on)) {\n const target = typeof trans === 'string' ? trans : (trans as JoopTransition<S,E>).target;\n lines.push(` ${state} --> ${target} : ${event}`);\n }\n }\n }\n return lines.join('\\n');\n }\n\n private _resolveTransition(from: S, event: E, context?: unknown): JoopTransition<S, E> | null {\n const rawTrans = this._cfg.states[from]?.on?.[event];\n if (!rawTrans) return null;\n const t: JoopTransition<S, E> = typeof rawTrans === 'string' ? { target: rawTrans as S } : rawTrans;\n if (t.guard && !t.guard(context ?? this._context)) return null;\n return t;\n }\n}\n","import { JoopBehaviorSubject, JoopSubject } from '../events';\n\nexport interface JoopWorkflowStep {\n id: string;\n name?: string;\n after?: string[]; // step IDs this depends on\n execute: (context: unknown) => Promise<unknown>;\n compensate?: (context: unknown) => Promise<void>; // saga rollback\n timeout?: number;\n retries?: number;\n}\n\nexport interface JoopWorkflowDefinition {\n id: string;\n steps: JoopWorkflowStep[];\n}\n\nexport type JoopWorkflowRunStatus = 'pending' | 'running' | 'completed' | 'failed' | 'cancelled' | 'compensating';\n\nexport interface JoopWorkflowRun {\n runId: string;\n workflowId: string;\n status: JoopWorkflowRunStatus;\n input: unknown;\n outputs: Record<string, unknown>;\n errors: Record<string, string>;\n startedAt: number;\n completedAt?: number;\n}\n\nexport interface JoopWorkflowResult {\n runId: string;\n status: 'completed' | 'failed';\n outputs: Record<string, unknown>;\n errors: Record<string, string>;\n durationMs: number;\n}\n\nexport class JoopWorkflowEngine {\n private _definitions = new Map<string, JoopWorkflowDefinition>();\n private _runs = new Map<string, JoopWorkflowRun>();\n private _runStatus$ = new JoopSubject<JoopWorkflowRun>();\n private _cancellations = new Set<string>();\n\n define(workflow: JoopWorkflowDefinition): void { this._definitions.set(workflow.id, workflow); }\n undefine(id: string): void { this._definitions.delete(id); }\n\n async run(workflowId: string, input: unknown = null): Promise<JoopWorkflowResult> {\n const def = this._definitions.get(workflowId);\n if (!def) throw new Error(`JoopWorkflowEngine: unknown workflow '${workflowId}'`);\n\n const runId = `${workflowId}_${Date.now()}_${Math.floor(Math.random() * 1000)}`;\n const run: JoopWorkflowRun = {\n runId, workflowId, status: 'running',\n input, outputs: {}, errors: {}, startedAt: Date.now(),\n };\n this._runs.set(runId, run);\n this._emit(run);\n\n const completed = new Set<string>();\n const context = { input, outputs: run.outputs };\n\n // Build execution order respecting `after` dependencies\n const remaining = [...def.steps];\n const executedSteps: JoopWorkflowStep[] = [];\n\n while (remaining.length > 0) {\n if (this._cancellations.has(runId)) {\n run.status = 'cancelled'; this._emit(run); break;\n }\n\n // Find steps whose dependencies are all satisfied\n const ready = remaining.filter(s => (s.after ?? []).every(dep => completed.has(dep)));\n if (ready.length === 0 && remaining.length > 0) throw new Error(`Workflow deadlock in '${workflowId}': circular/missing dependencies`);\n\n // Run ready steps in parallel\n const results = await Promise.allSettled(ready.map(s => this._runStep(s, context, runId)));\n for (let i = 0; i < ready.length; i++) {\n const step = ready[i];\n const result = results[i];\n remaining.splice(remaining.indexOf(step), 1);\n if (result.status === 'fulfilled') {\n run.outputs[step.id] = result.value;\n (context as Record<string, unknown>).outputs = run.outputs;\n completed.add(step.id);\n executedSteps.push(step);\n } else {\n run.errors[step.id] = String(result.reason);\n run.status = 'failed';\n break;\n }\n }\n if (run.status === 'failed') break;\n }\n\n if (run.status === 'failed') {\n // Saga: compensate in reverse order\n run.status = 'compensating'; this._emit(run);\n for (const step of [...executedSteps].reverse()) {\n if (step.compensate) { try { await step.compensate(context); } catch { /* best effort */ } }\n }\n } else if (run.status === 'running') {\n run.status = 'completed';\n }\n\n run.completedAt = Date.now();\n this._emit(run);\n this._cancellations.delete(runId);\n\n return {\n runId,\n status: run.status === 'completed' ? 'completed' : 'failed',\n outputs: run.outputs,\n errors: run.errors,\n durationMs: run.completedAt - run.startedAt,\n };\n }\n\n cancel(runId: string): void { this._cancellations.add(runId); }\n\n status(runId: string): JoopWorkflowRun | undefined { return this._runs.get(runId); }\n history(): JoopWorkflowRun[] { return Array.from(this._runs.values()); }\n runStatus$() { return this._runStatus$.asObservable(); }\n\n private async _runStep(step: JoopWorkflowStep, context: unknown, runId: string): Promise<unknown> {\n const maxAttempts = (step.retries ?? 0) + 1;\n let lastErr: unknown;\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n if (this._cancellations.has(runId)) throw new Error('Cancelled');\n try {\n const run = step.timeout\n ? await _withTimeout(step.execute(context), step.timeout, step.id)\n : await step.execute(context);\n return run;\n } catch (e) { lastErr = e; }\n }\n throw lastErr;\n }\n\n private _emit(run: JoopWorkflowRun): void { this._runStatus$.next({ ...run }); }\n}\n\nfunction _withTimeout<T>(promise: Promise<T>, ms: number, id: string): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => reject(new Error(`Step '${id}' timed out after ${ms}ms`)), ms);\n promise.then(v => { clearTimeout(timer); resolve(v); }, e => { clearTimeout(timer); reject(e); });\n });\n}\n"]}
@@ -1,4 +1,7 @@
1
1
  // src/events/index.ts
2
+ var _onListenerError = (error) => {
3
+ console.error("[joopjs] a subject subscriber threw during emission:", error);
4
+ };
2
5
  var JoopSubject = class {
3
6
  _listeners = [];
4
7
  subscribe(listener) {
@@ -8,8 +11,13 @@ var JoopSubject = class {
8
11
  };
9
12
  }
10
13
  next(value) {
11
- for (const listener of this._listeners) {
12
- listener(value);
14
+ const listeners = this._listeners.slice();
15
+ for (const listener of listeners) {
16
+ try {
17
+ listener(value);
18
+ } catch (error) {
19
+ _onListenerError(error);
20
+ }
13
21
  }
14
22
  }
15
23
  asObservable() {
@@ -30,7 +38,11 @@ var JoopBehaviorSubject = class extends JoopSubject {
30
38
  super.next(value);
31
39
  }
32
40
  subscribe(listener) {
33
- listener(this._value);
41
+ try {
42
+ listener(this._value);
43
+ } catch (error) {
44
+ _onListenerError(error);
45
+ }
34
46
  return super.subscribe(listener);
35
47
  }
36
48
  asObservable() {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/events/index.ts","../../src/workflow/state-machine.ts","../../src/workflow/workflow-engine.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["export type Unsubscribe = () => void;\nexport type Listener<T> = (value: T) => void;\n\n/**\n * Lightweight pub/sub subject — emits to all current subscribers.\n * Replaces RxJS Subject without pulling in the full RxJS dependency.\n */\nexport class JoopSubject<T> {\n private _listeners: Listener<T>[] = [];\n\n subscribe(listener: Listener<T>): Unsubscribe {\n this._listeners.push(listener);\n return () => {\n this._listeners = this._listeners.filter(l => l !== listener);\n };\n }\n\n next(value: T): void {\n for (const listener of this._listeners) {\n listener(value);\n }\n }\n\n asObservable(): JoopObservable<T> {\n return new JoopObservable<T>(listener => this.subscribe(listener));\n }\n}\n\n/**\n * Stateful subject — replays the current value to any new subscriber immediately.\n * Replaces RxJS BehaviorSubject.\n */\nexport class JoopBehaviorSubject<T> extends JoopSubject<T> {\n private _value: T;\n\n constructor(initialValue: T) {\n super();\n this._value = initialValue;\n }\n\n getValue(): T {\n return this._value;\n }\n\n override next(value: T): void {\n this._value = value;\n super.next(value);\n }\n\n override subscribe(listener: Listener<T>): Unsubscribe {\n listener(this._value);\n return super.subscribe(listener);\n }\n\n override asObservable(): JoopObservable<T> {\n return new JoopObservable<T>(listener => this.subscribe(listener));\n }\n}\n\n/**\n * Read-only observable handle returned from asObservable().\n */\nexport class JoopObservable<T> {\n constructor(private _subscribeFn: (listener: Listener<T>) => Unsubscribe) {}\n\n subscribe(listener: Listener<T>): Unsubscribe {\n return this._subscribeFn(listener);\n }\n\n /** Returns the current value without subscribing (only meaningful for BehaviorSubject-backed observables). */\n getOnce(): T | undefined {\n let result: T | undefined;\n const unsub = this.subscribe(v => { result = v; });\n unsub();\n return result;\n }\n}\n","import { JoopBehaviorSubject, JoopSubject } from '../events';\n\nexport interface JoopTransition<S extends string, E extends string> {\n target: S;\n guard?: (context?: unknown) => boolean;\n action?: (context?: unknown) => void;\n}\n\nexport interface JoopStateConfig<S extends string, E extends string> {\n on?: Partial<Record<E, JoopTransition<S, E> | S>>;\n onEnter?: (context?: unknown) => void;\n onExit?: (context?: unknown) => void;\n type?: 'final' | 'normal';\n}\n\nexport interface JoopMachineConfig<S extends string, E extends string> {\n id?: string;\n initial: S;\n context?: unknown;\n states: Record<S, JoopStateConfig<S, E>>;\n}\n\nexport interface JoopStateTransition<S extends string, E extends string> {\n from: S;\n event: E;\n to: S;\n timestamp: number;\n}\n\nexport class JoopStateMachine<S extends string, E extends string> {\n private _state$: JoopBehaviorSubject<S>;\n private _transition$ = new JoopSubject<JoopStateTransition<S, E>>();\n private _cfg: JoopMachineConfig<S, E>;\n private _history: JoopStateTransition<S, E>[] = [];\n private _context: unknown;\n\n constructor(config: JoopMachineConfig<S, E>) {\n this._cfg = config;\n this._context = config.context;\n this._state$ = new JoopBehaviorSubject<S>(config.initial);\n this._cfg.states[config.initial]?.onEnter?.(this._context);\n }\n\n getState(): S { return this._state$.getValue(); }\n getContext(): unknown { return this._context; }\n state$() { return this._state$.asObservable(); }\n transition$() { return this._transition$.asObservable(); }\n history(): JoopStateTransition<S, E>[] { return [...this._history]; }\n\n matches(state: S): boolean { return this._state$.getValue() === state; }\n isFinal(): boolean { return this._cfg.states[this.getState()]?.type === 'final'; }\n\n /** Returns true if the event can be sent from current state */\n can(event: E): boolean {\n const cfg = this._cfg.states[this.getState()]?.on;\n if (!cfg || !(event in cfg)) return false;\n const t = this._resolveTransition(this.getState(), event);\n return t !== null;\n }\n\n /** Send an event; returns true if a transition occurred */\n send(event: E, context?: unknown): boolean {\n const from = this.getState();\n const stateCfg = this._cfg.states[from];\n if (!stateCfg?.on || !(event in stateCfg.on)) return false;\n\n const t = this._resolveTransition(from, event, context);\n if (!t) return false;\n\n const to = t.target;\n stateCfg.onExit?.(this._context);\n t.action?.(this._context);\n if (context !== undefined) this._context = context;\n\n const record: JoopStateTransition<S, E> = { from, event, to, timestamp: Date.now() };\n this._history.push(record);\n this._state$.next(to);\n this._transition$.next(record);\n\n this._cfg.states[to]?.onEnter?.(this._context);\n return true;\n }\n\n /** Update context without triggering a transition */\n setContext(ctx: unknown): void { this._context = ctx; }\n\n reset(): void {\n const initial = this._cfg.initial;\n this._state$.next(initial);\n this._history = [];\n this._cfg.states[initial]?.onEnter?.(this._context);\n }\n\n /** Export as Mermaid state diagram */\n toMermaid(): string {\n const lines = ['stateDiagram-v2'];\n lines.push(` [*] --> ${this._cfg.initial}`);\n for (const [state, cfg] of Object.entries(this._cfg.states) as Array<[S, JoopStateConfig<S,E>]>) {\n if (cfg.type === 'final') lines.push(` ${state} --> [*]`);\n if (cfg.on) {\n for (const [event, trans] of Object.entries(cfg.on)) {\n const target = typeof trans === 'string' ? trans : (trans as JoopTransition<S,E>).target;\n lines.push(` ${state} --> ${target} : ${event}`);\n }\n }\n }\n return lines.join('\\n');\n }\n\n private _resolveTransition(from: S, event: E, context?: unknown): JoopTransition<S, E> | null {\n const rawTrans = this._cfg.states[from]?.on?.[event];\n if (!rawTrans) return null;\n const t: JoopTransition<S, E> = typeof rawTrans === 'string' ? { target: rawTrans as S } : rawTrans;\n if (t.guard && !t.guard(context ?? this._context)) return null;\n return t;\n }\n}\n","import { JoopBehaviorSubject, JoopSubject } from '../events';\n\nexport interface JoopWorkflowStep {\n id: string;\n name?: string;\n after?: string[]; // step IDs this depends on\n execute: (context: unknown) => Promise<unknown>;\n compensate?: (context: unknown) => Promise<void>; // saga rollback\n timeout?: number;\n retries?: number;\n}\n\nexport interface JoopWorkflowDefinition {\n id: string;\n steps: JoopWorkflowStep[];\n}\n\nexport type JoopWorkflowRunStatus = 'pending' | 'running' | 'completed' | 'failed' | 'cancelled' | 'compensating';\n\nexport interface JoopWorkflowRun {\n runId: string;\n workflowId: string;\n status: JoopWorkflowRunStatus;\n input: unknown;\n outputs: Record<string, unknown>;\n errors: Record<string, string>;\n startedAt: number;\n completedAt?: number;\n}\n\nexport interface JoopWorkflowResult {\n runId: string;\n status: 'completed' | 'failed';\n outputs: Record<string, unknown>;\n errors: Record<string, string>;\n durationMs: number;\n}\n\nexport class JoopWorkflowEngine {\n private _definitions = new Map<string, JoopWorkflowDefinition>();\n private _runs = new Map<string, JoopWorkflowRun>();\n private _runStatus$ = new JoopSubject<JoopWorkflowRun>();\n private _cancellations = new Set<string>();\n\n define(workflow: JoopWorkflowDefinition): void { this._definitions.set(workflow.id, workflow); }\n undefine(id: string): void { this._definitions.delete(id); }\n\n async run(workflowId: string, input: unknown = null): Promise<JoopWorkflowResult> {\n const def = this._definitions.get(workflowId);\n if (!def) throw new Error(`JoopWorkflowEngine: unknown workflow '${workflowId}'`);\n\n const runId = `${workflowId}_${Date.now()}_${Math.floor(Math.random() * 1000)}`;\n const run: JoopWorkflowRun = {\n runId, workflowId, status: 'running',\n input, outputs: {}, errors: {}, startedAt: Date.now(),\n };\n this._runs.set(runId, run);\n this._emit(run);\n\n const completed = new Set<string>();\n const context = { input, outputs: run.outputs };\n\n // Build execution order respecting `after` dependencies\n const remaining = [...def.steps];\n const executedSteps: JoopWorkflowStep[] = [];\n\n while (remaining.length > 0) {\n if (this._cancellations.has(runId)) {\n run.status = 'cancelled'; this._emit(run); break;\n }\n\n // Find steps whose dependencies are all satisfied\n const ready = remaining.filter(s => (s.after ?? []).every(dep => completed.has(dep)));\n if (ready.length === 0 && remaining.length > 0) throw new Error(`Workflow deadlock in '${workflowId}': circular/missing dependencies`);\n\n // Run ready steps in parallel\n const results = await Promise.allSettled(ready.map(s => this._runStep(s, context, runId)));\n for (let i = 0; i < ready.length; i++) {\n const step = ready[i];\n const result = results[i];\n remaining.splice(remaining.indexOf(step), 1);\n if (result.status === 'fulfilled') {\n run.outputs[step.id] = result.value;\n (context as Record<string, unknown>).outputs = run.outputs;\n completed.add(step.id);\n executedSteps.push(step);\n } else {\n run.errors[step.id] = String(result.reason);\n run.status = 'failed';\n break;\n }\n }\n if (run.status === 'failed') break;\n }\n\n if (run.status === 'failed') {\n // Saga: compensate in reverse order\n run.status = 'compensating'; this._emit(run);\n for (const step of [...executedSteps].reverse()) {\n if (step.compensate) { try { await step.compensate(context); } catch { /* best effort */ } }\n }\n } else if (run.status === 'running') {\n run.status = 'completed';\n }\n\n run.completedAt = Date.now();\n this._emit(run);\n this._cancellations.delete(runId);\n\n return {\n runId,\n status: run.status === 'completed' ? 'completed' : 'failed',\n outputs: run.outputs,\n errors: run.errors,\n durationMs: run.completedAt - run.startedAt,\n };\n }\n\n cancel(runId: string): void { this._cancellations.add(runId); }\n\n status(runId: string): JoopWorkflowRun | undefined { return this._runs.get(runId); }\n history(): JoopWorkflowRun[] { return Array.from(this._runs.values()); }\n runStatus$() { return this._runStatus$.asObservable(); }\n\n private async _runStep(step: JoopWorkflowStep, context: unknown, runId: string): Promise<unknown> {\n const maxAttempts = (step.retries ?? 0) + 1;\n let lastErr: unknown;\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n if (this._cancellations.has(runId)) throw new Error('Cancelled');\n try {\n const run = step.timeout\n ? await _withTimeout(step.execute(context), step.timeout, step.id)\n : await step.execute(context);\n return run;\n } catch (e) { lastErr = e; }\n }\n throw lastErr;\n }\n\n private _emit(run: JoopWorkflowRun): void { this._runStatus$.next({ ...run }); }\n}\n\nfunction _withTimeout<T>(promise: Promise<T>, ms: number, id: string): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => reject(new Error(`Step '${id}' timed out after ${ms}ms`)), ms);\n promise.then(v => { clearTimeout(timer); resolve(v); }, e => { clearTimeout(timer); reject(e); });\n });\n}\n"]}
1
+ {"version":3,"sources":["../../src/events/index.ts","../../src/workflow/state-machine.ts","../../src/workflow/workflow-engine.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["export type Unsubscribe = () => void;\nexport type Listener<T> = (value: T) => void;\n\n/**\n * Reports a subscriber that threw during emission, without aborting delivery\n * to the remaining subscribers. Defaults to console.error; override to route\n * to your own logger (e.g. in a banking app where dropped events matter).\n */\nlet _onListenerError: (error: unknown) => void = (error) => {\n // eslint-disable-next-line no-console\n console.error('[joopjs] a subject subscriber threw during emission:', error);\n};\n\n/** Override how subscriber errors are reported during emission. */\nexport function setSubjectErrorHandler(handler: (error: unknown) => void): void {\n _onListenerError = handler;\n}\n\n/**\n * Lightweight pub/sub subject — emits to all current subscribers.\n * Replaces RxJS Subject without pulling in the full RxJS dependency.\n */\nexport class JoopSubject<T> {\n private _listeners: Listener<T>[] = [];\n\n subscribe(listener: Listener<T>): Unsubscribe {\n this._listeners.push(listener);\n return () => {\n this._listeners = this._listeners.filter(l => l !== listener);\n };\n }\n\n next(value: T): void {\n // Snapshot so a subscribe()/unsubscribe() triggered by a listener can't\n // disturb this emission, and isolate each listener so one that throws\n // doesn't deprive later subscribers of the value.\n const listeners = this._listeners.slice();\n for (const listener of listeners) {\n try {\n listener(value);\n } catch (error) {\n _onListenerError(error);\n }\n }\n }\n\n asObservable(): JoopObservable<T> {\n return new JoopObservable<T>(listener => this.subscribe(listener));\n }\n}\n\n/**\n * Stateful subject — replays the current value to any new subscriber immediately.\n * Replaces RxJS BehaviorSubject.\n */\nexport class JoopBehaviorSubject<T> extends JoopSubject<T> {\n private _value: T;\n\n constructor(initialValue: T) {\n super();\n this._value = initialValue;\n }\n\n getValue(): T {\n return this._value;\n }\n\n override next(value: T): void {\n this._value = value;\n super.next(value);\n }\n\n override subscribe(listener: Listener<T>): Unsubscribe {\n try {\n listener(this._value);\n } catch (error) {\n _onListenerError(error);\n }\n return super.subscribe(listener);\n }\n\n override asObservable(): JoopObservable<T> {\n return new JoopObservable<T>(listener => this.subscribe(listener));\n }\n}\n\n/**\n * Read-only observable handle returned from asObservable().\n */\nexport class JoopObservable<T> {\n constructor(private _subscribeFn: (listener: Listener<T>) => Unsubscribe) {}\n\n subscribe(listener: Listener<T>): Unsubscribe {\n return this._subscribeFn(listener);\n }\n\n /** Returns the current value without subscribing (only meaningful for BehaviorSubject-backed observables). */\n getOnce(): T | undefined {\n let result: T | undefined;\n const unsub = this.subscribe(v => { result = v; });\n unsub();\n return result;\n }\n}\n","import { JoopBehaviorSubject, JoopSubject } from '../events';\n\nexport interface JoopTransition<S extends string, E extends string> {\n target: S;\n guard?: (context?: unknown) => boolean;\n action?: (context?: unknown) => void;\n}\n\nexport interface JoopStateConfig<S extends string, E extends string> {\n on?: Partial<Record<E, JoopTransition<S, E> | S>>;\n onEnter?: (context?: unknown) => void;\n onExit?: (context?: unknown) => void;\n type?: 'final' | 'normal';\n}\n\nexport interface JoopMachineConfig<S extends string, E extends string> {\n id?: string;\n initial: S;\n context?: unknown;\n states: Record<S, JoopStateConfig<S, E>>;\n}\n\nexport interface JoopStateTransition<S extends string, E extends string> {\n from: S;\n event: E;\n to: S;\n timestamp: number;\n}\n\nexport class JoopStateMachine<S extends string, E extends string> {\n private _state$: JoopBehaviorSubject<S>;\n private _transition$ = new JoopSubject<JoopStateTransition<S, E>>();\n private _cfg: JoopMachineConfig<S, E>;\n private _history: JoopStateTransition<S, E>[] = [];\n private _context: unknown;\n\n constructor(config: JoopMachineConfig<S, E>) {\n this._cfg = config;\n this._context = config.context;\n this._state$ = new JoopBehaviorSubject<S>(config.initial);\n this._cfg.states[config.initial]?.onEnter?.(this._context);\n }\n\n getState(): S { return this._state$.getValue(); }\n getContext(): unknown { return this._context; }\n state$() { return this._state$.asObservable(); }\n transition$() { return this._transition$.asObservable(); }\n history(): JoopStateTransition<S, E>[] { return [...this._history]; }\n\n matches(state: S): boolean { return this._state$.getValue() === state; }\n isFinal(): boolean { return this._cfg.states[this.getState()]?.type === 'final'; }\n\n /** Returns true if the event can be sent from current state */\n can(event: E): boolean {\n const cfg = this._cfg.states[this.getState()]?.on;\n if (!cfg || !(event in cfg)) return false;\n const t = this._resolveTransition(this.getState(), event);\n return t !== null;\n }\n\n /** Send an event; returns true if a transition occurred */\n send(event: E, context?: unknown): boolean {\n const from = this.getState();\n const stateCfg = this._cfg.states[from];\n if (!stateCfg?.on || !(event in stateCfg.on)) return false;\n\n const t = this._resolveTransition(from, event, context);\n if (!t) return false;\n\n const to = t.target;\n stateCfg.onExit?.(this._context);\n t.action?.(this._context);\n if (context !== undefined) this._context = context;\n\n const record: JoopStateTransition<S, E> = { from, event, to, timestamp: Date.now() };\n this._history.push(record);\n this._state$.next(to);\n this._transition$.next(record);\n\n this._cfg.states[to]?.onEnter?.(this._context);\n return true;\n }\n\n /** Update context without triggering a transition */\n setContext(ctx: unknown): void { this._context = ctx; }\n\n reset(): void {\n const initial = this._cfg.initial;\n this._state$.next(initial);\n this._history = [];\n this._cfg.states[initial]?.onEnter?.(this._context);\n }\n\n /** Export as Mermaid state diagram */\n toMermaid(): string {\n const lines = ['stateDiagram-v2'];\n lines.push(` [*] --> ${this._cfg.initial}`);\n for (const [state, cfg] of Object.entries(this._cfg.states) as Array<[S, JoopStateConfig<S,E>]>) {\n if (cfg.type === 'final') lines.push(` ${state} --> [*]`);\n if (cfg.on) {\n for (const [event, trans] of Object.entries(cfg.on)) {\n const target = typeof trans === 'string' ? trans : (trans as JoopTransition<S,E>).target;\n lines.push(` ${state} --> ${target} : ${event}`);\n }\n }\n }\n return lines.join('\\n');\n }\n\n private _resolveTransition(from: S, event: E, context?: unknown): JoopTransition<S, E> | null {\n const rawTrans = this._cfg.states[from]?.on?.[event];\n if (!rawTrans) return null;\n const t: JoopTransition<S, E> = typeof rawTrans === 'string' ? { target: rawTrans as S } : rawTrans;\n if (t.guard && !t.guard(context ?? this._context)) return null;\n return t;\n }\n}\n","import { JoopBehaviorSubject, JoopSubject } from '../events';\n\nexport interface JoopWorkflowStep {\n id: string;\n name?: string;\n after?: string[]; // step IDs this depends on\n execute: (context: unknown) => Promise<unknown>;\n compensate?: (context: unknown) => Promise<void>; // saga rollback\n timeout?: number;\n retries?: number;\n}\n\nexport interface JoopWorkflowDefinition {\n id: string;\n steps: JoopWorkflowStep[];\n}\n\nexport type JoopWorkflowRunStatus = 'pending' | 'running' | 'completed' | 'failed' | 'cancelled' | 'compensating';\n\nexport interface JoopWorkflowRun {\n runId: string;\n workflowId: string;\n status: JoopWorkflowRunStatus;\n input: unknown;\n outputs: Record<string, unknown>;\n errors: Record<string, string>;\n startedAt: number;\n completedAt?: number;\n}\n\nexport interface JoopWorkflowResult {\n runId: string;\n status: 'completed' | 'failed';\n outputs: Record<string, unknown>;\n errors: Record<string, string>;\n durationMs: number;\n}\n\nexport class JoopWorkflowEngine {\n private _definitions = new Map<string, JoopWorkflowDefinition>();\n private _runs = new Map<string, JoopWorkflowRun>();\n private _runStatus$ = new JoopSubject<JoopWorkflowRun>();\n private _cancellations = new Set<string>();\n\n define(workflow: JoopWorkflowDefinition): void { this._definitions.set(workflow.id, workflow); }\n undefine(id: string): void { this._definitions.delete(id); }\n\n async run(workflowId: string, input: unknown = null): Promise<JoopWorkflowResult> {\n const def = this._definitions.get(workflowId);\n if (!def) throw new Error(`JoopWorkflowEngine: unknown workflow '${workflowId}'`);\n\n const runId = `${workflowId}_${Date.now()}_${Math.floor(Math.random() * 1000)}`;\n const run: JoopWorkflowRun = {\n runId, workflowId, status: 'running',\n input, outputs: {}, errors: {}, startedAt: Date.now(),\n };\n this._runs.set(runId, run);\n this._emit(run);\n\n const completed = new Set<string>();\n const context = { input, outputs: run.outputs };\n\n // Build execution order respecting `after` dependencies\n const remaining = [...def.steps];\n const executedSteps: JoopWorkflowStep[] = [];\n\n while (remaining.length > 0) {\n if (this._cancellations.has(runId)) {\n run.status = 'cancelled'; this._emit(run); break;\n }\n\n // Find steps whose dependencies are all satisfied\n const ready = remaining.filter(s => (s.after ?? []).every(dep => completed.has(dep)));\n if (ready.length === 0 && remaining.length > 0) throw new Error(`Workflow deadlock in '${workflowId}': circular/missing dependencies`);\n\n // Run ready steps in parallel\n const results = await Promise.allSettled(ready.map(s => this._runStep(s, context, runId)));\n for (let i = 0; i < ready.length; i++) {\n const step = ready[i];\n const result = results[i];\n remaining.splice(remaining.indexOf(step), 1);\n if (result.status === 'fulfilled') {\n run.outputs[step.id] = result.value;\n (context as Record<string, unknown>).outputs = run.outputs;\n completed.add(step.id);\n executedSteps.push(step);\n } else {\n run.errors[step.id] = String(result.reason);\n run.status = 'failed';\n break;\n }\n }\n if (run.status === 'failed') break;\n }\n\n if (run.status === 'failed') {\n // Saga: compensate in reverse order\n run.status = 'compensating'; this._emit(run);\n for (const step of [...executedSteps].reverse()) {\n if (step.compensate) { try { await step.compensate(context); } catch { /* best effort */ } }\n }\n } else if (run.status === 'running') {\n run.status = 'completed';\n }\n\n run.completedAt = Date.now();\n this._emit(run);\n this._cancellations.delete(runId);\n\n return {\n runId,\n status: run.status === 'completed' ? 'completed' : 'failed',\n outputs: run.outputs,\n errors: run.errors,\n durationMs: run.completedAt - run.startedAt,\n };\n }\n\n cancel(runId: string): void { this._cancellations.add(runId); }\n\n status(runId: string): JoopWorkflowRun | undefined { return this._runs.get(runId); }\n history(): JoopWorkflowRun[] { return Array.from(this._runs.values()); }\n runStatus$() { return this._runStatus$.asObservable(); }\n\n private async _runStep(step: JoopWorkflowStep, context: unknown, runId: string): Promise<unknown> {\n const maxAttempts = (step.retries ?? 0) + 1;\n let lastErr: unknown;\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n if (this._cancellations.has(runId)) throw new Error('Cancelled');\n try {\n const run = step.timeout\n ? await _withTimeout(step.execute(context), step.timeout, step.id)\n : await step.execute(context);\n return run;\n } catch (e) { lastErr = e; }\n }\n throw lastErr;\n }\n\n private _emit(run: JoopWorkflowRun): void { this._runStatus$.next({ ...run }); }\n}\n\nfunction _withTimeout<T>(promise: Promise<T>, ms: number, id: string): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => reject(new Error(`Step '${id}' timed out after ${ms}ms`)), ms);\n promise.then(v => { clearTimeout(timer); resolve(v); }, e => { clearTimeout(timer); reject(e); });\n });\n}\n"]}
package/package.json CHANGED
@@ -1,10 +1,19 @@
1
1
  {
2
2
  "name": "joopjs",
3
- "version": "2.0.5",
3
+ "version": "2.1.0",
4
4
  "description": "Framework-agnostic JavaScript SDK for enterprise web applications. Works with React, Angular, Vue, and any JavaScript project.",
5
- "author": {
6
- "name": "Kundan Singh"
7
- },
5
+ "keywords": [
6
+ "sdk",
7
+ "encryption",
8
+ "session",
9
+ "storage",
10
+ "auth",
11
+ "http",
12
+ "logger",
13
+ "aes",
14
+ "x25519",
15
+ "typescript"
16
+ ],
8
17
  "license": "MIT",
9
18
  "homepage": "https://kundan-leo.github.io/JoopJs/demo/",
10
19
  "repository": {
@@ -14,30 +23,9 @@
14
23
  "bugs": {
15
24
  "url": "https://github.com/kundan-leo/JoopJs/issues"
16
25
  },
17
- "keywords": [
18
- "sdk",
19
- "banking",
20
- "fintech",
21
- "finance",
22
- "encryption",
23
- "auth",
24
- "aml",
25
- "sanctions",
26
- "wallet",
27
- "loan",
28
- "typescript",
29
- "react",
30
- "angular",
31
- "vue"
32
- ],
33
26
  "main": "dist/index.js",
34
27
  "module": "dist/index.mjs",
35
28
  "types": "dist/index.d.ts",
36
- "files": [
37
- "dist",
38
- "README.md",
39
- "CHANGELOG.md"
40
- ],
41
29
  "exports": {
42
30
  ".": {
43
31
  "import": "./dist/index.mjs",
@@ -94,6 +82,11 @@
94
82
  "require": "./dist/device/index.js",
95
83
  "types": "./dist/device/index.d.ts"
96
84
  },
85
+ "./dev": {
86
+ "import": "./dist/dev/index.mjs",
87
+ "require": "./dist/dev/index.js",
88
+ "types": "./dist/dev/index.d.ts"
89
+ },
97
90
  "./theme": {
98
91
  "import": "./dist/theme/index.mjs",
99
92
  "require": "./dist/theme/index.js",
@@ -210,26 +203,97 @@
210
203
  "types": "./dist/india/index.d.ts"
211
204
  }
212
205
  },
206
+ "files": [
207
+ "dist",
208
+ "CHANGELOG.md",
209
+ "ai-rules",
210
+ "scripts/setup-ai.mjs",
211
+ ".claude/skills/setup.md",
212
+ ".claude/skills/banking.md",
213
+ ".claude/skills/finance.md",
214
+ ".claude/skills/security.md",
215
+ ".claude/skills/auth.md",
216
+ ".claude/skills/encryption.md",
217
+ ".claude/skills/observables.md",
218
+ ".cursor/rules/joopjs.mdc",
219
+ ".windsurf/rules/joopjs.md",
220
+ ".github/copilot-instructions.md"
221
+ ],
222
+ "bin": {
223
+ "joopjs": "scripts/setup-ai.mjs"
224
+ },
225
+ "scripts": {
226
+ "build": "tsup",
227
+ "build:watch": "tsup --watch",
228
+ "typecheck": "tsc --noEmit",
229
+ "check:boundary": "node scripts/check-core-boundary.mjs",
230
+ "clean": "rimraf dist dist-playground",
231
+ "test": "vitest run",
232
+ "test:ui": "vitest --ui --open",
233
+ "test:watch": "vitest",
234
+ "test:coverage": "vitest run --coverage",
235
+ "playground": "vite playground/ --config playground/vite.config.ts",
236
+ "playground:build": "vite build playground/ --config playground/vite.config.ts",
237
+ "preflight": "node scripts/preflight.mjs",
238
+ "release:dry": "node scripts/release.mjs --dry-run",
239
+ "release:patch": "node scripts/release.mjs patch",
240
+ "release:minor": "node scripts/release.mjs minor",
241
+ "release:major": "node scripts/release.mjs major",
242
+ "release": "node scripts/release.mjs"
243
+ },
213
244
  "dependencies": {
214
245
  "@noble/ciphers": "^2.2.0",
215
246
  "@noble/curves": "^2.2.0",
216
247
  "base64-arraybuffer": "^1.0.2"
217
248
  },
218
249
  "peerDependencies": {
219
- "react": ">=18.0.0",
250
+ "@angular/common": ">=17.0.0",
220
251
  "@angular/core": ">=17.0.0",
252
+ "@angular/router": ">=17.0.0",
253
+ "react": ">=18.0.0",
221
254
  "rxjs": ">=7.0.0",
222
255
  "vue": ">=3.0.0"
223
256
  },
224
257
  "peerDependenciesMeta": {
225
- "react": { "optional": true },
226
- "@angular/core": { "optional": true },
227
- "rxjs": { "optional": true },
228
- "vue": { "optional": true }
258
+ "react": {
259
+ "optional": true
260
+ },
261
+ "@angular/common": {
262
+ "optional": true
263
+ },
264
+ "@angular/core": {
265
+ "optional": true
266
+ },
267
+ "@angular/router": {
268
+ "optional": true
269
+ },
270
+ "rxjs": {
271
+ "optional": true
272
+ },
273
+ "vue": {
274
+ "optional": true
275
+ }
276
+ },
277
+ "devDependencies": {
278
+ "@angular/common": "^17.3.12",
279
+ "@angular/compiler": "^17.3.12",
280
+ "@angular/core": "^17.3.12",
281
+ "@angular/router": "^17.3.12",
282
+ "@vitest/coverage-v8": "^2.1.0",
283
+ "@vitest/ui": "^2.1.0",
284
+ "fake-indexeddb": "^6.2.5",
285
+ "jsdom": "^29.1.1",
286
+ "rimraf": "^5.0.0",
287
+ "rxjs": "^7.8.2",
288
+ "tsup": "^8.3.0",
289
+ "typescript": "^5.3.3",
290
+ "vite": "^5.4.0",
291
+ "vitest": "^2.1.0"
229
292
  },
230
293
  "engines": {
231
294
  "node": ">=18.0.0"
232
295
  },
233
- "sideEffects": false
296
+ "author": {
297
+ "name": "Kundan Singh"
298
+ }
234
299
  }
235
-
@@ -0,0 +1,133 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * joopjs setup-ai
4
+ *
5
+ * Copies AI assistant rules for joopjs into your project so that
6
+ * Claude Code, Cursor, Windsurf, GitHub Copilot, Gemini CLI, and Codex
7
+ * all understand how to use the joopjs SDK correctly.
8
+ *
9
+ * Usage:
10
+ * npx joopjs setup-ai # copy rules (skip existing files)
11
+ * npx joopjs setup-ai --force # overwrite existing files
12
+ * npx joopjs # show help
13
+ */
14
+
15
+ import { copyFileSync, mkdirSync, existsSync } from 'fs';
16
+ import { resolve, dirname, join, basename } from 'path';
17
+ import { fileURLToPath } from 'url';
18
+
19
+ const __dirname = dirname(fileURLToPath(import.meta.url));
20
+ const PACKAGE_DIR = resolve(__dirname, '..');
21
+ const PROJECT_DIR = process.cwd();
22
+ const FORCE = process.argv.includes('--force');
23
+ const CMD = process.argv[2];
24
+
25
+ // ── helpers ──────────────────────────────────────────────────────────────────
26
+ const ok = msg => console.log(` ✓ ${msg}`);
27
+ const skip = msg => console.log(` · skipped ${msg} (use --force to overwrite)`);
28
+ const info = msg => console.log(` ${msg}`);
29
+ const hr = () => console.log(`\n${'━'.repeat(52)}`);
30
+
31
+ function ensureDir(dir) {
32
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
33
+ }
34
+
35
+ function copyFile(src, dest) {
36
+ const label = dest.replace(PROJECT_DIR + '/', '').replace(PROJECT_DIR + '\\', '');
37
+ if (!existsSync(src)) return;
38
+ if (existsSync(dest) && !FORCE) { skip(label); return; }
39
+ ensureDir(dirname(dest));
40
+ copyFileSync(src, dest);
41
+ ok(label);
42
+ }
43
+
44
+ // ── help ─────────────────────────────────────────────────────────────────────
45
+ function showHelp() {
46
+ console.log(`
47
+ joopjs — AI rules setup for joopjs
48
+
49
+ Usage:
50
+ npx joopjs setup-ai Copy AI rules to your project
51
+ npx joopjs setup-ai --force Overwrite existing rule files
52
+
53
+ What gets copied:
54
+ .claude/skills/joopjs-*.md Claude Code skills (7 skills)
55
+ .cursor/rules/joopjs.mdc Cursor rule
56
+ .windsurf/rules/joopjs.md Windsurf Cascade rule
57
+ .github/copilot-instructions.md GitHub Copilot instructions
58
+ GEMINI.md Gemini CLI instructions
59
+ AGENTS.md Codex / OpenAI Agents instructions
60
+ `);
61
+ }
62
+
63
+ // ── main ─────────────────────────────────────────────────────────────────────
64
+ if (CMD !== 'setup-ai') {
65
+ showHelp();
66
+ process.exit(0);
67
+ }
68
+
69
+ hr();
70
+ console.log(' joopjs — AI Rules Setup');
71
+ if (FORCE) console.log(' MODE: --force (existing files will be overwritten)');
72
+ hr();
73
+ console.log('');
74
+
75
+ // ── 1. Claude Code skills ─────────────────────────────────────────────────────
76
+ console.log(' Claude Code skills:');
77
+ const CONSUMER_SKILLS = ['setup', 'banking', 'finance', 'security', 'auth', 'encryption', 'observables'];
78
+ for (const skill of CONSUMER_SKILLS) {
79
+ copyFile(
80
+ join(PACKAGE_DIR, '.claude', 'skills', `${skill}.md`),
81
+ join(PROJECT_DIR, '.claude', 'skills', `joopjs-${skill}.md`)
82
+ );
83
+ }
84
+
85
+ // ── 2. Cursor ─────────────────────────────────────────────────────────────────
86
+ console.log('\n Cursor:');
87
+ copyFile(
88
+ join(PACKAGE_DIR, '.cursor', 'rules', 'joopjs.mdc'),
89
+ join(PROJECT_DIR, '.cursor', 'rules', 'joopjs.mdc')
90
+ );
91
+
92
+ // ── 3. Windsurf ───────────────────────────────────────────────────────────────
93
+ console.log('\n Windsurf Cascade:');
94
+ copyFile(
95
+ join(PACKAGE_DIR, '.windsurf', 'rules', 'joopjs.md'),
96
+ join(PROJECT_DIR, '.windsurf', 'rules', 'joopjs.md')
97
+ );
98
+
99
+ // ── 4. GitHub Copilot ─────────────────────────────────────────────────────────
100
+ console.log('\n GitHub Copilot:');
101
+ copyFile(
102
+ join(PACKAGE_DIR, '.github', 'copilot-instructions.md'),
103
+ join(PROJECT_DIR, '.github', 'copilot-instructions.md')
104
+ );
105
+
106
+ // ── 5. Gemini CLI ─────────────────────────────────────────────────────────────
107
+ console.log('\n Gemini CLI:');
108
+ copyFile(
109
+ join(PACKAGE_DIR, 'ai-rules', 'GEMINI.md'),
110
+ join(PROJECT_DIR, 'GEMINI.md')
111
+ );
112
+
113
+ // ── 6. Codex / OpenAI Agents ─────────────────────────────────────────────────
114
+ console.log('\n Codex / OpenAI Agents:');
115
+ copyFile(
116
+ join(PACKAGE_DIR, 'ai-rules', 'AGENTS.md'),
117
+ join(PROJECT_DIR, 'AGENTS.md')
118
+ );
119
+
120
+ // ── summary ───────────────────────────────────────────────────────────────────
121
+ hr();
122
+ console.log(' Done! Your AI tools now understand joopjs.\n');
123
+ console.log(' Next steps:');
124
+ console.log(' 1. Claude Code — add skills to your CLAUDE.md:');
125
+ console.log('');
126
+ for (const skill of CONSUMER_SKILLS) {
127
+ console.log(` | /joopjs-${skill.padEnd(11)} | JoopJS ${skill} guide |`);
128
+ }
129
+ console.log('');
130
+ console.log(' 2. Cursor / Windsurf — rules are auto-detected from their folders.');
131
+ console.log(' 3. Copilot / Gemini / Codex — files are at project root, ready to use.');
132
+ hr();
133
+ console.log('');