@plasius/schema 1.4.1 → 1.4.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.
- package/README.md +19 -2
- package/dist/{chunk-UQHPDQZX.js → chunk-GNL2RBO5.js} +133 -32
- package/dist/chunk-GNL2RBO5.js.map +1 -0
- package/dist/feedback-diagnostics.cjs +132 -31
- package/dist/feedback-diagnostics.cjs.map +1 -1
- package/dist/feedback-diagnostics.js +1 -1
- package/dist/index.cjs +184 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +39 -1
- package/dist/index.d.ts +39 -1
- package/dist/index.js +51 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-UQHPDQZX.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
FEEDBACK_ABUSE_BLOCK_BANDS: () => FEEDBACK_ABUSE_BLOCK_BANDS,
|
|
23
24
|
FEEDBACK_ANALYSIS_MODEL_VERSIONS: () => FEEDBACK_ANALYSIS_MODEL_VERSIONS,
|
|
24
25
|
FEEDBACK_BACKEND_BUCKETS: () => FEEDBACK_BACKEND_BUCKETS,
|
|
25
26
|
FEEDBACK_BUG_COOLDOWN_SECONDS: () => FEEDBACK_BUG_COOLDOWN_SECONDS,
|
|
@@ -51,6 +52,7 @@ __export(index_exports, {
|
|
|
51
52
|
FEEDBACK_VIEWPORT_BUCKETS: () => FEEDBACK_VIEWPORT_BUCKETS,
|
|
52
53
|
FeedbackAcceptanceReceiptSchema: () => FeedbackAcceptanceReceiptSchema,
|
|
53
54
|
FeedbackAnalysisReceiptSchema: () => FeedbackAnalysisReceiptSchema,
|
|
55
|
+
FeedbackBugHealthMetricsProjectionSchema: () => FeedbackBugHealthMetricsProjectionSchema,
|
|
54
56
|
FeedbackBugPacketSchema: () => FeedbackBugPacketSchema,
|
|
55
57
|
FeedbackBugSubmissionRequestSchema: () => FeedbackBugSubmissionRequestSchema,
|
|
56
58
|
FeedbackCommittedAcceptanceEvidenceSchema: () => FeedbackCommittedAcceptanceEvidenceSchema,
|
|
@@ -1783,45 +1785,113 @@ function getShape(def) {
|
|
|
1783
1785
|
var MAX_STRICT_VALIDATION_NODES = 1e4;
|
|
1784
1786
|
var MAX_STRICT_VALIDATION_DEPTH = 256;
|
|
1785
1787
|
var MAX_STRICT_VALIDATION_OBJECTS = MAX_STRICT_VALIDATION_NODES;
|
|
1786
|
-
function
|
|
1787
|
-
const
|
|
1788
|
-
|
|
1789
|
-
];
|
|
1788
|
+
function snapshotStrictInput(input) {
|
|
1789
|
+
const snapshot = Array.isArray(input) ? [] : {};
|
|
1790
|
+
const pending = [{ source: input, target: snapshot, depth: 0 }];
|
|
1790
1791
|
const seen = /* @__PURE__ */ new WeakSet();
|
|
1791
|
-
let visitedNodes =
|
|
1792
|
+
let visitedNodes = 1;
|
|
1792
1793
|
try {
|
|
1793
1794
|
while (pending.length > 0) {
|
|
1794
1795
|
const current = pending.pop();
|
|
1795
1796
|
if (!current) {
|
|
1796
1797
|
continue;
|
|
1797
1798
|
}
|
|
1798
|
-
visitedNodes += 1;
|
|
1799
1799
|
if (visitedNodes > MAX_STRICT_VALIDATION_NODES || current.depth > MAX_STRICT_VALIDATION_DEPTH) {
|
|
1800
|
-
return false;
|
|
1800
|
+
return { valid: false };
|
|
1801
1801
|
}
|
|
1802
|
-
if (
|
|
1803
|
-
|
|
1802
|
+
if (seen.has(current.source)) {
|
|
1803
|
+
return { valid: false };
|
|
1804
1804
|
}
|
|
1805
|
-
|
|
1806
|
-
|
|
1805
|
+
seen.add(current.source);
|
|
1806
|
+
const isArray = Array.isArray(current.source);
|
|
1807
|
+
const prototype = Object.getPrototypeOf(current.source);
|
|
1808
|
+
if (isArray && prototype !== Array.prototype || !isArray && prototype !== Object.prototype && prototype !== null) {
|
|
1809
|
+
return { valid: false };
|
|
1807
1810
|
}
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
return false;
|
|
1811
|
+
const ownKeys = Reflect.ownKeys(current.source);
|
|
1812
|
+
if (visitedNodes + ownKeys.length > MAX_STRICT_VALIDATION_NODES) {
|
|
1813
|
+
return { valid: false };
|
|
1812
1814
|
}
|
|
1813
|
-
const
|
|
1815
|
+
const descriptors = /* @__PURE__ */ new Map();
|
|
1816
|
+
for (const key of ownKeys) {
|
|
1817
|
+
const descriptor = Object.getOwnPropertyDescriptor(
|
|
1818
|
+
current.source,
|
|
1819
|
+
key
|
|
1820
|
+
);
|
|
1821
|
+
if (descriptor === void 0) {
|
|
1822
|
+
return { valid: false };
|
|
1823
|
+
}
|
|
1824
|
+
descriptors.set(key, descriptor);
|
|
1825
|
+
}
|
|
1826
|
+
if (isArray) {
|
|
1827
|
+
const lengthDescriptor = descriptors.get("length");
|
|
1828
|
+
if (lengthDescriptor === void 0 || !("value" in lengthDescriptor) || !Number.isSafeInteger(lengthDescriptor.value) || lengthDescriptor.value < 0 || lengthDescriptor.value > MAX_STRICT_VALIDATION_NODES) {
|
|
1829
|
+
return { valid: false };
|
|
1830
|
+
}
|
|
1831
|
+
let elementCount = 0;
|
|
1832
|
+
for (const key of ownKeys) {
|
|
1833
|
+
if (key === "length") {
|
|
1834
|
+
continue;
|
|
1835
|
+
}
|
|
1836
|
+
if (typeof key !== "string" || !/^(?:0|[1-9]\d*)$/.test(key)) {
|
|
1837
|
+
return { valid: false };
|
|
1838
|
+
}
|
|
1839
|
+
const descriptor = descriptors.get(key);
|
|
1840
|
+
if (descriptor === void 0 || descriptor.enumerable !== true || Number(key) >= lengthDescriptor.value) {
|
|
1841
|
+
return { valid: false };
|
|
1842
|
+
}
|
|
1843
|
+
elementCount += 1;
|
|
1844
|
+
}
|
|
1845
|
+
if (elementCount !== lengthDescriptor.value) {
|
|
1846
|
+
return { valid: false };
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
visitedNodes += ownKeys.length;
|
|
1850
|
+
const keys = ownKeys.filter(
|
|
1851
|
+
(key) => descriptors.get(key)?.enumerable
|
|
1852
|
+
);
|
|
1814
1853
|
for (const key of keys) {
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1854
|
+
if (typeof key !== "string") {
|
|
1855
|
+
return { valid: false };
|
|
1856
|
+
}
|
|
1857
|
+
if (isArray && !/^(?:0|[1-9]\d*)$/.test(key)) {
|
|
1858
|
+
return { valid: false };
|
|
1859
|
+
}
|
|
1860
|
+
const descriptor = descriptors.get(key);
|
|
1861
|
+
if (descriptor === void 0 || !("value" in descriptor) || descriptor.get !== void 0 || descriptor.set !== void 0) {
|
|
1862
|
+
return { valid: false };
|
|
1863
|
+
}
|
|
1864
|
+
const child = descriptor.value;
|
|
1865
|
+
if (typeof child === "function") {
|
|
1866
|
+
return { valid: false };
|
|
1867
|
+
}
|
|
1868
|
+
if (typeof child === "object" && child !== null) {
|
|
1869
|
+
const childSnapshot = Array.isArray(child) ? [] : {};
|
|
1870
|
+
Object.defineProperty(current.target, key, {
|
|
1871
|
+
value: childSnapshot,
|
|
1872
|
+
enumerable: true,
|
|
1873
|
+
configurable: true,
|
|
1874
|
+
writable: true
|
|
1875
|
+
});
|
|
1876
|
+
pending.push({
|
|
1877
|
+
source: child,
|
|
1878
|
+
target: childSnapshot,
|
|
1879
|
+
depth: current.depth + 1
|
|
1880
|
+
});
|
|
1881
|
+
continue;
|
|
1882
|
+
}
|
|
1883
|
+
Object.defineProperty(current.target, key, {
|
|
1884
|
+
value: child,
|
|
1885
|
+
enumerable: true,
|
|
1886
|
+
configurable: true,
|
|
1887
|
+
writable: true
|
|
1818
1888
|
});
|
|
1819
1889
|
}
|
|
1820
1890
|
}
|
|
1821
1891
|
} catch {
|
|
1822
|
-
return false;
|
|
1892
|
+
return { valid: false };
|
|
1823
1893
|
}
|
|
1824
|
-
return true;
|
|
1894
|
+
return { valid: true, value: snapshot };
|
|
1825
1895
|
}
|
|
1826
1896
|
function strictReferenceShape(def) {
|
|
1827
1897
|
return {
|
|
@@ -2388,8 +2458,10 @@ function createSchema(_shape, entityType, options = {
|
|
|
2388
2458
|
if (typeof input !== "object" || input === null) {
|
|
2389
2459
|
return { valid: false, errors: ["Input must be an object"] };
|
|
2390
2460
|
}
|
|
2461
|
+
let strictInputSnapshot;
|
|
2391
2462
|
if (options.unknownFields === "reject") {
|
|
2392
|
-
|
|
2463
|
+
const snapshot = snapshotStrictInput(input);
|
|
2464
|
+
if (!snapshot.valid) {
|
|
2393
2465
|
return {
|
|
2394
2466
|
valid: false,
|
|
2395
2467
|
errors: ["Strict validation complexity limit exceeded."],
|
|
@@ -2402,16 +2474,32 @@ function createSchema(_shape, entityType, options = {
|
|
|
2402
2474
|
]
|
|
2403
2475
|
};
|
|
2404
2476
|
}
|
|
2477
|
+
strictInputSnapshot = snapshot.value;
|
|
2405
2478
|
const scanState = {
|
|
2406
2479
|
remainingObjects: MAX_STRICT_VALIDATION_OBJECTS,
|
|
2407
2480
|
limitExceeded: false
|
|
2408
2481
|
};
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2482
|
+
let locations;
|
|
2483
|
+
try {
|
|
2484
|
+
locations = unknownFieldLocations(
|
|
2485
|
+
strictInputSnapshot,
|
|
2486
|
+
schema._shape,
|
|
2487
|
+
"root",
|
|
2488
|
+
scanState
|
|
2489
|
+
);
|
|
2490
|
+
} catch {
|
|
2491
|
+
return {
|
|
2492
|
+
valid: false,
|
|
2493
|
+
errors: ["Strict validation complexity limit exceeded."],
|
|
2494
|
+
issues: [
|
|
2495
|
+
{
|
|
2496
|
+
path: "root",
|
|
2497
|
+
code: "validation_complexity_limit",
|
|
2498
|
+
message: "Strict validation complexity limit exceeded."
|
|
2499
|
+
}
|
|
2500
|
+
]
|
|
2501
|
+
};
|
|
2502
|
+
}
|
|
2415
2503
|
if (scanState.limitExceeded) {
|
|
2416
2504
|
return {
|
|
2417
2505
|
valid: false,
|
|
@@ -2439,7 +2527,23 @@ function createSchema(_shape, entityType, options = {
|
|
|
2439
2527
|
};
|
|
2440
2528
|
}
|
|
2441
2529
|
}
|
|
2442
|
-
|
|
2530
|
+
let working;
|
|
2531
|
+
try {
|
|
2532
|
+
working = strictInputSnapshot ?? (typeof input === "object" && input !== null ? deepClone(input) : { ...input });
|
|
2533
|
+
} catch {
|
|
2534
|
+
return {
|
|
2535
|
+
valid: false,
|
|
2536
|
+
errors: ["Input could not be safely cloned."],
|
|
2537
|
+
issues: [
|
|
2538
|
+
{
|
|
2539
|
+
path: "root",
|
|
2540
|
+
code: "unsafe_input",
|
|
2541
|
+
message: "Input could not be safely cloned."
|
|
2542
|
+
}
|
|
2543
|
+
]
|
|
2544
|
+
};
|
|
2545
|
+
}
|
|
2546
|
+
const providedFieldNames = new Set(Object.keys(working));
|
|
2443
2547
|
if (working.type == null) working.type = entityType;
|
|
2444
2548
|
if (working.version == null) working.version = version;
|
|
2445
2549
|
const fromVersion = String(working.version ?? "0.0.0");
|
|
@@ -2556,9 +2660,8 @@ function createSchema(_shape, entityType, options = {
|
|
|
2556
2660
|
}
|
|
2557
2661
|
if (errors.length === 0 && options.schemaValidator) {
|
|
2558
2662
|
const castValue = result;
|
|
2559
|
-
const source = input;
|
|
2560
2663
|
const validationContext = Object.freeze({
|
|
2561
|
-
wasProvided: (fieldName) =>
|
|
2664
|
+
wasProvided: (fieldName) => providedFieldNames.has(fieldName)
|
|
2562
2665
|
});
|
|
2563
2666
|
if (!options.schemaValidator(castValue, validationContext)) {
|
|
2564
2667
|
errors.push("Schema-level validation failed.");
|
|
@@ -3398,6 +3501,15 @@ var FEEDBACK_BUG_COOLDOWN_SECONDS = Object.freeze([
|
|
|
3398
3501
|
24 * 60 * 60
|
|
3399
3502
|
]);
|
|
3400
3503
|
var FEEDBACK_REVIEW_COOLDOWN_SECONDS = 30 * 24 * 60 * 60;
|
|
3504
|
+
var FEEDBACK_ABUSE_BLOCK_BANDS = Object.freeze([
|
|
3505
|
+
"five-minutes",
|
|
3506
|
+
"fifteen-minutes",
|
|
3507
|
+
"one-hour",
|
|
3508
|
+
"six-hours",
|
|
3509
|
+
"twenty-four-hours",
|
|
3510
|
+
"fail-closed",
|
|
3511
|
+
"edge-blocked"
|
|
3512
|
+
]);
|
|
3401
3513
|
var FEEDBACK_ISSUE_TYPES = [
|
|
3402
3514
|
"visual-layout",
|
|
3403
3515
|
"functionality",
|
|
@@ -4305,6 +4417,43 @@ var FeedbackCommittedAcceptanceEvidenceSchema = createSchema(
|
|
|
4305
4417
|
"feedback-committed-acceptance-evidence",
|
|
4306
4418
|
strictOptions
|
|
4307
4419
|
);
|
|
4420
|
+
var FeedbackBugHealthMetricsProjectionSchema = createSchema(
|
|
4421
|
+
{
|
|
4422
|
+
projectionId: uuidField(),
|
|
4423
|
+
windowStart: canonicalServerUtcField(),
|
|
4424
|
+
windowEnd: canonicalServerUtcField(),
|
|
4425
|
+
observedAt: canonicalServerUtcField(),
|
|
4426
|
+
finalized: field.boolean().validator((value) => value === true),
|
|
4427
|
+
rejectedCount: countField(),
|
|
4428
|
+
trafficDenominator: countField(),
|
|
4429
|
+
abuseBlockBands: field.array(
|
|
4430
|
+
field.object({
|
|
4431
|
+
id: field.string().enum(FEEDBACK_ABUSE_BLOCK_BANDS),
|
|
4432
|
+
count: positiveCountField2()
|
|
4433
|
+
})
|
|
4434
|
+
).max(FEEDBACK_ABUSE_BLOCK_BANDS.length)
|
|
4435
|
+
},
|
|
4436
|
+
"feedback-bug-health-metrics-projection",
|
|
4437
|
+
{
|
|
4438
|
+
...strictOptions,
|
|
4439
|
+
schemaValidator: (value) => {
|
|
4440
|
+
const blockBands = value.abuseBlockBands;
|
|
4441
|
+
let previousIndex = -1;
|
|
4442
|
+
const canonicalBands = blockBands.every((bucket) => {
|
|
4443
|
+
const index = FEEDBACK_ABUSE_BLOCK_BANDS.indexOf(bucket.id);
|
|
4444
|
+
if (index <= previousIndex) {
|
|
4445
|
+
return false;
|
|
4446
|
+
}
|
|
4447
|
+
previousIndex = index;
|
|
4448
|
+
return true;
|
|
4449
|
+
});
|
|
4450
|
+
return orderedWindow(
|
|
4451
|
+
{ ...value, generatedAt: value.observedAt },
|
|
4452
|
+
60 * 60 * 1e3
|
|
4453
|
+
) && Date.parse(String(value.observedAt)) >= Date.parse(String(value.windowEnd)) && canonicalBands;
|
|
4454
|
+
}
|
|
4455
|
+
}
|
|
4456
|
+
);
|
|
4308
4457
|
var FeedbackGameReconstructionManifestSchema = createSchema(
|
|
4309
4458
|
{
|
|
4310
4459
|
reconstructionId: uuidField(),
|
|
@@ -4429,20 +4578,10 @@ var FeedbackHourlyBugReportSchema = createSchema(
|
|
|
4429
4578
|
abuseBlockBands: field.array(
|
|
4430
4579
|
field.object(
|
|
4431
4580
|
distributionShape(
|
|
4432
|
-
() => field.string().enum(
|
|
4433
|
-
[
|
|
4434
|
-
"five-minutes",
|
|
4435
|
-
"fifteen-minutes",
|
|
4436
|
-
"one-hour",
|
|
4437
|
-
"six-hours",
|
|
4438
|
-
"twenty-four-hours",
|
|
4439
|
-
"fail-closed",
|
|
4440
|
-
"edge-blocked"
|
|
4441
|
-
]
|
|
4442
|
-
)
|
|
4581
|
+
() => field.string().enum(FEEDBACK_ABUSE_BLOCK_BANDS)
|
|
4443
4582
|
)
|
|
4444
4583
|
)
|
|
4445
|
-
).max(
|
|
4584
|
+
).max(FEEDBACK_ABUSE_BLOCK_BANDS.length),
|
|
4446
4585
|
comparison: field.object({
|
|
4447
4586
|
previousHourRatio: field.number().min(0).max(1e3),
|
|
4448
4587
|
sevenDaySameHourRatio: field.number().min(0).max(1e3)
|
|
@@ -4763,6 +4902,7 @@ var FeedbackMaterializationManifestSchema = createSchema(
|
|
|
4763
4902
|
);
|
|
4764
4903
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4765
4904
|
0 && (module.exports = {
|
|
4905
|
+
FEEDBACK_ABUSE_BLOCK_BANDS,
|
|
4766
4906
|
FEEDBACK_ANALYSIS_MODEL_VERSIONS,
|
|
4767
4907
|
FEEDBACK_BACKEND_BUCKETS,
|
|
4768
4908
|
FEEDBACK_BUG_COOLDOWN_SECONDS,
|
|
@@ -4794,6 +4934,7 @@ var FeedbackMaterializationManifestSchema = createSchema(
|
|
|
4794
4934
|
FEEDBACK_VIEWPORT_BUCKETS,
|
|
4795
4935
|
FeedbackAcceptanceReceiptSchema,
|
|
4796
4936
|
FeedbackAnalysisReceiptSchema,
|
|
4937
|
+
FeedbackBugHealthMetricsProjectionSchema,
|
|
4797
4938
|
FeedbackBugPacketSchema,
|
|
4798
4939
|
FeedbackBugSubmissionRequestSchema,
|
|
4799
4940
|
FeedbackCommittedAcceptanceEvidenceSchema,
|