New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

hybrids

Package Overview
Dependencies
Maintainers
2
Versions
149
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

hybrids - npm Package Compare versions

Comparing version 8.1.2 to 8.1.3

8

docs/CHANGELOG.md

@@ -5,2 +5,10 @@ # Changelog

### [8.1.3](https://github.com/hybridsjs/hybrids/compare/v8.1.2...v8.1.3) (2022-09-16)
### Bug Fixes
* **store:** empty nested array with primitive values ([8df84d2](https://github.com/hybridsjs/hybrids/commit/8df84d215e1d680342796bb075ef406bfffbd9ee))
* **store:** resolve with support for using model definition ([95aa812](https://github.com/hybridsjs/hybrids/commit/95aa812b80f6c90fa14c5a4f0017b30fd37bbd3e))
### [8.1.2](https://github.com/hybridsjs/hybrids/compare/v8.1.1...v8.1.2) (2022-09-14)

@@ -7,0 +15,0 @@

30

docs/misc/api-reference.md

@@ -202,2 +202,21 @@ # API Reference

```typescript
store.resolve(model: Model): Promise<Model>
```
- **arguments**:
- `model` - a model instance
- **returns**:
- A promise instance resolving with the latest model value or rejecting with an error
```typescript
store.resolve(Model: object, id?: string | object): Promise<Model>
```
- **arguments**:
- `Model` - a model definition
- `id` - a string or an object representing identifier of the model instance
- **returns**:
- A promise instance resolving with the latest model value or rejecting with an error
```typescript
store.sync(modelOrDefinition: object, values: object | null) : Model;

@@ -297,13 +316,2 @@ ```

### Resolve
```typescript
store.resolve(model: Model): Promise<Model>
```
- **arguments**:
- `model` - a model instance
- **returns**:
- A promise instance resolving with the latest model value or rejecting with an error
## Router

@@ -310,0 +318,0 @@

@@ -241,2 +241,13 @@ # Model

If the nested array must be empty as a default value, you can use primitive constructor as the first item of the array:
```javascript
const Model = {
domains: [String],
numbers: [Number],
}
store.get(Model); // { domains: [], numbers: [] }
```
#### Models (External)

@@ -243,0 +254,0 @@

@@ -220,38 +220,2 @@ # Storage

#### Invalidation
Both memory and external storage uses a global cache mechanism based on the model definition reference. Model instances are global, so the cache mechanism cannot automatically predict which instance is no longer required. Because of that, the store provides the `store.clear()` method for invalidating model instances by the model definition or specific instance of the model.
```typescript
store.clear(model: object, clearValue?: boolean = true)
```
* **arguments**:
* `model` - a model definition (for all instances) or a model instance (for a specific one)
* `clearValue` - indicates if the cached value should be deleted (`true`), or it should only notify the cache mechanism, that the value expired, but leaves the value untouched (`false`)
For example, it might be useful to set the `clearValue` to `false` for the case when you want to implement the refresh button. Then, the values stay in the cache, but the store will fetch the next version of the instance.
```javascript
import Email from "./email.js";
function refresh(host) {
store.clear(host.emails, false);
}
define({
tag: "my-element",
emails: store([Email]),
render: ({ emails }) => html`
<button onclick="${refresh}">Refresh</button>
${store.ready(emails) && ...}
`,
});
```
#### Garbage Collector
The `store.clear()` method works as a garbage collector for unused model instances. Those that are not a dependency of any component connected to the DOM will be deleted entirely from the cache registry (as they would never exist) protecting from the memory leaks. It means, that even if you set `clearValue` to `false`, those instances that are not currently attached to the components, will be permanently deleted when the `store.clear()` method is invoked.
### offline

@@ -313,43 +277,1 @@

If the user does not have control over the model, it is recommended to keep that option off. You can avoid unnecessary calls to external storage when the list result does not depend on the model instance values.
## Observables
The storage methods are called only for the user interaction - when the model is got, or when a new value for the model instance is set. However, there might be a case, where your model instance is been updated outside of the user scope, for example by the server.
Using the `store.set()` method as a callback for the update will trigger the storage `set` method, which can lead to an endless loop of updates. Fortunately, the store provides a special `store.sync()` method, which does the trick. It only updates the memory cache synchronously of the model instance without calling any storage method from the `[store.connect]` configuration.
!> This method bypass the storage, so use it with caution, and only if you would use `store.get()` in another context. This method does not replace `store.set()`.
```typescript
store.sync(modelOrDefinition: object, values: object | null) : Model;
```
* **arguments**:
* `modelOrDefinition` - a model instance or model definition
* `values` - an object with partial values of the model instance or `null` for deleting the model
* **returns**:
* Model instance or model instance placeholder
```javascript
const Model = {
...,
[store.connect] : {
get: (id) => myApi.get("/model", id),
set: (id, values) => myApi.set("/model", id, values),
},
};
define({
tag: "my-element",
model: store(Model),
socket: (host) => {
const socket = io();
socket.on("model:update", (values) => {
store.sync(host.model, values);
});
},
});
```
In the above example, even though the `Model` is connected to the external storage, when the websocket emits an event, the values of the model update without calling `[store.connect].set()`, as we expect. It is an update triggered by the server, so we don't want to send new values to the server again.

@@ -23,3 +23,3 @@ # Usage

### Get
### get

@@ -58,3 +58,3 @@ ```typescript

### Set
### set

@@ -127,2 +127,130 @@ The `store.set()` method can create a new instance or update an existing model. According to the mode, the first argument should be a model definition or a model instance.

### resolve
You can use the `store.resolve()` method to simplify access to pending model instances, which can be updated at the moment. The function returns a promise resolving into the current model instance, regardless of the pending state. It also supports multiple chains of set methods, so the result will always be the latest instance.
#### Model Instance
```typescript
store.resolve(model: Model): Promise<Model>
```
* **arguments**:
* `model` - a model instance
* **returns**:
* A promise instance resolving with the latest model value or rejecting with an error
#### Model Definition
```typescript
store.resolve(Model: object, id?: string | object): Promise<Model>
```
* **arguments**:
* `Model` - a model definition
* `id` - a string or an object representing identifier of the model instance
* **returns**:
* A promise instance resolving with the latest model value or rejecting with an error
```javascript
const State = {
value: ""
};
async function sendValue(host) {
// state can be in pending state at the moment (updating by the change event)
const state = await store.resolve(host.state); // or store.resolve(State)
const res = await fetch("/my-endpoint", { method: "post", body: JSON.stringify(state) });
// do something with the response
}
define({
tag: "my-element",
state: store(State),
render: ({ state }) => html`
<my-async-data-source onupdate="${html.set(state, "value")}"></my-async-data-source>
<button onclick="${sendValue}">Send</button>
`,
});
```
### sync
The storage methods are called only for the user interaction - when the model is got, or when a new value for the model instance is set. However, there might be a case, where your model instance is been updated outside of the user scope, for example by the server.
Using the `store.set()` method as a callback for the update will trigger the storage `set` method, which can lead to an endless loop of updates. Fortunately, the store provides a special `store.sync()` method, which does the trick. It only updates the memory cache synchronously of the model instance without calling any storage method from the `[store.connect]` configuration.
!> This method bypass the storage, so use it with caution, and only if you would use `store.get()` in another context. This method does not replace `store.set()`.
```typescript
store.sync(modelOrDefinition: object, values: object | null) : Model;
```
* **arguments**:
* `modelOrDefinition` - a model instance or model definition
* `values` - an object with partial values of the model instance or `null` for deleting the model
* **returns**:
* Model instance or model instance placeholder
```javascript
const Model = {
...,
[store.connect] : {
get: (id) => myApi.get("/model", id),
set: (id, values) => myApi.set("/model", id, values),
},
};
define({
tag: "my-element",
model: store(Model),
socket: (host) => {
const socket = io();
socket.on("model:update", (values) => {
store.sync(host.model, values);
});
},
});
```
In the above example, even though the `Model` is connected to the external storage, when the websocket emits an event, the values of the model update without calling `[store.connect].set()`, as we expect. It is an update triggered by the server, so we don't want to send new values to the server again.
### clear
Both memory and external storage uses a global cache mechanism based on the model definition reference. Model instances are global, so the cache mechanism cannot automatically predict which instance is no longer required. Because of that, the store provides the `store.clear()` method for invalidating model instances by the model definition or specific instance of the model.
```typescript
store.clear(model: object, clearValue?: boolean = true)
```
* **arguments**:
* `model` - a model definition (for all instances) or a model instance (for a specific one)
* `clearValue` - indicates if the cached value should be deleted (`true`), or it should only notify the cache mechanism, that the value expired, but leaves the value untouched (`false`)
For example, it might be useful to set the `clearValue` to `false` for the case when you want to implement the refresh button. Then, the values stay in the cache, but the store will fetch the next version of the instance.
```javascript
import Email from "./email.js";
function refresh(host) {
store.clear(host.emails, false);
}
define({
tag: "my-element",
emails: store([Email]),
render: ({ emails }) => html`
<button onclick="${refresh}">Refresh</button>
${store.ready(emails) && ...}
`,
});
```
#### Garbage Collector
The `store.clear()` method works as a garbage collector for unused model instances. Those that are not a dependency of any component connected to the DOM will be deleted entirely from the cache registry (as they would never exist) protecting from the memory leaks. It means, that even if you set `clearValue` to `false`, those instances that are not currently attached to the components, will be permanently deleted when the `store.clear()` method is invoked.
## Factory

@@ -334,3 +462,3 @@

### `store.ready()`
### ready

@@ -371,3 +499,3 @@ ```typescript

### `store.pending()`
### pending

@@ -387,41 +515,5 @@ ```typescript

### `store.resolve()`
### error
You can use the `store.resolve()` method to simplify access to pending model instances, which can be updated at the moment. The function returns a promise resolving into the current model instance, regardless of the pending state. It also supports multiple chains of set methods, so the result will always be the latest instance.
```typescript
store.resolve(model: Model): Promise<Model>
```
* **arguments**:
* `model` - a model instance
* **returns**:
* A promise instance resolving with the latest model value or rejecting with an error
```javascript
const State = {
value: ""
};
async function sendValue(host) {
// state can be in pending state at the moment (updating by the change event)
const state = await store.resolve(host.state);
const res = await fetch("/my-endpoint", { method: "post", body: JSON.stringify(state) });
// do something with the response
}
define({
tag: "my-element",
state: store(State),
render: ({ state }) => html`
<my-async-data-source onupdate="${html.set(state, "value")}"></my-async-data-source>
<button onclick="${sendValue}">Send</button>
`,
});
```
### `store.error()`
```typescript
store.error(model: Model, propertyName?: string | null): boolean | Error | any

@@ -428,0 +520,0 @@ ```

{
"name": "hybrids",
"version": "8.1.2",
"version": "8.1.3",
"description": "A JavaScript framework for creating fully-featured web applications, components libraries, and single web components with unique declarative and functional architecture",

@@ -5,0 +5,0 @@ "type": "module",

@@ -540,4 +540,21 @@ /* eslint-disable no-use-before-define */

if (nestedType !== "object") {
const Constructor = getTypeConstructor(nestedType, key);
const defaultArray = Object.freeze(defaultValue.map(Constructor));
if (
nestedType === "function" &&
![String, Number, Boolean].includes(defaultValue[0])
) {
throw TypeError(
`The array item for the '${key}' must be one of the primitive types constructor: String, Number, or Boolean`,
);
}
const Constructor =
nestedType === "function"
? defaultValue[0]
: getTypeConstructor(nestedType, key);
const defaultArray =
nestedType === "function"
? []
: Object.freeze(defaultValue.map(Constructor));
return (model, data, lastModel) => {

@@ -1315,4 +1332,5 @@ if (hasOwnProperty.call(data, key)) {

function resolveToLatest(model) {
function resolveToLatest(model, id) {
model = stales.get(model) || model;
if (!definitions.get(model)) model = get(model, id);

@@ -1319,0 +1337,0 @@ const promise = pending(model);

@@ -77,3 +77,3 @@ declare module "hybrids" {

>
? [Model<T>] | ((model: M) => T[])
? NestedArrayModel<T> | ((model: M) => NestedArrayModel<T>)
: Required<M>[property] extends object

@@ -87,2 +87,10 @@ ? Model<Required<M>[property]> | ((model: M) => M[property])

type NestedArrayModel<T> = T extends string
? T[] | [StringConstructor]
: T extends number
? T[] | [NumberConstructor]
: T extends boolean
? T[] | [BooleanConstructor]
: T[] | [Model<T>] | [Model<T>, { loose?: boolean }];
type ModelIdentifier =

@@ -168,3 +176,6 @@ | string

function submit<M>(draft: M, values?: ModelValues<M>): Promise<M>;
function resolve<M>(model: M): Promise<M>;
function resolve<M>(model: Model<M>, id?: ModelIdentifier): Promise<M>;
function ref<M>(fn: () => M): M;

@@ -305,3 +316,2 @@

css: (parts: TemplateStringsArray, ...args: unknown[]) => this;
layout: (rules: string = "column") => this;
}

@@ -308,0 +318,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc