@plasius/schema 1.0.18 → 1.1.1
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 +140 -1
- package/dist/index.cjs +1934 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +391 -0
- package/dist/index.d.ts +391 -0
- package/dist/index.js +1883 -0
- package/dist/index.js.map +1 -0
- package/package.json +18 -6
- package/.eslintrc.cjs +0 -7
- package/.github/workflows/cd.yml +0 -186
- package/.github/workflows/ci.yml +0 -16
- package/.nvmrc +0 -1
- package/.vscode/launch.json +0 -15
- package/CHANGELOG.md +0 -86
- package/CODE_OF_CONDUCT.md +0 -79
- package/CONTRIBUTING.md +0 -201
- package/CONTRIBUTORS.md +0 -27
- package/SECURITY.md +0 -17
- package/docs/adrs/adr-0001: schema.md +0 -45
- package/docs/adrs/adr-template.md +0 -67
- package/legal/CLA-REGISTRY.csv +0 -2
- package/legal/CLA.md +0 -22
- package/legal/CORPORATE_CLA.md +0 -57
- package/legal/INDIVIDUAL_CLA.md +0 -91
- package/sbom.cdx.json +0 -66
- package/src/components.ts +0 -39
- package/src/field.builder.ts +0 -119
- package/src/field.ts +0 -14
- package/src/index.ts +0 -7
- package/src/infer.ts +0 -34
- package/src/pii.ts +0 -165
- package/src/schema.ts +0 -826
- package/src/types.ts +0 -156
- package/src/validation/countryCode.ISO3166.ts +0 -256
- package/src/validation/currencyCode.ISO4217.ts +0 -191
- package/src/validation/dateTime.ISO8601.ts +0 -9
- package/src/validation/email.RFC5322.ts +0 -9
- package/src/validation/generalText.OWASP.ts +0 -39
- package/src/validation/index.ts +0 -13
- package/src/validation/name.OWASP.ts +0 -25
- package/src/validation/percentage.ISO80000-1.ts +0 -8
- package/src/validation/phone.E.164.ts +0 -9
- package/src/validation/richtext.OWASP.ts +0 -34
- package/src/validation/url.WHATWG.ts +0 -16
- package/src/validation/user.MS-GOOGLE-APPLE.ts +0 -31
- package/src/validation/uuid.RFC4122.ts +0 -10
- package/src/validation/version.SEMVER2.0.0.ts +0 -8
- package/tests/pii.test.ts +0 -139
- package/tests/schema.test.ts +0 -501
- package/tests/test-utils.ts +0 -97
- package/tests/validate.test.ts +0 -97
- package/tests/validation.test.ts +0 -98
- package/tsconfig.build.json +0 -19
- package/tsconfig.json +0 -7
- package/tsup.config.ts +0 -10
- package/vitest.config.js +0 -20
package/sbom.cdx.json
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
|
|
3
|
-
"bomFormat": "CycloneDX",
|
|
4
|
-
"specVersion": "1.5",
|
|
5
|
-
"serialNumber": "urn:uuid:5e59b78b-f6f8-47c0-8329-d6447041544f",
|
|
6
|
-
"version": 1,
|
|
7
|
-
"metadata": {
|
|
8
|
-
"timestamp": "2025-09-17T16:14:58.925Z",
|
|
9
|
-
"lifecycles": [
|
|
10
|
-
{
|
|
11
|
-
"phase": "build"
|
|
12
|
-
}
|
|
13
|
-
],
|
|
14
|
-
"tools": [
|
|
15
|
-
{
|
|
16
|
-
"vendor": "npm",
|
|
17
|
-
"name": "cli",
|
|
18
|
-
"version": "10.9.3"
|
|
19
|
-
}
|
|
20
|
-
],
|
|
21
|
-
"component": {
|
|
22
|
-
"bom-ref": "@plasius/schema@1.0.18",
|
|
23
|
-
"type": "library",
|
|
24
|
-
"name": "schema",
|
|
25
|
-
"version": "1.0.18",
|
|
26
|
-
"scope": "required",
|
|
27
|
-
"author": "Plasius LTD",
|
|
28
|
-
"description": "Entity schema definition & validation helpers for Plasius ecosystem",
|
|
29
|
-
"purl": "pkg:npm/%40plasius/schema@1.0.18",
|
|
30
|
-
"properties": [
|
|
31
|
-
{
|
|
32
|
-
"name": "cdx:npm:package:path",
|
|
33
|
-
"value": ""
|
|
34
|
-
}
|
|
35
|
-
],
|
|
36
|
-
"externalReferences": [
|
|
37
|
-
{
|
|
38
|
-
"type": "vcs",
|
|
39
|
-
"url": "git+https://github.com/Plasius-LTD/schema.git"
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
"type": "website",
|
|
43
|
-
"url": "https://github.com/Plasius-LTD/schema#readme"
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
"type": "issue-tracker",
|
|
47
|
-
"url": "https://github.com/Plasius-LTD/schema/issues"
|
|
48
|
-
}
|
|
49
|
-
],
|
|
50
|
-
"licenses": [
|
|
51
|
-
{
|
|
52
|
-
"license": {
|
|
53
|
-
"id": "Apache-2.0"
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
]
|
|
57
|
-
}
|
|
58
|
-
},
|
|
59
|
-
"components": [],
|
|
60
|
-
"dependencies": [
|
|
61
|
-
{
|
|
62
|
-
"ref": "@plasius/schema@1.0.18",
|
|
63
|
-
"dependsOn": []
|
|
64
|
-
}
|
|
65
|
-
]
|
|
66
|
-
}
|
package/src/components.ts
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { Infer } from "./infer.js";
|
|
2
|
-
import { createSchema } from "./schema.js";
|
|
3
|
-
import { Schema, SchemaShape } from "./types.js";
|
|
4
|
-
// This module provides a registry for component schemas, allowing components to be registered and retrieved by type.
|
|
5
|
-
const componentSchemaRegistry = new Map<string, Schema<SchemaShape>>();
|
|
6
|
-
|
|
7
|
-
export function createComponentSchema<T extends SchemaShape>(
|
|
8
|
-
shape: SchemaShape,
|
|
9
|
-
name: string,
|
|
10
|
-
version: string,
|
|
11
|
-
tableName: string = "",
|
|
12
|
-
schemaValidator: (entity: Infer<T>) => boolean = () => true
|
|
13
|
-
): Schema<SchemaShape> {
|
|
14
|
-
const schema = createSchema<T>(shape as T, name, {
|
|
15
|
-
version: version,
|
|
16
|
-
piiEnforcement: "strict",
|
|
17
|
-
table: tableName,
|
|
18
|
-
schemaValidator,
|
|
19
|
-
});
|
|
20
|
-
registerComponentSchema(name, schema as Schema<SchemaShape>);
|
|
21
|
-
return schema as Schema<SchemaShape>;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export function registerComponentSchema(
|
|
25
|
-
type: string,
|
|
26
|
-
schema: Schema<SchemaShape>
|
|
27
|
-
) {
|
|
28
|
-
componentSchemaRegistry.set(type, schema);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function getComponentSchema(
|
|
32
|
-
type: string
|
|
33
|
-
): Schema<SchemaShape> | undefined {
|
|
34
|
-
return componentSchemaRegistry.get(type);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export function getAllComponentSchemas(): [string, Schema<SchemaShape>][] {
|
|
38
|
-
return Array.from(componentSchemaRegistry.entries());
|
|
39
|
-
}
|
package/src/field.builder.ts
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
type FieldType = "string" | "number" | "boolean" | "object" | "array" | "ref";
|
|
2
|
-
|
|
3
|
-
import { type PII } from "./pii.js";
|
|
4
|
-
import { getSchemaForType } from "./schema.js";
|
|
5
|
-
|
|
6
|
-
export class FieldBuilder<TExternal = unknown, TInternal = TExternal> {
|
|
7
|
-
_type!: TExternal;
|
|
8
|
-
_storageType!: TInternal;
|
|
9
|
-
isSystem = false;
|
|
10
|
-
isImmutable = false;
|
|
11
|
-
isRequired = true;
|
|
12
|
-
_validator?: (value: any) => boolean;
|
|
13
|
-
_description: string = "";
|
|
14
|
-
_version: string = "1.0";
|
|
15
|
-
_shape?: Record<string, FieldBuilder<any>>;
|
|
16
|
-
itemType?: FieldBuilder<any>;
|
|
17
|
-
refType?: string;
|
|
18
|
-
_pii: PII = {
|
|
19
|
-
classification: "none",
|
|
20
|
-
action: "none",
|
|
21
|
-
logHandling: "plain",
|
|
22
|
-
purpose: "an ordinary value",
|
|
23
|
-
};
|
|
24
|
-
enumValues?: readonly TInternal[];
|
|
25
|
-
|
|
26
|
-
constructor(
|
|
27
|
-
public type: FieldType,
|
|
28
|
-
options: {
|
|
29
|
-
shape?: Record<string, FieldBuilder<any>>;
|
|
30
|
-
itemType?: FieldBuilder<any>;
|
|
31
|
-
refType?: string;
|
|
32
|
-
} = {}
|
|
33
|
-
) {
|
|
34
|
-
this._shape = options.shape;
|
|
35
|
-
this.itemType = options.itemType;
|
|
36
|
-
this.refType = options.refType;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
immutable(): FieldBuilder<TExternal, TInternal> {
|
|
40
|
-
this.isImmutable = true;
|
|
41
|
-
return this;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
system(): FieldBuilder<TExternal, TInternal> {
|
|
45
|
-
this.isSystem = true;
|
|
46
|
-
return this;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
required(): FieldBuilder<TExternal, TInternal> {
|
|
50
|
-
this.isRequired = true;
|
|
51
|
-
return this;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
optional(): FieldBuilder<TExternal, TInternal> {
|
|
55
|
-
this.isRequired = false;
|
|
56
|
-
return this;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
validator(
|
|
60
|
-
fn: (value: TInternal) => boolean
|
|
61
|
-
): FieldBuilder<TExternal, TInternal> {
|
|
62
|
-
this._validator = fn;
|
|
63
|
-
return this;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
description(desc: string): FieldBuilder<TExternal, TInternal> {
|
|
67
|
-
this._description = desc;
|
|
68
|
-
return this;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
version(ver: string): FieldBuilder<TExternal, TInternal> {
|
|
72
|
-
this._version = ver;
|
|
73
|
-
return this;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/// PID informs the schema PII handling of the manner in
|
|
77
|
-
/// which to handle data relating to this field.
|
|
78
|
-
PID(pii: PII): FieldBuilder<TExternal, TInternal> {
|
|
79
|
-
this._pii = pii;
|
|
80
|
-
return this;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
enum<const U extends readonly TInternal[]>(
|
|
84
|
-
values: U
|
|
85
|
-
): FieldBuilder<U[number]> {
|
|
86
|
-
if (
|
|
87
|
-
this.type !== "string" &&
|
|
88
|
-
this.type !== "number" &&
|
|
89
|
-
!(
|
|
90
|
-
this.type === "array" &&
|
|
91
|
-
(this.itemType?.type === "string" || this.itemType?.type === "number")
|
|
92
|
-
)
|
|
93
|
-
) {
|
|
94
|
-
throw new Error(
|
|
95
|
-
"Enums are only supported on string or number fields or arrays of strings or numbers."
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
this.enumValues = values;
|
|
99
|
-
return this as any;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
as<U>(): FieldBuilder<U, TInternal> {
|
|
103
|
-
const clone = new FieldBuilder<U, TInternal>(this.type, {
|
|
104
|
-
shape: this._shape,
|
|
105
|
-
itemType: this.itemType,
|
|
106
|
-
});
|
|
107
|
-
clone.enumValues = this.enumValues;
|
|
108
|
-
clone.isImmutable = this.isImmutable;
|
|
109
|
-
clone.isSystem = this.isSystem;
|
|
110
|
-
clone.isRequired = this.isRequired;
|
|
111
|
-
clone._description = this._description;
|
|
112
|
-
clone._version = this._version;
|
|
113
|
-
clone._pii = this._pii;
|
|
114
|
-
clone._validator = this._validator as any;
|
|
115
|
-
return clone;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export default FieldBuilder;
|
package/src/field.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { FieldBuilder } from "./field.builder.js";
|
|
2
|
-
import { Infer } from "./infer.js";
|
|
3
|
-
import { SchemaShape } from "./types.js";
|
|
4
|
-
|
|
5
|
-
export const field = {
|
|
6
|
-
string: () => new FieldBuilder<string>("string"),
|
|
7
|
-
number: () => new FieldBuilder<number>("number"),
|
|
8
|
-
boolean: () => new FieldBuilder<boolean>("boolean"),
|
|
9
|
-
object: <T extends Record<string, FieldBuilder>>(fields: T) =>
|
|
10
|
-
new FieldBuilder<T>("object", { shape: fields }),
|
|
11
|
-
array: (itemType: FieldBuilder) => new FieldBuilder("array", { itemType }),
|
|
12
|
-
ref: <S extends SchemaShape>(refType: string) =>
|
|
13
|
-
new FieldBuilder<Infer<S>>("ref", { refType }),
|
|
14
|
-
};
|
package/src/index.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export type { Infer } from "./infer.js";
|
|
2
|
-
export { field } from "./field.js";
|
|
3
|
-
export { createSchema, getSchemaForType, getAllSchemas } from "./schema.js";
|
|
4
|
-
export type * from "./types.js";
|
|
5
|
-
export * from "./components.js";
|
|
6
|
-
export * from "./validation/index.js";
|
|
7
|
-
export * from "./field.builder.js";
|
package/src/infer.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { SchemaShape } from "./types.js";
|
|
2
|
-
|
|
3
|
-
type InferField<T> = T extends { _type: infer U }
|
|
4
|
-
? U
|
|
5
|
-
: T extends { type: "string" }
|
|
6
|
-
? string
|
|
7
|
-
: T extends { type: "number" }
|
|
8
|
-
? number
|
|
9
|
-
: T extends { type: "boolean" }
|
|
10
|
-
? boolean
|
|
11
|
-
: T extends { type: "array"; itemType: infer Item }
|
|
12
|
-
? InferField<Item>[]
|
|
13
|
-
: T extends { type: "object"; shape: infer Shape extends SchemaShape }
|
|
14
|
-
? InferFromShape<Shape>
|
|
15
|
-
: unknown;
|
|
16
|
-
|
|
17
|
-
type IsOptional<T> = T extends { optional: true } ? true : false;
|
|
18
|
-
|
|
19
|
-
type InferFromShape<S extends SchemaShape> = {
|
|
20
|
-
[K in keyof S]: IsOptional<S[K]> extends true
|
|
21
|
-
? InferField<S[K]> | undefined
|
|
22
|
-
: InferField<S[K]>;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
type InferFromSchema<T extends { shape: SchemaShape }> = InferFromShape<
|
|
26
|
-
T["shape"]
|
|
27
|
-
>;
|
|
28
|
-
|
|
29
|
-
type IsSchema<T> = T extends { shape: SchemaShape } ? true : false;
|
|
30
|
-
|
|
31
|
-
export type Infer<T> =
|
|
32
|
-
IsSchema<T> extends true
|
|
33
|
-
? InferFromSchema<T & { shape: SchemaShape }>
|
|
34
|
-
: InferFromShape<T & SchemaShape>;
|
package/src/pii.ts
DELETED
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
export type PIIClassification = "none" | "low" | "high";
|
|
2
|
-
|
|
3
|
-
export type PIIAction = "encrypt" | "hash" | "clear" | "none";
|
|
4
|
-
|
|
5
|
-
export type PIILogHandling = "redact" | "omit" | "pseudonym" | "plain";
|
|
6
|
-
|
|
7
|
-
export type PiiEnforcement = "strict" | "warn" | "none";
|
|
8
|
-
|
|
9
|
-
export interface PII {
|
|
10
|
-
classification: PIIClassification;
|
|
11
|
-
action: PIIAction;
|
|
12
|
-
logHandling?: PIILogHandling; // How should this PII be handled in logs?
|
|
13
|
-
purpose?: string; // optional, for audit: e.g. "user contact", "analytics"
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Centralized PII enforcement for field-level validation.
|
|
18
|
-
* Returns { shortCircuit: true } when in strict mode and value is missing for high PII.
|
|
19
|
-
*/
|
|
20
|
-
export function enforcePIIField(
|
|
21
|
-
parentKey: string,
|
|
22
|
-
key: string,
|
|
23
|
-
value: any,
|
|
24
|
-
def: any,
|
|
25
|
-
enforcement: PiiEnforcement = "none",
|
|
26
|
-
errors?: string[],
|
|
27
|
-
logger?: { warn: (msg: string) => void }
|
|
28
|
-
): { shortCircuit: boolean } {
|
|
29
|
-
const path = parentKey ? `${parentKey}.${key}` : key;
|
|
30
|
-
if (def?._pii?.classification === "high" && (def?.isRequired ?? true)) {
|
|
31
|
-
const missing = value === undefined || value === null || value === "";
|
|
32
|
-
if (missing) {
|
|
33
|
-
const msg = `High PII field must not be empty: ${path}`;
|
|
34
|
-
if (enforcement === "strict") {
|
|
35
|
-
errors?.push(msg);
|
|
36
|
-
return { shortCircuit: true };
|
|
37
|
-
}
|
|
38
|
-
if (enforcement === "warn") {
|
|
39
|
-
logger?.warn?.(`WARN (PII Enforcement): ${msg}`);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
return { shortCircuit: false };
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Apply storage-time PII transforms based on field definitions in shape.
|
|
48
|
-
*/
|
|
49
|
-
export function prepareForStorage(
|
|
50
|
-
shape: Record<string, any>,
|
|
51
|
-
input: Record<string, any>,
|
|
52
|
-
encryptFn: (value: any) => string,
|
|
53
|
-
hashFn: (value: any) => string
|
|
54
|
-
): Record<string, any> {
|
|
55
|
-
const result: any = {};
|
|
56
|
-
for (const key in shape) {
|
|
57
|
-
const def = shape[key];
|
|
58
|
-
if (!def) continue;
|
|
59
|
-
const value = input[key];
|
|
60
|
-
if (def._pii?.action === "encrypt") {
|
|
61
|
-
result[key + "Encrypted"] = encryptFn(value);
|
|
62
|
-
} else if (def._pii?.action === "hash") {
|
|
63
|
-
result[key + "Hash"] = hashFn(value);
|
|
64
|
-
} else {
|
|
65
|
-
result[key] = value;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
return result;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Apply read-time PII transforms (e.g., decrypt) based on field definitions in shape.
|
|
73
|
-
*/
|
|
74
|
-
export function prepareForRead(
|
|
75
|
-
shape: Record<string, any>,
|
|
76
|
-
stored: Record<string, any>,
|
|
77
|
-
decryptFn: (value: string) => any
|
|
78
|
-
): Record<string, any> {
|
|
79
|
-
const result: any = {};
|
|
80
|
-
for (const key in shape) {
|
|
81
|
-
const def = shape[key];
|
|
82
|
-
if (!def) continue;
|
|
83
|
-
if (def._pii?.action === "encrypt") {
|
|
84
|
-
result[key] = decryptFn(stored[key + "Encrypted"]);
|
|
85
|
-
} else {
|
|
86
|
-
result[key] = stored[key];
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
return result;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Sanitize data for logging according to PII logHandling.
|
|
94
|
-
*/
|
|
95
|
-
export function sanitizeForLog(
|
|
96
|
-
shape: Record<string, any>,
|
|
97
|
-
data: Record<string, any>,
|
|
98
|
-
pseudonymFn: (value: any) => string
|
|
99
|
-
): Record<string, any> {
|
|
100
|
-
const output: any = {};
|
|
101
|
-
for (const key in shape) {
|
|
102
|
-
const def = shape[key];
|
|
103
|
-
if (!def) continue;
|
|
104
|
-
const value = data[key];
|
|
105
|
-
const handling = def._pii?.logHandling as PIILogHandling | undefined;
|
|
106
|
-
if (handling === "omit") continue;
|
|
107
|
-
if (handling === "redact") {
|
|
108
|
-
output[key] = "[REDACTED]";
|
|
109
|
-
} else if (handling === "pseudonym") {
|
|
110
|
-
output[key] = pseudonymFn(value);
|
|
111
|
-
} else {
|
|
112
|
-
output[key] = value;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
return output;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Produce a PII audit list for the given shape.
|
|
120
|
-
*/
|
|
121
|
-
export function getPiiAudit(shape: Record<string, any>): Array<{
|
|
122
|
-
field: string;
|
|
123
|
-
classification: PIIClassification;
|
|
124
|
-
action: PIIAction;
|
|
125
|
-
logHandling?: PIILogHandling;
|
|
126
|
-
purpose?: string;
|
|
127
|
-
}> {
|
|
128
|
-
const piiFields: Array<any> = [];
|
|
129
|
-
for (const key in shape) {
|
|
130
|
-
const def = shape[key];
|
|
131
|
-
if (!def) continue;
|
|
132
|
-
if (def._pii && def._pii.classification !== "none") {
|
|
133
|
-
piiFields.push({
|
|
134
|
-
field: key,
|
|
135
|
-
classification: def._pii.classification,
|
|
136
|
-
action: def._pii.action,
|
|
137
|
-
logHandling: def._pii.logHandling,
|
|
138
|
-
purpose: def._pii.purpose,
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
return piiFields;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Scrub PII fields for delete/retention workflows.
|
|
147
|
-
*/
|
|
148
|
-
export function scrubPiiForDelete(
|
|
149
|
-
shape: Record<string, any>,
|
|
150
|
-
stored: Record<string, any>
|
|
151
|
-
): Record<string, any> {
|
|
152
|
-
const result: any = { ...stored };
|
|
153
|
-
for (const key in shape) {
|
|
154
|
-
const def = shape[key];
|
|
155
|
-
if (!def) continue;
|
|
156
|
-
if (def._pii?.action === "encrypt") {
|
|
157
|
-
result[key + "Encrypted"] = null;
|
|
158
|
-
} else if (def._pii?.action === "hash") {
|
|
159
|
-
result[key + "Hash"] = null;
|
|
160
|
-
} else if (def._pii?.action === "clear") {
|
|
161
|
-
result[key] = null;
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
return result;
|
|
165
|
-
}
|