@sigrea/vue 0.2.1 → 0.3.1

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/README.md CHANGED
@@ -1,19 +1,19 @@
1
1
  # @sigrea/vue
2
2
 
3
- `@sigrea/vue` adapts [@sigrea/core](https://www.npmjs.com/package/@sigrea/core) logic modules and signals for Vue 3's Composition API. It aligns lifecycle scopes with component lifecycles, preserves deep reactivity, and provides composables for `<script setup>` and traditional setup functions.
3
+ `@sigrea/vue` adapts [@sigrea/core](https://www.npmjs.com/package/@sigrea/core) molecule modules and signals for Vue 3's Composition API. It aligns lifecycle scopes with component lifecycles, preserves deep reactivity, and provides composables for `<script setup>` and traditional setup functions.
4
4
 
5
5
  - **Signal subscriptions.** `useSignal` subscribes to signals and computed values, returning a readonly ref that updates when they change.
6
6
  - **Computed subscriptions.** `useComputed` subscribes to computed values, mirroring Vue's `computed` while tracking through Sigrea scopes.
7
7
  - **Deep signal subscriptions.** `useDeepSignal` subscribes to deep signal objects and exposes them as mutable refs with automatic cleanup.
8
8
  - **Two-way bindings.** `useMutableSignal` wraps primitive signals as `WritableComputedRef` for two-way bindings like `v-model`.
9
- - **Logic lifecycles.** `useLogic` mounts logic factories and binds their lifecycles to Vue components.
9
+ - **Molecule lifecycles.** `useMolcule` mounts molecule factories and binds their lifecycles to Vue components.
10
10
 
11
11
  ## Table of Contents
12
12
 
13
13
  - [Install](#install)
14
14
  - [Quick Start](#quick-start)
15
15
  - [Consume a Signal](#consume-a-signal)
16
- - [Bridge Framework-Agnostic Logic](#bridge-framework-agnostic-logic)
16
+ - [Bridge Framework-Agnostic Molecules](#bridge-framework-agnostic-molecules)
17
17
  - [Bind Writable Primitive Signals](#bind-writable-primitive-signals)
18
18
  - [Bind Deep Reactive Objects](#bind-deep-reactive-objects)
19
19
  - [API Reference](#api-reference)
@@ -21,8 +21,9 @@
21
21
  - [useComputed](#usecomputed)
22
22
  - [useDeepSignal](#usedeepsignal)
23
23
  - [useMutableSignal](#usemutablesignal)
24
- - [useLogic](#uselogic)
24
+ - [useMolcule](#usemolcule)
25
25
  - [Testing](#testing)
26
+ - [Handling Scope Cleanup Errors](#handling-scope-cleanup-errors)
26
27
  - [Development](#development)
27
28
  - [License](#license)
28
29
 
@@ -52,13 +53,13 @@ const value = useSignal(count);
52
53
  </template>
53
54
  ```
54
55
 
55
- ### Bridge Framework-Agnostic Logic
56
+ ### Bridge Framework-Agnostic Molecules
56
57
 
57
58
  ```ts
58
- // CounterLogic.ts
59
- import { defineLogic, signal } from "@sigrea/core";
59
+ // CounterMolecule.ts
60
+ import { molecule, signal } from "@sigrea/core";
60
61
 
61
- export const CounterLogic = defineLogic<{ initialCount: number }>()((props) => {
62
+ export const CounterMolecule = molecule((props: { initialCount: number }) => {
62
63
  const count = signal(props.initialCount);
63
64
 
64
65
  const increment = () => {
@@ -76,11 +77,11 @@ export const CounterLogic = defineLogic<{ initialCount: number }>()((props) => {
76
77
  ```vue
77
78
  <!-- Counter.vue -->
78
79
  <script setup lang="ts">
79
- import { useLogic, useSignal } from "@sigrea/vue";
80
- import { CounterLogic } from "./CounterLogic";
80
+ import { useMolcule, useSignal } from "@sigrea/vue";
81
+ import { CounterMolecule } from "./CounterMolecule";
81
82
 
82
83
  const props = defineProps<{ initialCount: number }>();
83
- const counter = useLogic(CounterLogic, props);
84
+ const counter = useMolcule(CounterMolecule, props);
84
85
  const value = useSignal(counter.count);
85
86
  </script>
86
87
 
@@ -169,27 +170,24 @@ function useMutableSignal<T>(signal: Signal<T>): WritableComputedRef<T>
169
170
 
170
171
  Wraps a Sigrea signal as a Vue `WritableComputedRef` for two-way bindings like `v-model`. Expects a writable signal created by `signal()`. Passing a readonly signal throws at runtime.
171
172
 
172
- ### useLogic
173
+ ### useMolcule
173
174
 
174
175
  ```ts
175
- function useLogic<TReturn extends object, TProps = void>(
176
- logic: LogicFunction<TReturn, TProps>,
177
- ...args: LogicArgs<TProps>
178
- ): LogicInstance<TReturn>
176
+ function useMolcule<TReturn extends object, TProps = void>(
177
+ molecule: MoleculeFactory<TReturn, TProps>,
178
+ ...args: MoleculeArgs<TProps>
179
+ ): MoleculeInstance<TReturn>
179
180
  ```
180
181
 
181
- Mounts a logic factory and returns its LogicInstance. Sigrea augments the logic with lifecycle metadata: `onMount` callbacks run after the component mounts, and `onUnmount` callbacks run before it unmounts.
182
+ Mounts a molecule factory and returns its MoleculeInstance. Sigrea augments the molecule with lifecycle metadata: `onMount` callbacks run after the component mounts, and `onUnmount` callbacks run before it unmounts.
182
183
 
183
184
  ## Testing
184
185
 
185
186
  ```ts
186
187
  // tests/Counter.test.ts
187
188
  import { mount } from "@vue/test-utils";
188
- import { cleanupLogics } from "@sigrea/core";
189
189
  import Counter from "../components/Counter.vue";
190
190
 
191
- afterEach(() => cleanupLogics());
192
-
193
191
  it("increments and displays the updated count", async () => {
194
192
  const wrapper = mount(Counter, {
195
193
  props: { initialCount: 10 },
@@ -201,15 +199,54 @@ it("increments and displays the updated count", async () => {
201
199
  });
202
200
  ```
203
201
 
202
+ ## Handling Scope Cleanup Errors
203
+
204
+ For global error handling configuration, see [@sigrea/core - Handling Scope Cleanup Errors](https://github.com/sigrea/core#handling-scope-cleanup-errors).
205
+
206
+ In Vue apps, configure the handler in your application entry point before mounting:
207
+
208
+ ```ts
209
+ // main.ts
210
+ import { setScopeCleanupErrorHandler } from "@sigrea/core";
211
+ import { createApp } from "vue";
212
+ import App from "./App.vue";
213
+
214
+ setScopeCleanupErrorHandler((error, context) => {
215
+ console.error(`Cleanup failed:`, error);
216
+
217
+ // Forward to monitoring service
218
+ if (typeof Sentry !== "undefined") {
219
+ Sentry.captureException(error, {
220
+ tags: { scopeId: context.scopeId, phase: context.phase },
221
+ });
222
+ }
223
+ });
224
+
225
+ createApp(App).mount("#app");
226
+ ```
227
+
204
228
  ## Development
205
229
 
206
- Development scripts prefer pnpm. npm or yarn work too, but pnpm keeps dependency resolution identical to CI.
230
+ This repo targets Node.js 20 or later.
231
+
232
+ If you use mise:
233
+
234
+ - `mise trust -y` — trust `mise.toml` (first run only).
235
+ - `mise run ci` — run CI-equivalent checks locally.
236
+ - `mise run notes` — preview release notes (optional).
237
+
238
+ You can also run pnpm scripts directly:
207
239
 
208
240
  - `pnpm install` — install dependencies.
209
241
  - `pnpm test` — run the Vitest suite once (no watch).
242
+ - `pnpm typecheck` — run TypeScript type checking.
243
+ - `pnpm test:coverage` — collect coverage.
210
244
  - `pnpm build` — compile via unbuild to produce dual CJS/ESM bundles.
245
+ - `pnpm cicheck` — run CI checks locally.
211
246
  - `pnpm dev` — launch the playground counter demo.
212
247
 
248
+ See [CONTRIBUTING.md](./CONTRIBUTING.md) for workflow details.
249
+
213
250
  ## License
214
251
 
215
252
  MIT — see [LICENSE](./LICENSE).
package/dist/index.cjs CHANGED
@@ -3,15 +3,15 @@
3
3
  const vue = require('vue');
4
4
  const core = require('@sigrea/core');
5
5
 
6
- function useLogic(logic, ...args) {
6
+ function useMolcule(molecule, ...args) {
7
7
  if (vue.getCurrentInstance() === null) {
8
8
  throw new Error(
9
- "useLogic can only be used within a Vue component setup()."
9
+ "useMolcule can only be used within a Vue component setup()."
10
10
  );
11
11
  }
12
- const instance = core.mountLogic(logic, ...args);
12
+ const instance = molecule(...args);
13
13
  vue.onScopeDispose(() => {
14
- core.cleanupLogic(instance);
14
+ core.disposeMolecule(instance);
15
15
  });
16
16
  return instance;
17
17
  }
@@ -85,7 +85,7 @@ function useMutableSignal(source) {
85
85
 
86
86
  exports.useComputed = useComputed;
87
87
  exports.useDeepSignal = useDeepSignal;
88
- exports.useLogic = useLogic;
88
+ exports.useMolcule = useMolcule;
89
89
  exports.useMutableSignal = useMutableSignal;
90
90
  exports.useSignal = useSignal;
91
91
  exports.useSnapshot = useSnapshot;
package/dist/index.d.cts CHANGED
@@ -1,8 +1,8 @@
1
- import { LogicFunction, LogicArgs, LogicInstance, Signal, ReadonlySignal, Computed, DeepSignal, SnapshotHandler } from '@sigrea/core';
1
+ import { MoleculeFactory, MoleculeArgs, MoleculeInstance, Signal, ReadonlySignal, Computed, DeepSignal, SnapshotHandler } from '@sigrea/core';
2
2
  import * as vue from 'vue';
3
3
  import { DeepReadonly, ShallowRef } from 'vue';
4
4
 
5
- declare function useLogic<TReturn extends object, TProps = void>(logic: LogicFunction<TReturn, TProps>, ...args: LogicArgs<TProps>): LogicInstance<TReturn>;
5
+ declare function useMolcule<TReturn extends object, TProps = void>(molecule: MoleculeFactory<TReturn, TProps>, ...args: MoleculeArgs<TProps>): MoleculeInstance<TReturn>;
6
6
 
7
7
  type ReadableSignal<T> = Signal<T> | ReadonlySignal<T>;
8
8
  declare function useSignal<T>(source: ReadableSignal<T>): Readonly<vue.Ref<vue.DeepReadonly<T>, vue.DeepReadonly<T>>>;
@@ -21,4 +21,4 @@ declare function useSnapshot<T>(handler: SnapshotHandler<T>, options: UseSnapsho
21
21
  mode: "mutable";
22
22
  }): ShallowRef<T>;
23
23
 
24
- export { useComputed, useDeepSignal, useLogic, useMutableSignal, useSignal, useSnapshot };
24
+ export { useComputed, useDeepSignal, useMolcule, useMutableSignal, useSignal, useSnapshot };
package/dist/index.d.mts CHANGED
@@ -1,8 +1,8 @@
1
- import { LogicFunction, LogicArgs, LogicInstance, Signal, ReadonlySignal, Computed, DeepSignal, SnapshotHandler } from '@sigrea/core';
1
+ import { MoleculeFactory, MoleculeArgs, MoleculeInstance, Signal, ReadonlySignal, Computed, DeepSignal, SnapshotHandler } from '@sigrea/core';
2
2
  import * as vue from 'vue';
3
3
  import { DeepReadonly, ShallowRef } from 'vue';
4
4
 
5
- declare function useLogic<TReturn extends object, TProps = void>(logic: LogicFunction<TReturn, TProps>, ...args: LogicArgs<TProps>): LogicInstance<TReturn>;
5
+ declare function useMolcule<TReturn extends object, TProps = void>(molecule: MoleculeFactory<TReturn, TProps>, ...args: MoleculeArgs<TProps>): MoleculeInstance<TReturn>;
6
6
 
7
7
  type ReadableSignal<T> = Signal<T> | ReadonlySignal<T>;
8
8
  declare function useSignal<T>(source: ReadableSignal<T>): Readonly<vue.Ref<vue.DeepReadonly<T>, vue.DeepReadonly<T>>>;
@@ -21,4 +21,4 @@ declare function useSnapshot<T>(handler: SnapshotHandler<T>, options: UseSnapsho
21
21
  mode: "mutable";
22
22
  }): ShallowRef<T>;
23
23
 
24
- export { useComputed, useDeepSignal, useLogic, useMutableSignal, useSignal, useSnapshot };
24
+ export { useComputed, useDeepSignal, useMolcule, useMutableSignal, useSignal, useSnapshot };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { LogicFunction, LogicArgs, LogicInstance, Signal, ReadonlySignal, Computed, DeepSignal, SnapshotHandler } from '@sigrea/core';
1
+ import { MoleculeFactory, MoleculeArgs, MoleculeInstance, Signal, ReadonlySignal, Computed, DeepSignal, SnapshotHandler } from '@sigrea/core';
2
2
  import * as vue from 'vue';
3
3
  import { DeepReadonly, ShallowRef } from 'vue';
4
4
 
5
- declare function useLogic<TReturn extends object, TProps = void>(logic: LogicFunction<TReturn, TProps>, ...args: LogicArgs<TProps>): LogicInstance<TReturn>;
5
+ declare function useMolcule<TReturn extends object, TProps = void>(molecule: MoleculeFactory<TReturn, TProps>, ...args: MoleculeArgs<TProps>): MoleculeInstance<TReturn>;
6
6
 
7
7
  type ReadableSignal<T> = Signal<T> | ReadonlySignal<T>;
8
8
  declare function useSignal<T>(source: ReadableSignal<T>): Readonly<vue.Ref<vue.DeepReadonly<T>, vue.DeepReadonly<T>>>;
@@ -21,4 +21,4 @@ declare function useSnapshot<T>(handler: SnapshotHandler<T>, options: UseSnapsho
21
21
  mode: "mutable";
22
22
  }): ShallowRef<T>;
23
23
 
24
- export { useComputed, useDeepSignal, useLogic, useMutableSignal, useSignal, useSnapshot };
24
+ export { useComputed, useDeepSignal, useMolcule, useMutableSignal, useSignal, useSnapshot };
package/dist/index.mjs CHANGED
@@ -1,15 +1,15 @@
1
1
  import { getCurrentInstance, onScopeDispose, shallowRef, readonly, triggerRef, computed } from 'vue';
2
- import { mountLogic, cleanupLogic, createSignalHandler, createComputedHandler, createDeepSignalHandler } from '@sigrea/core';
2
+ import { disposeMolecule, createSignalHandler, createComputedHandler, createDeepSignalHandler } from '@sigrea/core';
3
3
 
4
- function useLogic(logic, ...args) {
4
+ function useMolcule(molecule, ...args) {
5
5
  if (getCurrentInstance() === null) {
6
6
  throw new Error(
7
- "useLogic can only be used within a Vue component setup()."
7
+ "useMolcule can only be used within a Vue component setup()."
8
8
  );
9
9
  }
10
- const instance = mountLogic(logic, ...args);
10
+ const instance = molecule(...args);
11
11
  onScopeDispose(() => {
12
- cleanupLogic(instance);
12
+ disposeMolecule(instance);
13
13
  });
14
14
  return instance;
15
15
  }
@@ -81,4 +81,4 @@ function useMutableSignal(source) {
81
81
  });
82
82
  }
83
83
 
84
- export { useComputed, useDeepSignal, useLogic, useMutableSignal, useSignal, useSnapshot };
84
+ export { useComputed, useDeepSignal, useMolcule, useMutableSignal, useSignal, useSnapshot };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sigrea/vue",
3
- "version": "0.2.1",
4
- "description": "Vue adapter bindings for Sigrea logic modules.",
3
+ "version": "0.3.1",
4
+ "description": "Vue adapter bindings for Sigrea molecule modules.",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "packageManager": "pnpm@10.0.0",
@@ -36,7 +36,7 @@
36
36
  "signals",
37
37
  "reactivity",
38
38
  "vue",
39
- "logic",
39
+ "molecule",
40
40
  "typescript"
41
41
  ],
42
42
  "scripts": {
@@ -49,10 +49,11 @@
49
49
  "test:coverage": "vitest --coverage",
50
50
  "typecheck": "tsc -p tsconfig.json --noEmit",
51
51
  "format": "biome check .",
52
- "format:fix": "biome check --write ."
52
+ "format:fix": "biome check --write .",
53
+ "cicheck": "pnpm test && pnpm typecheck && pnpm format:fix"
53
54
  },
54
55
  "peerDependencies": {
55
- "@sigrea/core": "^0.3.1",
56
+ "@sigrea/core": "^0.4.3",
56
57
  "vue": "^3.4.0"
57
58
  },
58
59
  "devDependencies": {