@happyvertical/smrt-svelte 0.37.7 → 0.37.9

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/AGENTS.md CHANGED
@@ -233,7 +233,7 @@ await expectNoA11yViolations(container); // axe; color-contrast off (jsdom has n
233
233
  - `@happyvertical/smrt-types` (shared types) — includes the identity data contracts (`User`, `Role`, `Membership`, `Tenant`) the role/membership components type against, so no dependency on `smrt-users` / `smrt-profiles` is needed
234
234
  - `@happyvertical/smrt-ui` (UI runtime: primitives, theme system, i18n client, module registry) is a hard `dependency`. The agent-admin shells that used to type against `@happyvertical/smrt-agents/ui` moved to `@happyvertical/smrt-agents/svelte` (#1589), so `smrt-agents` is no longer a dependency here — this drops smrt-svelte below smrt-agents in the package DAG.
235
235
  - `@happyvertical/smrt-languages` is a hard `dependency` (not an optional peer): the Node-only `/i18n/server` subpath imports its resolver. The browser bundle still excludes it — the client `/i18n` layer never imports the languages root, so it tree-shakes out.
236
- - `@happyvertical/logger` (SDK) is a `dependency` — the browser-safe console logger used for voice/AI error reporting in the form components.
236
+ - `@happyvertical/logger` (SDK) is a `dependency` — the console logger used for voice/AI error reporting in the form components. Consume it **only** through `src/internal/logger.ts`, never `createLogger()` at module scope: `createLogger()` reads `HAVE_LOGGER_LEVEL` from `process.env`, so a top-level call throws `ReferenceError: process is not defined` in the browser and kills client-side hydration under `vite dev` (prod builds tree-shake/define it away, so this only bites in dev). The `internal/logger` wrapper constructs the logger lazily and falls back to a bare `ConsoleLogger` when `process.env` is absent, keeping this browser-reachable module (imported by `Provider` + the form primitives) safe.
237
237
  - Peer (all optional): `svelte` >=5.18.2, plus the browser-AI engines (`@huggingface/transformers`, `@mlc-ai/web-llm`, `@remotion/whisper-web`, `@xenova/transformers`) and `chrono-node`.
238
238
 
239
239
  ## Workspace shell primitives
@@ -1,12 +1,19 @@
1
1
  /**
2
2
  * Shared package logger for `@happyvertical/smrt-svelte`.
3
3
  *
4
- * Browser-safe: the `@happyvertical/logger` console adapter pulls no Node
5
- * built-ins and its `@sentry/node` integration is an optional peer that is
6
- * never imported here. Centralising the instance keeps voice/AI error reporting
7
- * consistent across the form components (mic permission denials, STT init
8
- * failures) instead of swallowing them in empty `catch` blocks or scattering
9
- * raw `console.*` calls.
4
+ * This module is browser-reachable (Provider + the form components import it),
5
+ * so it must never touch Node globals at module scope. `createLogger()` reads
6
+ * `HAVE_LOGGER_LEVEL` from `process.env`, and `process` does not exist in
7
+ * browsers calling it during module init threw
8
+ * `ReferenceError: process is not defined` under `vite dev` and killed
9
+ * client-side hydration for every consuming app. The logger is therefore
10
+ * created lazily on first use, and the env-config path is only consulted when
11
+ * a usable `process.env` actually exists; browsers get the plain console
12
+ * logger at the same level.
13
+ *
14
+ * Centralising the instance keeps voice/AI error reporting consistent across
15
+ * the form components (mic permission denials, STT init failures) instead of
16
+ * swallowing them in empty `catch` blocks or scattering raw `console.*` calls.
10
17
  */
11
18
  import { type Logger } from '@happyvertical/logger';
12
19
  export declare const logger: Logger;
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/internal/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAElE,eAAO,MAAM,MAAM,EAAE,MAAwC,CAAC"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/internal/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAGL,KAAK,MAAM,EACZ,MAAM,uBAAuB,CAAC;AAmB/B,eAAO,MAAM,MAAM,EAAE,MAKpB,CAAC"}
@@ -1,12 +1,37 @@
1
1
  /**
2
2
  * Shared package logger for `@happyvertical/smrt-svelte`.
3
3
  *
4
- * Browser-safe: the `@happyvertical/logger` console adapter pulls no Node
5
- * built-ins and its `@sentry/node` integration is an optional peer that is
6
- * never imported here. Centralising the instance keeps voice/AI error reporting
7
- * consistent across the form components (mic permission denials, STT init
8
- * failures) instead of swallowing them in empty `catch` blocks or scattering
9
- * raw `console.*` calls.
4
+ * This module is browser-reachable (Provider + the form components import it),
5
+ * so it must never touch Node globals at module scope. `createLogger()` reads
6
+ * `HAVE_LOGGER_LEVEL` from `process.env`, and `process` does not exist in
7
+ * browsers calling it during module init threw
8
+ * `ReferenceError: process is not defined` under `vite dev` and killed
9
+ * client-side hydration for every consuming app. The logger is therefore
10
+ * created lazily on first use, and the env-config path is only consulted when
11
+ * a usable `process.env` actually exists; browsers get the plain console
12
+ * logger at the same level.
13
+ *
14
+ * Centralising the instance keeps voice/AI error reporting consistent across
15
+ * the form components (mic permission denials, STT init failures) instead of
16
+ * swallowing them in empty `catch` blocks or scattering raw `console.*` calls.
10
17
  */
11
- import { createLogger } from '@happyvertical/logger';
12
- export const logger = createLogger({ level: 'warn' });
18
+ import { ConsoleLogger, createLogger, } from '@happyvertical/logger';
19
+ const LEVEL = 'warn';
20
+ let instance;
21
+ function resolveLogger() {
22
+ if (!instance) {
23
+ const hasProcessEnv = typeof process !== 'undefined' &&
24
+ typeof process.env === 'object' &&
25
+ process.env !== null;
26
+ instance = hasProcessEnv
27
+ ? createLogger({ level: LEVEL })
28
+ : new ConsoleLogger(LEVEL);
29
+ }
30
+ return instance;
31
+ }
32
+ export const logger = {
33
+ debug: (message, context) => resolveLogger().debug(message, context),
34
+ info: (message, context) => resolveLogger().info(message, context),
35
+ warn: (message, context) => resolveLogger().warn(message, context),
36
+ error: (message, context) => resolveLogger().error(message, context),
37
+ };
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Regression coverage for the "process is not defined" hydration killer.
3
+ *
4
+ * `internal/logger` is browser-reachable through Provider and the form
5
+ * components, and `@happyvertical/logger`'s `createLogger()` eagerly reads
6
+ * `process.env` (HAVE_LOGGER_LEVEL). Constructing the logger at module scope
7
+ * therefore threw during Vite dev pre-bundle evaluation in browsers and killed
8
+ * client-side hydration for every consuming app.
9
+ *
10
+ * vite-node's module runner itself needs `process.platform` to load inline
11
+ * modules, so the test cannot delete `process` outright the way a real browser
12
+ * lacks it. Stubbing it to an object without a usable `env` reproduces the
13
+ * same failure mode: the pre-fix module init still blows up at import time
14
+ * (`Object.keys(process.env)`), and the fixed guard must route to the plain
15
+ * console logger.
16
+ */
17
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
18
+ describe('internal/logger', () => {
19
+ beforeEach(() => {
20
+ vi.resetModules();
21
+ });
22
+ afterEach(() => {
23
+ vi.unstubAllGlobals();
24
+ vi.restoreAllMocks();
25
+ });
26
+ it('imports and logs without a usable process.env (browser)', async () => {
27
+ vi.stubGlobal('process', {});
28
+ const { logger } = await import('./logger.js');
29
+ const warn = vi.spyOn(console, 'warn').mockImplementation(() => { });
30
+ logger.warn('mic permission denied');
31
+ expect(warn).toHaveBeenCalledTimes(1);
32
+ expect(warn.mock.calls[0][0]).toContain('mic permission denied');
33
+ });
34
+ it('filters below the warn level in the browser fallback', async () => {
35
+ vi.stubGlobal('process', {});
36
+ const { logger } = await import('./logger.js');
37
+ const debug = vi.spyOn(console, 'debug').mockImplementation(() => { });
38
+ const info = vi.spyOn(console, 'info').mockImplementation(() => { });
39
+ const error = vi.spyOn(console, 'error').mockImplementation(() => { });
40
+ logger.debug('below threshold');
41
+ logger.info('below threshold');
42
+ logger.error('stt init failed');
43
+ expect(debug).not.toHaveBeenCalled();
44
+ expect(info).not.toHaveBeenCalled();
45
+ expect(error).toHaveBeenCalledTimes(1);
46
+ });
47
+ it('logs through the env-aware logger when process exists (node/SSR)', async () => {
48
+ const { logger } = await import('./logger.js');
49
+ const warn = vi.spyOn(console, 'warn').mockImplementation(() => { });
50
+ logger.warn('stt init failed', { adapter: 'whisper-cpp' });
51
+ expect(warn).toHaveBeenCalledTimes(1);
52
+ expect(warn.mock.calls[0][0]).toContain('stt init failed');
53
+ });
54
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happyvertical/smrt-svelte",
3
- "version": "0.37.7",
3
+ "version": "0.37.9",
4
4
  "description": "Svelte 5 components for SMRT user management - auth, users, tenants, roles, permissions, groups",
5
5
  "type": "module",
6
6
  "smrtRawPrimitives": "strict",
@@ -78,9 +78,9 @@
78
78
  "dependencies": {
79
79
  "@happyvertical/logger": "^0.74.11",
80
80
  "esm-env": "^1.2.2",
81
- "@happyvertical/smrt-languages": "0.37.7",
82
- "@happyvertical/smrt-types": "0.37.7",
83
- "@happyvertical/smrt-ui": "0.37.7"
81
+ "@happyvertical/smrt-languages": "0.37.9",
82
+ "@happyvertical/smrt-ui": "0.37.9",
83
+ "@happyvertical/smrt-types": "0.37.9"
84
84
  },
85
85
  "peerDependencies": {
86
86
  "@huggingface/transformers": ">=3.8.1",