@ecosplay/e-brocante 1.0.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.
Files changed (110) hide show
  1. package/AGENTS.md +141 -0
  2. package/CHANGELOG.md +76 -0
  3. package/LICENSE +64 -0
  4. package/README.md +246 -0
  5. package/dist/EBrocanteClient.d.ts +38 -0
  6. package/dist/EBrocanteClient.d.ts.map +1 -0
  7. package/dist/EBrocanteClient.js +99 -0
  8. package/dist/EBrocanteClient.js.map +1 -0
  9. package/dist/cache/CacheBackend.d.ts +20 -0
  10. package/dist/cache/CacheBackend.d.ts.map +1 -0
  11. package/dist/cache/CacheBackend.js +6 -0
  12. package/dist/cache/CacheBackend.js.map +1 -0
  13. package/dist/cache/LocalCache.d.ts +22 -0
  14. package/dist/cache/LocalCache.d.ts.map +1 -0
  15. package/dist/cache/LocalCache.js +53 -0
  16. package/dist/cache/LocalCache.js.map +1 -0
  17. package/dist/cache/NullCache.d.ts +17 -0
  18. package/dist/cache/NullCache.d.ts.map +1 -0
  19. package/dist/cache/NullCache.js +26 -0
  20. package/dist/cache/NullCache.js.map +1 -0
  21. package/dist/cache/RedisCache.d.ts +39 -0
  22. package/dist/cache/RedisCache.d.ts.map +1 -0
  23. package/dist/cache/RedisCache.js +104 -0
  24. package/dist/cache/RedisCache.js.map +1 -0
  25. package/dist/cache/RedisConfig.d.ts +17 -0
  26. package/dist/cache/RedisConfig.d.ts.map +1 -0
  27. package/dist/cache/RedisConfig.js +13 -0
  28. package/dist/cache/RedisConfig.js.map +1 -0
  29. package/dist/cache/stableHashKey.d.ts +11 -0
  30. package/dist/cache/stableHashKey.d.ts.map +1 -0
  31. package/dist/cache/stableHashKey.js +27 -0
  32. package/dist/cache/stableHashKey.js.map +1 -0
  33. package/dist/exceptions/index.d.ts +41 -0
  34. package/dist/exceptions/index.d.ts.map +1 -0
  35. package/dist/exceptions/index.js +62 -0
  36. package/dist/exceptions/index.js.map +1 -0
  37. package/dist/http/HttpClient.d.ts +41 -0
  38. package/dist/http/HttpClient.d.ts.map +1 -0
  39. package/dist/http/HttpClient.js +222 -0
  40. package/dist/http/HttpClient.js.map +1 -0
  41. package/dist/index.d.ts +22 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +17 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/internal/safeStrings.d.ts +52 -0
  46. package/dist/internal/safeStrings.d.ts.map +1 -0
  47. package/dist/internal/safeStrings.js +156 -0
  48. package/dist/internal/safeStrings.js.map +1 -0
  49. package/dist/logger/DebugWriter.d.ts +24 -0
  50. package/dist/logger/DebugWriter.d.ts.map +1 -0
  51. package/dist/logger/DebugWriter.js +62 -0
  52. package/dist/logger/DebugWriter.js.map +1 -0
  53. package/dist/logger/FileLogger.d.ts +26 -0
  54. package/dist/logger/FileLogger.d.ts.map +1 -0
  55. package/dist/logger/FileLogger.js +96 -0
  56. package/dist/logger/FileLogger.js.map +1 -0
  57. package/dist/logger/Logger.d.ts +12 -0
  58. package/dist/logger/Logger.d.ts.map +1 -0
  59. package/dist/logger/Logger.js +6 -0
  60. package/dist/logger/Logger.js.map +1 -0
  61. package/dist/logger/NullLogger.d.ts +13 -0
  62. package/dist/logger/NullLogger.d.ts.map +1 -0
  63. package/dist/logger/NullLogger.js +20 -0
  64. package/dist/logger/NullLogger.js.map +1 -0
  65. package/dist/models/Event.d.ts +37 -0
  66. package/dist/models/Event.d.ts.map +1 -0
  67. package/dist/models/Event.js +42 -0
  68. package/dist/models/Event.js.map +1 -0
  69. package/dist/models/Orga.d.ts +33 -0
  70. package/dist/models/Orga.d.ts.map +1 -0
  71. package/dist/models/Orga.js +39 -0
  72. package/dist/models/Orga.js.map +1 -0
  73. package/dist/models/PaginatedResult.d.ts +27 -0
  74. package/dist/models/PaginatedResult.d.ts.map +1 -0
  75. package/dist/models/PaginatedResult.js +46 -0
  76. package/dist/models/PaginatedResult.js.map +1 -0
  77. package/dist/resources/EventsResource.d.ts +20 -0
  78. package/dist/resources/EventsResource.d.ts.map +1 -0
  79. package/dist/resources/EventsResource.js +46 -0
  80. package/dist/resources/EventsResource.js.map +1 -0
  81. package/dist/resources/OrgaResource.d.ts +20 -0
  82. package/dist/resources/OrgaResource.d.ts.map +1 -0
  83. package/dist/resources/OrgaResource.js +51 -0
  84. package/dist/resources/OrgaResource.js.map +1 -0
  85. package/dist/types.d.ts +81 -0
  86. package/dist/types.d.ts.map +1 -0
  87. package/dist/types.js +8 -0
  88. package/dist/types.js.map +1 -0
  89. package/package.json +72 -0
  90. package/src/EBrocanteClient.ts +110 -0
  91. package/src/cache/CacheBackend.ts +20 -0
  92. package/src/cache/LocalCache.ts +64 -0
  93. package/src/cache/NullCache.ts +32 -0
  94. package/src/cache/RedisCache.ts +123 -0
  95. package/src/cache/RedisConfig.ts +23 -0
  96. package/src/cache/stableHashKey.ts +28 -0
  97. package/src/exceptions/index.ts +75 -0
  98. package/src/http/HttpClient.ts +266 -0
  99. package/src/index.ts +42 -0
  100. package/src/internal/safeStrings.ts +154 -0
  101. package/src/logger/DebugWriter.ts +61 -0
  102. package/src/logger/FileLogger.ts +106 -0
  103. package/src/logger/Logger.ts +13 -0
  104. package/src/logger/NullLogger.ts +22 -0
  105. package/src/models/Event.ts +92 -0
  106. package/src/models/Orga.ts +76 -0
  107. package/src/models/PaginatedResult.ts +62 -0
  108. package/src/resources/EventsResource.ts +48 -0
  109. package/src/resources/OrgaResource.ts +53 -0
  110. package/src/types.ts +86 -0
@@ -0,0 +1,222 @@
1
+ /**
2
+ * @copyright 2026 Association E-Cosplay
3
+ * @license Proprietary — see LICENSE
4
+ */
5
+ import { stableHashKey } from '../cache/stableHashKey.js';
6
+ import { AuthenticationError, NetworkError, NotFoundError, RateLimitError, ServerError, ValidationError, } from '../exceptions/index.js';
7
+ import { stringifyPrimitive, trimLeadingSlash, trimTrailingSlash } from '../internal/safeStrings.js';
8
+ export const SDK_VERSION = '1.0.2';
9
+ /** @internal */
10
+ export class HttpClient {
11
+ deps;
12
+ constructor(deps) {
13
+ this.deps = deps;
14
+ }
15
+ get cache() {
16
+ return this.deps.cache;
17
+ }
18
+ async get(endpoint, query = {}, opts = {}) {
19
+ const path = this.buildPath(endpoint);
20
+ const cacheKey = this.makeCacheKey(endpoint, query);
21
+ const skipCache = opts.skipCache === true;
22
+ if (!skipCache) {
23
+ const cached = await this.deps.cache.get(cacheKey);
24
+ if (cached !== null && cached !== undefined) {
25
+ this.deps.logger.debug('cache hit', { endpoint, key: cacheKey });
26
+ this.deps.debugWriter?.log(`GET ${path}`, { cache: 'hit', key: cacheKey });
27
+ return cached;
28
+ }
29
+ }
30
+ const url = `${trimTrailingSlash(this.deps.baseUrl)}${path}${this.encodeQuery(query)}`;
31
+ const start = performance.now();
32
+ const response = await this.sendWithRetry(url);
33
+ const durationMs = Math.round(performance.now() - start);
34
+ const body = await response.text();
35
+ const payload = this.decode(body);
36
+ const reqId = response.headers.get('x-request-id');
37
+ this.deps.logger.info('api call', {
38
+ method: 'GET',
39
+ endpoint,
40
+ mode: this.deps.mode,
41
+ status: response.status,
42
+ duration_ms: durationMs,
43
+ cached: false,
44
+ request_id: reqId,
45
+ });
46
+ this.deps.debugWriter?.log(`GET ${path}${this.encodeQuery(query)} -> ${response.status}`, {
47
+ ms: durationMs,
48
+ cache: 'miss',
49
+ req: reqId,
50
+ });
51
+ if (!skipCache) {
52
+ await this.deps.cache.set(cacheKey, payload, opts.ttl);
53
+ this.deps.debugWriter?.log('cache.set', { key: cacheKey, ttl: opts.ttl ?? 'default' });
54
+ }
55
+ return payload;
56
+ }
57
+ makeCacheKey(endpoint, query) {
58
+ return `${this.deps.mode}:${stableHashKey(endpoint, { ...query, _broc: this.deps.brocEmail })}`;
59
+ }
60
+ buildPath(endpoint) {
61
+ return `/api/${this.deps.mode}/${trimLeadingSlash(endpoint)}`;
62
+ }
63
+ encodeQuery(query) {
64
+ const parts = [];
65
+ for (const [k, v] of Object.entries(query)) {
66
+ if (v === null || v === undefined || v === '')
67
+ continue;
68
+ const value = stringifyPrimitive(v);
69
+ parts.push(`${encodeURIComponent(k)}=${encodeURIComponent(value)}`);
70
+ }
71
+ return parts.length === 0 ? '' : `?${parts.join('&')}`;
72
+ }
73
+ async sendWithRetry(url) {
74
+ let attempt = 0;
75
+ while (true) {
76
+ attempt++;
77
+ const response = await this.attemptOrRetryConnect(url, attempt);
78
+ if (response === null)
79
+ continue;
80
+ if (response.status >= 200 && response.status < 300) {
81
+ return response;
82
+ }
83
+ if (this.shouldRetryStatus(response.status, attempt)) {
84
+ await this.applyRetryDelay(response, response.status, attempt);
85
+ continue;
86
+ }
87
+ throw await this.buildHttpError(response);
88
+ }
89
+ }
90
+ async attemptOrRetryConnect(url, attempt) {
91
+ const ac = new AbortController();
92
+ const timer = setTimeout(() => ac.abort(), this.deps.timeoutMs);
93
+ let response;
94
+ try {
95
+ response = await this.deps.fetchImpl(url, {
96
+ method: 'GET',
97
+ headers: {
98
+ 'X-KEY': this.deps.apiKey,
99
+ 'X-BROC': this.deps.brocEmail,
100
+ Accept: 'application/json',
101
+ 'User-Agent': `e-brocante-js/${SDK_VERSION} (Node/Bun)`,
102
+ },
103
+ signal: ac.signal,
104
+ });
105
+ }
106
+ catch (cause) {
107
+ clearTimeout(timer);
108
+ return this.handleConnectError(cause, attempt);
109
+ }
110
+ clearTimeout(timer);
111
+ return response;
112
+ }
113
+ async handleConnectError(cause, attempt) {
114
+ const message = errorMessage(cause);
115
+ if (attempt > this.deps.maxRetries) {
116
+ this.deps.logger.error('connection failed (gave up)', { attempt, error: message });
117
+ throw new NetworkError(`Connection failed after ${this.deps.maxRetries} retries: ${message}`, {
118
+ cause,
119
+ });
120
+ }
121
+ this.deps.logger.warn('connection failed, retrying', { attempt, error: message });
122
+ await this.sleepBackoff(attempt);
123
+ return null;
124
+ }
125
+ shouldRetryStatus(status, attempt) {
126
+ return (status === 429 || status >= 500) && attempt <= this.deps.maxRetries;
127
+ }
128
+ async applyRetryDelay(response, status, attempt) {
129
+ const retryAfter = Number(response.headers.get('retry-after') ?? 0);
130
+ this.deps.logger.warn('retryable status, retrying', {
131
+ status,
132
+ attempt,
133
+ retry_after: retryAfter,
134
+ });
135
+ this.deps.debugWriter?.log('retry', { attempt, status, retry_after: retryAfter });
136
+ if (retryAfter > 0) {
137
+ await sleep(Math.min(retryAfter, 30) * 1000);
138
+ return;
139
+ }
140
+ await this.sleepBackoff(attempt);
141
+ }
142
+ async buildHttpError(response) {
143
+ const body = await response.text();
144
+ const message = this.extractErrorMessage(body) ?? `HTTP ${response.status}`;
145
+ this.deps.logger.error('api error', { status: response.status, message });
146
+ this.deps.debugWriter?.log('error', { status: response.status, message });
147
+ const status = response.status;
148
+ if (status === 401 || status === 403)
149
+ return new AuthenticationError(message, status);
150
+ if (status === 404 || status === 410)
151
+ return new NotFoundError(message, status);
152
+ if (status === 422)
153
+ return new ValidationError(message, status, body);
154
+ if (status === 429) {
155
+ const retryAfter = response.headers.get('retry-after');
156
+ return new RateLimitError(message, status, retryAfter ? Number(retryAfter) : 0);
157
+ }
158
+ return new ServerError(message, status);
159
+ }
160
+ async sleepBackoff(attempt) {
161
+ // Exponential backoff with jitter (0.5s -> 1s -> 2s -> 4s …, capped at 30s).
162
+ const base = Math.min(0.5 * 2 ** (attempt - 1), 30);
163
+ const jitter = secureJitter() / 1000;
164
+ await sleep((base + jitter) * 1000);
165
+ }
166
+ decode(body) {
167
+ if (body === '')
168
+ return {};
169
+ let decoded;
170
+ try {
171
+ decoded = JSON.parse(body);
172
+ }
173
+ catch (cause) {
174
+ throw new ServerError(`Invalid JSON response: ${cause.message}`, 0, { cause });
175
+ }
176
+ if (decoded === null || typeof decoded !== 'object' || Array.isArray(decoded)) {
177
+ throw new ServerError('Unexpected JSON response (not an object)', 0);
178
+ }
179
+ return decoded;
180
+ }
181
+ extractErrorMessage(body) {
182
+ if (body === '')
183
+ return null;
184
+ let decoded;
185
+ try {
186
+ decoded = JSON.parse(body);
187
+ }
188
+ catch {
189
+ decoded = null;
190
+ }
191
+ let candidate = null;
192
+ if (decoded && typeof decoded === 'object') {
193
+ const d = decoded;
194
+ const errs = d.errors;
195
+ if (Array.isArray(errs) && errs[0] && typeof errs[0] === 'object') {
196
+ const first = errs[0];
197
+ candidate = first.title;
198
+ }
199
+ if (typeof candidate !== 'string') {
200
+ candidate = d.message;
201
+ }
202
+ }
203
+ return typeof candidate === 'string' ? candidate : null;
204
+ }
205
+ }
206
+ function sleep(ms) {
207
+ return new Promise((resolve) => setTimeout(resolve, ms));
208
+ }
209
+ function errorMessage(cause) {
210
+ return cause instanceof Error ? cause.message : String(cause);
211
+ }
212
+ function secureJitter() {
213
+ // 0..250 ms, derived from a CSPRNG to satisfy SonarQube S2245.
214
+ const buf = new Uint32Array(1);
215
+ crypto.getRandomValues(buf);
216
+ const raw = buf[0];
217
+ /* v8 ignore next — buf[0] is always populated by getRandomValues */
218
+ if (raw === undefined)
219
+ return 0;
220
+ return Math.floor(raw % 251);
221
+ }
222
+ //# sourceMappingURL=HttpClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HttpClient.js","sourceRoot":"","sources":["../../src/http/HttpClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * e-brocante JavaScript / TypeScript SDK — public entry point
3
+ *
4
+ * @copyright 2026 Association E-Cosplay
5
+ * @license Proprietary — see LICENSE
6
+ */
7
+ export { EBrocanteClient } from './EBrocanteClient.js';
8
+ export type { EBrocanteClientOptions, EventFilters, OrgaFilters, Mode, CacheType, RequestOptions, } from './types.js';
9
+ export type { CacheBackend } from './cache/CacheBackend.js';
10
+ export { LocalCache } from './cache/LocalCache.js';
11
+ export { NullCache } from './cache/NullCache.js';
12
+ export { RedisCache, type RedisLikeClient } from './cache/RedisCache.js';
13
+ export { type RedisConfig, DEFAULT_REDIS_CONFIG } from './cache/RedisConfig.js';
14
+ export type { Logger, LogLevel } from './logger/Logger.js';
15
+ export { NullLogger } from './logger/NullLogger.js';
16
+ export { FileLogger } from './logger/FileLogger.js';
17
+ export { DebugWriter } from './logger/DebugWriter.js';
18
+ export { EBrocanteError, AuthenticationError, NotFoundError, ValidationError, RateLimitError, ServerError, NetworkError, } from './exceptions/index.js';
19
+ export type { EventDto } from './models/Event.js';
20
+ export type { OrgaDto } from './models/Orga.js';
21
+ export { PaginatedResult, type PaginationMeta } from './models/PaginatedResult.js';
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,YAAY,EACR,sBAAsB,EACtB,YAAY,EACZ,WAAW,EACX,IAAI,EACJ,SAAS,EACT,cAAc,GACjB,MAAM,YAAY,CAAC;AAEpB,YAAY,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAAE,KAAK,WAAW,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAEhF,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,EACH,cAAc,EACd,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,cAAc,EACd,WAAW,EACX,YAAY,GACf,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,YAAY,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,6BAA6B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * e-brocante JavaScript / TypeScript SDK — public entry point
3
+ *
4
+ * @copyright 2026 Association E-Cosplay
5
+ * @license Proprietary — see LICENSE
6
+ */
7
+ export { EBrocanteClient } from './EBrocanteClient.js';
8
+ export { LocalCache } from './cache/LocalCache.js';
9
+ export { NullCache } from './cache/NullCache.js';
10
+ export { RedisCache } from './cache/RedisCache.js';
11
+ export { DEFAULT_REDIS_CONFIG } from './cache/RedisConfig.js';
12
+ export { NullLogger } from './logger/NullLogger.js';
13
+ export { FileLogger } from './logger/FileLogger.js';
14
+ export { DebugWriter } from './logger/DebugWriter.js';
15
+ export { EBrocanteError, AuthenticationError, NotFoundError, ValidationError, RateLimitError, ServerError, NetworkError, } from './exceptions/index.js';
16
+ export { PaginatedResult } from './models/PaginatedResult.js';
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAYvD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAwB,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAAoB,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAGhF,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,EACH,cAAc,EACd,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,cAAc,EACd,WAAW,EACX,YAAY,GACf,MAAM,uBAAuB,CAAC;AAI/B,OAAO,EAAE,eAAe,EAAuB,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @copyright 2026 Association E-Cosplay
3
+ * @license Proprietary — see LICENSE
4
+ *
5
+ * Hand-rolled string helpers used in place of unbounded regular
6
+ * expressions so that no input can trigger super-linear runtime
7
+ * (SonarQube rule S5852 / ReDoS). Every loop here is strictly O(n).
8
+ *
9
+ * @internal
10
+ */
11
+ /** Strip every leading `/` from a string. O(n). */
12
+ export declare function trimLeadingSlash(s: string): string;
13
+ /** Strip every trailing `/` from a string. O(n). */
14
+ export declare function trimTrailingSlash(s: string): string;
15
+ /** Strip leading AND trailing `/`. O(n). */
16
+ export declare function trimSlashes(s: string): string;
17
+ /** Replace every `/` with `.`. O(n). */
18
+ export declare function slashesToDots(s: string): string;
19
+ /** Coerce an unknown value to a string, falling back when it isn't one. */
20
+ export declare function asString(v: unknown, fallback?: string): string;
21
+ /** Coerce an unknown value to a finite number, falling back when it isn't. */
22
+ export declare function asNumber(v: unknown, fallback?: number): number;
23
+ /** Coerce an unknown value to a boolean (truthy primitives only). */
24
+ export declare function asBoolean(v: unknown): boolean;
25
+ /** Returns the string value when truthy, otherwise null. */
26
+ export declare function asNullableString(v: unknown): string | null;
27
+ /** Parse an ISO-8601 string into a Date, returning null on garbage. */
28
+ export declare function asDate(v: unknown): Date | null;
29
+ /**
30
+ * Coerce an unknown value to a plain record. Returns an empty record
31
+ * on null, undefined, primitives, or arrays — never throws.
32
+ */
33
+ export declare function asRecord(v: unknown): Record<string, unknown>;
34
+ /**
35
+ * Coerce an unknown value to an integer, returning null when the input
36
+ * is empty, missing or not finite (vs. asNumber which falls back to 0).
37
+ */
38
+ export declare function asNullableInt(v: unknown): number | null;
39
+ /**
40
+ * Stringify a primitive value for use in URL query strings or cache keys.
41
+ * Refuses non-primitive values (objects, arrays, functions) to avoid the
42
+ * `[object Object]` foot-gun that `String(v)` produces for them.
43
+ */
44
+ export declare function stringifyPrimitive(v: unknown): string;
45
+ /**
46
+ * Strict, ReDoS-safe email validator. Constant-time wrt structure
47
+ * (single forward scan + a couple of bounded slices). Intentionally
48
+ * conservative — accepts the same shape as `/^[^@\s]+@[^@\s]+\.[^@\s]+$/`
49
+ * but with explicit upper bounds.
50
+ */
51
+ export declare function isValidEmail(value: string): boolean;
52
+ //# sourceMappingURL=safeStrings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safeStrings.d.ts","sourceRoot":"","sources":["../../src/internal/safeStrings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAWH,mDAAmD;AACnD,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAIlD;AAED,oDAAoD;AACpD,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAInD;AAED,4CAA4C;AAC5C,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED,wCAAwC;AACxC,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,2EAA2E;AAC3E,wBAAgB,QAAQ,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,SAAK,GAAG,MAAM,CAE1D;AAED,8EAA8E;AAC9E,wBAAgB,QAAQ,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,SAAI,GAAG,MAAM,CAOzD;AAED,qEAAqE;AACrE,wBAAgB,SAAS,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAE7C;AAED,4DAA4D;AAC5D,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAE1D;AAED,uEAAuE;AACvE,wBAAgB,MAAM,CAAC,CAAC,EAAE,OAAO,GAAG,IAAI,GAAG,IAAI,CAI9C;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAK5D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAIvD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAMrD;AAiCD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAMnD"}
@@ -0,0 +1,156 @@
1
+ /**
2
+ * @copyright 2026 Association E-Cosplay
3
+ * @license Proprietary — see LICENSE
4
+ *
5
+ * Hand-rolled string helpers used in place of unbounded regular
6
+ * expressions so that no input can trigger super-linear runtime
7
+ * (SonarQube rule S5852 / ReDoS). Every loop here is strictly O(n).
8
+ *
9
+ * @internal
10
+ */
11
+ const SLASH = 0x2f;
12
+ const AT = 0x40;
13
+ const DOT = 0x2e;
14
+ const SPACE = 0x20;
15
+ const TAB = 0x09;
16
+ const LF = 0x0a;
17
+ const CR = 0x0d;
18
+ const MAX_EMAIL_LENGTH = 254;
19
+ /** Strip every leading `/` from a string. O(n). */
20
+ export function trimLeadingSlash(s) {
21
+ let i = 0;
22
+ while (i < s.length && s.codePointAt(i) === SLASH)
23
+ i++;
24
+ return i === 0 ? s : s.slice(i);
25
+ }
26
+ /** Strip every trailing `/` from a string. O(n). */
27
+ export function trimTrailingSlash(s) {
28
+ let end = s.length;
29
+ while (end > 0 && s.codePointAt(end - 1) === SLASH)
30
+ end--;
31
+ return end === s.length ? s : s.slice(0, end);
32
+ }
33
+ /** Strip leading AND trailing `/`. O(n). */
34
+ export function trimSlashes(s) {
35
+ return trimTrailingSlash(trimLeadingSlash(s));
36
+ }
37
+ /** Replace every `/` with `.`. O(n). */
38
+ export function slashesToDots(s) {
39
+ return s.replaceAll('/', '.');
40
+ }
41
+ /** Coerce an unknown value to a string, falling back when it isn't one. */
42
+ export function asString(v, fallback = '') {
43
+ return typeof v === 'string' ? v : fallback;
44
+ }
45
+ /** Coerce an unknown value to a finite number, falling back when it isn't. */
46
+ export function asNumber(v, fallback = 0) {
47
+ if (typeof v === 'number' && Number.isFinite(v))
48
+ return v;
49
+ if (typeof v === 'string' && v !== '') {
50
+ const n = Number(v);
51
+ if (Number.isFinite(n))
52
+ return n;
53
+ }
54
+ return fallback;
55
+ }
56
+ /** Coerce an unknown value to a boolean (truthy primitives only). */
57
+ export function asBoolean(v) {
58
+ return v === true || v === 'true' || v === 1 || v === '1';
59
+ }
60
+ /** Returns the string value when truthy, otherwise null. */
61
+ export function asNullableString(v) {
62
+ return typeof v === 'string' && v !== '' ? v : null;
63
+ }
64
+ /** Parse an ISO-8601 string into a Date, returning null on garbage. */
65
+ export function asDate(v) {
66
+ if (typeof v !== 'string' || v === '')
67
+ return null;
68
+ const d = new Date(v);
69
+ return Number.isNaN(d.getTime()) ? null : d;
70
+ }
71
+ /**
72
+ * Coerce an unknown value to a plain record. Returns an empty record
73
+ * on null, undefined, primitives, or arrays — never throws.
74
+ */
75
+ export function asRecord(v) {
76
+ if (v === null || v === undefined)
77
+ return {};
78
+ if (typeof v !== 'object')
79
+ return {};
80
+ if (Array.isArray(v))
81
+ return {};
82
+ return v;
83
+ }
84
+ /**
85
+ * Coerce an unknown value to an integer, returning null when the input
86
+ * is empty, missing or not finite (vs. asNumber which falls back to 0).
87
+ */
88
+ export function asNullableInt(v) {
89
+ if (v === null || v === undefined || v === '')
90
+ return null;
91
+ const n = asNumber(v, Number.NaN);
92
+ return Number.isFinite(n) ? n : null;
93
+ }
94
+ /**
95
+ * Stringify a primitive value for use in URL query strings or cache keys.
96
+ * Refuses non-primitive values (objects, arrays, functions) to avoid the
97
+ * `[object Object]` foot-gun that `String(v)` produces for them.
98
+ */
99
+ export function stringifyPrimitive(v) {
100
+ if (v === null || v === undefined)
101
+ return '';
102
+ if (typeof v === 'string')
103
+ return v;
104
+ if (typeof v === 'number' || typeof v === 'bigint')
105
+ return String(v);
106
+ if (typeof v === 'boolean')
107
+ return v ? 'true' : 'false';
108
+ throw new TypeError(`Cannot stringify ${typeof v} value as a query/cache parameter.`);
109
+ }
110
+ function isWhitespaceCode(code) {
111
+ return code === SPACE || code === TAB || code === LF || code === CR;
112
+ }
113
+ /** Find the index of `@` in a single forward scan, returning -1 on failure
114
+ * (no `@`, multiple `@`, or any whitespace anywhere). */
115
+ function findSingleAt(value) {
116
+ let at = -1;
117
+ for (let i = 0; i < value.length; i++) {
118
+ const c = value.codePointAt(i);
119
+ if (isWhitespaceCode(c))
120
+ return -1;
121
+ if (c === AT) {
122
+ if (at !== -1)
123
+ return -1; // more than one '@'
124
+ at = i;
125
+ }
126
+ }
127
+ return at;
128
+ }
129
+ /** Validate the domain part has a valid dot (not at the boundary). */
130
+ function hasInteriorDot(domain) {
131
+ for (let i = 0; i < domain.length; i++) {
132
+ if (domain.codePointAt(i) === DOT) {
133
+ // Reject leading dot, trailing dot.
134
+ if (i === 0 || i === domain.length - 1)
135
+ return false;
136
+ return true;
137
+ }
138
+ }
139
+ return false;
140
+ }
141
+ /**
142
+ * Strict, ReDoS-safe email validator. Constant-time wrt structure
143
+ * (single forward scan + a couple of bounded slices). Intentionally
144
+ * conservative — accepts the same shape as `/^[^@\s]+@[^@\s]+\.[^@\s]+$/`
145
+ * but with explicit upper bounds.
146
+ */
147
+ export function isValidEmail(value) {
148
+ const len = value.length;
149
+ if (len === 0 || len > MAX_EMAIL_LENGTH)
150
+ return false;
151
+ const at = findSingleAt(value);
152
+ if (at < 1 || at >= len - 1)
153
+ return false;
154
+ return hasInteriorDot(value.slice(at + 1));
155
+ }
156
+ //# sourceMappingURL=safeStrings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safeStrings.js","sourceRoot":"","sources":["../../src/internal/safeStrings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @copyright 2026 Association E-Cosplay
3
+ * @license Proprietary — see LICENSE
4
+ */
5
+ /**
6
+ * Plain-text debug writer. Appends ONE LINE per SDK action to a file
7
+ * (default: `./DEBUG.TXT`). Designed for `tail -f DEBUG.TXT` during
8
+ * development; not intended for production observability — use
9
+ * FileLogger or a custom Logger for that.
10
+ *
11
+ * Output format:
12
+ * [2026-05-10 19:30:01.123] GET /api/prod/events?city=Paris -> 200 ms=45 cache=miss req=req_xxx
13
+ * [2026-05-10 19:30:01.456] cache.set key=events.list:abc ttl=300
14
+ * [2026-05-10 19:30:05.789] GET /api/prod/events?city=Paris cache=hit
15
+ * [2026-05-10 19:31:10.001] retry attempt=2 status=429 retry_after=3
16
+ * [2026-05-10 19:32:00.555] error status=401 message="HTTP 401"
17
+ */
18
+ export declare class DebugWriter {
19
+ readonly file: string;
20
+ constructor(file?: string);
21
+ log(action: string, fields?: Record<string, unknown>): void;
22
+ private stringify;
23
+ }
24
+ //# sourceMappingURL=DebugWriter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DebugWriter.d.ts","sourceRoot":"","sources":["../../src/logger/DebugWriter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH;;;;;;;;;;;;GAYG;AACH,qBAAa,WAAW;aACQ,IAAI,EAAE,MAAM;gBAAZ,IAAI,GAAE,MAAoB;IAatD,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,IAAI;IAmB/D,OAAO,CAAC,SAAS;CAKpB"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * @copyright 2026 Association E-Cosplay
3
+ * @license Proprietary — see LICENSE
4
+ */
5
+ import { appendFileSync, existsSync, mkdirSync } from 'node:fs';
6
+ import { dirname } from 'node:path';
7
+ import { EBrocanteError } from '../exceptions/index.js';
8
+ /**
9
+ * Plain-text debug writer. Appends ONE LINE per SDK action to a file
10
+ * (default: `./DEBUG.TXT`). Designed for `tail -f DEBUG.TXT` during
11
+ * development; not intended for production observability — use
12
+ * FileLogger or a custom Logger for that.
13
+ *
14
+ * Output format:
15
+ * [2026-05-10 19:30:01.123] GET /api/prod/events?city=Paris -> 200 ms=45 cache=miss req=req_xxx
16
+ * [2026-05-10 19:30:01.456] cache.set key=events.list:abc ttl=300
17
+ * [2026-05-10 19:30:05.789] GET /api/prod/events?city=Paris cache=hit
18
+ * [2026-05-10 19:31:10.001] retry attempt=2 status=429 retry_after=3
19
+ * [2026-05-10 19:32:00.555] error status=401 message="HTTP 401"
20
+ */
21
+ export class DebugWriter {
22
+ file;
23
+ constructor(file = 'DEBUG.TXT') {
24
+ this.file = file;
25
+ const dir = dirname(file);
26
+ if (dir && dir !== '.' && !existsSync(dir)) {
27
+ /* v8 ignore start — fs error mid-process (full disk, EROFS) */
28
+ try {
29
+ mkdirSync(dir, { recursive: true, mode: 0o755 });
30
+ }
31
+ catch (cause) {
32
+ throw new EBrocanteError(`Cannot create debug directory: ${dir}`, { cause });
33
+ }
34
+ /* v8 ignore stop */
35
+ }
36
+ }
37
+ log(action, fields = {}) {
38
+ const parts = [];
39
+ for (const [k, v] of Object.entries(fields)) {
40
+ if (v === null || v === undefined || v === '')
41
+ continue;
42
+ parts.push(`${k}=${this.stringify(v)}`);
43
+ }
44
+ const ts = new Date().toISOString().replace('T', ' ').replace('Z', '').slice(0, 23);
45
+ const line = parts.length > 0 ? `[${ts}] ${action} ${parts.join(' ')}` : `[${ts}] ${action}`;
46
+ try {
47
+ appendFileSync(this.file, `${line}\n`, { mode: 0o644 });
48
+ /* v8 ignore start — best-effort; only triggers on fs errors */
49
+ }
50
+ catch {
51
+ // swallowed
52
+ }
53
+ /* v8 ignore stop */
54
+ }
55
+ stringify(v) {
56
+ if (typeof v === 'boolean')
57
+ return v ? 'true' : 'false';
58
+ const s = String(v);
59
+ return s.includes(' ') ? `"${s}"` : s;
60
+ }
61
+ }
62
+ //# sourceMappingURL=DebugWriter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DebugWriter.js","sourceRoot":"","sources":["../../src/logger/DebugWriter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,WAAW;IACQ;IAA5B,YAA4B,OAAe,WAAW;QAA1B,SAAI,GAAJ,IAAI,CAAsB;QAClD,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC1B,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACzC,+DAA+D;YAC/D,IAAI,CAAC;gBACD,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YACrD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACb,MAAM,IAAI,cAAc,CAAC,kCAAkC,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;YACjF,CAAC;YACD,oBAAoB;QACxB,CAAC;IACL,CAAC;IAED,GAAG,CAAC,MAAc,EAAE,SAAkC,EAAE;QACpD,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1C,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,EAAE;gBAAE,SAAS;YACxD,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC5C,CAAC;QAED,MAAM,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAEpF,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,MAAM,EAAE,CAAC;QAC7F,IAAI,CAAC;YACD,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YACxD,+DAA+D;QACnE,CAAC;QAAC,MAAM,CAAC;YACL,YAAY;QAChB,CAAC;QACD,oBAAoB;IACxB,CAAC;IAEO,SAAS,CAAC,CAAU;QACxB,IAAI,OAAO,CAAC,KAAK,SAAS;YAAE,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;QACxD,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACpB,OAAO,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1C,CAAC;CACJ"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @copyright 2026 Association E-Cosplay
3
+ * @license Proprietary — see LICENSE
4
+ */
5
+ import type { LogLevel, Logger } from './Logger.js';
6
+ /**
7
+ * File logger that appends one JSON-line per record to a date-stamped
8
+ * file in the configured directory. One file per UTC day:
9
+ * `ebrocante-YYYY-MM-DD.log`. Suitable for log shippers (Vector,
10
+ * Filebeat, Fluent Bit) and `tail -f` during local development.
11
+ *
12
+ * Sensitive context keys are automatically redacted (`api_key`,
13
+ * `X-KEY` and `Authorization` headers).
14
+ */
15
+ export declare class FileLogger implements Logger {
16
+ private readonly directory;
17
+ private readonly minLevel;
18
+ constructor(directory: string, minLevel?: LogLevel);
19
+ debug(message: string, context?: Record<string, unknown>): void;
20
+ info(message: string, context?: Record<string, unknown>): void;
21
+ warn(message: string, context?: Record<string, unknown>): void;
22
+ error(message: string, context?: Record<string, unknown>): void;
23
+ private write;
24
+ private sanitize;
25
+ }
26
+ //# sourceMappingURL=FileLogger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileLogger.d.ts","sourceRoot":"","sources":["../../src/logger/FileLogger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AASpD;;;;;;;;GAQG;AACH,qBAAa,UAAW,YAAW,MAAM;IAIjC,OAAO,CAAC,QAAQ,CAAC,SAAS;IAH9B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAGb,SAAS,EAAE,MAAM,EAClC,QAAQ,GAAE,QAAiB;IAqB/B,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,IAAI;IAInE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,IAAI;IAIlE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,IAAI;IAIlE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,IAAI;IAInE,OAAO,CAAC,KAAK;IAqBb,OAAO,CAAC,QAAQ;CAgBnB"}