@codecks/fetch 0.1.3 → 0.1.5

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.
@@ -1,7 +1,7 @@
1
1
  import "../query-type-Dx5ZCv5N.js";
2
2
  import "../index-DUBsesYl.js";
3
3
  import { FetchOptions } from "../loader-utils-Du-CTKH-.js";
4
- import { BaseRequester, MissingDataRequest } from "../loader-types-CMF96Ae1.js";
4
+ import { BaseRequester, MissingDataRequest } from "../loader-types-Dp0CSVTf.js";
5
5
 
6
6
  //#region src/_exploration/api-requester.d.ts
7
7
  declare class ApiRequester implements BaseRequester {
@@ -1,8 +1,8 @@
1
1
  import { InferModelQuery, InferRelQuery, ModelDesc, ModelQuery, RelQuery, RelationEntry, TypedField } from "../query-type-Dx5ZCv5N.js";
2
2
  import { AccountId, AccountOnboardingStepId, ActiveTimeTrackerId, ActivityId, AffiliateCodeId, AppId, AppInstallationId, AttachmentId, CardId, CardPresetId, CardSubscriptionId, CardUpvoteId, DeckId, DeckSubscriptionId, DiscordGuildId, DiscordMemberId, DiscordProjectNotificationId, DiscordSlashCommandId, FileId, IntegrationId, InvoiceId, MilestoneId, PinnedMilestoneId, ProjectId, ProjectSelectionId, ProjectTagId, QueueEntryId, QueueSelectionId, ReleaseId, ResolvableEntryId, ResolvableEntryReactionId, ResolvableId, SavedSearchId, SprintConfigId, SprintId, TimeTrackingSegmentId, UserEmailId, UserId, UserInvitationId, UserInviteCodeId, UserReportEmailId, UserReportSettingId, UserReportTokenId, UserTagId, VisionBoardId, VisionBoardQueryId, WizardId, WorkflowItemId } from "../index-DUBsesYl.js";
3
- import "../loader-types-CMF96Ae1.js";
3
+ import "../loader-types-Dp0CSVTf.js";
4
4
  import { _rootDesc$1 as _rootDesc } from "../_root-D1Faf8cg.js";
5
- import { Store } from "../store-C_DXGjif.js";
5
+ import { Store } from "../store-B6JWZnAO.js";
6
6
 
7
7
  //#region src/_exploration/create-hooks.d.ts
8
8
  declare const createHooks: (store: Store) => {
@@ -2,28 +2,32 @@ import { queryToKey } from "../query-helpers-DsMMOtSO.js";
2
2
  import { use, useSyncExternalStore } from "react";
3
3
 
4
4
  //#region src/_exploration/user-query-manager.ts
5
- const diffResults = (prevResult, prevParts, nextResult) => {
6
- const nextParts = [];
5
+ const diffResults = (prevTrackedData, nextStorePayload) => {
6
+ const nextPartKeys = nextStorePayload.partKeys;
7
+ const prevSet = new Set(prevTrackedData.partKeys);
8
+ const nextSet = new Set(nextPartKeys);
9
+ const added = nextPartKeys.filter((key) => !prevSet.has(key));
10
+ const removed = prevTrackedData.partKeys.filter((key) => !nextSet.has(key));
7
11
  return {
8
- added: nextParts,
9
- removed: prevParts,
10
- reconciledResult: {
11
- parts: nextParts,
12
- data: nextResult
12
+ added,
13
+ removed,
14
+ nextTrackedData: {
15
+ partKeys: nextPartKeys,
16
+ value: nextStorePayload.value
13
17
  }
14
18
  };
15
19
  };
16
20
  const createStoreQuery = (opts) => {
17
21
  const { onDispose, updateDataListener, store, q, ids, model } = opts;
18
22
  const queryListeners = new Set();
19
- let lastData = {
20
- parts: [],
21
- data: null
23
+ let trackedData = {
24
+ partKeys: [],
25
+ value: null
22
26
  };
23
- const reconcileNextResult = (nextData) => {
24
- const { added, removed, reconciledResult } = diffResults(lastData.data, lastData.parts, nextData);
25
- if (!added.length && !removed.length) {
26
- lastData = reconciledResult;
27
+ const reconcileNextResult = (storePayload) => {
28
+ const { added, removed, nextTrackedData } = diffResults(trackedData, storePayload);
29
+ if (added.length || removed.length) {
30
+ trackedData = nextTrackedData;
27
31
  updateDataListener({
28
32
  added,
29
33
  removed
@@ -34,13 +38,26 @@ const createStoreQuery = (opts) => {
34
38
  const notify = () => {
35
39
  loadData();
36
40
  };
41
+ let userQueryResult;
37
42
  const loadData = () => {
38
- const res = store.loadData(model, ids, q);
39
- if (res.state === "pending") res.promise.then(reconcileNextResult);
40
- else reconcileNextResult(res.value);
41
- return res;
43
+ const storeResult = store.loadData(model, ids, q);
44
+ if (storeResult.state === "pending") userQueryResult = {
45
+ state: "pending",
46
+ promise: storeResult.promise.then((storePayload) => {
47
+ reconcileNextResult(storePayload);
48
+ return storePayload.value;
49
+ })
50
+ };
51
+ else {
52
+ const storePayload = storeResult.payload;
53
+ reconcileNextResult(storePayload);
54
+ userQueryResult = {
55
+ state: "resolved",
56
+ value: storePayload.value
57
+ };
58
+ }
42
59
  };
43
- let data = loadData();
60
+ loadData();
44
61
  const subscribe = (listener) => {
45
62
  queryListeners.add(listener);
46
63
  return () => {
@@ -48,12 +65,12 @@ const createStoreQuery = (opts) => {
48
65
  if (queryListeners.size === 0) onDispose();
49
66
  updateDataListener({
50
67
  added: [],
51
- removed: lastData.parts
68
+ removed: trackedData.partKeys
52
69
  }, notify);
53
70
  };
54
71
  };
55
72
  const get = () => {
56
- return data;
73
+ return userQueryResult;
57
74
  };
58
75
  return {
59
76
  subscribe,
@@ -122,10 +139,12 @@ const createHooks = (store) => {
122
139
  return val.value;
123
140
  };
124
141
  const useFetch = (model, id, q) => {
125
- return useQueryManager(model, [id], q);
142
+ const res = useQueryManager(model, [id], q);
143
+ return res[id];
126
144
  };
127
145
  const useFetchFromRoot = (q) => {
128
- return useQueryManager("_root", [""], { relations: q });
146
+ const res = useQueryManager("_root", [""], { relations: q });
147
+ return res[""];
129
148
  };
130
149
  return {
131
150
  useFetch,
@@ -1,5 +1,5 @@
1
1
  import "../query-type-Dx5ZCv5N.js";
2
- import { BaseLoader, BaseRequester, MissingDataRequest, OnLoadedFn } from "../loader-types-CMF96Ae1.js";
2
+ import { BaseLoader, BaseRequester, MissingDataRequest, OnLoadedFn } from "../loader-types-Dp0CSVTf.js";
3
3
 
4
4
  //#region src/_exploration/loader.d.ts
5
5
  type DataRequestWithKey = {
@@ -1,5 +1,5 @@
1
1
  import "../query-type-Dx5ZCv5N.js";
2
2
  import "../index-DUBsesYl.js";
3
- import "../loader-types-CMF96Ae1.js";
4
- import { Store } from "../store-C_DXGjif.js";
3
+ import "../loader-types-Dp0CSVTf.js";
4
+ import { Store } from "../store-B6JWZnAO.js";
5
5
  export { Store };
@@ -71,14 +71,15 @@ var Store = class {
71
71
  if (missingRequests.length > 0) this.loader.loadBatch(missingRequests);
72
72
  return {
73
73
  state: "resolved",
74
- value: {
74
+ payload: {
75
75
  value: resultObj,
76
76
  partKeys: allPartKeys
77
77
  }
78
78
  };
79
79
  }
80
80
  const promise = this.loader.loadBatch(missingRequests).then(() => {
81
- return this.loadData(model, ids, q, acceptDirty, iteration + 1);
81
+ const res = this.loadData(model, ids, q, acceptDirty, iteration + 1);
82
+ return res.state === "pending" ? res.promise : res.payload;
82
83
  });
83
84
  return {
84
85
  state: "pending",
@@ -97,7 +98,10 @@ var Store = class {
97
98
  * Accumulates missing requests in the missingRequests array
98
99
  */
99
100
  checkQueryRecursive(desc, model, id, query, missingRequests, acceptDirty) {
100
- const data = {};
101
+ const data = model === "_root" ? {} : {
102
+ "~model": model,
103
+ "~key": id
104
+ };
101
105
  const partKeys = [];
102
106
  let allPresent = true;
103
107
  if (query.fields) for (const field of query.fields) {
@@ -135,13 +139,18 @@ var Store = class {
135
139
  if (acceptsData) {
136
140
  if (!relatedModelDesc) throw new Error(`Model ${relatedModel} not found`);
137
141
  const fieldName = relQuery.as || relationName;
138
- if (Array.isArray(cachedValue.value)) {
139
- const relationResults = cachedValue.value.map((key) => this.checkQueryRecursive(relatedModelDesc, relatedModel, key, relQuery, missingRequests, acceptDirty));
142
+ if (relQuery.type === "count" || relQuery.type === "exists") {
143
+ data[fieldName] = cachedValue.value;
144
+ partKeys.push(...cachedValue.partKeys);
145
+ } else if (Array.isArray(cachedValue.value)) {
146
+ const relationResults = cachedValue.value.map((key) => this.checkQueryRecursive(relatedModelDesc, relatedModel, `${key}`, relQuery, missingRequests, acceptDirty));
147
+ data[`~${fieldName}`] = cachedValue.value.map((v) => `${v}`);
140
148
  data[fieldName] = relationResults.map((result) => result.data);
141
149
  partKeys.push(...relationResults.flatMap((result) => result.partKeys));
142
150
  if (relationResults.some((result) => !result.allPresent)) allPresent = false;
143
151
  } else {
144
- const relationResult = this.checkQueryRecursive(relatedModelDesc, relatedModel, cachedValue.value, relQuery, missingRequests, acceptDirty);
152
+ const relationResult = this.checkQueryRecursive(relatedModelDesc, relatedModel, `${cachedValue.value}`, relQuery, missingRequests, acceptDirty);
153
+ data[`~${fieldName}`] = cachedValue.value != null ? `${cachedValue.value}` : null;
145
154
  data[fieldName] = relationResult.data;
146
155
  partKeys.push(...relationResult.partKeys);
147
156
  if (!relationResult.allPresent) allPresent = false;
package/dist/index.js CHANGED
@@ -75,10 +75,11 @@ const reconcileInstanceQuery = (query, response, instanceModel, key, store) => {
75
75
  switch (opts.type) {
76
76
  case "belongsTo":
77
77
  result[opts.fk] = instance[relName];
78
+ result[`~${relName}`] = instance[relName] != null ? `${instance[relName]}` : null;
78
79
  result[relName] = opts.fk ? reconcileInstanceQuery(relEntry, response, relModel, `${instance[relName]}`, store) : null;
79
80
  break;
80
81
  case "hasOne":
81
- result[`~${relName}`] = instance[relName];
82
+ result[`~${relName}`] = instance[relName] != null ? `${instance[relName]}` : null;
82
83
  result[relName] = reconcileInstanceQuery(relEntry, response, relModel, `${instance[relName]}`, store);
83
84
  break;
84
85
  case "hasMany":
@@ -92,11 +93,11 @@ const reconcileInstanceQuery = (query, response, instanceModel, key, store) => {
92
93
  break;
93
94
  }
94
95
  case "first":
95
- result[`~${asName}`] = val;
96
+ result[`~${asName}`] = val != null ? `${val}` : null;
96
97
  result[asName] = reconcileInstanceQuery(relEntry, response, relModel, `${val}`, store);
97
98
  break;
98
99
  default: {
99
- result[`~${asName}`] = val;
100
+ result[`~${asName}`] = val.map((v) => `${v}`);
100
101
  result[asName] = val.map((id) => reconcileInstanceQuery(relEntry, response, relModel, `${id}`, store));
101
102
  }
102
103
  }
@@ -12,10 +12,10 @@ type LoaderPayload = {
12
12
  };
13
13
  type LoaderResult = {
14
14
  state: "resolved";
15
- value: LoaderPayload;
15
+ payload: LoaderPayload;
16
16
  } | {
17
17
  state: "pending";
18
- promise: Promise<LoaderResult>;
18
+ promise: Promise<LoaderPayload>;
19
19
  };
20
20
  type MissingDataRequest = {
21
21
  type: "field";
@@ -1,6 +1,6 @@
1
1
  import { ModelDesc, ModelQuery, RelationEntry, TypedField } from "./query-type-Dx5ZCv5N.js";
2
2
  import { AccountId, AccountOnboardingStepId, ActiveTimeTrackerId, ActivityId, AffiliateCodeId, AppId, AppInstallationId, AttachmentId, CardId, CardPresetId, CardSubscriptionId, CardUpvoteId, DeckId, DeckSubscriptionId, DiscordGuildId, DiscordMemberId, DiscordProjectNotificationId, DiscordSlashCommandId, FileId, IntegrationId, InvoiceId, MilestoneId, PinnedMilestoneId, ProjectId, ProjectSelectionId, ProjectTagId, QueueEntryId, QueueSelectionId, ReleaseId, ResolvableEntryId, ResolvableEntryReactionId, ResolvableId, SavedSearchId, SprintConfigId, SprintId, TimeTrackingSegmentId, UserEmailId, UserId, UserInvitationId, UserInviteCodeId, UserReportEmailId, UserReportSettingId, UserReportTokenId, UserTagId, VisionBoardId, VisionBoardQueryId, WizardId, WorkflowItemId, modelMap$1 as modelMap } from "./index-DUBsesYl.js";
3
- import { BaseLoader, LoaderResult } from "./loader-types-CMF96Ae1.js";
3
+ import { BaseLoader, LoaderResult } from "./loader-types-Dp0CSVTf.js";
4
4
 
5
5
  //#region src/_exploration/immediate-cache.d.ts
6
6
  type FieldMeta = {
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@codecks/fetch",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Quickly create deeply nested queries for the Codecks API with advanced TypeScript support",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
- "homepage": "https://github.com/codecks-io/cdx-fetch#readme",
7
+ "homepage": "https://github.com/codecks-io/fetch#readme",
8
8
  "bugs": {
9
- "url": "https://github.com/codecks-io/cdx-fetch/issues"
9
+ "url": "https://github.com/codecks-io/fetch/issues"
10
10
  },
11
11
  "repository": {
12
12
  "type": "git",
13
- "url": "git+https://github.com/codecks-io/cdx-fetch.git"
13
+ "url": "git+https://github.com/codecks-io/fetch.git"
14
14
  },
15
15
  "author": "Daniel Berndt <daniel@codecks.io>",
16
16
  "files": [
@@ -44,8 +44,13 @@
44
44
  },
45
45
  "devDependencies": {
46
46
  "@changesets/cli": "^2.29.7",
47
+ "@testing-library/dom": "^10.4.1",
48
+ "@testing-library/jest-dom": "^6.9.1",
49
+ "@testing-library/react": "^16.3.0",
50
+ "@testing-library/user-event": "^14.6.1",
47
51
  "@types/node": "^22.15.17",
48
52
  "@types/react": "^19.2.2",
53
+ "happy-dom": "^20.0.10",
49
54
  "msw": "^2.10.4",
50
55
  "prettier": "^3.6.2",
51
56
  "tsdown": "^0.11.9",