@codecks/fetch 0.0.4 → 0.1.0

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.
package/dist/index.d.ts CHANGED
@@ -2755,7 +2755,7 @@ type Filter<T extends AnyDesc, TMap extends ModelMap$3> = SimpleFilter<T, TMap>
2755
2755
  //#region src/query-type.d.ts
2756
2756
  type ModelMap$2 = Record<string, AnyDesc>;
2757
2757
  interface ModelQuery<T extends AnyDesc, TMap extends ModelMap$2> {
2758
- fields?: (keyof T["fields"])[];
2758
+ fields?: (keyof T["fields"] & string)[];
2759
2759
  relations?: RelQuery<T, TMap>;
2760
2760
  }
2761
2761
  interface SimpleHasManyQuery<T extends AnyDesc, TMap extends ModelMap$2> extends ModelQuery<T, TMap> {
@@ -2873,7 +2873,7 @@ declare const _rootDesc: ModelDesc<"_root", {}, {
2873
2873
  }>;
2874
2874
  }, []>;
2875
2875
  //#endregion
2876
- //#region src/loader-utils.d.ts
2876
+ //#region src/loaders/loader-utils.d.ts
2877
2877
  type ModelMap$1 = typeof modelMap;
2878
2878
  type DataLoader = {
2879
2879
  fetchModel: <K extends keyof ModelMap$1, Id extends string, const Q extends ModelQuery<ModelMap$1[K], ModelMap$1>>(model: K, id: Id[], q: Q) => Promise<Record<Id, InferModelQuery<ModelMap$1[K], Q, ModelMap$1>>>;
@@ -2888,7 +2888,7 @@ type FetchOptions = {
2888
2888
  timeout?: number;
2889
2889
  };
2890
2890
  //#endregion
2891
- //#region src/simple-loader.d.ts
2891
+ //#region src/loaders/simple-loader.d.ts
2892
2892
  type SimpleLoaderOptions = FetchOptions;
2893
2893
  //#endregion
2894
2894
  //#region src/index.d.ts
package/dist/index.js CHANGED
@@ -2952,7 +2952,7 @@ const modelMap = {
2952
2952
  };
2953
2953
 
2954
2954
  //#endregion
2955
- //#region src/loader-utils.ts
2955
+ //#region src/loaders/loader-utils.ts
2956
2956
  const configuredFetch = async (opts, url, init = {}) => {
2957
2957
  const fetchImpl = opts.fetch || globalThis.fetch;
2958
2958
  const headers = new Headers(init.headers);
@@ -2965,6 +2965,10 @@ const configuredFetch = async (opts, url, init = {}) => {
2965
2965
  return fetchImpl(fullUrl, {
2966
2966
  ...init,
2967
2967
  headers
2968
+ }).then(async (r) => {
2969
+ const content = await r.json();
2970
+ if (r.status !== 200) throw new Error(`[${r.status}] ${JSON.stringify(content)}`);
2971
+ return content;
2968
2972
  });
2969
2973
  };
2970
2974
 
@@ -3031,7 +3035,16 @@ var ModelPool = class {
3031
3035
 
3032
3036
  //#endregion
3033
3037
  //#region src/query-helpers.ts
3038
+ const normalizeQuery = (q) => {
3039
+ return JSON.stringify(q);
3040
+ };
3034
3041
  const getRelKey = (r, k) => {
3042
+ const getSuffix = () => {
3043
+ if (r.type === "exists") return `exists:`;
3044
+ if (r.type === "count") return `count:`;
3045
+ return "";
3046
+ };
3047
+ const suffix = getSuffix();
3035
3048
  const isPlainKey = () => {
3036
3049
  if (r.type === "first") return false;
3037
3050
  if (r.filter && Object.keys(r.filter).length > 0) return false;
@@ -3040,7 +3053,7 @@ const getRelKey = (r, k) => {
3040
3053
  }
3041
3054
  return true;
3042
3055
  };
3043
- if (isPlainKey()) return k;
3056
+ if (isPlainKey()) return `${suffix}${k}`;
3044
3057
  const q = { ...r.filter };
3045
3058
  if (r.type === "first") {
3046
3059
  q.$first = true;
@@ -3051,41 +3064,53 @@ const getRelKey = (r, k) => {
3051
3064
  if (r.offset) q.$offset = r.offset;
3052
3065
  if (r.orderBy) q.$order = r.orderBy;
3053
3066
  }
3054
- return `${k}(${JSON.stringify(q)})`;
3067
+ return `${suffix}${k}(${normalizeQuery(q)})`;
3068
+ };
3069
+ const processRelations = (rels) => {
3070
+ const result = {};
3071
+ for (const [key, relq] of Object.entries(rels)) {
3072
+ const asArray = Array.isArray(relq) ? relq : [relq];
3073
+ for (const rel of asArray) {
3074
+ if (!rel) continue;
3075
+ result[getRelKey(rel, key)] = makeRelQuerySerializable(rel);
3076
+ }
3077
+ }
3078
+ return result;
3055
3079
  };
3056
- const serializeModel = (q, modelDesc) => {
3080
+ const makeModelQuerySerializable = (q) => {
3081
+ if (!q.relations) return q;
3082
+ return {
3083
+ ...q,
3084
+ relations: processRelations(q.relations)
3085
+ };
3086
+ };
3087
+ const makeRelQuerySerializable = (r) => {
3088
+ if (r.type === "exists" || r.type === "count") return { asField: true };
3089
+ return {
3090
+ asField: false,
3091
+ fields: r.fields,
3092
+ relations: r.relations ? processRelations(r.relations) : void 0
3093
+ };
3094
+ };
3095
+ const serializeModel = (q) => {
3057
3096
  const list = q.fields ? [...q.fields] : [];
3058
3097
  if (!q.relations) return list;
3059
3098
  const relObj = {};
3060
- Object.entries(q.relations).forEach(([k, _v]) => {
3061
- const rels = Array.isArray(_v) ? _v : [_v];
3062
- rels.forEach((r) => {
3063
- switch (r?.type) {
3064
- case "count": {
3065
- list.push(`count:${getRelKey(r, k)}`);
3066
- break;
3067
- }
3068
- case "exists": {
3069
- list.push(`exists:${getRelKey(r, k)}`);
3070
- break;
3071
- }
3072
- default:
3073
- relObj[getRelKey(r, k)] = serializeModel(r, modelDesc);
3074
- break;
3075
- }
3076
- });
3099
+ Object.entries(q.relations).forEach(([k, r]) => {
3100
+ if (r.asField) list.push(k);
3101
+ else relObj[k] = serializeModel(r);
3077
3102
  });
3078
3103
  if (Object.keys(relObj).length) list.push(relObj);
3079
3104
  return list;
3080
3105
  };
3081
- const serializeInstanceQuery = (q, instances, modelMap$1) => {
3106
+ const serializeInstanceQuery = (q, instances) => {
3082
3107
  return Object.fromEntries(instances.map((instance) => {
3083
3108
  const name = instance["~model"];
3084
3109
  const getKey = () => {
3085
3110
  if (name === "_root") return "_root";
3086
3111
  return `${name}(${instance["~key"]})`;
3087
3112
  };
3088
- return [getKey(), serializeModel(q, modelMap$1[name])];
3113
+ return [getKey(), serializeModel(q)];
3089
3114
  }));
3090
3115
  };
3091
3116
 
@@ -3124,12 +3149,9 @@ const reconcileInstanceQuery = (query, response, instanceModel, key, store) => {
3124
3149
  const relKey = getRelKey(relEntry, relName);
3125
3150
  const val = instance[relKey];
3126
3151
  switch (relEntry.type) {
3127
- case "count": {
3128
- result[asName] = instance[`count:${relKey}`];
3129
- break;
3130
- }
3152
+ case "count":
3131
3153
  case "exists": {
3132
- result[asName] = instance[`exists:${relKey}`];
3154
+ result[asName] = instance[relKey];
3133
3155
  break;
3134
3156
  }
3135
3157
  case "first":
@@ -3149,19 +3171,14 @@ const reconcileInstanceQuery = (query, response, instanceModel, key, store) => {
3149
3171
  };
3150
3172
 
3151
3173
  //#endregion
3152
- //#region src/simple-loader.ts
3174
+ //#region src/loaders/simple-loader.ts
3153
3175
  const createSimpleLoader = (opts = {}) => {
3154
3176
  const fetchWithQuery = async (query) => {
3155
- const response = await configuredFetch(opts, "", {
3177
+ return configuredFetch(opts, "", {
3156
3178
  method: "POST",
3157
3179
  headers: { "Content-Type": "application/json" },
3158
3180
  body: JSON.stringify({ query })
3159
- }).then(async (r) => {
3160
- const content = await r.json();
3161
- if (r.status !== 200) throw new Error(`[${r.status}] ${JSON.stringify(content)}`);
3162
- return content;
3163
3181
  });
3164
- return response;
3165
3182
  };
3166
3183
  return { fetchModel: async (model, ids, q) => {
3167
3184
  const modelDesc = modelMap[model];
@@ -3169,7 +3186,7 @@ const createSimpleLoader = (opts = {}) => {
3169
3186
  "~model": model,
3170
3187
  "~key": id$1
3171
3188
  }));
3172
- const response = await fetchWithQuery(serializeInstanceQuery(q, instances, modelMap));
3189
+ const response = await fetchWithQuery(serializeInstanceQuery(makeModelQuerySerializable(q), instances));
3173
3190
  const pool = new ModelPool(modelMap);
3174
3191
  pool.add(response);
3175
3192
  return Object.fromEntries(ids.map((id$1) => [id$1, reconcileInstanceQuery(q, response, modelDesc, id$1, pool)]));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codecks/fetch",
3
- "version": "0.0.4",
3
+ "version": "0.1.0",
4
4
  "description": "Quickly create deeply nested queries for the Codecks API with advanced TypeScript support",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -21,6 +21,10 @@
21
21
  "types": "./dist/index.d.ts",
22
22
  "exports": {
23
23
  ".": "./dist/index.js",
24
+ "./_exploration/store": "./dist/_exploration/store.js",
25
+ "./_exploration/loader": "./dist/_exploration/loader.js",
26
+ "./_exploration/api-requester": "./dist/_exploration/api-requester.js",
27
+ "./_exploration/react": "./dist/_exploration/create-hooks.js",
24
28
  "./package.json": "./package.json"
25
29
  },
26
30
  "publishConfig": {
@@ -41,11 +45,15 @@
41
45
  "devDependencies": {
42
46
  "@changesets/cli": "^2.29.7",
43
47
  "@types/node": "^22.15.17",
48
+ "@types/react": "^19.2.2",
44
49
  "msw": "^2.10.4",
45
50
  "prettier": "^3.6.2",
46
51
  "tsdown": "^0.11.9",
47
52
  "typescript": "^5.9.2",
48
53
  "vite-node": "^3.2.4",
49
54
  "vitest": "^3.1.3"
55
+ },
56
+ "peerDependencies": {
57
+ "react": "^19.0.0"
50
58
  }
51
59
  }