@furystack/core 15.2.5 → 16.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,40 @@
1
1
  # Changelog
2
2
 
3
+ ## [16.0.0] - 2026-03-10
4
+
5
+ ### 💥 Breaking Changes
6
+
7
+ ### IdentityContext lifetime changed from `scoped` to `explicit`
8
+
9
+ `IdentityContext` now uses `@Injectable({ lifetime: 'explicit' })` instead of `@Injectable({ lifetime: 'scoped' })`.
10
+
11
+ **Why:** With `scoped` lifetime, child injectors created via `createChild()` could not inherit the `IdentityContext` from their parent. Each child silently created a new default instance whose methods returned `false` or threw `"No IdentityContext"`. This was a common source of confusion, especially in Shades frontend applications where nested component injectors should share the same identity.
12
+
13
+ With `explicit` lifetime, `getInstance(IdentityContext)` walks up the parent injector chain, so you only need to set it once on the root (or request-scoped) injector and all descendants will find it.
14
+
15
+ **Who is affected:** Code that called `injector.getInstance(IdentityContext)` without a prior `setExplicitInstance` call. Previously this returned a useless default instance; now it throws `CannotInstantiateExplicitLifetimeError`.
16
+
17
+ **Who is NOT affected:** All standard FuryStack server-side setups (`useHttpAuthentication`, `useJwtAuthentication`, `useSystemIdentityContext`, REST/WebSocket API managers) already call `setExplicitInstance` before accessing `IdentityContext` and will continue to work without changes.
18
+
19
+ **Migration:**
20
+
21
+ ```typescript
22
+ // ❌ Before (scoped) — silently returned a broken default
23
+ const ctx = injector.getInstance(IdentityContext)
24
+
25
+ // ✅ After (explicit) — set it before accessing
26
+ injector.setExplicitInstance(myIdentityContext, IdentityContext)
27
+ const ctx = injector.getInstance(IdentityContext) // works
28
+
29
+ // ✅ Child injectors now inherit automatically
30
+ const child = injector.createChild()
31
+ const ctx = child.getInstance(IdentityContext) // same instance from parent
32
+ ```
33
+
34
+ ### 📚 Documentation
35
+
36
+ - Updated `IdentityContext` JSDoc to reflect the `explicit` lifetime, including setup instructions and parent inheritance behavior
37
+
3
38
  ## [15.2.5] - 2026-03-07
4
39
 
5
40
  ### ⬆️ Dependencies
@@ -4,17 +4,23 @@ import type { User } from './models/user.js';
4
4
  * This is a base implementation that should be extended or replaced with a concrete
5
5
  * implementation that connects to your authentication system.
6
6
  *
7
- * The IdentityContext is scoped to the request, meaning each request gets its own instance.
8
- * Override this class or set an explicit instance to provide actual authentication logic.
7
+ * The IdentityContext uses `explicit` lifetime, meaning it must be provided via
8
+ * `setExplicitInstance` or a setup helper (e.g. {@link useSystemIdentityContext})
9
+ * before it can be resolved with `getInstance`. Child injectors automatically
10
+ * inherit the instance from their parent, so you only need to set it once on the
11
+ * root (or request-scoped) injector.
9
12
  *
10
13
  * @example
11
14
  * ```ts
12
- * // Use the helper functions instead of accessing IdentityContext directly
15
+ * // Set up the context on your root or request injector
16
+ * injector.setExplicitInstance(myIdentityContextImpl, IdentityContext)
17
+ *
18
+ * // Then use the helper functions from any injector in the hierarchy
13
19
  * import { isAuthenticated, isAuthorized, getCurrentUser } from '@furystack/core'
14
20
  *
15
- * const authenticated = await isAuthenticated(injector)
16
- * const authorized = await isAuthorized(injector, 'admin')
17
- * const user = await getCurrentUser(injector)
21
+ * const authenticated = await isAuthenticated(childInjector)
22
+ * const authorized = await isAuthorized(childInjector, 'admin')
23
+ * const user = await getCurrentUser(childInjector)
18
24
  * ```
19
25
  */
20
26
  export declare class IdentityContext {
@@ -1 +1 @@
1
- {"version":3,"file":"identity-context.d.ts","sourceRoot":"","sources":["../src/identity-context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AAE5C;;;;;;;;;;;;;;;;;GAiBG;AACH,qBACa,eAAe;IAC1B;;;OAGG;IACI,eAAe;IAItB;;;;OAIG;IACI,YAAY,CAAC,GAAG,MAAM,EAAE,MAAM,EAAE;IAIvC;;;;OAIG;IACI,cAAc,CAAC,KAAK,SAAS,IAAI,KAAK,OAAO,CAAC,KAAK,CAAC;CAG5D"}
1
+ {"version":3,"file":"identity-context.d.ts","sourceRoot":"","sources":["../src/identity-context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AAE5C;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBACa,eAAe;IAC1B;;;OAGG;IACI,eAAe;IAItB;;;;OAIG;IACI,YAAY,CAAC,GAAG,MAAM,EAAE,MAAM,EAAE;IAIvC;;;;OAIG;IACI,cAAc,CAAC,KAAK,SAAS,IAAI,KAAK,OAAO,CAAC,KAAK,CAAC;CAG5D"}
@@ -10,17 +10,23 @@ import { Injectable } from '@furystack/inject';
10
10
  * This is a base implementation that should be extended or replaced with a concrete
11
11
  * implementation that connects to your authentication system.
12
12
  *
13
- * The IdentityContext is scoped to the request, meaning each request gets its own instance.
14
- * Override this class or set an explicit instance to provide actual authentication logic.
13
+ * The IdentityContext uses `explicit` lifetime, meaning it must be provided via
14
+ * `setExplicitInstance` or a setup helper (e.g. {@link useSystemIdentityContext})
15
+ * before it can be resolved with `getInstance`. Child injectors automatically
16
+ * inherit the instance from their parent, so you only need to set it once on the
17
+ * root (or request-scoped) injector.
15
18
  *
16
19
  * @example
17
20
  * ```ts
18
- * // Use the helper functions instead of accessing IdentityContext directly
21
+ * // Set up the context on your root or request injector
22
+ * injector.setExplicitInstance(myIdentityContextImpl, IdentityContext)
23
+ *
24
+ * // Then use the helper functions from any injector in the hierarchy
19
25
  * import { isAuthenticated, isAuthorized, getCurrentUser } from '@furystack/core'
20
26
  *
21
- * const authenticated = await isAuthenticated(injector)
22
- * const authorized = await isAuthorized(injector, 'admin')
23
- * const user = await getCurrentUser(injector)
27
+ * const authenticated = await isAuthenticated(childInjector)
28
+ * const authorized = await isAuthorized(childInjector, 'admin')
29
+ * const user = await getCurrentUser(childInjector)
24
30
  * ```
25
31
  */
26
32
  let IdentityContext = class IdentityContext {
@@ -49,7 +55,7 @@ let IdentityContext = class IdentityContext {
49
55
  }
50
56
  };
51
57
  IdentityContext = __decorate([
52
- Injectable({ lifetime: 'scoped' })
58
+ Injectable({ lifetime: 'explicit' })
53
59
  ], IdentityContext);
54
60
  export { IdentityContext };
55
61
  //# sourceMappingURL=identity-context.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"identity-context.js","sourceRoot":"","sources":["../src/identity-context.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAG9C;;;;;;;;;;;;;;;;;GAiBG;AAEI,IAAM,eAAe,GAArB,MAAM,eAAe;IAC1B;;;OAGG;IACI,eAAe;QACpB,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IAC/B,CAAC;IAED;;;;OAIG;IACI,YAAY,CAAC,GAAG,MAAgB;QACrC,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IAC/B,CAAC;IAED;;;;OAIG;IACI,cAAc;QACnB,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAA;IACvC,CAAC;CACF,CAAA;AA1BY,eAAe;IAD3B,UAAU,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;GACtB,eAAe,CA0B3B"}
1
+ {"version":3,"file":"identity-context.js","sourceRoot":"","sources":["../src/identity-context.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAG9C;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEI,IAAM,eAAe,GAArB,MAAM,eAAe;IAC1B;;;OAGG;IACI,eAAe;QACpB,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IAC/B,CAAC;IAED;;;;OAIG;IACI,YAAY,CAAC,GAAG,MAAgB;QACrC,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IAC/B,CAAC;IAED;;;;OAIG;IACI,cAAc;QACnB,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAA;IACvC,CAAC;CACF,CAAA;AA1BY,eAAe;IAD3B,UAAU,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;GACxB,eAAe,CA0B3B"}
@@ -4,15 +4,31 @@ import { describe, expect, it, vi } from 'vitest';
4
4
  import { getCurrentUser, isAuthenticated, isAuthorized } from './helpers.js';
5
5
  import { IdentityContext } from './identity-context.js';
6
6
  describe('IdentityContext', () => {
7
- it('Should be retrieved from an Injector', async () => {
7
+ it('Should throw when no explicit instance is set', async () => {
8
8
  await usingAsync(new Injector(), async (i) => {
9
- const ctx = i.getInstance(IdentityContext);
10
- expect(ctx).toBeInstanceOf(IdentityContext);
9
+ expect(() => i.getInstance(IdentityContext)).toThrow("'IdentityContext'");
10
+ });
11
+ });
12
+ it('Should be retrieved from an Injector after setExplicitInstance', async () => {
13
+ await usingAsync(new Injector(), async (i) => {
14
+ const ctx = new IdentityContext();
15
+ i.setExplicitInstance(ctx, IdentityContext);
16
+ expect(i.getInstance(IdentityContext)).toBe(ctx);
17
+ });
18
+ });
19
+ it('Should be inherited by a child injector', async () => {
20
+ await usingAsync(new Injector(), async (i) => {
21
+ const ctx = new IdentityContext();
22
+ i.setExplicitInstance(ctx, IdentityContext);
23
+ await usingAsync(i.createChild(), async (child) => {
24
+ expect(child.getInstance(IdentityContext)).toBe(ctx);
25
+ });
11
26
  });
12
27
  });
13
28
  it('isAuthenticated should be called from helper', async () => {
14
29
  await usingAsync(new Injector(), async (i) => {
15
- const ctx = i.getInstance(IdentityContext);
30
+ const ctx = new IdentityContext();
31
+ i.setExplicitInstance(ctx, IdentityContext);
16
32
  const spy = vi.spyOn(ctx, 'isAuthenticated');
17
33
  const isAuth = await isAuthenticated(i);
18
34
  expect(isAuth).toBeFalsy();
@@ -21,7 +37,8 @@ describe('IdentityContext', () => {
21
37
  });
22
38
  it('isAuthorized should be called from helper', async () => {
23
39
  await usingAsync(new Injector(), async (i) => {
24
- const ctx = i.getInstance(IdentityContext);
40
+ const ctx = new IdentityContext();
41
+ i.setExplicitInstance(ctx, IdentityContext);
25
42
  const spy = vi.spyOn(ctx, 'isAuthorized');
26
43
  const isAuth = await isAuthorized(i);
27
44
  expect(isAuth).toBeFalsy();
@@ -30,7 +47,8 @@ describe('IdentityContext', () => {
30
47
  });
31
48
  it('getCurrentUser should be called from helper', async () => {
32
49
  await usingAsync(new Injector(), async (i) => {
33
- const ctx = i.getInstance(IdentityContext);
50
+ const ctx = new IdentityContext();
51
+ i.setExplicitInstance(ctx, IdentityContext);
34
52
  const spy = vi.spyOn(ctx, 'getCurrentUser');
35
53
  await expect(getCurrentUser(i)).rejects.toThrowError('No IdentityContext');
36
54
  expect(spy).toBeCalledTimes(1);
@@ -1 +1 @@
1
- {"version":3,"file":"identity-context.spec.js","sourceRoot":"","sources":["../src/identity-context.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AACjD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC5E,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAEvD,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;QACpD,MAAM,UAAU,CAAC,IAAI,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;YAC3C,MAAM,GAAG,GAAG,CAAC,CAAC,WAAW,CAAC,eAAe,CAAC,CAAA;YAC1C,MAAM,CAAC,GAAG,CAAC,CAAC,cAAc,CAAC,eAAe,CAAC,CAAA;QAC7C,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;QAC5D,MAAM,UAAU,CAAC,IAAI,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;YAC3C,MAAM,GAAG,GAAG,CAAC,CAAC,WAAW,CAAC,eAAe,CAAC,CAAA;YAC1C,MAAM,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAA;YAC5C,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,CAAC,CAAC,CAAA;YACvC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,CAAA;YAC1B,MAAM,CAAC,GAAG,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAA;QAChC,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,UAAU,CAAC,IAAI,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;YAC3C,MAAM,GAAG,GAAG,CAAC,CAAC,WAAW,CAAC,eAAe,CAAC,CAAA;YAC1C,MAAM,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,cAAc,CAAC,CAAA;YACzC,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,CAAC,CAAC,CAAA;YACpC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,CAAA;YAC1B,MAAM,CAAC,GAAG,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAA;QAChC,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;QAC3D,MAAM,UAAU,CAAC,IAAI,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;YAC3C,MAAM,GAAG,GAAG,CAAC,CAAC,WAAW,CAAC,eAAe,CAAC,CAAA;YAC1C,MAAM,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAA;YAC3C,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,oBAAoB,CAAC,CAAA;YAC1E,MAAM,CAAC,GAAG,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAA;QAChC,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
1
+ {"version":3,"file":"identity-context.spec.js","sourceRoot":"","sources":["../src/identity-context.spec.ts"],"names":[],"mappings":"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"}
@@ -83,7 +83,7 @@ describe('useSystemIdentityContext', () => {
83
83
  await usingAsync(useSystemIdentityContext({ injector: parent }), async () => {
84
84
  // no-op
85
85
  });
86
- expect(() => parent.getInstance(IdentityContext)).not.toThrow();
86
+ expect(() => parent.createChild()).not.toThrow();
87
87
  });
88
88
  });
89
89
  });
@@ -1 +1 @@
1
- {"version":3,"file":"system-identity-context.spec.js","sourceRoot":"","sources":["../src/system-identity-context.spec.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"system-identity-context.spec.js","sourceRoot":"","sources":["../src/system-identity-context.spec.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@furystack/core",
3
- "version": "15.2.5",
3
+ "version": "16.0.0",
4
4
  "description": "Core FuryStack package",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -5,16 +5,34 @@ import { getCurrentUser, isAuthenticated, isAuthorized } from './helpers.js'
5
5
  import { IdentityContext } from './identity-context.js'
6
6
 
7
7
  describe('IdentityContext', () => {
8
- it('Should be retrieved from an Injector', async () => {
8
+ it('Should throw when no explicit instance is set', async () => {
9
9
  await usingAsync(new Injector(), async (i) => {
10
- const ctx = i.getInstance(IdentityContext)
11
- expect(ctx).toBeInstanceOf(IdentityContext)
10
+ expect(() => i.getInstance(IdentityContext)).toThrow("'IdentityContext'")
11
+ })
12
+ })
13
+
14
+ it('Should be retrieved from an Injector after setExplicitInstance', async () => {
15
+ await usingAsync(new Injector(), async (i) => {
16
+ const ctx = new IdentityContext()
17
+ i.setExplicitInstance(ctx, IdentityContext)
18
+ expect(i.getInstance(IdentityContext)).toBe(ctx)
19
+ })
20
+ })
21
+
22
+ it('Should be inherited by a child injector', async () => {
23
+ await usingAsync(new Injector(), async (i) => {
24
+ const ctx = new IdentityContext()
25
+ i.setExplicitInstance(ctx, IdentityContext)
26
+ await usingAsync(i.createChild(), async (child) => {
27
+ expect(child.getInstance(IdentityContext)).toBe(ctx)
28
+ })
12
29
  })
13
30
  })
14
31
 
15
32
  it('isAuthenticated should be called from helper', async () => {
16
33
  await usingAsync(new Injector(), async (i) => {
17
- const ctx = i.getInstance(IdentityContext)
34
+ const ctx = new IdentityContext()
35
+ i.setExplicitInstance(ctx, IdentityContext)
18
36
  const spy = vi.spyOn(ctx, 'isAuthenticated')
19
37
  const isAuth = await isAuthenticated(i)
20
38
  expect(isAuth).toBeFalsy()
@@ -24,7 +42,8 @@ describe('IdentityContext', () => {
24
42
 
25
43
  it('isAuthorized should be called from helper', async () => {
26
44
  await usingAsync(new Injector(), async (i) => {
27
- const ctx = i.getInstance(IdentityContext)
45
+ const ctx = new IdentityContext()
46
+ i.setExplicitInstance(ctx, IdentityContext)
28
47
  const spy = vi.spyOn(ctx, 'isAuthorized')
29
48
  const isAuth = await isAuthorized(i)
30
49
  expect(isAuth).toBeFalsy()
@@ -34,7 +53,8 @@ describe('IdentityContext', () => {
34
53
 
35
54
  it('getCurrentUser should be called from helper', async () => {
36
55
  await usingAsync(new Injector(), async (i) => {
37
- const ctx = i.getInstance(IdentityContext)
56
+ const ctx = new IdentityContext()
57
+ i.setExplicitInstance(ctx, IdentityContext)
38
58
  const spy = vi.spyOn(ctx, 'getCurrentUser')
39
59
  await expect(getCurrentUser(i)).rejects.toThrowError('No IdentityContext')
40
60
  expect(spy).toBeCalledTimes(1)
@@ -6,20 +6,26 @@ import type { User } from './models/user.js'
6
6
  * This is a base implementation that should be extended or replaced with a concrete
7
7
  * implementation that connects to your authentication system.
8
8
  *
9
- * The IdentityContext is scoped to the request, meaning each request gets its own instance.
10
- * Override this class or set an explicit instance to provide actual authentication logic.
9
+ * The IdentityContext uses `explicit` lifetime, meaning it must be provided via
10
+ * `setExplicitInstance` or a setup helper (e.g. {@link useSystemIdentityContext})
11
+ * before it can be resolved with `getInstance`. Child injectors automatically
12
+ * inherit the instance from their parent, so you only need to set it once on the
13
+ * root (or request-scoped) injector.
11
14
  *
12
15
  * @example
13
16
  * ```ts
14
- * // Use the helper functions instead of accessing IdentityContext directly
17
+ * // Set up the context on your root or request injector
18
+ * injector.setExplicitInstance(myIdentityContextImpl, IdentityContext)
19
+ *
20
+ * // Then use the helper functions from any injector in the hierarchy
15
21
  * import { isAuthenticated, isAuthorized, getCurrentUser } from '@furystack/core'
16
22
  *
17
- * const authenticated = await isAuthenticated(injector)
18
- * const authorized = await isAuthorized(injector, 'admin')
19
- * const user = await getCurrentUser(injector)
23
+ * const authenticated = await isAuthenticated(childInjector)
24
+ * const authorized = await isAuthorized(childInjector, 'admin')
25
+ * const user = await getCurrentUser(childInjector)
20
26
  * ```
21
27
  */
22
- @Injectable({ lifetime: 'scoped' })
28
+ @Injectable({ lifetime: 'explicit' })
23
29
  export class IdentityContext {
24
30
  /**
25
31
  * Checks if the current user is authenticated.
@@ -95,7 +95,7 @@ describe('useSystemIdentityContext', () => {
95
95
  await usingAsync(useSystemIdentityContext({ injector: parent }), async () => {
96
96
  // no-op
97
97
  })
98
- expect(() => parent.getInstance(IdentityContext)).not.toThrow()
98
+ expect(() => parent.createChild()).not.toThrow()
99
99
  })
100
100
  })
101
101
  })