Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/en/v1/api/common/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ Async pause to wait for a certain time.
### [memo](/en/v1/api/common/memo)
Evaluates a function only once and reuses the result (lazy memoization).

### [memoObject](/en/v1/api/common/memoObject)
Memoizes an object exposed through a `Proxy` and keeps keys aligned with writes.

### [memoPromise](/en/v1/api/common/memoPromise)
Lazy memoization for functions returning a value or a promise.

Expand Down
4 changes: 2 additions & 2 deletions docs/en/v1/api/common/memo.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ prev:
text: "sleep"
link: "/en/v1/api/common/sleep"
next:
text: "memoPromise"
link: "/en/v1/api/common/memoPromise"
text: "memoObject"
link: "/en/v1/api/common/memoObject"
---

# memo
Expand Down
49 changes: 49 additions & 0 deletions docs/en/v1/api/common/memoObject.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
outline: [2, 3]
description: "The memoObject() function builds a proxy around a memoized object. The getter is evaluated once, then reads/writes target the same reference."
prev:
text: "memo"
link: "/en/v1/api/common/memo"
next:
text: "memoPromise"
link: "/en/v1/api/common/memoPromise"
---

# memoObject

The **`memoObject()`** function builds a proxy around a memoized object. The getter is evaluated lazily on first access, then all reads/writes target the same object.

## Interactive example

<MonacoTSEditor
src="/examples/v1/api/common/memoObject/tryout.doc.ts"
majorVersion="v1"
height="355px"
/>

## Syntax

```typescript
function memoObject<
GenericOutput extends object
>(
getter: () => GenericOutput
): GenericOutput;
```

## Parameters

- `getter` : Function called on first access to produce the proxied object.

## Return value

A proxied `GenericOutput` object:
- reads (`obj.prop`) return values from the memoized object;
- writes (`obj.prop = value`) mutate the memoized object;
- `Object.keys()` and the `in` operator reflect keys after writes.

## See also

- [`memo`](/en/v1/api/common/memo) - Lazy memoization for synchronous values
- [`memoPromise`](/en/v1/api/common/memoPromise) - Lazy memoization for async-capable values
- [`override`](/en/v1/api/common/override) - Override methods and default properties on an object
4 changes: 2 additions & 2 deletions docs/en/v1/api/common/memoPromise.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
outline: [2, 3]
description: "The memoPromise() function lazily evaluates a function that returns a value or a promise, then memoizes the resolved result."
prev:
text: "memo"
link: "/en/v1/api/common/memo"
text: "memoObject"
link: "/en/v1/api/common/memoObject"
next:
text: "stringToMillisecond"
link: "/en/v1/api/common/stringToMillisecond"
Expand Down
4 changes: 2 additions & 2 deletions docs/examples/v1/api/clean/flag/tryout.doc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ namespace User {
export const MajorFlag = C.createFlag<
Entity, // mandatory
"majorUser", // mandatory
Age // optional
{ age: Age } // optional
>("majorUser");
export type MajorFlag = C.GetFlag<typeof MajorFlag>;

export function isMajor(entity: Entity) {
if (C.greaterThan(entity.age, 18)) {
return E.success(
MajorFlag.append(entity, entity.age),
MajorFlag.append(entity, { age: entity.age }),
);
}
return E.left("not-major");
Expand Down
4 changes: 2 additions & 2 deletions docs/examples/v1/api/clean/unwrapEntity/tryout.doc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export namespace User {
export const IsAdmin = C.createFlag<
Entity,
"isAdmin",
boolean
{ value: boolean }
>("isAdmin");
export type IsAdmin = C.GetFlag<typeof IsAdmin>;
}
Expand All @@ -33,7 +33,7 @@ const user = User.Entity.new({
createdAt: User.CreatedAt.createOrThrow(D.now()),
});

const flaggedUser = User.IsAdmin.append(user, true);
const flaggedUser = User.IsAdmin.append(user, { value: true });
const unwrappedUser = C.unwrapEntity(flaggedUser);

type check = ExpectType<
Expand Down
15 changes: 15 additions & 0 deletions docs/examples/v1/api/common/memoObject/tryout.doc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { memoObject } from "@duplojs/utils";

let calls = 0;
const state = memoObject(() => {
calls += 1;
return { count: 1 };
});

const first = state.count;
const second = state.count;
// calls = 1

state.count = 2;
const updated = state.count;
// updated = 2
3 changes: 3 additions & 0 deletions docs/fr/v1/api/common/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ Pause asynchrone pour attendre un certain temps.
### [memo](/fr/v1/api/common/memo)
Évalue une fonction une seule fois et réutilise le résultat (memoization lazy).

### [memoObject](/fr/v1/api/common/memoObject)
Mémoïse un objet exposé via `Proxy` et garde les clés alignées avec les écritures.

### [memoPromise](/fr/v1/api/common/memoPromise)
Mémoïsation paresseuse pour des fonctions retournant une valeur ou une promesse.

Expand Down
4 changes: 2 additions & 2 deletions docs/fr/v1/api/common/memo.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ prev:
text: "sleep"
link: "/fr/v1/api/common/sleep"
next:
text: "memoPromise"
link: "/fr/v1/api/common/memoPromise"
text: "memoObject"
link: "/fr/v1/api/common/memoObject"
---

# memo
Expand Down
49 changes: 49 additions & 0 deletions docs/fr/v1/api/common/memoObject.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
outline: [2, 3]
description: "La fonction memoObject() crée un proxy autour d'un objet mémorisé. Le getter n'est évalué qu'une fois, puis les lectures/écritures passent par la même référence."
prev:
text: "memo"
link: "/fr/v1/api/common/memo"
next:
text: "memoPromise"
link: "/fr/v1/api/common/memoPromise"
---

# memoObject

La fonction **`memoObject()`** crée un proxy autour d'un objet mémorisé. Le getter est évalué paresseusement au premier accès, puis toutes les lectures/écritures utilisent le même objet.

## Exemple interactif

<MonacoTSEditor
src="/examples/v1/api/common/memoObject/tryout.doc.ts"
majorVersion="v1"
height="355px"
/>

## Syntaxe

```typescript
function memoObject<
GenericOutput extends object
>(
getter: () => GenericOutput
): GenericOutput;
```

## Paramètres

- `getter` : Fonction appelée au premier accès pour produire l'objet proxifié.

## Valeur de retour

Un objet de type `GenericOutput` proxifié :
- les lectures (`obj.prop`) renvoient les valeurs de l'objet mémorisé ;
- les écritures (`obj.prop = value`) modifient l'objet mémorisé ;
- `Object.keys()` et l'opérateur `in` reflètent les clés après écriture.

## Voir aussi

- [`memo`](/fr/v1/api/common/memo) - Mémoïsation paresseuse synchrone
- [`memoPromise`](/fr/v1/api/common/memoPromise) - Mémoïsation paresseuse pour valeurs async
- [`override`](/fr/v1/api/common/override) - Surcharger méthodes et propriétés d'un objet
4 changes: 2 additions & 2 deletions docs/fr/v1/api/common/memoPromise.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
outline: [2, 3]
description: "La fonction memoPromise() évalue paresseusement une fonction qui retourne une valeur ou une promesse, puis mémorise le résultat résolu."
prev:
text: "memo"
link: "/fr/v1/api/common/memo"
text: "memoObject"
link: "/fr/v1/api/common/memoObject"
next:
text: "stringToMillisecond"
link: "/fr/v1/api/common/stringToMillisecond"
Expand Down
50 changes: 31 additions & 19 deletions docs/public/libs/v1/clean/entity/index.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,22 @@ var newType = require('../newType.cjs');
var property = require('./property.cjs');
var kind$1 = require('../../common/kind.cjs');
var pipe = require('../../common/pipe.cjs');
var map = require('../../array/map.cjs');
var entry = require('../../object/entry.cjs');
var base = require('../constraint/base.cjs');
var transform = require('../../dataParser/parsers/transform.cjs');
var entries = require('../../object/entries.cjs');
var forward = require('../../common/forward.cjs');
var errorKindNamespace = require('../../common/errorKindNamespace.cjs');
var index = require('../../dataParser/parsers/object/index.cjs');
var fromEntries = require('../../object/fromEntries.cjs');
var wrapValue = require('../../common/wrapValue.cjs');
var memo = require('../../common/memo.cjs');
var override = require('../../common/override.cjs');
var is = require('../../either/left/is.cjs');
var unwrap$1 = require('../../common/unwrap.cjs');
var create = require('../../either/left/create.cjs');
var create$1 = require('../../either/right/create.cjs');
var transform = require('../../dataParser/parsers/transform.cjs');
var index = require('../../dataParser/parsers/object/index.cjs');
var fromEntries = require('../../object/fromEntries.cjs');
var map = require('../../array/map.cjs');
var entry = require('../../object/entry.cjs');
var base = require('../constraint/base.cjs');
var wrapValue = require('../../common/wrapValue.cjs');
var entries = require('../../object/entries.cjs');
var forward = require('../../common/forward.cjs');

const entityKind = kind.createCleanKind("entity");
const entityHandlerKind = kind.createCleanKind("entity-handler");
Expand All @@ -39,8 +40,8 @@ function createEntity(name, getPropertiesDefinition) {
function theNew(properties) {
return entityKind.addTo(properties, name);
}
const propertiesDefinition = getPropertiesDefinition(property.entityPropertyDefinitionTools);
const mapDataParser = pipe.pipe(forward.forward(propertiesDefinition), entries.entries, map.map(([key, property$1]) => entry.entry(key, property.entityPropertyDefinitionToDataParser(property$1, (newTypeHandler) => {
const propertiesDefinition = memo.memo(() => getPropertiesDefinition(property.entityPropertyDefinitionTools));
const mapDataParser = memo.memo(() => pipe.pipe(forward.forward(propertiesDefinition.value), entries.entries, map.map(([key, property$1]) => entry.entry(key, property.entityPropertyDefinitionToDataParser(property$1, (newTypeHandler) => {
const allKind = {
...base.constrainedTypeKind.setTo({}, newTypeHandler.internal.constraintKindValue),
...newType.newTypeKind.setTo({}, newTypeHandler.name),
Expand All @@ -49,16 +50,16 @@ function createEntity(name, getPropertiesDefinition) {
...allKind,
[wrapValue.keyWrappedValue]: value,
}));
}))), fromEntries.fromEntries, index.object, (dataParser) => transform.transform(dataParser, (value) => entityKind.setTo(value, name)));
}))), fromEntries.fromEntries, index.object, (dataParser) => transform.transform(dataParser, (value) => entityKind.setTo(value, name))));
function map$1(rawProperties) {
const result = mapDataParser.parse(rawProperties);
const result = mapDataParser.value.parse(rawProperties);
if (is.isLeft(result)) {
return create.left("createEntityError", unwrap$1.unwrap(result));
}
return create$1.right("createEntity", unwrap$1.unwrap(result));
}
function mapOrThrow(rawProperties) {
const result = mapDataParser.parse(rawProperties);
const result = mapDataParser.value.parse(rawProperties);
if (is.isLeft(result)) {
throw new CreateEntityError(rawProperties, unwrap$1.unwrap(result));
}
Expand All @@ -67,9 +68,14 @@ function createEntity(name, getPropertiesDefinition) {
function is$1(input) {
return entityKind.has(input) && entityKind.getValue(input) === name;
}
function update(entity, newProperties) {
function update(...args) {
if (args.length === 1) {
const [newProperties] = args;
return (entity) => update(entity, newProperties);
}
const [entity, newProperties] = args;
const updatedEntity = {};
for (const key in propertiesDefinition) {
for (const key in propertiesDefinition.value) {
updatedEntity[key] = newProperties[key] !== undefined
? newProperties[key]
: entity[key];
Expand All @@ -78,10 +84,16 @@ function createEntity(name, getPropertiesDefinition) {
}
return pipe.pipe({
name,
propertiesDefinition,
mapDataParser,
get propertiesDefinition() {
return propertiesDefinition.value;
},
get mapDataParser() {
return mapDataParser.value;
},
internal: {
mapDataParser,
get mapDataParser() {
return mapDataParser.value;
},
},
new: theNew,
map: map$1,
Expand Down
1 change: 1 addition & 0 deletions docs/public/libs/v1/clean/entity/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ export interface EntityHandler<GenericName extends string = string, GenericPrope
* ```
*
*/
update<const GenericEntity extends Entity<GenericName>, const GenericProperties extends Partial<EntityProperties<GenericPropertiesDefinition>>>(properties: GenericProperties): (entity: GenericEntity) => EntityUpdate<GenericEntity, GenericProperties>;
update<const GenericEntity extends Entity<GenericName>, const GenericProperties extends Partial<EntityProperties<GenericPropertiesDefinition>>>(entity: GenericEntity, properties: GenericProperties): EntityUpdate<GenericEntity, GenericProperties>;
}
declare const CreateEntityError_base: new (params: {
Expand Down
Loading
Loading