sdk-garden-js 0.2.0 → 0.3.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/README.md +2 -0
- package/dist/index.d.mts +24 -1
- package/dist/index.d.ts +24 -1
- package/dist/index.js +57 -2
- package/dist/index.mjs +57 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -63,6 +63,8 @@ Requires Node.js 18+ (for the global `fetch`) or any modern browser.
|
|
|
63
63
|
| `startedAt` | `number` | module load time | `Date.now()` when your SDK began initializing; reported as `time_to_init_ms` for the dashboard's init timing |
|
|
64
64
|
| `methods` | `string[]` | `[]` | Public methods of your SDK that are not wrapped with `trackMethod()`, so the dashboard's API Surface panel can show them when nobody calls them |
|
|
65
65
|
| `customer` | `{ id: string; name?: string }` | _(none)_ | The app or customer account this session runs for (see [Customers](#customers)) |
|
|
66
|
+
| `advisories` | `boolean` | `true` | Show the version advisories you set on the Releases page as one `console.warn` per process (0.3.0+) |
|
|
67
|
+
| `onAdvisory` | `(advisory) => void` | _(none)_ | Handle an advisory yourself instead: `{ version, severity, message, upgradeTo? }` |
|
|
66
68
|
|
|
67
69
|
### API surface
|
|
68
70
|
|
package/dist/index.d.mts
CHANGED
|
@@ -60,6 +60,29 @@ interface SdkGardenConfig {
|
|
|
60
60
|
* setCustomer(). Default: none.
|
|
61
61
|
*/
|
|
62
62
|
customer?: SdkGardenCustomer;
|
|
63
|
+
/**
|
|
64
|
+
* Show the notices you attach to versions on the SDK Garden Releases page
|
|
65
|
+
* (deprecated, broken, security) to developers still running them, as one
|
|
66
|
+
* console.warn per process. Default: true. Set onAdvisory to handle them
|
|
67
|
+
* yourself instead.
|
|
68
|
+
*/
|
|
69
|
+
advisories?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Called once per process when the version in use has an advisory, instead
|
|
72
|
+
* of the default console.warn. Use it to route the notice through your
|
|
73
|
+
* SDK's own logger. Exceptions it throws are ignored.
|
|
74
|
+
*/
|
|
75
|
+
onAdvisory?: (advisory: SdkGardenAdvisory) => void;
|
|
76
|
+
}
|
|
77
|
+
/** A notice the SDK publisher attached to the running version (see SdkGardenConfig.advisories). */
|
|
78
|
+
interface SdkGardenAdvisory {
|
|
79
|
+
/** The version this process runs, e.g. "1.2.0". */
|
|
80
|
+
version: string;
|
|
81
|
+
severity: 'deprecated' | 'broken' | 'security';
|
|
82
|
+
/** The publisher's message; may be empty. */
|
|
83
|
+
message: string;
|
|
84
|
+
/** The version the publisher recommends, if they named one. */
|
|
85
|
+
upgradeTo?: string;
|
|
63
86
|
}
|
|
64
87
|
/** The app or customer account a session is attributed to (see setCustomer()). */
|
|
65
88
|
interface SdkGardenCustomer {
|
|
@@ -140,4 +163,4 @@ interface SdkGardenObject {
|
|
|
140
163
|
*/
|
|
141
164
|
declare const SdkGarden: SdkGardenObject;
|
|
142
165
|
|
|
143
|
-
export { type SdkGardenConfig, type SdkGardenCustomer, type SdkMethodDecorator, SdkGarden as default };
|
|
166
|
+
export { type SdkGardenAdvisory, type SdkGardenConfig, type SdkGardenCustomer, type SdkMethodDecorator, SdkGarden as default };
|
package/dist/index.d.ts
CHANGED
|
@@ -60,6 +60,29 @@ interface SdkGardenConfig {
|
|
|
60
60
|
* setCustomer(). Default: none.
|
|
61
61
|
*/
|
|
62
62
|
customer?: SdkGardenCustomer;
|
|
63
|
+
/**
|
|
64
|
+
* Show the notices you attach to versions on the SDK Garden Releases page
|
|
65
|
+
* (deprecated, broken, security) to developers still running them, as one
|
|
66
|
+
* console.warn per process. Default: true. Set onAdvisory to handle them
|
|
67
|
+
* yourself instead.
|
|
68
|
+
*/
|
|
69
|
+
advisories?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Called once per process when the version in use has an advisory, instead
|
|
72
|
+
* of the default console.warn. Use it to route the notice through your
|
|
73
|
+
* SDK's own logger. Exceptions it throws are ignored.
|
|
74
|
+
*/
|
|
75
|
+
onAdvisory?: (advisory: SdkGardenAdvisory) => void;
|
|
76
|
+
}
|
|
77
|
+
/** A notice the SDK publisher attached to the running version (see SdkGardenConfig.advisories). */
|
|
78
|
+
interface SdkGardenAdvisory {
|
|
79
|
+
/** The version this process runs, e.g. "1.2.0". */
|
|
80
|
+
version: string;
|
|
81
|
+
severity: 'deprecated' | 'broken' | 'security';
|
|
82
|
+
/** The publisher's message; may be empty. */
|
|
83
|
+
message: string;
|
|
84
|
+
/** The version the publisher recommends, if they named one. */
|
|
85
|
+
upgradeTo?: string;
|
|
63
86
|
}
|
|
64
87
|
/** The app or customer account a session is attributed to (see setCustomer()). */
|
|
65
88
|
interface SdkGardenCustomer {
|
|
@@ -140,4 +163,4 @@ interface SdkGardenObject {
|
|
|
140
163
|
*/
|
|
141
164
|
declare const SdkGarden: SdkGardenObject;
|
|
142
165
|
|
|
143
|
-
export { type SdkGardenConfig, type SdkGardenCustomer, type SdkMethodDecorator, SdkGarden as default };
|
|
166
|
+
export { type SdkGardenAdvisory, type SdkGardenConfig, type SdkGardenCustomer, type SdkMethodDecorator, SdkGarden as default };
|
package/dist/index.js
CHANGED
|
@@ -41,6 +41,8 @@ var _pending = /* @__PURE__ */ new Set();
|
|
|
41
41
|
var _registered = /* @__PURE__ */ new Set();
|
|
42
42
|
var _undeclared = [];
|
|
43
43
|
var _declareScheduled = false;
|
|
44
|
+
var _advisoriesShown = /* @__PURE__ */ new Set();
|
|
45
|
+
var ADVISORY_HEADER = "SDK-Garden-Advisory";
|
|
44
46
|
var DEFAULT_ENDPOINT = "https://ingest.sdkgarden.com/track";
|
|
45
47
|
var MAX_BATCH_SIZE = 100;
|
|
46
48
|
var MAX_QUEUE_SIZE = 1e3;
|
|
@@ -69,7 +71,7 @@ function _clamp(value, min, max, fallback) {
|
|
|
69
71
|
return Math.min(max, Math.max(min, Math.floor(value)));
|
|
70
72
|
}
|
|
71
73
|
function _mergeDefaults(config) {
|
|
72
|
-
var _a, _b;
|
|
74
|
+
var _a, _b, _c;
|
|
73
75
|
return {
|
|
74
76
|
apiKey: config.apiKey,
|
|
75
77
|
sdkName: config.sdkName,
|
|
@@ -81,7 +83,9 @@ function _mergeDefaults(config) {
|
|
|
81
83
|
// A batch size below 1 would never empty the queue; above 100 the endpoint rejects it.
|
|
82
84
|
batchSize: _clamp(config.batchSize, 1, MAX_BATCH_SIZE, 10),
|
|
83
85
|
// A tiny interval would send constantly; one too large for a timer would fire every 1 ms.
|
|
84
|
-
flushInterval: _clamp(config.flushInterval, 100, MAX_TIMER_MS, 5e3)
|
|
86
|
+
flushInterval: _clamp(config.flushInterval, 100, MAX_TIMER_MS, 5e3),
|
|
87
|
+
advisories: (_c = config.advisories) != null ? _c : true,
|
|
88
|
+
onAdvisory: typeof config.onAdvisory === "function" ? config.onAdvisory : null
|
|
85
89
|
};
|
|
86
90
|
}
|
|
87
91
|
function _generateSessionId() {
|
|
@@ -385,6 +389,55 @@ function _takeBatch(events, maxEvents) {
|
|
|
385
389
|
}
|
|
386
390
|
return events.splice(0, count).map((event) => event.json);
|
|
387
391
|
}
|
|
392
|
+
function _parseAdvisory(raw) {
|
|
393
|
+
var _a;
|
|
394
|
+
const fields = {};
|
|
395
|
+
for (const part of raw.split("&")) {
|
|
396
|
+
const eq = part.indexOf("=");
|
|
397
|
+
if (eq <= 0) continue;
|
|
398
|
+
try {
|
|
399
|
+
fields[decodeURIComponent(part.slice(0, eq))] = decodeURIComponent(part.slice(eq + 1).replace(/\+/g, " "));
|
|
400
|
+
} catch (e) {
|
|
401
|
+
return null;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
const severity = fields["severity"];
|
|
405
|
+
if (!fields["version"] || severity !== "deprecated" && severity !== "broken" && severity !== "security") {
|
|
406
|
+
return null;
|
|
407
|
+
}
|
|
408
|
+
return {
|
|
409
|
+
version: fields["version"],
|
|
410
|
+
severity,
|
|
411
|
+
message: ((_a = fields["message"]) != null ? _a : "").slice(0, 280),
|
|
412
|
+
...fields["upgrade_to"] ? { upgradeTo: fields["upgrade_to"].slice(0, 50) } : {}
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
function _advisoryText(sdkName, a) {
|
|
416
|
+
const what = { deprecated: "is deprecated", broken: "has a known problem", security: "has a security issue" }[a.severity];
|
|
417
|
+
let text = `[${sdkName}] Version ${a.version} ${what}.`;
|
|
418
|
+
if (a.message) text += ` ${a.message}`;
|
|
419
|
+
if (a.upgradeTo) text += ` Upgrade to ${a.upgradeTo}.`;
|
|
420
|
+
return text;
|
|
421
|
+
}
|
|
422
|
+
function _handleAdvisory(config, response) {
|
|
423
|
+
var _a, _b;
|
|
424
|
+
if (!config.advisories) return;
|
|
425
|
+
const raw = (_b = (_a = response == null ? void 0 : response.headers) == null ? void 0 : _a.get) == null ? void 0 : _b.call(_a, ADVISORY_HEADER);
|
|
426
|
+
if (typeof raw !== "string" || raw === "") return;
|
|
427
|
+
const advisory = _parseAdvisory(raw);
|
|
428
|
+
if (!advisory || _advisoriesShown.has(advisory.version)) return;
|
|
429
|
+
_advisoriesShown.add(advisory.version);
|
|
430
|
+
if (config.onAdvisory) {
|
|
431
|
+
try {
|
|
432
|
+
config.onAdvisory(advisory);
|
|
433
|
+
} catch (e) {
|
|
434
|
+
}
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
if (typeof console !== "undefined" && typeof console.warn === "function") {
|
|
438
|
+
console.warn(_advisoryText(config.sdkName, advisory));
|
|
439
|
+
}
|
|
440
|
+
}
|
|
388
441
|
function _send(config, batch, keepalive) {
|
|
389
442
|
var _a;
|
|
390
443
|
if (typeof fetch !== "function") {
|
|
@@ -449,6 +502,7 @@ function _send(config, batch, keepalive) {
|
|
|
449
502
|
if (stream && typeof stream.cancel === "function") discarded = stream.cancel();
|
|
450
503
|
} catch (e) {
|
|
451
504
|
}
|
|
505
|
+
if (delivered) _safely(() => _handleAdvisory(config, response));
|
|
452
506
|
Promise.resolve(discarded).then(settle, settle);
|
|
453
507
|
},
|
|
454
508
|
() => settle()
|
|
@@ -846,6 +900,7 @@ var SdkGarden = {
|
|
|
846
900
|
_pending.clear();
|
|
847
901
|
_registered.clear();
|
|
848
902
|
_undeclared = [];
|
|
903
|
+
_advisoriesShown.clear();
|
|
849
904
|
}
|
|
850
905
|
};
|
|
851
906
|
var index_default = SdkGarden;
|
package/dist/index.mjs
CHANGED
|
@@ -17,6 +17,8 @@ var _pending = /* @__PURE__ */ new Set();
|
|
|
17
17
|
var _registered = /* @__PURE__ */ new Set();
|
|
18
18
|
var _undeclared = [];
|
|
19
19
|
var _declareScheduled = false;
|
|
20
|
+
var _advisoriesShown = /* @__PURE__ */ new Set();
|
|
21
|
+
var ADVISORY_HEADER = "SDK-Garden-Advisory";
|
|
20
22
|
var DEFAULT_ENDPOINT = "https://ingest.sdkgarden.com/track";
|
|
21
23
|
var MAX_BATCH_SIZE = 100;
|
|
22
24
|
var MAX_QUEUE_SIZE = 1e3;
|
|
@@ -45,7 +47,7 @@ function _clamp(value, min, max, fallback) {
|
|
|
45
47
|
return Math.min(max, Math.max(min, Math.floor(value)));
|
|
46
48
|
}
|
|
47
49
|
function _mergeDefaults(config) {
|
|
48
|
-
var _a, _b;
|
|
50
|
+
var _a, _b, _c;
|
|
49
51
|
return {
|
|
50
52
|
apiKey: config.apiKey,
|
|
51
53
|
sdkName: config.sdkName,
|
|
@@ -57,7 +59,9 @@ function _mergeDefaults(config) {
|
|
|
57
59
|
// A batch size below 1 would never empty the queue; above 100 the endpoint rejects it.
|
|
58
60
|
batchSize: _clamp(config.batchSize, 1, MAX_BATCH_SIZE, 10),
|
|
59
61
|
// A tiny interval would send constantly; one too large for a timer would fire every 1 ms.
|
|
60
|
-
flushInterval: _clamp(config.flushInterval, 100, MAX_TIMER_MS, 5e3)
|
|
62
|
+
flushInterval: _clamp(config.flushInterval, 100, MAX_TIMER_MS, 5e3),
|
|
63
|
+
advisories: (_c = config.advisories) != null ? _c : true,
|
|
64
|
+
onAdvisory: typeof config.onAdvisory === "function" ? config.onAdvisory : null
|
|
61
65
|
};
|
|
62
66
|
}
|
|
63
67
|
function _generateSessionId() {
|
|
@@ -361,6 +365,55 @@ function _takeBatch(events, maxEvents) {
|
|
|
361
365
|
}
|
|
362
366
|
return events.splice(0, count).map((event) => event.json);
|
|
363
367
|
}
|
|
368
|
+
function _parseAdvisory(raw) {
|
|
369
|
+
var _a;
|
|
370
|
+
const fields = {};
|
|
371
|
+
for (const part of raw.split("&")) {
|
|
372
|
+
const eq = part.indexOf("=");
|
|
373
|
+
if (eq <= 0) continue;
|
|
374
|
+
try {
|
|
375
|
+
fields[decodeURIComponent(part.slice(0, eq))] = decodeURIComponent(part.slice(eq + 1).replace(/\+/g, " "));
|
|
376
|
+
} catch (e) {
|
|
377
|
+
return null;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
const severity = fields["severity"];
|
|
381
|
+
if (!fields["version"] || severity !== "deprecated" && severity !== "broken" && severity !== "security") {
|
|
382
|
+
return null;
|
|
383
|
+
}
|
|
384
|
+
return {
|
|
385
|
+
version: fields["version"],
|
|
386
|
+
severity,
|
|
387
|
+
message: ((_a = fields["message"]) != null ? _a : "").slice(0, 280),
|
|
388
|
+
...fields["upgrade_to"] ? { upgradeTo: fields["upgrade_to"].slice(0, 50) } : {}
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
function _advisoryText(sdkName, a) {
|
|
392
|
+
const what = { deprecated: "is deprecated", broken: "has a known problem", security: "has a security issue" }[a.severity];
|
|
393
|
+
let text = `[${sdkName}] Version ${a.version} ${what}.`;
|
|
394
|
+
if (a.message) text += ` ${a.message}`;
|
|
395
|
+
if (a.upgradeTo) text += ` Upgrade to ${a.upgradeTo}.`;
|
|
396
|
+
return text;
|
|
397
|
+
}
|
|
398
|
+
function _handleAdvisory(config, response) {
|
|
399
|
+
var _a, _b;
|
|
400
|
+
if (!config.advisories) return;
|
|
401
|
+
const raw = (_b = (_a = response == null ? void 0 : response.headers) == null ? void 0 : _a.get) == null ? void 0 : _b.call(_a, ADVISORY_HEADER);
|
|
402
|
+
if (typeof raw !== "string" || raw === "") return;
|
|
403
|
+
const advisory = _parseAdvisory(raw);
|
|
404
|
+
if (!advisory || _advisoriesShown.has(advisory.version)) return;
|
|
405
|
+
_advisoriesShown.add(advisory.version);
|
|
406
|
+
if (config.onAdvisory) {
|
|
407
|
+
try {
|
|
408
|
+
config.onAdvisory(advisory);
|
|
409
|
+
} catch (e) {
|
|
410
|
+
}
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
if (typeof console !== "undefined" && typeof console.warn === "function") {
|
|
414
|
+
console.warn(_advisoryText(config.sdkName, advisory));
|
|
415
|
+
}
|
|
416
|
+
}
|
|
364
417
|
function _send(config, batch, keepalive) {
|
|
365
418
|
var _a;
|
|
366
419
|
if (typeof fetch !== "function") {
|
|
@@ -425,6 +478,7 @@ function _send(config, batch, keepalive) {
|
|
|
425
478
|
if (stream && typeof stream.cancel === "function") discarded = stream.cancel();
|
|
426
479
|
} catch (e) {
|
|
427
480
|
}
|
|
481
|
+
if (delivered) _safely(() => _handleAdvisory(config, response));
|
|
428
482
|
Promise.resolve(discarded).then(settle, settle);
|
|
429
483
|
},
|
|
430
484
|
() => settle()
|
|
@@ -822,6 +876,7 @@ var SdkGarden = {
|
|
|
822
876
|
_pending.clear();
|
|
823
877
|
_registered.clear();
|
|
824
878
|
_undeclared = [];
|
|
879
|
+
_advisoriesShown.clear();
|
|
825
880
|
}
|
|
826
881
|
};
|
|
827
882
|
var index_default = SdkGarden;
|
package/package.json
CHANGED