@sentroy-co/client-sdk 2.5.0 → 2.5.2

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 +1 @@
1
- {"version":3,"file":"use-upload-queue.d.ts","sourceRoot":"","sources":["../../../src/react/lib/use-upload-queue.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AACpC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAExC;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,IAAI,CAAA;IACV,MAAM,EAAE,QAAQ,GAAG,WAAW,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,CAAA;IAC9D,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,4CAA4C;IAC5C,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,sDAAsD;IACtD,MAAM,EAAE,MAAM,IAAI,CAAA;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,gDAAgD;IAChD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CACpC;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,WAAW,EAAE,CAAA;IACtB,0DAA0D;IAC1D,OAAO,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAA;IACpD,yEAAyE;IACzE,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5B,uEAAuE;IACvE,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5B,sDAAsD;IACtD,SAAS,EAAE,MAAM,IAAI,CAAA;IACrB,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAA;CACpB;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,OAAO,EACf,IAAI,GAAE,qBAA0B,GAC/B,oBAAoB,CAyJtB"}
1
+ {"version":3,"file":"use-upload-queue.d.ts","sourceRoot":"","sources":["../../../src/react/lib/use-upload-queue.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AACpC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAExC;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,IAAI,CAAA;IACV,MAAM,EAAE,QAAQ,GAAG,WAAW,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,CAAA;IAC9D,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,4CAA4C;IAC5C,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,sDAAsD;IACtD,MAAM,EAAE,MAAM,IAAI,CAAA;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,gDAAgD;IAChD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CACpC;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,WAAW,EAAE,CAAA;IACtB,0DAA0D;IAC1D,OAAO,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAA;IACpD,yEAAyE;IACzE,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5B,uEAAuE;IACvE,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5B,sDAAsD;IACtD,SAAS,EAAE,MAAM,IAAI,CAAA;IACrB,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAA;CACpB;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,OAAO,EACf,IAAI,GAAE,qBAA0B,GAC/B,oBAAoB,CAgMtB"}
@@ -20,61 +20,86 @@ function useUploadQueue(client, opts = {}) {
20
20
  onUploadedRef.current = opts.onUploaded;
21
21
  // Worker pump — queued entry varsa ve aktif < concurrency ise başlat.
22
22
  const pumpRef = (0, react_1.useRef)(() => { });
23
+ /**
24
+ * Aktif (in-flight) upload sayısını synchronous olarak takip eden ref.
25
+ * `entries` state setEntries ile async güncellendiğinden, recursive
26
+ * `pump` çağrılarında `entries.filter(e => e.status === "uploading")`
27
+ * eski listeyi görür → aynı queued entry birden çok kez başlatılır
28
+ * (Chrome side `ERR_INSUFFICIENT_RESOURCES`). Ref ile incre/decre
29
+ * synchronous; concurrency limiti gerçekten devreye girer.
30
+ */
31
+ const inFlightRef = (0, react_1.useRef)(0);
32
+ /**
33
+ * Henüz başlatılmamış queued entry id'lerinin sıralı listesi. setEntries
34
+ * async olduğu için listeden seçim yapmak yarış koşulu üretir; ref
35
+ * üzerinden FIFO push/shift hem deterministik hem hızlı.
36
+ */
37
+ const queueRef = (0, react_1.useRef)([]);
23
38
  const updateEntry = (0, react_1.useCallback)((id, patch) => {
24
39
  setEntries((prev) => prev.map((e) => (e.id === id ? { ...e, ...patch } : e)));
25
40
  }, []);
26
41
  pumpRef.current = () => {
27
- const list = entriesRef.current;
28
- const active = list.filter((e) => e.status === "uploading").length;
29
- if (active >= concurrency)
42
+ // Slot doluysa veya queue boşsa erken dön.
43
+ if (inFlightRef.current >= concurrency)
30
44
  return;
31
- const next = list.find((e) => e.status === "queued");
32
- if (!next)
45
+ const nextId = queueRef.current.shift();
46
+ if (!nextId)
33
47
  return;
48
+ // Slot'u synchronously rezerve et — bir sonraki pump çağrısı bu
49
+ // entry'i tekrar shift edemez.
50
+ inFlightRef.current++;
51
+ const entry = entriesRef.current.find((e) => e.id === nextId);
52
+ if (!entry) {
53
+ // Cancel öncesi remove edilmiş; slot'u iade et ve pump'a devam.
54
+ inFlightRef.current--;
55
+ pumpRef.current?.();
56
+ return;
57
+ }
34
58
  // Mark uploading
35
- updateEntry(next.id, { status: "uploading" });
36
- // Bucket slug entry içine save edilemiyor (entry shape'i bilmesi
37
- // gerekmez); enqueue closure'unda capture edilir, ayrı bucket map.
38
- const bucketSlug = bucketMapRef.current[next.id];
59
+ updateEntry(entry.id, { status: "uploading" });
60
+ const bucketSlug = bucketMapRef.current[entry.id];
39
61
  if (!bucketSlug) {
40
- updateEntry(next.id, { status: "error", error: "No bucket" });
62
+ updateEntry(entry.id, { status: "error", error: "No bucket" });
63
+ inFlightRef.current--;
41
64
  pumpRef.current?.();
42
65
  return;
43
66
  }
44
67
  const controller = new AbortController();
45
- cancelMapRef.current[next.id] = () => controller.abort();
68
+ cancelMapRef.current[entry.id] = () => controller.abort();
46
69
  client.media
47
- .upload(bucketSlug, { body: next.file, filename: next.file.name }, {
70
+ .upload(bucketSlug, { body: entry.file, filename: entry.file.name }, {
48
71
  onProgress: (loaded, total) => {
49
- updateEntry(next.id, { loaded, total });
72
+ updateEntry(entry.id, { loaded, total });
50
73
  },
51
74
  signal: controller.signal,
52
75
  })
53
76
  .then((media) => {
54
- updateEntry(next.id, {
77
+ updateEntry(entry.id, {
55
78
  status: "done",
56
79
  media,
57
- loaded: next.file.size,
58
- total: next.file.size,
80
+ loaded: entry.file.size,
81
+ total: entry.file.size,
59
82
  });
60
83
  onUploadedRef.current?.(media);
61
84
  })
62
85
  .catch((err) => {
63
86
  const aborted = err?.message === "Upload aborted";
64
- updateEntry(next.id, {
87
+ updateEntry(entry.id, {
65
88
  status: aborted ? "canceled" : "error",
66
89
  error: aborted
67
90
  ? undefined
68
- : err?.message ?? "Upload failed",
91
+ : (err?.message ?? "Upload failed"),
69
92
  });
70
93
  })
71
94
  .finally(() => {
72
- delete cancelMapRef.current[next.id];
73
- // Yeni slot açıldı; başka queued varsa al.
95
+ delete cancelMapRef.current[entry.id];
96
+ inFlightRef.current--;
97
+ // Slot açıldı, sıradakini başlat.
74
98
  pumpRef.current?.();
75
99
  });
76
- // Aynı tick'te birden fazla slot doldur.
77
- if (active + 1 < concurrency)
100
+ // Aynı tick'te kalan slot'ları doldur — concurrency artık
101
+ // synchronously inFlightRef ile guard'lı, çift başlatma yok.
102
+ if (inFlightRef.current < concurrency)
78
103
  pumpRef.current?.();
79
104
  };
80
105
  const bucketMapRef = (0, react_1.useRef)({});
@@ -85,6 +110,9 @@ function useUploadQueue(client, opts = {}) {
85
110
  const newEntries = files.map((file) => {
86
111
  const id = `up-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
87
112
  bucketMapRef.current[id] = bucketSlug;
113
+ // FIFO queue — pump bu sıradan shift eder; setEntries async
114
+ // güncellemesinden bağımsız synchronous source-of-truth.
115
+ queueRef.current.push(id);
88
116
  return {
89
117
  id,
90
118
  file,
@@ -95,28 +123,36 @@ function useUploadQueue(client, opts = {}) {
95
123
  const c = cancelMapRef.current[id];
96
124
  if (c)
97
125
  c();
98
- else
126
+ else {
127
+ queueRef.current = queueRef.current.filter((qid) => qid !== id);
99
128
  setEntries((prev) => prev.map((e) => e.id === id && e.status === "queued"
100
129
  ? { ...e, status: "canceled" }
101
130
  : e));
131
+ }
102
132
  },
103
133
  };
104
134
  });
105
135
  setEntries((prev) => [...prev, ...newEntries]);
106
- // pump on next tick — state update'ten sonra entriesRef güncel olsun
136
+ // pump on next tick — state update'ten sonra entriesRef güncel olsun.
137
+ // pumpRef kendi içinde sequential pump zincirini sürdürür (her
138
+ // başarılı slot rezervasyonundan sonra bir dahaki pump'ı çağırır),
139
+ // dolayısıyla burada tek tetikleme yeterli.
107
140
  Promise.resolve().then(() => pumpRef.current?.());
108
141
  }, []);
109
142
  const cancel = (0, react_1.useCallback)((id) => {
110
143
  const c = cancelMapRef.current[id];
111
144
  if (c)
112
145
  c();
113
- else
146
+ else {
147
+ queueRef.current = queueRef.current.filter((qid) => qid !== id);
114
148
  setEntries((prev) => prev.map((e) => e.id === id && e.status === "queued"
115
149
  ? { ...e, status: "canceled" }
116
150
  : e));
151
+ }
117
152
  }, []);
118
153
  const remove = (0, react_1.useCallback)((id) => {
119
154
  setEntries((prev) => prev.filter((e) => e.id !== id));
155
+ queueRef.current = queueRef.current.filter((qid) => qid !== id);
120
156
  delete bucketMapRef.current[id];
121
157
  delete cancelMapRef.current[id];
122
158
  }, []);
@@ -1 +1 @@
1
- {"version":3,"file":"use-upload-queue.js","sourceRoot":"","sources":["../../../src/react/lib/use-upload-queue.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"use-upload-queue.js","sourceRoot":"","sources":["../../../src/react/lib/use-upload-queue.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentroy-co/client-sdk",
3
- "version": "2.5.0",
3
+ "version": "2.5.2",
4
4
  "description": "TypeScript SDK for the Sentroy platform — REST resources + React components.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -66,6 +66,22 @@ export function useUploadQueue(
66
66
  // Worker pump — queued entry varsa ve aktif < concurrency ise başlat.
67
67
  const pumpRef = useRef<() => void>(() => {})
68
68
 
69
+ /**
70
+ * Aktif (in-flight) upload sayısını synchronous olarak takip eden ref.
71
+ * `entries` state setEntries ile async güncellendiğinden, recursive
72
+ * `pump` çağrılarında `entries.filter(e => e.status === "uploading")`
73
+ * eski listeyi görür → aynı queued entry birden çok kez başlatılır
74
+ * (Chrome side `ERR_INSUFFICIENT_RESOURCES`). Ref ile incre/decre
75
+ * synchronous; concurrency limiti gerçekten devreye girer.
76
+ */
77
+ const inFlightRef = useRef(0)
78
+ /**
79
+ * Henüz başlatılmamış queued entry id'lerinin sıralı listesi. setEntries
80
+ * async olduğu için listeden seçim yapmak yarış koşulu üretir; ref
81
+ * üzerinden FIFO push/shift hem deterministik hem hızlı.
82
+ */
83
+ const queueRef = useRef<string[]>([])
84
+
69
85
  const updateEntry = useCallback(
70
86
  (id: string, patch: Partial<UploadEntry>) => {
71
87
  setEntries((prev) =>
@@ -76,65 +92,77 @@ export function useUploadQueue(
76
92
  )
77
93
 
78
94
  pumpRef.current = () => {
79
- const list = entriesRef.current
80
- const active = list.filter((e) => e.status === "uploading").length
81
- if (active >= concurrency) return
82
- const next = list.find((e) => e.status === "queued")
83
- if (!next) return
95
+ // Slot doluysa veya queue boşsa erken dön.
96
+ if (inFlightRef.current >= concurrency) return
97
+ const nextId = queueRef.current.shift()
98
+ if (!nextId) return
99
+
100
+ // Slot'u synchronously rezerve et — bir sonraki pump çağrısı bu
101
+ // entry'i tekrar shift edemez.
102
+ inFlightRef.current++
103
+
104
+ const entry = entriesRef.current.find((e) => e.id === nextId)
105
+ if (!entry) {
106
+ // Cancel öncesi remove edilmiş; slot'u iade et ve pump'a devam.
107
+ inFlightRef.current--
108
+ pumpRef.current?.()
109
+ return
110
+ }
84
111
 
85
112
  // Mark uploading
86
- updateEntry(next.id, { status: "uploading" })
113
+ updateEntry(entry.id, { status: "uploading" })
87
114
 
88
- // Bucket slug entry içine save edilemiyor (entry shape'i bilmesi
89
- // gerekmez); enqueue closure'unda capture edilir, ayrı bucket map.
90
- const bucketSlug = bucketMapRef.current[next.id]
115
+ const bucketSlug = bucketMapRef.current[entry.id]
91
116
  if (!bucketSlug) {
92
- updateEntry(next.id, { status: "error", error: "No bucket" })
117
+ updateEntry(entry.id, { status: "error", error: "No bucket" })
118
+ inFlightRef.current--
93
119
  pumpRef.current?.()
94
120
  return
95
121
  }
96
122
 
97
123
  const controller = new AbortController()
98
- cancelMapRef.current[next.id] = () => controller.abort()
124
+ cancelMapRef.current[entry.id] = () => controller.abort()
99
125
 
100
126
  client.media
101
127
  .upload(
102
128
  bucketSlug,
103
- { body: next.file, filename: next.file.name },
129
+ { body: entry.file, filename: entry.file.name },
104
130
  {
105
131
  onProgress: (loaded, total) => {
106
- updateEntry(next.id, { loaded, total })
132
+ updateEntry(entry.id, { loaded, total })
107
133
  },
108
134
  signal: controller.signal,
109
135
  },
110
136
  )
111
137
  .then((media) => {
112
- updateEntry(next.id, {
138
+ updateEntry(entry.id, {
113
139
  status: "done",
114
140
  media,
115
- loaded: next.file.size,
116
- total: next.file.size,
141
+ loaded: entry.file.size,
142
+ total: entry.file.size,
117
143
  })
118
144
  onUploadedRef.current?.(media)
119
145
  })
120
146
  .catch((err: unknown) => {
121
147
  const aborted =
122
148
  (err as { message?: string })?.message === "Upload aborted"
123
- updateEntry(next.id, {
149
+ updateEntry(entry.id, {
124
150
  status: aborted ? "canceled" : "error",
125
151
  error: aborted
126
152
  ? undefined
127
- : (err as Error)?.message ?? "Upload failed",
153
+ : ((err as Error)?.message ?? "Upload failed"),
128
154
  })
129
155
  })
130
156
  .finally(() => {
131
- delete cancelMapRef.current[next.id]
132
- // Yeni slot açıldı; başka queued varsa al.
157
+ delete cancelMapRef.current[entry.id]
158
+ inFlightRef.current--
159
+ // Slot açıldı, sıradakini başlat.
133
160
  pumpRef.current?.()
134
161
  })
135
162
 
136
- // Aynı tick'te birden fazla slot doldur.
137
- if (active + 1 < concurrency) pumpRef.current?.()
163
+ // Aynı tick'te kalan slot'ları doldur — concurrency artık
164
+ // synchronously inFlightRef ile guard'lı, çift başlatma yok.
165
+ if (inFlightRef.current < concurrency) pumpRef.current?.()
138
166
  }
139
167
 
140
168
  const bucketMapRef = useRef<Record<string, string>>({})
@@ -146,6 +174,9 @@ export function useUploadQueue(
146
174
  const newEntries: UploadEntry[] = files.map((file) => {
147
175
  const id = `up-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
148
176
  bucketMapRef.current[id] = bucketSlug
177
+ // FIFO queue — pump bu sıradan shift eder; setEntries async
178
+ // güncellemesinden bağımsız synchronous source-of-truth.
179
+ queueRef.current.push(id)
149
180
  return {
150
181
  id,
151
182
  file,
@@ -155,7 +186,8 @@ export function useUploadQueue(
155
186
  cancel: () => {
156
187
  const c = cancelMapRef.current[id]
157
188
  if (c) c()
158
- else
189
+ else {
190
+ queueRef.current = queueRef.current.filter((qid) => qid !== id)
159
191
  setEntries((prev) =>
160
192
  prev.map((e) =>
161
193
  e.id === id && e.status === "queued"
@@ -163,11 +195,15 @@ export function useUploadQueue(
163
195
  : e,
164
196
  ),
165
197
  )
198
+ }
166
199
  },
167
200
  }
168
201
  })
169
202
  setEntries((prev) => [...prev, ...newEntries])
170
- // pump on next tick — state update'ten sonra entriesRef güncel olsun
203
+ // pump on next tick — state update'ten sonra entriesRef güncel olsun.
204
+ // pumpRef kendi içinde sequential pump zincirini sürdürür (her
205
+ // başarılı slot rezervasyonundan sonra bir dahaki pump'ı çağırır),
206
+ // dolayısıyla burada tek tetikleme yeterli.
171
207
  Promise.resolve().then(() => pumpRef.current?.())
172
208
  },
173
209
  [],
@@ -176,7 +212,8 @@ export function useUploadQueue(
176
212
  const cancel = useCallback((id: string) => {
177
213
  const c = cancelMapRef.current[id]
178
214
  if (c) c()
179
- else
215
+ else {
216
+ queueRef.current = queueRef.current.filter((qid) => qid !== id)
180
217
  setEntries((prev) =>
181
218
  prev.map((e) =>
182
219
  e.id === id && e.status === "queued"
@@ -184,10 +221,12 @@ export function useUploadQueue(
184
221
  : e,
185
222
  ),
186
223
  )
224
+ }
187
225
  }, [])
188
226
 
189
227
  const remove = useCallback((id: string) => {
190
228
  setEntries((prev) => prev.filter((e) => e.id !== id))
229
+ queueRef.current = queueRef.current.filter((qid) => qid !== id)
191
230
  delete bucketMapRef.current[id]
192
231
  delete cancelMapRef.current[id]
193
232
  }, [])