@codecks/fetch 0.1.7 → 0.1.8

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.
@@ -108,11 +108,23 @@ var ApiRequester = class {
108
108
  key: "",
109
109
  partialInstance: instances
110
110
  });
111
- else for (const [id, data] of Object.entries(instances)) results.push({
112
- model: modelName,
113
- key: id,
114
- partialInstance: data
115
- });
111
+ else for (const [id, data] of Object.entries(instances)) {
112
+ if (data == null) {
113
+ const requested = dataByModel.get(modelName)?.get(id);
114
+ if (!requested) continue;
115
+ results.push({
116
+ model: modelName,
117
+ key: id,
118
+ partialInstance: Object.fromEntries([...requested.fields, ...requested.relations.keys()].map((key) => [key, null]))
119
+ });
120
+ continue;
121
+ }
122
+ results.push({
123
+ model: modelName,
124
+ key: id,
125
+ partialInstance: data
126
+ });
127
+ }
116
128
  return results;
117
129
  }
118
130
  };
@@ -118,6 +118,9 @@ var Store = class {
118
118
  data[`~${fieldName}`] = cachedValue.value.map((v) => `${v}`);
119
119
  data[fieldName] = relationResults.map((result) => result.data);
120
120
  if (relationResults.some((result) => !result.allPresent)) allPresent = false;
121
+ } else if (cachedValue.value == null) {
122
+ data[`~${fieldName}`] = null;
123
+ data[fieldName] = null;
121
124
  } else {
122
125
  const relationResult = this.checkQueryRecursive(relatedModelDesc, relatedModel, `${cachedValue.value}`, relQuery, missingRequests, acceptDirty);
123
126
  data[`~${fieldName}`] = cachedValue.value != null ? `${cachedValue.value}` : null;
package/dist/index.js CHANGED
@@ -41,6 +41,7 @@ var ModelPool = class {
41
41
  Object.entries(data).forEach(([modelName, payload]) => {
42
42
  if (modelName === _rootDesc.name) this.addModelInstance(modelName, ROOT_ID, payload);
43
43
  else Object.entries(payload).forEach(([id, payload$1]) => {
44
+ if (payload$1 == null) return;
44
45
  this.addModelInstance(modelName, id, payload$1);
45
46
  });
46
47
  });
@@ -53,10 +54,16 @@ var ModelPool = class {
53
54
 
54
55
  //#endregion
55
56
  //#region src/reconcile-query.ts
57
+ /**
58
+ * The API names an id but answers `null` for it when the token may not read that
59
+ * record. Such an id never enters the pool, and the caller can do nothing about it —
60
+ * unlike an id the response never mentioned at all, which points at a bug worth a warning.
61
+ */
62
+ const isWithheldByApi = (response, model, key) => response[model]?.[key] === null;
56
63
  const reconcileInstanceQuery = (query, response, instanceModel, key, store) => {
57
64
  const instance = store.get(instanceModel.name, key);
58
65
  if (!instance) {
59
- console.warn(`no instance found in pool: [${instanceModel.name}, ${key}]`);
66
+ if (!isWithheldByApi(response, instanceModel.name, key)) console.warn(`no instance found in pool: [${instanceModel.name}, ${key}]`);
60
67
  return null;
61
68
  }
62
69
  const result = instanceModel.name === "_root" ? {} : {
@@ -80,7 +87,7 @@ const reconcileInstanceQuery = (query, response, instanceModel, key, store) => {
80
87
  break;
81
88
  case "hasOne":
82
89
  result[`~${relName}`] = instance[relName] != null ? `${instance[relName]}` : null;
83
- result[relName] = reconcileInstanceQuery(relEntry, response, relModel, `${instance[relName]}`, store);
90
+ result[relName] = instance[relName] != null ? reconcileInstanceQuery(relEntry, response, relModel, `${instance[relName]}`, store) : null;
84
91
  break;
85
92
  case "hasMany":
86
93
  const asName = relEntry.as ?? relName;
@@ -94,12 +101,20 @@ const reconcileInstanceQuery = (query, response, instanceModel, key, store) => {
94
101
  }
95
102
  case "first":
96
103
  result[`~${asName}`] = val != null ? `${val}` : null;
97
- result[asName] = reconcileInstanceQuery(relEntry, response, relModel, `${val}`, store);
104
+ result[asName] = val != null ? reconcileInstanceQuery(relEntry, response, relModel, `${val}`, store) : null;
98
105
  break;
99
106
  default: {
100
107
  const ids = val ?? [];
101
- result[`~${asName}`] = ids.map((v) => `${v}`);
102
- result[asName] = ids.map((id) => reconcileInstanceQuery(relEntry, response, relModel, `${id}`, store));
108
+ const members = [];
109
+ for (const id of ids) {
110
+ const instance$1 = reconcileInstanceQuery(relEntry, response, relModel, `${id}`, store);
111
+ if (instance$1 != null) members.push({
112
+ key: `${id}`,
113
+ instance: instance$1
114
+ });
115
+ }
116
+ result[`~${asName}`] = members.map((m) => m.key);
117
+ result[asName] = members.map((m) => m.instance);
103
118
  }
104
119
  }
105
120
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codecks/fetch",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "Quickly create deeply nested queries for the Codecks API with advanced TypeScript support",
5
5
  "type": "module",
6
6
  "license": "MIT",