svelte-ag 1.2.5 → 1.2.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelte-ag",
3
- "version": "1.2.5",
3
+ "version": "1.2.7",
4
4
  "description": "Useful svelte components",
5
5
  "bugs": "https://github.com/ageorgeh/svelte-ag/issues",
6
6
  "author": "Alexander Hornung",
@@ -53,7 +53,7 @@
53
53
  "bits-ui": "^2.18.1",
54
54
  "clsx": "^2.1.1",
55
55
  "dequal": "^2.0.3",
56
- "devalue": "^5.8.0",
56
+ "devalue": "^5.8.1",
57
57
  "embla-carousel-svelte": "8.6.0",
58
58
  "es-module-lexer": "^2.1.0",
59
59
  "formsnap": "2.0.1",
@@ -61,56 +61,56 @@
61
61
  "runed": "0.37.1",
62
62
  "svelte-toolbelt": "^0.10.6",
63
63
  "sveltekit-superforms": "2.30.1",
64
- "tailwind-merge": "^3.5.0",
64
+ "tailwind-merge": "^3.6.0",
65
65
  "tailwind-variants": "^3.2.2",
66
- "ts-ag": "^1.2.3",
66
+ "ts-ag": "^1.2.7",
67
67
  "tsc-alias": "^1.8.17",
68
- "valibot": "^1.4.0"
68
+ "valibot": "^1.4.1"
69
69
  },
70
70
  "devDependencies": {
71
- "@actions/languageserver": "^0.3.55",
71
+ "@actions/languageserver": "^0.3.57",
72
72
  "@eslint/js": "^10.0.1",
73
- "@iconify/json": "^2.2.470",
73
+ "@iconify/json": "^2.2.483",
74
74
  "@iconify/tailwind4": "^1.2.3",
75
75
  "@iconify/types": "^2.0.0",
76
- "@internationalized/date": "^3.12.1",
77
- "@lucide/svelte": "^1.14.0",
78
- "@playwright/test": "1.59.1",
76
+ "@internationalized/date": "^3.12.2",
77
+ "@lucide/svelte": "^1.17.0",
78
+ "@playwright/test": "1.60.0",
79
79
  "@rollup/plugin-typescript": "^12.3.0",
80
- "@sveltejs/kit": "^2.59.1",
81
- "@sveltejs/package": "^2.5.7",
82
- "@sveltejs/vite-plugin-svelte": "^7.1.1",
80
+ "@sveltejs/kit": "^2.63.0",
81
+ "@sveltejs/package": "^2.5.8",
82
+ "@sveltejs/vite-plugin-svelte": "^7.1.2",
83
83
  "@tailwindcss/typography": "^0.5.19",
84
- "@tailwindcss/vite": "^4.2.4",
84
+ "@tailwindcss/vite": "^4.3.0",
85
85
  "@testing-library/svelte": "^5.3.1",
86
- "@types/node": "^24.12.2",
87
- "@typescript/native-preview": "7.0.0-dev.20260506.1",
88
- "eslint": "^10.3.0",
86
+ "@types/node": "^24.13.0",
87
+ "@typescript/native-preview": "7.0.0-dev.20260604.1",
88
+ "eslint": "^10.4.1",
89
89
  "eslint-plugin-better-tailwindcss": "^4.5.0",
90
- "eslint-plugin-svelte": "^3.17.1",
90
+ "eslint-plugin-svelte": "^3.19.0",
91
91
  "globals": "^17.6.0",
92
- "happy-dom": "^20.9.0",
92
+ "happy-dom": "^20.10.1",
93
93
  "husky": "^9.1.7",
94
- "lint-staged": "^17.0.2",
95
- "oxfmt": "^0.51.0",
96
- "rolldown": "1.0.0-rc.18",
97
- "rolldown-plugin-dts": "^0.24.1",
94
+ "lint-staged": "^17.0.7",
95
+ "oxfmt": "^0.53.0",
96
+ "rolldown": "1.1.0",
97
+ "rolldown-plugin-dts": "^0.25.2",
98
98
  "rollup-plugin-svelte": "^7.2.3",
99
99
  "semantic-release": "^25.0.3",
100
- "svelte": "^5.55.5",
101
- "svelte-check": "^4.4.8",
102
- "svelte-preprocess": "^6.0.3",
103
- "svelte2tsx": "^0.7.55",
104
- "tailwindcss": "4.2.4",
105
- "tsdown": "^0.21.10",
106
- "tsx": "^4.21.0",
100
+ "svelte": "^5.56.2",
101
+ "svelte-check": "^4.6.0",
102
+ "svelte-preprocess": "^6.0.5",
103
+ "svelte2tsx": "^0.7.56",
104
+ "tailwindcss": "4.3.0",
105
+ "tsdown": "^0.22.2",
106
+ "tsx": "^4.22.4",
107
107
  "tw-animate-css": "^1.4.0",
108
- "type-fest": "^5.6.0",
108
+ "type-fest": "^5.7.0",
109
109
  "typescript": "^6.0.3",
110
- "typescript-eslint": "^8.59.2",
110
+ "typescript-eslint": "^8.60.1",
111
111
  "typescript-svelte-plugin": "^0.3.52",
112
- "vite": "^8.0.10",
113
- "vitest": "^4.1.5"
112
+ "vite": "^8.0.16",
113
+ "vitest": "^4.1.8"
114
114
  },
115
115
  "peerDependencies": {
116
116
  "@sveltejs/kit": "^2.0.0",
@@ -195,19 +195,19 @@ export class Requestor<
195
195
  * Then it separates the outputs and resolves each of the promises
196
196
  */
197
197
  private async flushBatchQueue(batchId: string): Promise<void> {
198
- const queue = this.#batchQueue[batchId].splice(0);
198
+ const queue = this.#batchQueue[batchId]?.splice(0) ?? [];
199
+ if (queue.length === 0) return;
199
200
 
200
201
  // TODO maybe remove the unBatchOutput function and just always return the
201
202
  // same response and then its on each consumer of each query to find the relevant records
202
203
  try {
203
204
  const batchedInput = this.#batchInput(queue.map((q) => q.input));
204
-
205
205
  const res = await this.fetch(batchedInput);
206
+
206
207
  const output = await this.#unBatchOutput(
207
208
  queue.map((q) => q.input),
208
209
  res
209
210
  );
210
-
211
211
  if (output.length !== queue.length) {
212
212
  throw new Error(`Batch output length mismatch for ${batchId}`);
213
213
  }
@@ -232,8 +232,12 @@ export class Requestor<
232
232
 
233
233
  if (!this.#batchTimers[batchId]) {
234
234
  this.#batchTimers[batchId] = setTimeout(() => {
235
+ delete this.#batchTimers[batchId];
236
+
235
237
  void this.flushBatchQueue(batchId).finally(() => {
236
- delete this.#batchTimers[batchId];
238
+ if (this.#batchQueue[batchId]?.length === 0) {
239
+ delete this.#batchQueue[batchId];
240
+ }
237
241
  });
238
242
  }, this.#batchDelay);
239
243
  }
@@ -272,6 +272,70 @@ describe('Requestor', () => {
272
272
 
273
273
  await Promise.all([p1Expectation, p2Expectation]);
274
274
  });
275
+
276
+ it('schedules a new batch for requests added while a previous batch is in flight', async () => {
277
+ const firstFetch = deferred<Response>();
278
+ const secondFetch = deferred<Response>();
279
+
280
+ const fetchMock = vi.fn((_url: string, init?: RequestInit) => {
281
+ if (init?.body === JSON.stringify({ ids: [1] })) {
282
+ return firstFetch.promise;
283
+ }
284
+
285
+ if (init?.body === JSON.stringify({ ids: [2] })) {
286
+ return secondFetch.promise;
287
+ }
288
+
289
+ throw new Error(`Unexpected request body: ${String(init?.body)}`);
290
+ });
291
+
292
+ vi.stubGlobal('fetch', fetchMock);
293
+
294
+ const requestor = createBatchedRequestor({
295
+ canBatch: (input) => ('group' in input && input.group) || false,
296
+ batchInput: (inputs) => ({ ids: inputs.map(getSingleId) }),
297
+ unBatchOutput: (inputs) => inputs.map((input) => jsonResponse({ id: getSingleId(input) }))
298
+ });
299
+
300
+ const p1 = requestor.request({ id: 1, group: 'team' });
301
+
302
+ await vi.advanceTimersByTimeAsync(100);
303
+
304
+ expect(fetchMock).toHaveBeenCalledTimes(1);
305
+ expect(fetchMock).toHaveBeenLastCalledWith(
306
+ `${API_URL}//users`,
307
+ expect.objectContaining({
308
+ method: 'POST',
309
+ body: JSON.stringify({ ids: [1] }),
310
+ credentials: 'include'
311
+ })
312
+ );
313
+
314
+ const p2 = requestor.request({ id: 2, group: 'team' });
315
+
316
+ await vi.advanceTimersByTimeAsync(99);
317
+ expect(fetchMock).toHaveBeenCalledTimes(1);
318
+
319
+ await vi.advanceTimersByTimeAsync(1);
320
+
321
+ expect(fetchMock).toHaveBeenCalledTimes(2);
322
+ expect(fetchMock).toHaveBeenLastCalledWith(
323
+ `${API_URL}//users`,
324
+ expect.objectContaining({
325
+ method: 'POST',
326
+ body: JSON.stringify({ ids: [2] }),
327
+ credentials: 'include'
328
+ })
329
+ );
330
+
331
+ firstFetch.resolve(jsonFetchResponse({ ok: true }));
332
+ secondFetch.resolve(jsonFetchResponse({ ok: true }));
333
+
334
+ const [response1, response2] = await Promise.all([p1, p2]);
335
+
336
+ await expect(response1.json()).resolves.toEqual({ id: 1 });
337
+ await expect(response2.json()).resolves.toEqual({ id: 2 });
338
+ });
275
339
  });
276
340
 
277
341
  describe('Query', () => {