@entifix/react-integration 0.1.1 → 0.1.3

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.
Files changed (42) hide show
  1. package/README.md +4 -3
  2. package/dist/hooks/use-entity-form/use-entity-form.d.ts.map +1 -1
  3. package/dist/hooks/use-entity-form/use-entity-form.helpers.d.ts +11 -2
  4. package/dist/hooks/use-entity-form/use-entity-form.helpers.d.ts.map +1 -1
  5. package/dist/hooks/use-entity-form/use-entity-form.helpers.js +15 -14
  6. package/dist/hooks/use-entity-form/use-entity-form.helpers.js.map +1 -1
  7. package/dist/hooks/use-entity-form/use-entity-form.js +20 -8
  8. package/dist/hooks/use-entity-form/use-entity-form.js.map +1 -1
  9. package/dist/hooks/use-entity-form/use-entity-form.types.d.ts +4 -4
  10. package/dist/hooks/use-entity-form/use-entity-form.types.js.map +1 -1
  11. package/dist/hooks/use-entity-link-source/use-entity-link-source.d.ts +1 -1
  12. package/dist/hooks/use-entity-link-source/use-entity-link-source.js +1 -1
  13. package/dist/hooks/use-entity-link-source/use-entity-link-source.js.map +1 -1
  14. package/dist/hooks/use-wizard/use-wizard.types.d.ts +2 -2
  15. package/dist/hooks/use-wizard/use-wizard.types.js.map +1 -1
  16. package/dist/reactive/use-transaction-settlement.d.ts +1 -1
  17. package/dist/reactive/use-transaction-settlement.js.map +1 -1
  18. package/dist/url/entity-source.d.ts +9 -0
  19. package/dist/url/entity-source.d.ts.map +1 -0
  20. package/dist/url/entity-source.js +8 -0
  21. package/dist/url/entity-source.js.map +1 -0
  22. package/dist/url/url-filter.d.ts +40 -0
  23. package/dist/url/url-filter.d.ts.map +1 -0
  24. package/dist/url/url-filter.js +65 -0
  25. package/dist/url/url-filter.js.map +1 -0
  26. package/dist/url/url-query.d.ts +83 -0
  27. package/dist/url/url-query.d.ts.map +1 -0
  28. package/dist/url/url-query.js +122 -0
  29. package/dist/url/url-query.js.map +1 -0
  30. package/dist/url/url-state.d.ts +11 -0
  31. package/dist/url/url-state.d.ts.map +1 -0
  32. package/dist/url/url-state.js +40 -0
  33. package/dist/url/url-state.js.map +1 -0
  34. package/dist/url/use-entity-load.d.ts +29 -0
  35. package/dist/url/use-entity-load.d.ts.map +1 -0
  36. package/dist/url/use-entity-load.js +67 -0
  37. package/dist/url/use-entity-load.js.map +1 -0
  38. package/dist/url.d.ts +11 -0
  39. package/dist/url.d.ts.map +1 -0
  40. package/dist/url.js +11 -0
  41. package/dist/url.js.map +1 -0
  42. package/package.json +11 -8
@@ -0,0 +1,67 @@
1
+ import { ConfigurationRepositoryTag, EntityLoadRequestTag, EntityRepositoryTag, loadAllUCFactory } from '@entifix/business';
2
+ import { ConfigurationClientInMemory } from '@entifix/core';
3
+ import { Context, Effect } from 'effect';
4
+ import { useEffect, useState } from 'react';
5
+ const IDLE = {
6
+ status: 'idle'
7
+ };
8
+ /**
9
+ * Every record a request keeps, through the `loadAll` use case: a filter
10
+ * never pages. A source's repository reads no configuration here, but the
11
+ * port leaves `ConfigurationRepositoryTag` on every method's requirement
12
+ * channel, so an empty one discharges it.
13
+ */ async function loadEvery(repository, request) {
14
+ const context = Context.make(EntityRepositoryTag, repository).pipe(Context.add(ConfigurationRepositoryTag, new ConfigurationClientInMemory({})), Context.add(EntityLoadRequestTag, request));
15
+ const items = await Effect.runPromise(Effect.provide(loadAllUCFactory(), context));
16
+ return {
17
+ items,
18
+ total: items.length,
19
+ request
20
+ };
21
+ }
22
+ /**
23
+ * Every record a request selects, through the `loadAll` use case over a source.
24
+ *
25
+ * `null` asks for nothing and answers `idle`: before hydration, and while no
26
+ * filter is set, the page shows what the build rendered. An answer counts only
27
+ * for the request it was asked for, so a late answer to an older filter is
28
+ * never shown as the current one.
29
+ */ export function useEntityLoad(source, request) {
30
+ const [answer, setAnswer] = useState();
31
+ // Requests are rebuilt on every render; their content is what changes.
32
+ const key = request === null ? null : JSON.stringify(request);
33
+ useEffect(()=>{
34
+ if (request === null || key === null) return;
35
+ const settle = (load)=>setAnswer({
36
+ source,
37
+ key,
38
+ load
39
+ });
40
+ source().then((repository)=>loadEvery(repository, request)).then((page)=>settle({
41
+ status: 'done',
42
+ page
43
+ }), (error)=>settle({
44
+ status: 'failed',
45
+ error
46
+ }));
47
+ // `request` is read through `key`, its content: a new object with the
48
+ // same content is the same request.
49
+ // eslint-disable-next-line react-hooks/exhaustive-deps
50
+ }, [
51
+ source,
52
+ key
53
+ ]);
54
+ if (key === null) return IDLE;
55
+ if ((answer == null ? void 0 : answer.source) !== source) return {
56
+ status: 'pending'
57
+ };
58
+ if (answer.key === key) return answer.load;
59
+ return answer.load.status === 'done' ? {
60
+ status: 'pending',
61
+ previous: answer.load.page
62
+ } : {
63
+ status: 'pending'
64
+ };
65
+ }
66
+
67
+ //# sourceMappingURL=use-entity-load.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/url/use-entity-load.ts"],"sourcesContent":["import {\n ConfigurationRepositoryTag,\n EntityLoadRequestTag,\n type EntityRepository,\n EntityRepositoryTag,\n loadAllUCFactory,\n} from '@entifix/business';\nimport {\n ConfigurationClientInMemory,\n type Entity,\n type EntityLoadRequest,\n type EntityPage,\n} from '@entifix/core';\nimport { Context, Effect } from 'effect';\nimport { useEffect, useState } from 'react';\n\nimport type { EntitySource } from './entity-source.js';\n\nexport type EntityLoad<TEntity extends Entity> =\n | { readonly status: 'idle' }\n /**\n * Waiting for an answer. `previous` is the last answer from the same\n * source, so a filter being changed keeps showing what it showed.\n */\n | { readonly status: 'pending'; readonly previous?: EntityPage<TEntity> }\n | { readonly status: 'done'; readonly page: EntityPage<TEntity> }\n | { readonly status: 'failed'; readonly error: unknown };\n\nconst IDLE = { status: 'idle' } as const;\n\n/**\n * Every record a request keeps, through the `loadAll` use case: a filter\n * never pages. A source's repository reads no configuration here, but the\n * port leaves `ConfigurationRepositoryTag` on every method's requirement\n * channel, so an empty one discharges it.\n */\nasync function loadEvery<TEntity extends Entity>(\n repository: EntityRepository,\n request: EntityLoadRequest<TEntity>,\n): Promise<EntityPage<TEntity>> {\n const context = Context.make(EntityRepositoryTag, repository).pipe(\n Context.add(\n ConfigurationRepositoryTag,\n new ConfigurationClientInMemory({}),\n ),\n Context.add(EntityLoadRequestTag, request as unknown as EntityLoadRequest),\n );\n const items = await Effect.runPromise(\n Effect.provide(loadAllUCFactory<TEntity>(), context),\n );\n return { items, total: items.length, request };\n}\n\ninterface Answer<TEntity extends Entity> {\n readonly source: EntitySource;\n readonly key: string;\n readonly load: EntityLoad<TEntity>;\n}\n\n/**\n * Every record a request selects, through the `loadAll` use case over a source.\n *\n * `null` asks for nothing and answers `idle`: before hydration, and while no\n * filter is set, the page shows what the build rendered. An answer counts only\n * for the request it was asked for, so a late answer to an older filter is\n * never shown as the current one.\n */\nexport function useEntityLoad<TEntity extends Entity>(\n source: EntitySource,\n request: EntityLoadRequest<TEntity> | null,\n): EntityLoad<TEntity> {\n const [answer, setAnswer] = useState<Answer<TEntity>>();\n // Requests are rebuilt on every render; their content is what changes.\n const key = request === null ? null : JSON.stringify(request);\n\n useEffect(() => {\n if (request === null || key === null) return;\n const settle = (load: EntityLoad<TEntity>) =>\n setAnswer({ source, key, load });\n source()\n .then(repository => loadEvery<TEntity>(repository, request))\n .then(\n page => settle({ status: 'done', page }),\n (error: unknown) => settle({ status: 'failed', error }),\n );\n // `request` is read through `key`, its content: a new object with the\n // same content is the same request.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [source, key]);\n\n if (key === null) return IDLE;\n if (answer?.source !== source) return { status: 'pending' };\n if (answer.key === key) return answer.load;\n return answer.load.status === 'done'\n ? { status: 'pending', previous: answer.load.page }\n : { status: 'pending' };\n}\n"],"names":["ConfigurationRepositoryTag","EntityLoadRequestTag","EntityRepositoryTag","loadAllUCFactory","ConfigurationClientInMemory","Context","Effect","useEffect","useState","IDLE","status","loadEvery","repository","request","context","make","pipe","add","items","runPromise","provide","total","length","useEntityLoad","source","answer","setAnswer","key","JSON","stringify","settle","load","then","page","error","previous"],"mappings":"AAAA,SACEA,0BAA0B,EAC1BC,oBAAoB,EAEpBC,mBAAmB,EACnBC,gBAAgB,QACX,oBAAoB;AAC3B,SACEC,2BAA2B,QAItB,gBAAgB;AACvB,SAASC,OAAO,EAAEC,MAAM,QAAQ,SAAS;AACzC,SAASC,SAAS,EAAEC,QAAQ,QAAQ,QAAQ;AAc5C,MAAMC,OAAO;IAAEC,QAAQ;AAAO;AAE9B;;;;;CAKC,GACD,eAAeC,UACbC,UAA4B,EAC5BC,OAAmC;IAEnC,MAAMC,UAAUT,QAAQU,IAAI,CAACb,qBAAqBU,YAAYI,IAAI,CAChEX,QAAQY,GAAG,CACTjB,4BACA,IAAII,4BAA4B,CAAC,KAEnCC,QAAQY,GAAG,CAAChB,sBAAsBY;IAEpC,MAAMK,QAAQ,MAAMZ,OAAOa,UAAU,CACnCb,OAAOc,OAAO,CAACjB,oBAA6BW;IAE9C,OAAO;QAAEI;QAAOG,OAAOH,MAAMI,MAAM;QAAET;IAAQ;AAC/C;AAQA;;;;;;;CAOC,GACD,OAAO,SAASU,cACdC,MAAoB,EACpBX,OAA0C;IAE1C,MAAM,CAACY,QAAQC,UAAU,GAAGlB;IAC5B,uEAAuE;IACvE,MAAMmB,MAAMd,YAAY,OAAO,OAAOe,KAAKC,SAAS,CAAChB;IAErDN,UAAU;QACR,IAAIM,YAAY,QAAQc,QAAQ,MAAM;QACtC,MAAMG,SAAS,CAACC,OACdL,UAAU;gBAAEF;gBAAQG;gBAAKI;YAAK;QAChCP,SACGQ,IAAI,CAACpB,CAAAA,aAAcD,UAAmBC,YAAYC,UAClDmB,IAAI,CACHC,CAAAA,OAAQH,OAAO;gBAAEpB,QAAQ;gBAAQuB;YAAK,IACtC,CAACC,QAAmBJ,OAAO;gBAAEpB,QAAQ;gBAAUwB;YAAM;IAEzD,sEAAsE;IACtE,oCAAoC;IACpC,uDAAuD;IACzD,GAAG;QAACV;QAAQG;KAAI;IAEhB,IAAIA,QAAQ,MAAM,OAAOlB;IACzB,IAAIgB,CAAAA,0BAAAA,OAAQD,MAAM,MAAKA,QAAQ,OAAO;QAAEd,QAAQ;IAAU;IAC1D,IAAIe,OAAOE,GAAG,KAAKA,KAAK,OAAOF,OAAOM,IAAI;IAC1C,OAAON,OAAOM,IAAI,CAACrB,MAAM,KAAK,SAC1B;QAAEA,QAAQ;QAAWyB,UAAUV,OAAOM,IAAI,CAACE,IAAI;IAAC,IAChD;QAAEvB,QAAQ;IAAU;AAC1B"}
package/dist/url.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ /**
2
+ * A filter kept in the URL and answered by the `loadAll` use case, apart from
3
+ * the main entry: a page that only filters a list must not pull TanStack
4
+ * Query and Form, which every hook behind `.` builds on.
5
+ */
6
+ export * from './url/entity-source.js';
7
+ export * from './url/url-filter.js';
8
+ export * from './url/url-query.js';
9
+ export * from './url/url-state.js';
10
+ export * from './url/use-entity-load.js';
11
+ //# sourceMappingURL=url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../src/url.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC"}
package/dist/url.js ADDED
@@ -0,0 +1,11 @@
1
+ /**
2
+ * A filter kept in the URL and answered by the `loadAll` use case, apart from
3
+ * the main entry: a page that only filters a list must not pull TanStack
4
+ * Query and Form, which every hook behind `.` builds on.
5
+ */ export * from './url/entity-source.js';
6
+ export * from './url/url-filter.js';
7
+ export * from './url/url-query.js';
8
+ export * from './url/url-state.js';
9
+ export * from './url/use-entity-load.js';
10
+
11
+ //# sourceMappingURL=url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/url.ts"],"sourcesContent":["/**\n * A filter kept in the URL and answered by the `loadAll` use case, apart from\n * the main entry: a page that only filters a list must not pull TanStack\n * Query and Form, which every hook behind `.` builds on.\n */\nexport * from './url/entity-source.js';\nexport * from './url/url-filter.js';\nexport * from './url/url-query.js';\nexport * from './url/url-state.js';\nexport * from './url/use-entity-load.js';\n"],"names":[],"mappings":"AAAA;;;;CAIC,GACD,cAAc,yBAAyB;AACvC,cAAc,sBAAsB;AACpC,cAAc,qBAAqB;AACnC,cAAc,qBAAqB;AACnC,cAAc,2BAA2B"}
package/package.json CHANGED
@@ -2,9 +2,6 @@
2
2
  "name": "@entifix/react-integration",
3
3
  "nx": {
4
4
  "tags": [
5
- "layer:entifix",
6
- "scope:shared",
7
- "entifix:react",
8
5
  "tier:3"
9
6
  ],
10
7
  "sourceRoot": "packages/react/integration/src",
@@ -24,7 +21,7 @@
24
21
  }
25
22
  }
26
23
  },
27
- "version": "0.1.1",
24
+ "version": "0.1.3",
28
25
  "description": "React hooks that bind entities to data: TanStack Query and Form over the entity adapters, drafts, mutations and live invalidation.",
29
26
  "license": "MIT",
30
27
  "repository": {
@@ -46,6 +43,12 @@
46
43
  "types": "./dist/index.d.ts",
47
44
  "import": "./dist/index.js",
48
45
  "default": "./dist/index.js"
46
+ },
47
+ "./url": {
48
+ "@entifix/source": "./src/url.ts",
49
+ "types": "./dist/url.d.ts",
50
+ "import": "./dist/url.js",
51
+ "default": "./dist/url.js"
49
52
  }
50
53
  },
51
54
  "files": [
@@ -54,16 +57,16 @@
54
57
  "LICENSE"
55
58
  ],
56
59
  "dependencies": {
57
- "@entifix/transactions": "0.1.1",
58
- "@entifix/business": "0.1.1",
59
- "@entifix/core": "0.1.1"
60
+ "@entifix/transactions": "0.1.3",
61
+ "@entifix/business": "0.1.3",
62
+ "@entifix/core": "0.1.3"
60
63
  },
61
64
  "devDependencies": {
62
65
  "@tanstack/react-form": "1.33.5",
63
66
  "@tanstack/react-query": "^5.101.4",
64
67
  "effect": "3.22.1",
65
68
  "react": "19.2.8",
66
- "@entifix/testing-unit": "0.1.1"
69
+ "@entifix/testing-unit": "0.1.3"
67
70
  },
68
71
  "peerDependencies": {
69
72
  "@tanstack/react-form": ">=1.33 <2",