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

@solid-primitives/immutable

Package Overview
Dependencies
Maintainers
3
Versions
28
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@solid-primitives/immutable - npm Package Compare versions

Comparing version 1.0.12 to 1.1.0

17

dist/index.d.ts

@@ -1,10 +0,9 @@

import { Accessor } from 'solid-js';
import { ReconcileOptions } from 'solid-js/store';
type ImmutablePrimitive = string | number | boolean | null | undefined | object;
type ImmutableObject = {
import { Accessor } from "solid-js";
import { ReconcileOptions } from "solid-js/store";
export type ImmutablePrimitive = string | number | boolean | null | undefined | object;
export type ImmutableObject = {
[key: string]: ImmutableValue;
};
type ImmutableArray = ImmutableValue[];
type ImmutableValue = ImmutablePrimitive | ImmutableObject | ImmutableArray;
export type ImmutableArray = ImmutableValue[];
export type ImmutableValue = ImmutablePrimitive | ImmutableObject | ImmutableArray;
/**

@@ -29,4 +28,2 @@ * Creates a deeply nested reactive object derived from the given immutable source. The source can be any signal that is updated in an immutable fashion.

*/
declare function createImmutable<T extends object>(source: Accessor<T>, options?: ReconcileOptions): T;
export { type ImmutableArray, type ImmutableObject, type ImmutablePrimitive, type ImmutableValue, createImmutable };
export declare function createImmutable<T extends object>(source: Accessor<T>, options?: ReconcileOptions): T;

@@ -1,162 +0,190 @@

import { createMemo, untrack, $PROXY, $TRACK, runWithOwner, getOwner, onCleanup, createRoot, getListener } from 'solid-js';
import { $RAW } from 'solid-js/store';
import { noop, arrayEquals, trueFn } from '@solid-primitives/utils';
import { keyArray } from '@solid-primitives/keyed';
// src/index.ts
var $NO_KEY = Symbol("no-key");
var ARRAY_EQUALS_OPTIONS = { equals: arrayEquals };
var isWrappable = (v) => !!v && (v.constructor === Object || Array.isArray(v));
var CommonTraps = class {
constructor(s, c) {
this.s = s;
this.c = c;
}
o = getOwner();
has(target, property) {
if (property === $RAW || property === $PROXY || property === $TRACK || property === "__proto__")
return true;
this.ownKeys();
return property in untrack(this.s);
}
#trackKeys;
ownKeys() {
if (!this.#trackKeys && getListener())
runWithOwner(
this.o,
() => this.#trackKeys = createMemo(() => Reflect.ownKeys(this.s()), [], ARRAY_EQUALS_OPTIONS)
);
return this.#trackKeys ? this.#trackKeys() : Reflect.ownKeys(this.s());
}
getOwnPropertyDescriptor(target, property) {
let desc = Reflect.getOwnPropertyDescriptor(target, property);
if (desc) {
if (desc.get) {
desc.get = this.get.bind(this, target, property, this);
delete desc.writable;
} else {
desc.value = this.get(target, property, this);
}
} else {
desc = this.has(target, property) ? {
enumerable: true,
configurable: true,
get: this.get.bind(this, target, property, this)
} : void 0;
import { createRoot, createMemo, untrack, getOwner, runWithOwner, $TRACK, $PROXY, onCleanup, getListener, } from "solid-js";
import { $RAW } from "solid-js/store";
import { trueFn, arrayEquals, noop } from "@solid-primitives/utils";
import { keyArray } from "@solid-primitives/keyed";
const $NO_KEY = Symbol("no-key");
const ARRAY_EQUALS_OPTIONS = { equals: arrayEquals };
const isWrappable = (v) => !!v && (v.constructor === Object || Array.isArray(v));
class CommonTraps {
s;
c;
o = getOwner();
constructor(s, c) {
this.s = s;
this.c = c;
}
return desc;
}
set = trueFn;
deleteProperty = trueFn;
};
var ObjectTraps = class extends CommonTraps {
#cache = /* @__PURE__ */ new Map();
constructor(source, config) {
super(source, config);
}
get(target, property, receiver) {
if (property === $RAW) return untrack(this.s);
if (property === $PROXY || property === $TRACK) return receiver;
if (property === Symbol.iterator) return void 0;
if (property === this.c.key) return untrack(this.s)[this.c.key];
let cached = this.#cache.get(property);
if (cached) return cached.get();
let valueAccessor = () => {
const source = this.s();
return source ? source[property] : void 0;
};
let memo = false;
this.#cache.set(
property,
cached = new PropertyWrapper(
() => {
const v = valueAccessor();
if (!memo && isWrappable(v)) {
runWithOwner(this.o, () => valueAccessor = createMemo(valueAccessor));
memo = true;
return valueAccessor();
}
return v;
},
this.o,
this.c
)
);
return cached.get();
}
};
var ArrayTraps = class extends CommonTraps {
#trackLength;
#trackItems;
constructor(source, config) {
super(source, config);
this.#trackItems = createMemo(
keyArray(
source,
(item, index) => isWrappable(item) ? config.key in item ? item[config.key] : config.merge ? index : item : index,
(item) => new PropertyWrapper(item, getOwner(), config)
),
[],
ARRAY_EQUALS_OPTIONS
);
this.#trackLength = createMemo(() => this.#trackItems().length, 0);
}
get(_, property, receiver) {
if (property === $RAW) return untrack(this.s);
if (property === $PROXY) return receiver;
if (property === $TRACK) return this.#trackItems(), receiver;
if (property === Symbol.iterator) return this.#trackItems(), untrack(this.s)[property];
if (property === "length") return this.#trackLength();
if (typeof property === "symbol") return this.s()[property];
if (property in Array.prototype) return Array.prototype[property].bind(receiver);
const num = typeof property === "string" ? parseInt(property) : property;
if (!Number.isInteger(num) || num < 0) return this.s()[property];
if (num >= untrack(this.#trackLength)) return this.#trackLength(), this.s()[num];
return untrack(this.#trackItems)[num].get();
}
};
var PropertyWrapper = class {
constructor(s, o, c) {
this.s = s;
this.o = o;
this.c = c;
runWithOwner(o, () => onCleanup(() => this.#dispose()));
}
#lastId;
#prev;
#dispose = noop;
#memo;
#calc() {
const v = this.s();
if (!isWrappable(v)) {
this.#lastId = void 0;
this.#dispose();
return this.#prev = v;
has(target, property) {
if (property === $RAW || property === $PROXY || property === $TRACK || property === "__proto__")
return true;
this.ownKeys();
return property in untrack(this.s);
}
const id = v[this.c.key];
if (id === this.#lastId && isWrappable(this.#prev)) return this.#prev;
this.#lastId = id;
this.#dispose();
return createRoot(
(_dispose) => (this.#dispose = _dispose, this.#prev = wrap(v, this.s, this.c)),
this.o
);
}
get() {
if (!this.#memo && getListener())
runWithOwner(this.o, () => this.#memo = createMemo(() => this.#calc()));
return this.#memo ? this.#memo() : this.#calc();
}
};
var wrap = (initialValue, source, config) => Array.isArray(initialValue) ? new Proxy([], new ArrayTraps(source, config)) : new Proxy({}, new ObjectTraps(source, config));
function createImmutable(source, options = {}) {
const memo = createMemo(source);
return untrack(
() => wrap(memo(), memo, {
key: options.key === null ? $NO_KEY : options.key ?? "id",
merge: options.merge
})
);
#trackKeys;
ownKeys() {
if (!this.#trackKeys && getListener())
runWithOwner(this.o, () => (this.#trackKeys = createMemo(() => Reflect.ownKeys(this.s()), [], ARRAY_EQUALS_OPTIONS)));
return this.#trackKeys ? this.#trackKeys() : Reflect.ownKeys(this.s());
}
getOwnPropertyDescriptor(target, property) {
let desc = Reflect.getOwnPropertyDescriptor(target, property);
if (desc) {
if (desc.get) {
desc.get = this.get.bind(this, target, property, this);
delete desc.writable;
}
else {
desc.value = this.get(target, property, this);
}
}
else {
desc = this.has(target, property)
? {
enumerable: true,
configurable: true,
get: this.get.bind(this, target, property, this),
}
: undefined;
}
return desc;
}
set = trueFn;
deleteProperty = trueFn;
}
export { createImmutable };
class ObjectTraps extends CommonTraps {
#cache = new Map();
constructor(source, config) {
super(source, config);
}
get(target, property, receiver) {
if (property === $RAW)
return untrack(this.s);
if (property === $PROXY || property === $TRACK)
return receiver;
if (property === Symbol.iterator)
return undefined;
if (property === this.c.key)
return untrack(this.s)[this.c.key];
let cached = this.#cache.get(property);
if (cached)
return cached.get();
let valueAccessor = () => {
const source = this.s();
return source ? source[property] : undefined;
};
let memo = false;
this.#cache.set(property, (cached = new PropertyWrapper(() => {
const v = valueAccessor();
// memoize property access if it is an object limit traversal to one level
if (!memo && isWrappable(v)) {
runWithOwner(this.o, () => (valueAccessor = createMemo(valueAccessor)));
memo = true;
return valueAccessor();
}
return v;
}, this.o, this.c)));
return cached.get();
}
}
class ArrayTraps extends CommonTraps {
#trackLength;
#trackItems;
constructor(source, config) {
super(source, config);
this.#trackItems = createMemo(keyArray(source, (item, index) => isWrappable(item)
? config.key in item
? item[config.key]
: config.merge
? index
: item
: index, item => new PropertyWrapper(item, getOwner(), config)), [], ARRAY_EQUALS_OPTIONS);
this.#trackLength = createMemo(() => this.#trackItems().length, 0);
}
get(_, property, receiver) {
if (property === $RAW)
return untrack(this.s);
if (property === $PROXY)
return receiver;
if (property === $TRACK)
return this.#trackItems(), receiver;
if (property === Symbol.iterator)
return this.#trackItems(), untrack(this.s)[property];
if (property === "length")
return this.#trackLength();
if (typeof property === "symbol")
return this.s()[property];
if (property in Array.prototype)
return Array.prototype[property].bind(receiver);
const num = typeof property === "string" ? parseInt(property) : property;
// invalid index - treat as obj property
if (!Number.isInteger(num) || num < 0)
return this.s()[property];
// out of bounds
if (num >= untrack(this.#trackLength))
return this.#trackLength(), this.s()[num];
// valid index
return untrack(this.#trackItems)[num].get();
}
}
class PropertyWrapper {
s;
o;
c;
constructor(s, o, c) {
this.s = s;
this.o = o;
this.c = c;
runWithOwner(o, () => onCleanup(() => this.#dispose()));
}
#lastId;
#prev;
#dispose = noop;
#memo;
#calc() {
const v = this.s();
if (!isWrappable(v)) {
this.#lastId = undefined;
this.#dispose();
return (this.#prev = v);
}
const id = v[this.c.key];
if (id === this.#lastId && isWrappable(this.#prev))
return this.#prev;
this.#lastId = id;
this.#dispose();
return createRoot(_dispose => ((this.#dispose = _dispose), (this.#prev = wrap(v, this.s, this.c))), this.o);
}
get() {
if (!this.#memo && getListener())
runWithOwner(this.o, () => (this.#memo = createMemo(() => this.#calc())));
return this.#memo ? this.#memo() : this.#calc();
}
}
const wrap = (initialValue, source, config) => Array.isArray(initialValue)
? new Proxy([], new ArrayTraps(source, config))
: new Proxy({}, new ObjectTraps(source, config));
/**
* Creates a deeply nested reactive object derived from the given immutable source. The source can be any signal that is updated in an immutable fashion.
* @param source reactive function returning an immutable object
* @param options optional configuration
* - `key` property name to use as unique identifier for objects when their reference changes
* - `merge` controls how objects witohut a unique identifier are identified when reconciling an array. If `true` the index is used, otherwise the object reference itself is used.
* @returns a reactive object derived from the given source
* @example
* ```ts
* const [data, setData] = createSignal({ a: 1, b: 2 });
* const state = createImmutable(data);
* const a = () => state().a;
* const b = () => state().b;
* createEffect(() => console.log(a(), b()));
* // logs 1 2
* setData({ a: 2, b: 3 });
* // logs 2 3
* ```
*/
export function createImmutable(source, options = {}) {
const memo = createMemo(source);
return untrack(() => wrap(memo(), memo, {
key: options.key === null ? $NO_KEY : (options.key ?? "id"),
merge: options.merge,
}));
}
{
"name": "@solid-primitives/immutable",
"version": "1.0.12",
"version": "1.1.0",
"description": "Primitive for rectifying immutable values and dealing with immutability in Solid.",

@@ -36,3 +36,2 @@ "author": "Damian Tarnawski <gthetarnav@gmail.com>",

"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",

@@ -46,6 +45,2 @@ "types": "./dist/index.d.ts",

"default": "./dist/index.js"
},
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
}

@@ -58,4 +53,4 @@ },

"dependencies": {
"@solid-primitives/keyed": "^1.4.0",
"@solid-primitives/utils": "^6.2.3"
"@solid-primitives/keyed": "^1.5.0",
"@solid-primitives/utils": "^6.3.0"
},

@@ -62,0 +57,0 @@ "devDependencies": {

@@ -7,3 +7,2 @@ <p>

[![turborepo](https://img.shields.io/badge/built%20with-turborepo-cc00ff.svg?style=for-the-badge&logo=turborepo)](https://turborepo.org/)
[![size](https://img.shields.io/bundlephobia/minzip/@solid-primitives/immutable?style=for-the-badge&label=size)](https://bundlephobia.com/package/@solid-primitives/immutable)

@@ -10,0 +9,0 @@ [![version](https://img.shields.io/npm/v/@solid-primitives/immutable?style=for-the-badge)](https://www.npmjs.com/package/@solid-primitives/immutable)

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